pierre@1: . pierre@1: */ pierre@1: pierre@1: /** pierre@1: * Filter advertisements not in an appropriate channel, from cache. pierre@1: */ pierre@1: function ad_channel_cache_filter($ads) { pierre@1: _debug_echo("ad_channel_cache: adserve_cache_filter"); pierre@1: pierre@1: $channels = adserve_cache('get_cache', 'channel'); pierre@1: $valid = array(); pierre@1: $nochannel = array(); sly@2: $nochannel_weight = array(); sly@2: $matched_channel = array(); pierre@1: foreach ($ads as $aid) { pierre@1: _debug_echo("ad_channel_cache: checking aid($aid)"); pierre@1: if (is_array($channels['ads']) && isset($channels['ads'][$aid]) && pierre@1: is_array($channels['ads'][$aid])) { pierre@1: foreach ($channels['ads'][$aid] as $chid) { pierre@1: $channel = $channels['channels'][$chid]; pierre@1: $display = $channel->display; pierre@1: $urls = unserialize($channel->urls); pierre@1: $frontpage = adserve_variable('site_frontpage') ? adserve_variable('site_frontpage') : 'node'; pierre@1: $regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\($|\|)/'), array('|', '.*', '\1'. preg_quote($frontpage, '/') .'\2'), preg_quote($urls, '/')) .')$/'; pierre@1: $match = preg_match($regexp, adserve_variable('url')); pierre@1: _debug_echo("ad_channel_cache: checking aid($aid) against channel($chid) path(". adserve_variable('url') .") regexp($regexp) match($match)"); pierre@1: if ($display == 0) { // display on all except listed urls pierre@1: if (empty($urls) || !$match) { pierre@1: _debug_echo("ad_channel_cache: aid($aid) is valid"); pierre@1: $valid[] = $aid; sly@2: if ($display == 1) { sly@2: $nochannel_weight[$chid] = $channel->no_channel_weight; sly@2: } sly@2: $matched_channel[$aid] = $chid; sly@2: _debug_echo("ad_channel_cache: channel($channel->chid) no_channel_weight(". $nochannel_weight[$chid] .')'); pierre@1: break; pierre@1: } pierre@1: } pierre@1: else { // display only on listed urls pierre@1: if (!empty($urls) && $match) { pierre@1: _debug_echo("ad_channel_cache: aid($aid) is valid"); pierre@1: $valid[] = $aid; sly@2: if ($display == 1) { sly@2: $nochannel_weight[$chid] = $channel->no_channel_weight; sly@2: } sly@2: $matched_channel[$aid] = $chid; pierre@1: break; pierre@1: } pierre@1: } pierre@1: _debug_echo("ad_channel_cache: aid($aid) is not valid"); pierre@1: } pierre@1: } pierre@1: else { pierre@1: // no channel information for ad, it's valid pierre@1: $display = $channels['display']; pierre@1: _debug_echo("ad_channel_cache: aid($aid) has no channel info [$display]"); pierre@1: switch ($display) { pierre@1: case 0: pierre@1: $nochannel[] = $aid; pierre@1: _debug_echo("ad_channel_cache: aid($aid) is valid if no valid ads found in current channel"); pierre@1: break; pierre@1: case 1: pierre@1: $valid[] = $aid; pierre@1: _debug_echo("ad_channel_cache: aid($aid) is valid"); pierre@1: break; pierre@1: case 2: pierre@1: _debug_echo("ad_channel_cache: aid($aid) is not valid"); pierre@1: break; pierre@1: } pierre@1: } pierre@1: } pierre@1: sly@2: // Apply weights, applicable for advertisements that are not assigned to any sly@2: // channel. sly@2: if (!empty($valid) && !empty($nochannel_weight)) { sly@2: $weights = array(); sly@2: foreach ($valid as $aid) { sly@2: if (isset($matched_channel[$aid])) { sly@2: $chid = $matched_channel[$aid]; sly@2: if (isset($nochannel_weight[$chid])) { sly@2: $weights[$aid] = $nochannel_weight[$chid]; sly@2: _debug_echo("ad_channel_cache: ad $aid in channel $chid with weight ". $nochannel_weight[$chid]); sly@2: } sly@2: else { sly@2: // by default, ads are assigned a weight of 100% sly@2: $weights[$aid] = 100; sly@2: _debug_echo("ad_channel_cache: ad $aid in channel $chid with default weight of 100"); sly@2: } sly@2: } sly@2: else { sly@2: // by default, ads are assigned a weight of 100% sly@2: $weights[$aid] = 100; sly@2: _debug_echo("ad_channel_cache: ad $aid in no channel with default weight of 100"); sly@2: } sly@2: } sly@2: if (!empty($weights)) { sly@2: $gcd = ad_channel_probability_gcd($weights); sly@2: $display = array(); sly@2: _debug_echo("ad_channel_cache: adjusting channel weights, gcd ($gcd)"); sly@2: foreach ($valid as $aid) { sly@2: $weight = $weights[$aid] / $gcd; sly@2: for ($i = 1; $i <= $weight; $i++) { sly@2: $display[] = $aid; sly@2: } sly@2: } sly@2: $valid = $display; sly@2: } sly@2: } sly@2: else if (empty($valid) && !empty($nochannel)) { pierre@1: _debug_echo("ad_channel_cache: using ads with no channel info"); pierre@1: $valid = $nochannel; pierre@1: } pierre@1: pierre@1: $premiere = adserve_cache('get_cache', 'premiere'); pierre@1: $premieres = array(); pierre@1: if (is_array($premiere)) { pierre@1: foreach ($valid as $aid) { pierre@1: if (in_array($aid, $premiere)) { pierre@1: _debug_echo("ad_channel_cache: aid($aid) is premiere advertisement"); pierre@1: $premieres[$aid] = $aid; pierre@1: } pierre@1: else { pierre@1: _debug_echo("ad_channel_cache: aid($aid) is not a premiere advertisement"); pierre@1: } pierre@1: } pierre@1: if (!empty($premieres)) { pierre@1: _debug_echo("ad_channel_cache: returning premiere advertisements"); pierre@1: return $premieres; pierre@1: } pierre@1: } pierre@1: _debug_echo("ad_channel_cache: returning non-premiere advertisements"); pierre@1: return $valid; pierre@1: } sly@2: sly@2: /** sly@2: * Returns the greatest common divisor of an array of integers. sly@2: */ sly@2: function ad_channel_probability_gcd($integers) { sly@2: $gcd = array_shift($integers); sly@2: sly@2: while (!empty($integers)) { sly@2: $gcd = _ad_channel_probability_gcd($gcd, array_shift($integers)); sly@2: } sly@2: return $gcd; sly@2: } sly@2: sly@2: /** sly@2: * Helper function to calculate the greatest common divisor using the Euclidean sly@2: * algorithm (http://en.wikipedia.org/wiki/Euclidean_algorithm). sly@2: */ sly@2: function _ad_channel_probability_gcd($a, $b) { sly@2: if ($b == 0) { sly@2: return $a; sly@2: } sly@2: else { sly@2: return _ad_channel_probability_gcd($b, $a % $b); sly@2: } sly@2: }