pierre@1
|
1 <?php |
pierre@1
|
2 |
pierre@1
|
3 /** |
pierre@1
|
4 * @file |
pierre@1
|
5 * Ad Channel include file. |
pierre@1
|
6 * |
pierre@1
|
7 * Copyright (c) 2008-2009. |
pierre@1
|
8 * Jeremy Andrews <jeremy@tag1consulting.com>. |
pierre@1
|
9 */ |
pierre@1
|
10 |
pierre@1
|
11 /** |
pierre@1
|
12 * Filter advertisements not in an appropriate channel, from cache. |
pierre@1
|
13 */ |
pierre@1
|
14 function ad_channel_cache_filter($ads) { |
pierre@1
|
15 _debug_echo("ad_channel_cache: adserve_cache_filter"); |
pierre@1
|
16 |
piotre@7
|
17 // get channel array from cache |
pierre@1
|
18 $channels = adserve_cache('get_cache', 'channel'); |
piotre@7
|
19 // 0 = only display advertisements not assigned to any channel if no matching |
piotre@7
|
20 // ads in selected channel; 1 = always display advertisements not assigned to |
piotre@7
|
21 // any channel; 2 = never display advertisements not assigned to any channel |
piotre@7
|
22 $nochannel_display = $channels['display']; |
piotre@7
|
23 $valid_ads = array(); |
piotre@7
|
24 $nochannel_fallback_ads = array(); |
piotre@7
|
25 $nochannel_percent = array(); |
piotre@7
|
26 // determine which channels each advertisement is assigned to |
pierre@1
|
27 foreach ($ads as $aid) { |
pierre@1
|
28 _debug_echo("ad_channel_cache: checking aid($aid)"); |
pierre@1
|
29 if (is_array($channels['ads']) && isset($channels['ads'][$aid]) && |
pierre@1
|
30 is_array($channels['ads'][$aid])) { |
pierre@1
|
31 foreach ($channels['ads'][$aid] as $chid) { |
pierre@1
|
32 $channel = $channels['channels'][$chid]; |
piotre@7
|
33 $display_by_url = $channel->display; |
pierre@1
|
34 $urls = unserialize($channel->urls); |
pierre@1
|
35 $frontpage = adserve_variable('site_frontpage') ? adserve_variable('site_frontpage') : 'node'; |
pierre@1
|
36 $regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\<front\\\\>($|\|)/'), array('|', '.*', '\1'. preg_quote($frontpage, '/') .'\2'), preg_quote($urls, '/')) .')$/'; |
pierre@1
|
37 $match = preg_match($regexp, adserve_variable('url')); |
piotre@7
|
38 _debug_echo("ad_channel_cache: checking aid($aid) against channel($chid) path(". adserve_variable('url') .") regexp($regexp) match($match) display[$display_by_url]"); |
piotre@7
|
39 // display ad on all except matching urls |
piotre@7
|
40 if ($display_by_url == 0) { |
pierre@1
|
41 if (empty($urls) || !$match) { |
pierre@1
|
42 _debug_echo("ad_channel_cache: aid($aid) is valid"); |
piotre@7
|
43 $valid_ads[$chid][] = $aid; |
piotre@7
|
44 if ($nochannel_display == 1) { |
piotre@7
|
45 $nochannel_percent[$chid] = $channel->no_channel_percent; |
piotre@7
|
46 _debug_echo("ad_channel_cache: channel($chid) no_channel_percent($nochannel_percent[$chid])"); |
sly@2
|
47 } |
piotre@7
|
48 else { |
piotre@7
|
49 _debug_echo("ad_channel_cache: channel($chid)"); |
piotre@7
|
50 } |
pierre@1
|
51 break; |
pierre@1
|
52 } |
pierre@1
|
53 } |
piotre@7
|
54 // display ad on matching urls |
piotre@7
|
55 else { |
pierre@1
|
56 if (!empty($urls) && $match) { |
pierre@1
|
57 _debug_echo("ad_channel_cache: aid($aid) is valid"); |
piotre@7
|
58 $valid_ads[$chid][] = $aid; |
piotre@7
|
59 if ($nochannel_display == 1) { |
piotre@7
|
60 $nochannel_percent[$chid] = $channel->no_channel_percent; |
piotre@7
|
61 _debug_echo("ad_channel_cache: channel($chid) no_channel_percent($nochannel_percent[$chid])"); |
sly@2
|
62 } |
piotre@7
|
63 else { |
piotre@7
|
64 _debug_echo("ad_channel_cache: channel($chid)"); |
piotre@7
|
65 } |
pierre@1
|
66 break; |
pierre@1
|
67 } |
pierre@1
|
68 } |
piotre@7
|
69 // no match so we didn't hit a break, ad is not valid |
pierre@1
|
70 _debug_echo("ad_channel_cache: aid($aid) is not valid"); |
pierre@1
|
71 } |
pierre@1
|
72 } |
pierre@1
|
73 else { |
piotre@7
|
74 // no channel information for ad |
piotre@7
|
75 _debug_echo("ad_channel_cache: aid($aid) has no channel info, nochannel_display($nochannel_display)"); |
piotre@7
|
76 switch ($nochannel_display) { |
pierre@1
|
77 case 0: |
piotre@7
|
78 $nochannel_fallback_ads[] = $aid; |
piotre@7
|
79 _debug_echo("ad_channel_cache: non-channel aid($aid) is valid if no valid ads are assigned to current channel"); |
pierre@1
|
80 break; |
pierre@1
|
81 case 1: |
piotre@7
|
82 $valid_ads[0][] = $aid; |
piotre@7
|
83 _debug_echo("ad_channel_cache: non-channel aid($aid) is valid"); |
pierre@1
|
84 break; |
pierre@1
|
85 case 2: |
pierre@1
|
86 _debug_echo("ad_channel_cache: aid($aid) is not valid"); |
pierre@1
|
87 break; |
pierre@1
|
88 } |
pierre@1
|
89 } |
pierre@1
|
90 } |
pierre@1
|
91 |
piotre@7
|
92 // Apply frequencies, applicable to all channels |
piotre@7
|
93 if (!empty($valid_ads) && !empty($nochannel_percent)) { |
piotre@7
|
94 $frequencies = array(); |
piotre@7
|
95 foreach (array_keys($valid_ads) as $chid) { |
piotre@7
|
96 if ($chid) { |
piotre@7
|
97 if (isset($nochannel_percent[$chid]) && $nochannel_percent[$chid]) { |
piotre@7
|
98 $frequencies[$chid] = $nochannel_percent[$chid]; |
piotre@7
|
99 _debug_echo("ad_channel_cache: channel $chid has a non-channel ad frequency of ". $nochannel_percent[$chid]."%"); |
sly@2
|
100 } |
sly@2
|
101 else { |
piotre@7
|
102 // by default, channels return 'non-channel ads' with a frequency |
piotre@7
|
103 // of 10% |
piotre@7
|
104 $frequencies[$chid] = 10; |
piotre@7
|
105 _debug_echo("ad_channel_cache: channel $chid assigned a default non-channel ad frequency of 10%"); |
sly@2
|
106 } |
sly@2
|
107 } |
sly@2
|
108 else { |
piotre@7
|
109 // frequency for non-channel ads is not meaningful |
sly@2
|
110 } |
sly@2
|
111 } |
piotre@7
|
112 if (!empty($frequencies)) { |
piotre@7
|
113 $balanced_channels = array(); |
piotre@7
|
114 $num_channels = sizeof($valid_ads); |
piotre@7
|
115 |
piotre@7
|
116 foreach (array_keys($valid_ads) as $chid) { |
piotre@7
|
117 if (isset($frequencies[$chid])) { |
piotre@7
|
118 // for a given channel, ensure the proper ratio to non-channel ads |
piotre@7
|
119 if ($frequencies[$chid] <= 50) { // increase occurrences of $chid |
piotre@7
|
120 $balanced_channels[] = 0; |
piotre@7
|
121 $frequency = round(100 / $frequencies[$chid]) - 1; |
piotre@7
|
122 _debug_echo("ad_channel_cache: adjusting ratio of channel($chid) to $frequency:1 relative non-channel ads"); |
piotre@7
|
123 for ($i = 1; $i <= $frequency; $i++) { |
piotre@7
|
124 $balanced_channels[] = $chid; |
piotre@7
|
125 } |
piotre@7
|
126 } |
piotre@7
|
127 else { // add $chid and additional non-channel ads |
piotre@7
|
128 $balanced_channels[] = $chid; |
piotre@7
|
129 $frequency = round(100 / (100 - $frequencies[$chid])) - 1; |
piotre@7
|
130 _debug_echo("ad_channel_cache: adjusting ratio of channel($chid) to 1:$frequency relative non-channel ads"); |
piotre@7
|
131 for ($i = 1; $i <= $frequency; $i++) { |
piotre@7
|
132 $balanced_channels[] = 0; |
piotre@7
|
133 } |
piotre@7
|
134 } |
sly@2
|
135 } |
sly@2
|
136 } |
piotre@7
|
137 _debug_echo('ad_channel_cache: channel 0 contains all non-channel ads'); |
piotre@7
|
138 if (adserve_variable('debug') >= 2) { |
piotre@7
|
139 foreach ($balanced_channels as $key => $chid) { |
piotre@7
|
140 _debug_echo("ad_channel_cache: channel $chid => index $key"); |
piotre@7
|
141 } |
piotre@7
|
142 } |
sly@2
|
143 } |
piotre@7
|
144 $random_channel = _select_channel_id($balanced_channels); |
sly@2
|
145 } |
piotre@7
|
146 else if (!empty($valid_ads)) { |
piotre@7
|
147 foreach ($valid_ads as $chid => $ads) { |
piotre@7
|
148 $chids[$chid] = $chid; |
piotre@7
|
149 } |
piotre@7
|
150 shuffle($chids); |
piotre@7
|
151 $random_channel = array_pop($chids); |
piotre@7
|
152 } |
piotre@7
|
153 else if (empty($valid_ads) && !empty($nochannel_fallback_ads)) { |
pierre@1
|
154 _debug_echo("ad_channel_cache: using ads with no channel info"); |
piotre@7
|
155 $valid_ads[0] = $nochannel_fallback_ads; |
piotre@7
|
156 $random_channel = 0; |
pierre@1
|
157 } |
pierre@1
|
158 |
pierre@1
|
159 $premiere = adserve_cache('get_cache', 'premiere'); |
pierre@1
|
160 if (is_array($premiere)) { |
piotre@7
|
161 $premieres = array(); |
piotre@7
|
162 foreach (array_keys($valid_ads) as $chid) { |
piotre@7
|
163 foreach ($valid_ads[$chid] as $aid) { |
piotre@7
|
164 if (in_array($aid, $premiere)) { |
piotre@7
|
165 _debug_echo("ad_channel_cache: aid($aid) is premiere advertisement"); |
piotre@7
|
166 $premieres[$aid] = $aid; |
piotre@7
|
167 } |
piotre@7
|
168 else { |
piotre@7
|
169 _debug_echo("ad_channel_cache: aid($aid) is not a premiere advertisement"); |
piotre@7
|
170 } |
pierre@1
|
171 } |
pierre@1
|
172 } |
pierre@1
|
173 if (!empty($premieres)) { |
pierre@1
|
174 _debug_echo("ad_channel_cache: returning premiere advertisements"); |
pierre@1
|
175 return $premieres; |
pierre@1
|
176 } |
pierre@1
|
177 } |
piotre@7
|
178 _debug_echo("ad_channel_cache: returning non-premiere advertisements from randomly selected channel $random_channel"); |
piotre@7
|
179 |
piotre@7
|
180 if (isset($valid_ads[$random_channel])) { |
piotre@7
|
181 return ad_channel_enforce_inventory_level($random_channel, $valid_ads[$random_channel]); |
piotre@7
|
182 } |
pierre@1
|
183 } |
sly@2
|
184 |
sly@2
|
185 /** |
piotre@7
|
186 * Randomly select a valid channel id from an array channel ids |
piotre@7
|
187 * @param array, valid array. |
sly@2
|
188 */ |
piotre@7
|
189 function _select_channel_id($choices) { |
piotre@7
|
190 $selected = 0; |
piotre@7
|
191 if (is_array($choices)) { |
piotre@7
|
192 $available = sizeof($choices); |
piotre@7
|
193 _debug_echo("ad_channel_cache: randomly selecting from $available indexes."); |
piotre@7
|
194 $selected = $available > 1 ? $choices[mt_rand(0, $available - 1)] : $choices[0]; |
piotre@7
|
195 _debug_echo("ad_channel_cache: randomly selected channel $selected."); |
piotre@7
|
196 } |
sly@2
|
197 |
piotre@7
|
198 return $selected; |
sly@2
|
199 } |
sly@2
|
200 |
piotre@7
|
201 /* |
piotre@7
|
202 * Augment the selected channel with 'remnant' ads to ensure that any specified |
piotre@7
|
203 * inventory level is honored |
piotre@7
|
204 * @param int, channel id |
piotre@7
|
205 * @param array, valid array. |
sly@2
|
206 */ |
piotre@7
|
207 function ad_channel_enforce_inventory_level($chid, $ads) { |
piotre@7
|
208 if ($chid > 0) { |
piotre@7
|
209 $channels = adserve_cache('get_cache', 'channel'); |
piotre@7
|
210 $channel = $channels['channels'][$chid]; |
piotre@7
|
211 $level = $channel->inventory; |
piotre@7
|
212 $num_ads = count($ads); |
piotre@7
|
213 if ($num_ads < $level) { |
piotre@7
|
214 _debug_echo("ad_channel_enforce_inventory_level: channel($chid) has $num_ads and needs $level"); |
piotre@7
|
215 $remnants = array_values(adserve_cache('get_cache', 'remnant')); |
piotre@7
|
216 $available = count($remnants); |
piotre@7
|
217 if ($available > 0) { |
piotre@7
|
218 _debug_echo("ad_channel_enforce_inventory_level: randomly selecting from $available remnants."); |
piotre@7
|
219 while (count($ads) < $level) { |
piotre@7
|
220 shuffle($remnants); |
piotre@7
|
221 $selected = array_pop($remnants); |
piotre@7
|
222 _debug_echo("ad_channel_enforce_inventory_level: selected $selected."); |
piotre@7
|
223 $ads[] = $selected; |
piotre@7
|
224 } |
piotre@7
|
225 } |
piotre@7
|
226 else { |
piotre@7
|
227 _debug_echo("ad_channel_enforce_inventory_level: no remnants to choose from."); |
piotre@7
|
228 } |
piotre@7
|
229 } |
piotre@7
|
230 else { |
piotre@7
|
231 _debug_echo("ad_channel_enforce_inventory_level: channel($chid) no inventory level assigned"); |
piotre@7
|
232 } |
sly@2
|
233 } |
sly@2
|
234 else { |
piotre@7
|
235 _debug_echo("ad_channel_enforce_inventory_level: not needed for channel($chid)"); |
sly@2
|
236 } |
piotre@7
|
237 return $ads; |
sly@2
|
238 } |
piotre@7
|
239 |