/** * Process an aggregate-type bucket. This is MySQL specific. * * @param Plugins_DeliveryLog $oBucket a reference to the using (context) object. * @param Date $oEnd A PEAR_Date instance, interval_start to process up to (inclusive). */ public function processBucket($oBucket, $oEnd) { $sTableName = $oBucket->getBucketTableName(); $oMainDbh =& OA_DB_Distributed::singleton(); if (PEAR::isError($oMainDbh)) { MAX::raiseError($oMainDbh, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } OA::debug(' - Processing the ' . $sTableName . ' table for data with operation interval start equal to or before ' . $oEnd->format('%Y-%m-%d %H:%M:%S') . ' ' . $oEnd->tz->getShortName(), PEAR_LOG_INFO); // Select all rows with interval_start <= previous OI start. $rsData =& $this->getBucketTableContent($sTableName, $oEnd); $rowCount = $rsData->getRowCount(); OA::debug(' - ' . $rsData->getRowCount() . ' records found', PEAR_LOG_DEBUG); if ($rowCount) { // We can't do bulk inserts with ON DUPLICATE. $aExecQueries = array(); while ($rsData->fetch()) { // Get first row $aRow = $rsData->toArray(); // Insert or update $aExecQueries[] = "SELECT bucket_update_{$sTableName}(" . join(',', array_map(array(&$oMainDbh, 'quote'), $aRow)) . ")"; } if (count($aExecQueries)) { foreach ($aExecQueries as $execQuery) { $result = $oMainDbh->exec($execQuery); if (PEAR::isError($result)) { MAX::raiseError($result, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } } } } }
function _getControllerClass($controllerType = '', $aParams = null, &$class, &$file) { if (!is_array($aParams)) { $aParams = array(); } if (empty($controllerType) || $controllerType == '-') { $controllerType = basename($_SERVER['SCRIPT_NAME']); $controllerType = preg_replace('#^(?:stats-)?(.*)\\.php#', '$1', $controllerType); } // Validate if (!preg_match('/^[a-z-]+$/Di', $controllerType)) { $errMsg = "OA_Admin_Statistics_Factory::_getControllerClass() Unsupported controller type"; return MAX::raiseError($errMsg, MAX_ERROR_INVALIDARGS, PEAR_ERROR_RETURN); } // Prepare the strings required to generate the file and class names list($primary, $secondary) = explode('-', $controllerType, 2); $primary = ucfirst(strtolower($primary)); $aSecondary = explode('-', $secondary); foreach ($aSecondary as $key => $string) { $aSecondary[$key] = ucfirst(strtolower($string)); } $file = MAX_PATH . '/lib/OA/Admin/Statistics/Delivery/Controller/'; $file .= $primary; foreach ($aSecondary as $string) { $file .= $string; } $file .= '.php'; $class = 'OA_Admin_Statistics_Delivery_Controller_'; $class .= $primary; foreach ($aSecondary as $string) { $class .= $string; } }
/** * The belongsToAccount() method behaves in a different way when looking * at entries in the "audit" table. To check if an account has access * to view specific audit data, we only need to check if the account's * ID is set in the appropriate column in the record. * * @param string $accountId The account ID to test if this DB_DataObject is * owned by. * @return boolean|null Returns true if the entity belongs to the specified * account, false if doesn't, or null if it was not * possible to find the required object references. */ function belongsToAccount($accountId = null) { // Set the account ID, if not passed in if (empty($accountId)) { $accountId = OA_Permission::getAccountId(); } // Prepare $this with the required info of the "entity" to be tested if (!$this->N) { $key = $this->getFirstPrimaryKey(); if (empty($this->{$key})) { MAX::raiseError('Key on object is not set, table: ' . $this->getTableWithoutPrefix()); return null; } if (!$this->find($autoFetch = true)) { return null; } } // Test the account ID type, and then test for access $accountType = OA_Permission::getAccountTypeByAccountId($accountId); // Test the access to the audit trail entry if ($accountType == OA_ACCOUNT_ADMIN) { // Admin always has access return true; } else { if ($accountType == OA_ACCOUNT_MANAGER) { // Test if the account ID is equal to the account_id field if (is_null($this->account_id)) { return null; } if ($this->account_id == $accountId) { return true; } } else { if ($accountType == OA_ACCOUNT_ADVERTISER) { // Test if the account ID is equal to the advertiser_account_id field if (is_null($this->advertiser_account_id)) { return null; } if ($this->advertiser_account_id == $accountId) { return true; } } else { if ($accountType == OA_ACCOUNT_TRAFFICKER) { // Test if the account ID is equal to the website_account_id field if (is_null($this->website_account_id)) { return null; } if ($this->website_account_id == $accountId) { return true; } } } } } return false; }
/** * Process a raw-type bucket. * * @param Plugins_DeliveryLog a reference to the using (context) object. * @param Date $oEnd A PEAR_Date instance, interval_start to process up to (inclusive). */ public function processBucket($oBucket, $oEnd) { $sTableName = $oBucket->getBucketTableName(); $oMainDbh =& OA_DB_Distributed::singleton(); if (PEAR::isError($oMainDbh)) { MAX::raiseError($oMainDbh, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } OA::debug(' - Processing the ' . $sTableName . ' table for data with operation interval start equal to or before ' . $oEnd->format('%Y-%m-%d %H:%M:%S') . ' ' . $oEnd->tz->getShortName(), PEAR_LOG_INFO); // As this is raw data being processed, data will not be logged based on the operation interval, // but based on the time the raw data was collected. Adjust the $oEnd value accordingly... $aDates = OX_OperationInterval::convertDateToOperationIntervalStartAndEndDates($oEnd); OA::debug(' - The ' . $sTableName . ' table is a raw data table. Data logged in real-time, not operation intervals.', PEAR_LOG_INFO); OA::debug(' - Accordingly, processing of the ' . $sTableName . ' table will be performed based on data that has a logged date equal to', PEAR_LOG_INFO); OA::debug(' or before ' . $aDates['end']->format('%Y-%m-%d %H:%M:%S') . ' ' . $aDates['end']->tz->getShortName(), PEAR_LOG_INFO); // Select all rows with interval_start <= previous OI start. $rsData =& $this->getBucketTableContent($sTableName, $aDates['end']); $count = $rsData->getRowCount(); OA::debug(' - ' . $rsData->getRowCount() . ' records found', PEAR_LOG_DEBUG); if ($count) { $packetSize = 16777216; // 16 MB hardcoded (there's no max limit) $i = 0; while ($rsData->fetch()) { $aRow = $rsData->toArray(); $sRow = '(' . join(',', array_map(array(&$oMainDbh, 'quote'), $aRow)) . ')'; if (!$i) { $sInsert = "INSERT INTO {$sTableName} (" . join(',', array_keys($aRow)) . ") VALUES "; $query = ''; $aExecQueries = array(); } if (!$query) { $query = $sInsert . $sRow; // Leave 4 bytes headroom for max_allowed_packet } elseif (strlen($query) + strlen($sRow) + 4 < $packetSize) { $query .= ',' . $sRow; } else { $aExecQueries[] = $query; $query = $sInsert . $sRow; } if (++$i >= $count || strlen($query) >= $packetSize) { $aExecQueries[] = $query; $query = ''; } if (count($aExecQueries)) { foreach ($aExecQueries as $execQuery) { $result = $oMainDbh->exec($execQuery); if (PEAR::isError($result)) { MAX::raiseError($result, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } } $aExecQueries = array(); } } } }
/** * This method returns class field type. * * @param string $fieldName * @return string field type */ function getFieldType($fieldName) { $aFieldsTypes = $this->getFieldsTypes(); if (!isset($aFieldsTypes) || !is_array($aFieldsTypes)) { MAX::raiseError('Please provide field types array for Info object creation'); } if (!array_key_exists($fieldName, $aFieldsTypes)) { MAX::raiseError('Unknown type for field \'' . $fieldName . '\''); } return $aFieldsTypes[$fieldName]; }
function OX_Maintenance() { $this->aConf = $GLOBALS['_MAX']['CONF']; OA_Preferences::loadAdminAccountPreferences(); $this->aPref = $GLOBALS['_MAX']['PREF']; // Get a connection to the datbase $this->oDbh =& OA_DB::singleton(); if (PEAR::isError($this->oDbh)) { // Unable to continue! MAX::raiseError($this->oDbh, null, PEAR_ERROR_DIE); } }
/** * Registers OA_Admin_UI_Decorator for a decorator * * @return true if successfully registered, false if there is already decorator * registered for this name. */ function registerDecorator($decoratorName, $path, $className) { $decoratorName = strtolower($decoratorName); if (empty($decoratorName) || empty($path) || empty($className)) { $errMsg = "DecoratorRegistry::add() Cannot register decorator {$decoratorName} from class {$className} included from {$path}"; return MAX::raiseError($errMsg); } if (isset($GLOBALS['_OA_Admin_UI_Decorator_Factory_registered_decorators'][$decoratorName])) { return false; } $GLOBALS['_OA_Admin_UI_Decorator_Factory_registered_decorators'][$decoratorName] = array($path, $className); return true; }
/** * Registers OA_Admin_UI_Rule_QuickFormToJQueryRuleAdaptor for a given quickform rule * * @return true if successfully registered, false if there is already adaptor * registered for this quickform rule. */ function registerJQueryRuleAdaptor($quickFormRuleName, $path, $className) { $quickFormRuleName = strtolower($quickFormRuleName); if (empty($quickFormRuleName) || empty($path) || empty($className)) { $errMsg = "JQueryRuleAdaptorRegistry::add() Cannot register adaptor for class {$className} for rule {$quickFormRuleName} included from {$path}"; return MAX::raiseError($errMsg); } if (isset($GLOBALS['_OA_Admin_UI_Rule_JQueryRuleAdaptorRegistry_registered_adaptors'][$quickFormRuleName])) { return false; } $GLOBALS['_OA_Admin_UI_Rule_JQueryRuleAdaptorRegistry_registered_adaptors'][$quickFormRuleName] = array($path, $className); return true; }
/** * Process an aggregate-type bucket. This is MySQL specific. * * @param Plugins_DeliveryLog $oBucket a reference to the using (context) object. * @param Date $oEnd A PEAR_Date instance, interval_start to process up to (inclusive). */ public function processBucket($oBucket, $oEnd) { $sTableName = $oBucket->getBucketTableName(); $oMainDbh =& OA_DB_Distributed::singleton(); if (PEAR::isError($oMainDbh)) { MAX::raiseError($oMainDbh, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } OA::debug(' - Processing the ' . $sTableName . ' table for data with operation interval start equal to or before ' . $oEnd->format('%Y-%m-%d %H:%M:%S') . ' ' . $oEnd->tz->getShortName(), PEAR_LOG_INFO); // Select all rows with interval_start <= previous OI start. $rsData =& $this->getBucketTableContent($sTableName, $oEnd); $rowCount = $rsData->getRowCount(); OA::debug(' - ' . $rsData->getRowCount() . ' records found', PEAR_LOG_DEBUG); if ($rowCount) { // We can't do bulk inserts with ON DUPLICATE. $aExecQueries = array(); if ($rsData->fetch()) { // Get first row $aRow = $rsData->toArray(); // Prepare INSERT $sInsert = "INSERT INTO {$sTableName} (" . join(',', array_keys($aRow)) . ") VALUES "; // Add first row data $sRow = '(' . join(',', array_map(array(&$oMainDbh, 'quote'), $aRow)) . ')'; $sOnDuplicate = ' ON DUPLICATE KEY UPDATE count = count + ' . $aRow['count']; // Add first insert $aExecQueries[] = $sInsert . $sRow . $sOnDuplicate; // Deal with the other rows while ($rsData->fetch()) { $aRow = $rsData->toArray(); $sRow = '(' . join(',', array_map(array(&$oMainDbh, 'quote'), $aRow)) . ')'; $sOnDuplicate = ' ON DUPLICATE KEY UPDATE count = count + ' . $aRow['count']; $aExecQueries[] = $sInsert . $sRow . $sOnDuplicate; } } if (count($aExecQueries)) { // Try to disable the binlog for the inserts so we don't // replicate back out over our logged data. PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $result = $oMainDbh->exec('SET SQL_LOG_BIN = 0'); if (PEAR::isError($result)) { OA::debug('Unable to disable the bin log, proceeding anyway.', PEAR_LOG_WARNING); } PEAR::staticPopErrorHandling(); foreach ($aExecQueries as $execQuery) { $result = $oMainDbh->exec($execQuery); if (PEAR::isError($result)) { MAX::raiseError($result, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } } } } }
/** * Creates a new Field object of the appropriate subclass. * * @param string $fieldType The type of field to create. * @return Admin_UI_Field An instance of the correct {@link Admin_UI_Field} subclass. */ function &newField($fieldType) { switch ($fieldType) { case 'advertiser': $oField = new Admin_UI_AdvertiserIdField(); break; case 'affiliateid-dropdown': case 'publisherid-dropdown': $oField = new Admin_UI_PublisherIdField(); break; case 'campaignid-dropdown': $oField = new Admin_UI_CampaignSelectionField(); break; case 'clientid-dropdown': $oField = new Admin_UI_AdvertiserIdField(); break; case 'channelid-dropdown': $oField = new Admin_UI_ChannelIdField(); break; case 'date-month': case 'day-span': case 'day-span-selector': $oField = new Admin_UI_DaySpanField(); break; case 'dropdown': $oField = new Admin_UI_DropdownField(); break; case 'edit': $oField = new Admin_UI_TextField(); break; case 'scope': $oField = new Admin_UI_OrganisationSelectionField(); break; case 'sheet': $oField = new Admin_UI_SheetSelectionField(); break; case 'trackerid-dropdown': $oField = new Admin_UI_TrackerField(); break; case 'zone-scope': $oField = new Admin_UI_ZoneScopeField(); break; case 'zoneid-dropdown': $oField = new Admin_UI_ZoneIdField(); break; default: MAX::raiseError("The report module discovered a field type that it didn't know how to handle.", MAX_ERROR_INVALIDARGS); } return $oField; }
/** * A private method to get the required default deliveryLog extension * bucket processing strategy class. * * @access private * @param string $type Either "Aggregate" or "Raw". * @return OX_Extension_DeliveryLog_BucketProcessingStrategy */ private static function _getBucketProcessingStrategy($type) { $dbType = $GLOBALS['_MAX']['CONF']['database']['type']; // Prepare the required filename for the default bucket processing strategy needed $fileName = LIB_PATH . '/Extension/deliveryLog/' . ucfirst(strtolower($type)) . 'BucketProcessingStrategy' . ucfirst(strtolower($dbType)) . '.php'; // Include the required bucket processing strategy file if (file_exists($fileName)) { @(include_once $fileName); // Prepare the required class name for the default bucket processing strategy needed $className = 'OX_Extension_DeliveryLog_' . ucfirst(strtolower($type)) . 'BucketProcessingStrategy' . ucfirst(strtolower($dbType)); if (class_exists($className)) { return new $className(); } } $message = 'Unable to instantiate the required default ' . strtolower($type) . " datbase bucket processing strategy for database type '{$dbType}'."; MAX::raiseError($message, MAX_ERROR_INVALIDARGS, PEAR_ERROR_DIE); }
/** * Class constructor * * @param DataObjects_Users $doUsers * @return OA_Permission_User */ function OA_Permission_User($doUsers, $skipDatabaseAccess = false) { if (!is_a($doUsers, 'DataObjects_Users')) { MAX::raiseError('doUser not a DataObjects_Users'); } // Store user information as array $this->aUser = $doUsers->toArray(); // For safety reasons, do not store the password unset($this->aUser['password']); // Make sure we start with an empty account $this->_clearAccountData(); if (!$skipDatabaseAccess) { // Check if the user is linked to the admin account $this->aUser['is_admin'] = $this->_isAdmin(); $this->loadAccountData($this->aUser['default_account_id']); } else { $this->aUser['is_admin'] = false; } }
/** * A class to test if an operation interval value is valid. * * @static * @param integer $oi The operation interval value in minutes. * @param mixed True if the operation interval value is valid, a {@link PEAR_Error} * object with error type MAX_ERROR_INVALIDOPERATIONINT otherwise. */ function checkOperationIntervalValue($oi) { if ($oi < 1) { // Operation interval must be at least every minute $error = 'The operation interval of ' . $oi . ' is invalud'; return MAX::raiseError($error, MAX_ERROR_INVALIDOPERATIONINT); } elseif ($oi < 60) { // Operation interval is more often than once an hour if (60 % $oi != 0) { // Operation interval must be a factor of 60 minutes $error = 'The operation interval of ' . $oi . ' is invalud'; return MAX::raiseError($error, MAX_ERROR_INVALIDOPERATIONINT); } } elseif ($oi > 60) { // Operation interval must not be more than 60 $error = 'The operation interval of ' . $oi . ' is invalud'; return MAX::raiseError($error, MAX_ERROR_INVALIDOPERATIONINT); } return true; }
/** * A method to determine if the delivery limitation stored will prevent an * ad from delivering or not, given a time/date. * * @abstract * @param object $oDate PEAR:Date, represeting the time/date to test if the ACL would * block delivery at that point in time. * @return mixed A boolean (true if the ad is BLOCKED (i.e. will NOT deliver), false * if the ad is NOT BLOCKED (i.e. WILL deliver), or a PEAR::Error. */ function deliveryBlocked($oDate) { $aConf = $GLOBALS['_MAX']['CONF']; if (!is_a($oDate, 'Date')) { return MAX::raiseError('Parameter passed to OA_Maintenance_Priority_DeliveryLimitation_Common is not a PEAR::Date object', MAX_ERROR_INVALIDARGS); } $aParts = OX_Component::parseComponentIdentifier($this->type); if (!empty($aParts) && count($aParts) == 3) { $fileName = MAX_PATH . $aConf['pluginPaths']['plugins'] . join('/', $aParts) . '.delivery.php'; $funcName = "MAX_check{$aParts[1]}_{$aParts[2]}"; $callable = function_exists($funcName); if (!$callable && file_exists($fileName)) { require_once $fileName; $callable = true; } $aParams = array('timestamp' => $oDate->getDate(DATE_FORMAT_UNIXTIME)); if ($callable) { // Return non-delivery return !$funcName($this->data, $this->comparison, $aParams); } } return MAX::raiseError('Limitation parameter passed to OA_Maintenance_Priority_DeliveryLimitation_Common is not correct', MAX_ERROR_INVALIDARGS); }
function setAppendCodes($tracker_id, $codes) { $tracker_id = is_numeric($tracker_id) ? $tracker_id : (int) $tracker_id; $query = "\n DELETE FROM {$this->prefix}{$this->conf['table']['tracker_append']}\n WHERE tracker_id = " . $this->oDbh->quote($tracker_id, 'integer'); $result = $this->oDbh->exec($query); if (PEAR::isError($result)) { MAX::raiseError($result, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } $rank = 0; $appendcodes = array(); $doTrackerAppend = OA_Dal::factoryDO('tracker_append'); $doTrackerAppend->tracker_id = $tracker_id; foreach ($codes as $v) { $tagcode = trim($v['tagcode']); $paused = $v['paused'] ? 't' : 'f'; $autotrack = $v['autotrack'] ? 't' : 'f'; if (!strlen($tagcode)) { continue; } $doTA = clone $doTrackerAppend; $doTA->tagcode = $tagcode; $doTA->paused = $paused; $doTA->autotrack = $autotrack; $doTA->rank = ++$rank; $result = $doTA->insert(); if (empty($result)) { MAX::raiseError("Could not insert tracker append row", MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } $appendcodes[] = array('tagcode' => $tagcode, 'paused' => $paused, 'autotrack' => $autotrack); } $query = "\n UPDATE {$this->prefix}{$this->conf['table']['trackers']}\n SET appendcode = " . $this->oDbh->quote($this->generateAppendCode($appendcodes)) . "\n WHERE trackerid = " . $this->oDbh->quote($tracker_id); $result = $this->oDbh->exec($query); if (PEAR::isError($result)) { MAX::raiseError($result, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } }
/** * A method to determine if the delivery limitation stored will prevent an * ad from delivering or not, given a time/date. * * @abstract * @param object $oDate PEAR:Date, represeting the time/date to test if the ACL would * block delivery at that point in time. * @return mixed A boolean (true if the ad is BLOCKED (i.e. will NOT deliver), false * if the ad is NOT BLOCKED (i.e. WILL deliver), or a PEAR::Error. */ function deliveryBlocked($oDate) { if (!is_a($oDate, 'Date')) { return MAX::raiseError('Parameter passed to OA_Maintenance_Priority_DeliveryLimitation_Date is not a PEAR::Date object', MAX_ERROR_INVALIDARGS); } // Clone the date $oCloneDate = new Date(); $oCloneDate->copy($oDate); // Reset time part of date $oCloneDate->setHour(0); $oCloneDate->setMinute(0); $oCloneDate->setSecond(0); // 0 if the dates are equal; // -1 if $oCloneDate is before $this->date; // 1 if $oCloneDate is after $this->date $val = Date::compare($oCloneDate, $this->date); switch ($this->comparison) { case '==': return $val == 0; break; case '!=': return $val != 0; break; case '<=': return $val == -1 || $val == 0; break; case '>=': return $val == 1 || $val == 0; break; case '<': return $val == -1; break; case '>': return $val == 1; break; } return 0; }
/** * Factory the specific layer for invocation tag plugin * * @static * @param string $layerName Name of the invocation tag layer * * @return object Plugin object or false if any error occurred * */ function factoryLayer($style = PLUGINS_INVOCATIONS_TAGS_ADLAYER_DEFAULT_LAYERSTYLE, $type = 'invocation') { $fileName = dirname(__FILE__) . "/layerstyles/{$style}/{$type}.inc.php"; if (!file_exists($fileName)) { MAX::raiseError("Unable to include the {$fileName} file"); return false; } else { include_once $fileName; } $className = "Plugins_" . ucfirst($this->group) . '_' . ucfirst($this->component) . '_Layerstyles_' . ucfirst($style) . '_' . ucfirst($type); if (!class_exists($className)) { MAX::raiseError("Plugin file included but class '{$className}' doesn't exists"); return false; } $obj = new $className(); // Assign this component group's translation resource to the created layer object $obj->oTrans = $this->oTrans; return $obj; }
/** * This method gets the handler that should be used for a particulat extension if the component * doesn't provide it's own specific handler * * @param string $extension The extension to get the fallback handler for * @return object The handler object */ function &getFallbackHandler($extension) { //$path = $GLOBALS['_MAX']['CONF']['pluginPaths']['plugins'].$extension.'/'; $fileName = LIB_PATH . '/Extension/' . $extension . '/' . $extension . '.php'; if (!file_exists($fileName)) { MAX::raiseError("Unable to include the file {$fileName}."); return false; } include_once $fileName; $className = 'Plugins_' . $extension; if (!class_exists($className)) { MAX::raiseError("Plugin file included but class '{$className}' does not exist."); return false; } $oPlugin = new $className(); $oPlugin->extension = $extension; $oPlugin->enabled = false; return $oPlugin; }
function insertAfter($sectionId, &$section) { if (!array_key_exists($sectionId, $this->aAllSections)) { $errMsg = "Menu::insertAfter() Cannot insert section '" . $section->getId() . "' after a non existent menu section with id '" . $sectionId . "'"; return MAX::raiseError($errMsg); } $siblingSection =& $this->aAllSections[$sectionId]; $parent =& $siblingSection->getParent(); $result = $parent->insertAfter($sectionId, $section); //add new section to hash array if (!PEAR::isError($result)) { $this->_addToHash($section); } return $result; }
/** * A method to determine if the delivery limitation stored will prevent an * ad from delivering or not, given a time/date. * * @abstract * @param object $oDate PEAR:Date, represeting the time/date to test if the ACL would * block delivery at that point in time. * @return mixed A boolean (true if the ad is BLOCKED (i.e. will NOT deliver), false * if the ad is NOT BLOCKED (i.e. WILL deliver), or a PEAR::Error. */ function deliveryBlocked($oDate) { if (!is_a($oDate, 'Date')) { return MAX::raiseError('Parameter passed to OA_Maintenance_Priority_DeliveryLimitation_Day is not a PEAR::Date object', MAX_ERROR_INVALIDARGS); } $val = in_array($oDate->getDayOfWeek(), $this->data) ? 1 : 0; switch ($this->comparison) { case '=~': return !$val; case '!~': return $val; } }
/** * A method to build the PEAR::Cache_Lite options for a plugin's cache file(s), * given a module/package name. Also creates the required cache store directory * if it doesn't exist. * * @static * @param string $module The plugin module name (i.e. /plugins/module directory). * @param string $package The plugin package name (i.e. /plugins/module/package * directory). * @param string $cacheDir An optional specification for the cache directory. * The default is /var/plugins/cache/module/package/). * @param integer $cacheExpire An optional specification for the cache lifetime * in seconds. The default is 1 hour. * @return mixed An array with the cache options for PEAR Cache_Lite class, or * false if the cache directory does not exist/cannot be created. */ function prepareCacheOptions($module, $package, $cacheDir = null, $cacheExpire = 3600) { $aConf = $GLOBALS['_MAX']['CONF']; // Prepare the options for PEAR::Cache_Lite if (is_null($cacheDir)) { $cacheDir = MAX_PATH . $aConf['pluginPaths']['var'] . 'cache/' . $module . '/' . $package . '/'; } $aOptions = array('cacheDir' => $cacheDir, 'lifeTime' => $cacheExpire, 'automaticSerialization' => true); if (!is_dir($aOptions['cacheDir'])) { if (!MAX_Plugin::_mkDirRecursive($aOptions['cacheDir'], MAX_PLUGINS_VAR_WRITE_MODE)) { MAX::raiseError('Folder: "' . $aOptions['cacheDir'] . '" is not writeable.', PEAR_LOG_ERR); return false; } } return $aOptions; }
/** * A method to reject conversions which variables which are required to be * non-empty, but which are in reality, empty, between the supplied operation * interval start and end dates. * * @param PEAR::Date $oStart The start date/time of the operation interval. * @param PEAR::Date $oEnd The end date/time of the operation interval. */ function rejectEmptyVarConversions($oStart, $oEnd) { $aConf = $GLOBALS['_MAX']['CONF']; $query = "\n UPDATE\n {$aConf['table']['prefix']}{$aConf['table']['data_intermediate_ad_connection']} AS diac\n JOIN\n {$aConf['table']['prefix']}{$aConf['table']['variables']} AS v\n ON\n (\n diac.tracker_id = v.trackerid\n )\n LEFT JOIN\n {$aConf['table']['prefix']}{$aConf['table']['data_intermediate_ad_variable_value']} AS diavv\n ON\n (\n diac.data_intermediate_ad_connection_id = diavv.data_intermediate_ad_connection_id\n AND\n v.variableid = diavv.tracker_variable_id\n )\n SET\n diac.connection_status = " . MAX_CONNECTION_STATUS_DISAPPROVED . ",\n diac.updated = '" . OA::getNow() . "',\n diac.comments = CONCAT('Rejected because ', COALESCE(NULLIF(v.description, ''), v.name), ' is empty')\n WHERE\n diac.tracker_date_time >= " . $this->oDbh->quote($oStart->format('%Y-%m-%d %H:%M:%S'), 'timestamp') . "\n AND\n diac.tracker_date_time <= " . $this->oDbh->quote($oEnd->format('%Y-%m-%d %H:%M:%S'), 'timestamp') . "\n AND\n diac.inside_window = 1\n AND\n v.reject_if_empty = 1\n AND\n (diavv.value IS NULL OR diavv.value = '')\n "; $message = '- Rejecting conversions with empty required variables between ' . $oStart->format('%Y-%m-%d %H:%M:%S') . ' ' . $oStart->tz->getShortName() . ' and ' . $oEnd->format('%Y-%m-%d %H:%M:%S') . ' ' . $oEnd->tz->getShortName(); OA::debug($message, PEAR_LOG_DEBUG); $rows = $this->oDbh->exec($query); if (PEAR::isError($rows)) { return MAX::raiseError($rows, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } }
/** * Inserts new section after the section with the specified id. If the section * with the specified id does not exists MAX::raiseError is returned. * * @param String $existingSectionId * @param OA_Admin_Menu_Section $newSection */ function insertAfter($existingSectionId, &$newSection) { if (!isset($this->aSectionsMap[$existingSectionId])) { $errMsg = "MenuSection::insertAfter() Cannot insert section '" . $newSection->getId() . "' after a non existent menu section with id '" . $existingSectionId . "'"; return MAX::raiseError($errMsg); } //check if added section is unique in menu if (isset($this->aSectionsMap[$newSection->getId()])) { $errMsg = "MenuSection::insertAfter() Cannot insert section '" . $newSection->getId() . "': section with given id already exists"; return MAX::raiseError($errMsg); } $sectionIndex = $this->_getSectionIndex($existingSectionId, $this->aSections); array_insert($this->aSections, $sectionIndex + 1, $newSection); $newSection->setParent($this); $this->_addToHash($newSection); return true; }
/** * Batch linking list of zones to banner * * @param array $aZonesIds array of zones IDs * @param int $bannerId the banner ID. * @return int number of linked zones , -1 if invalid parameters was detected, PEAR:Errors on DB errors */ function linkZonesToBanner($aZonesIds, $bannerId) { // Check realm of given zones and campaign $checkResult = $this->_checkZonesRealm($aZonesIds, null, $bannerId); if ($checkResult == false) { return -1; } elseif (PEAR::isError($checkResult)) { MAX::raiseError($checkResult, MAX_ERROR_DBFAILURE); return -1; } // Call sql queries to link zones to banners $linkedZones = $this->_linkZonesToCampaignsBannersOrSingleBanner($aZonesIds, null, $bannerId); if (PEAR::isError($linkedZones)) { return $linkedZones; } return $linkedZones; }
/** * 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']); } } } } } } }
/** * Returns integer equivalent (ID) of account type * * @static * @param unknown_type $acountType * @return unknown */ public static function convertAccountTypeToId($accountType) { $accountTypeIdConstant = 'OA_ACCOUNT_' . $accountType . '_ID'; if (!defined($accountTypeIdConstant)) { MAX::raiseError('No such account type ID: ' . $accountType); return false; } return constant($accountTypeIdConstant); }
/** * A method to return an array of account IDs of the account(s) that * should "own" any audit trail entries for this entity type; these * are NOT related to the account ID of the currently active account * (which is performing some kind of action on the entity), but is * instead related to the type of entity, and where in the account * heirrachy the entity is located. * * @return array An array containing up to three indexes: * - "OA_ACCOUNT_ADMIN" or "OA_ACCOUNT_MANAGER": * Contains the account ID of the manager account * that needs to be able to see the audit trail * entry, or, the admin account, if the entity * is a special case where only the admin account * should see the entry. * - "OA_ACCOUNT_ADVERTISER": * Contains the account ID of the advertiser account * that needs to be able to see the audit trail * entry, if such an account exists. * - "OA_ACCOUNT_TRAFFICKER": * Contains the account ID of the trafficker account * that needs to be able to see the audit trail * entry, if such an account exists. */ function getOwningAccountIds() { // Placement/zone associations are a special case, as both the // advertiser and the website accounts should be able to see // the audit entries, so the results of two calls need to be // merged $aAdvertiserAccountIds = array(); if (!empty($this->placement_id)) { // Placement/zone assocs don't have an account_id, get it from // the parent campaign (stored in the "campaigns" table) using // the "placement_id" key $aAdvertiserAccountIds = parent::getOwningAccountIds('campaigns', 'placement_id'); } $aWebsiteAccountIds = array(); if (!empty($this->zone_id)) { // Placement/zone assocs don't have an account_id, get it from // the parent zone (stored in the "zones" table) using // the "zone_id" key $aWebsiteAccountIds = parent::getOwningAccountIds('zones', 'zone_id'); } // Check that the manager account IDs match from the two results if (isset($aAdvertiserAccountIds[OA_ACCOUNT_MANAGER]) && isset($aWebsiteAccountIds[OA_ACCOUNT_MANAGER])) { if ($aAdvertiserAccountIds[OA_ACCOUNT_MANAGER] != $aWebsiteAccountIds[OA_ACCOUNT_MANAGER]) { $message = "Cannot locate owning account IDs for ad/zone association, as manager account IDs, " . "do not match, where ad ID was {$this->ad_id} and zone ID was {$this->zone_id}."; MAX::raiseError($message, PEAR_LOG_ERR); } } // Merge the arrays and return $aResult = array_merge($aAdvertiserAccountIds, $aWebsiteAccountIds); return $aResult; }
/** * Fetch DataObject by property * * @param unknown_type $propertyName * @param unknown_type $propertyValue * @return unknown */ function loadByProperty($propertyName, $propertyValue) { $fields = $this->table(); if (!isset($fields[$propertyName])) { MAX::raiseError($propertyName . ' is not a field in table ' . $this->getTableWithoutPrefix(), PEAR_LOG_ERR); return false; } $this->{$propertyName} = $propertyValue; if (!$this->find()) { return false; } return $this->fetch(); }
function batchInsertPlain($tableName, $aFields, $aValues) { if (!is_array($aFields) || !is_array($aValues)) { return MAX::raiseError('$aFields and $aData must be arrays', PEAR_ERROR_RETURN); } $oDbh = OA_DB::singleton(); // Quote table name $tableName = $oDbh->quoteIdentifier($tableName); // Quote fields list $fieldList = '(' . join(',', array_map(array($oDbh, 'quoteIdentifier'), $aFields)) . ')'; foreach ($aValues as $aRow) { $values = implode(', ', array_map(array($oDbh, 'quote'), $aRow)); $query = "INSERT INTO {$tableName} {$fieldList} VALUES ({$values})"; $result = $oDbh->exec($query); if (PEAR::isError($result)) { return $result; } } return count($aValues); }
/** * 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. $prefix = $this->getTablePrefix(); $oNowDate = new Date($oDate); $oNowDate->toUTC(); $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_time AS start,\n ca.expire_time AS end\n FROM\n {$prefix}campaigns AS ca,\n {$prefix}clients AS cl\n WHERE\n ca.clientid = cl.clientid\n AND\n ((\n ca.status = " . $this->oDbh->quote(OA_ENTITY_STATUS_RUNNING, 'integer') . " AND\n (\n ca.expire_time IS NOT NULL\n OR\n (\n ca.views > 0\n OR\n ca.clicks > 0\n OR\n ca.conversions > 0\n )\n )\n ) OR (\n ca.status = " . $this->oDbh->quote(OA_ENTITY_STATUS_AWAITING, 'integer') . " AND\n (\n ca.activate_time <= " . $this->oDbh->quote($oNowDate->getDate(DATE_FORMAT_ISO), 'timestamp') . "\n AND\n (\n ca.weight > 0\n OR\n ca.priority > 0\n )\n AND\n (\n ca.expire_time >= " . $this->oDbh->quote($oNowDate->getDate(DATE_FORMAT_ISO), 'timestamp') . "\n OR\n ca.expire_time IS NULL\n )\n )\n ))\n ORDER BY\n advertiser_id"; OA::debug('- Requesting campaigns to test for activation/deactivation', PEAR_LOG_DEBUG); $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) { OA::debug(' - Selecting impressions, clicks and conversions for this running campaign ID = ' . $aCampaign['campaign_id'], PEAR_LOG_DEBUG); // 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 (isset($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 (!isset($valuesRow['impressions'])) { // No impressions $valuesRow['impressions'] = 0; } if (!isset($valuesRow['clicks'])) { // No clicks $valuesRow['clicks'] = 0; } if (!isset($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 (!empty($aCampaign['end'])) { // The campaign has a valid end date, stored in in UTC $oEndDate = new Date($aCampaign['end']); $oEndDate->setTZByID('UTC'); if ($oDate->after($oEndDate)) { // The end date has been passed; disable the campaign $disableReason |= OX_CAMPAIGN_DISABLED_DATE; $message = " - Passed campaign end time of '" . $oEndDate->getDate() . " UTC" . "': 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') { OA::debug(" - Sending campaign deactivated email ", PEAR_LOG_DEBUG); $oEmail->sendCampaignActivatedDeactivatedEmail($aCampaign['campaign_id'], $disableReason); // Also send campaignDeliveryEmail for the campaign we just deactivated. $doClients = OA_Dal::staticGetDO('clients', $aCampaign['advertiser_id']); $aAdvertiser = $doClients->toArray(); OA::debug(" - Sending campaign delivery email ", PEAR_LOG_DEBUG); $oStart = new Date($aAdvertiser['reportlastdate']); $oEnd = new Date($oDate); // Set end date to tomorrow so we get stats for today. $oEnd->addSpan(new Date_Span('1-0-0-0')); $oEmail->sendCampaignDeliveryEmail($aAdvertiser, $oStart, $oEnd, $aCampaign['campaign_id']); } } 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 OA::debug(" - Sending campaign 'soon deactivated' email ", PEAR_LOG_DEBUG); $oEmail->sendCampaignImpendingExpiryEmail($oDate, $aCampaign['campaign_id']); } } } elseif (!empty($aCampaign['start'])) { // The campaign is awaiting activation and has a valid start date, stored in UTC $oStartDate = new Date($aCampaign['start']); $oStartDate->setTZByID('UTC'); // 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) { OA::debug(" - The campaign ID " . $aCampaign['campaign_id'] . " has an impression, click and/or conversion target, requesting impressions so far", PEAR_LOG_DEBUG); $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) 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)) { $message = "- Passed campaign start time of '" . $oStartDate->getDate() . " UTC" . "': 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']); if ($aCampaign['send_activate_deactivate_email'] == 't') { OA::debug(" - Sending activation email for campaign ID " . $aCampaign['campaign_id'], PEAR_LOG_DEBUG); $oEmail->sendCampaignActivatedDeactivatedEmail($aCampaign['campaign_id']); } } } } }