Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 821 lines (730 sloc) 29.772 kb
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
1 <?php
2 /*
3 Plugin Name: Ad Code Manager
4 Plugin URI: http://automattic.com
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
5 Description: Easy ad code management
765bd1a bumped version to 0.1.3
Rinat Khaziev authored
6 Author: Daniel Bachhuber, Automattic, Rinat Khaziev, doejo
1ebff24 @danielbachhuber Retagging v0.1.3
danielbachhuber authored
7 Version: 0.1.3
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
8 Author URI: http://automattic.com
9
10 GNU General Public License, Free Software Foundation <http://creativecommons.org/licenses/GPL/2.0/>
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
26 */
0b8328a @danielbachhuber This one too
danielbachhuber authored
27 define( 'AD_CODE_MANAGER_VERSION', '0.1.3' );
b2bb7a6 WP code standards
rinatkhaziev authored
28 define( 'AD_CODE_MANAGER_ROOT' , dirname( __FILE__ ) );
29 define( 'AD_CODE_MANAGER_FILE_PATH' , AD_CODE_MANAGER_ROOT . '/' . basename( __FILE__ ) );
e894810 @danielbachhuber Better plugins_url for loading resources
danielbachhuber authored
30 define( 'AD_CODE_MANAGER_URL' , plugins_url( '/', __FILE__ ) );
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
31
32 class Ad_Code_Manager
33 {
34
799b6ca @danielbachhuber s/ad tag/ad code/
danielbachhuber authored
35 var $ad_codes = array();
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
36 var $whitelisted_script_urls = array();
37 var $whitelisted_conditionals = array();
c982fb7 update UI to match presentation logic
Rinat Khaziev authored
38 var $whitelisted_conditionals_titles = array();
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
39 var $output_html;
40 var $output_tokens = array();
3f73c30 start of jqGrid implementation / basic ui
Rinat Khaziev authored
41 var $title = 'Ad Code Manager';
42 var $post_type = 'acm-code';
3020fef @danielbachhuber Move Ad Code Manager page under the Tools menu, and only print JS hea…
danielbachhuber authored
43 var $plugin_slug = 'ad-code-manager';
3b064c0 @danielbachhuber Include a caps check when making AJAX requests too
danielbachhuber authored
44 var $manage_ads_cap = 'manage_options';
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
45 var $post_type_labels ;
1d4983e making OR default logical operator, but allow users to filter it
Rinat Khaziev authored
46 var $logical_operator;
8a1e904 expand default tag_ids for
Rinat Khaziev authored
47 var $ad_tag_ids;
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
48
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
49 /**
50 * Instantiate the plugin
51 *
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
52 * @since 0.1
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
53 */
54 function __construct() {
aea51a1 nonce & wp_ajax_
Rinat Khaziev authored
55 add_action('wp_ajax_acm_ajax_handler', array( &$this, 'ajax_handler' ) );
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
56 add_action( 'init', array( &$this, 'action_init' ) );
3020fef @danielbachhuber Move Ad Code Manager page under the Tools menu, and only print JS hea…
danielbachhuber authored
57
58 // Incorporate the link to our admin menu
59 add_action( 'admin_menu' , array( $this, 'action_admin_menu' ) );
b2bb7a6 WP code standards
rinatkhaziev authored
60 add_action( 'admin_enqueue_scripts', array( &$this, 'register_scripts_and_styles' ) );
475678f remove hardcode in acm.js
Rinat Khaziev authored
61 add_action( 'admin_print_scripts', array( &$this, 'post_admin_header' ) );
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
62 }
63
64 /**
65 * Code to run on WordPress' 'init' hook
66 *
721b720 @danielbachhuber Moar cleanup
danielbachhuber authored
67 * @since 0.1
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
68 */
69 function action_init() {
8a1e904 expand default tag_ids for
Rinat Khaziev authored
70 $this->post_type_labels = array(
71 'name' => __( 'DFP Ad Codes' ),
72 'singular_name' => __( 'DFP Ad Codes' ),
73 );
74
51b4444 @danielbachhuber Include descriptions for what each filter does at the code level
danielbachhuber authored
75 /**
76 * Configuration filter: acm_whitelisted_script_urls
77 * A security filter to whitelist which ad code script URLs can be added in the admin
78 */
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
79 $this->whitelisted_script_urls = apply_filters( 'acm_whitelisted_script_urls', $this->whitelisted_script_urls );
80
81 // Allow other conditionals to be used
82 $this->whitelisted_conditionals = array(
83 'is_home',
84 'is_front_page',
85 'is_category',
86 'has_category',
c982fb7 update UI to match presentation logic
Rinat Khaziev authored
87 'is_page',
88 'is_tag',
89 'has_tag',
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
90 );
51b4444 @danielbachhuber Include descriptions for what each filter does at the code level
danielbachhuber authored
91 /**
92 * Configuration filter: acm_whitelisted_conditionals
93 * Extend the list of usable conditional functions with your own awesome ones.
94 */
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
95 $this->whitelisted_conditionals = apply_filters( 'acm_whitelisted_conditionals', $this->whitelisted_conditionals );
1d4983e making OR default logical operator, but allow users to filter it
Rinat Khaziev authored
96 $this->logical_operator = apply_filters( 'acm_logical_operator', 'OR'); //allow users to filter default logical operator
4da2b93 late night fixes
rinatkhaziev authored
97
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
98 // Set our default output HTML
99 // This can be filtered in action_acm_tag()
100 $this->output_html = '<script type="text/javascript" src="%url%"></script>';
101
3b064c0 @danielbachhuber Include a caps check when making AJAX requests too
danielbachhuber authored
102 // Allow the ad management cap to be filtered if need be
103 $this->manage_ads_cap = apply_filters( 'acm_manage_ads_cap', $this->manage_ads_cap );
104
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
105 // Set our default tokens to replace
106 // This can be filtered in action_acm_tag()
721b720 @danielbachhuber Moar cleanup
danielbachhuber authored
107 $this->output_tokens = array();
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
108
fd2e97b moving property setting from constructor to init action
Rinat Khaziev authored
109 // These are common DFP tags
110 $this->ad_tag_ids = array(
111 array(
112 'tag' => '728x90-atf',
113 'url_vars' => array(
114 'sz' => '728x90',
115 'fold' => 'atf'
116 )
117 ),
118 array(
119 'tag' => '728x90-btf',
120 'url_vars' => array(
121 'sz' => '728x90',
122 'fold' => 'btf'
123 )
124 ) ,
125 array(
126 'tag' => '300x250-atf',
127 'url_vars' => array(
128 'sz' => '300x250',
129 'fold' => 'atf'
130 )
131 ),
132 array(
133 'tag' => '300x250-btf',
134 'url_vars' => array(
135 'sz' => '300x250',
c30c8f1 do not add ad code with no conditionals in the array of codes to disp…
Rinat Khaziev authored
136 'fold' => 'btf'
fd2e97b moving property setting from constructor to init action
Rinat Khaziev authored
137 )
138 ),
139 array(
140 'tag' => '160x600-atf',
141 'url_vars' => array(
142 'sz' => '160x600',
143 'fold' => 'atf'
144 )
c30c8f1 do not add ad code with no conditionals in the array of codes to disp…
Rinat Khaziev authored
145 ),
fd2e97b moving property setting from constructor to init action
Rinat Khaziev authored
146 );
51b4444 @danielbachhuber Include descriptions for what each filter does at the code level
danielbachhuber authored
147 /**
148 * Configuration filter: acm_ad_tag_ids
149 * Extend set of default tag ids. Ad tag ids are used as a parameter
150 * for your template tag (e.g. do_action( 'acm_tag', 'my_top_leaderboard' ))
151 */
0fe1625 moving property setting from constructor to init action, pass 2
Rinat Khaziev authored
152 $this->ad_tag_ids = apply_filters( 'acm_ad_tag_ids', $this->ad_tag_ids );
5164301 code cleanup
rinatkhaziev authored
153
0727539 @danielbachhuber Todos
danielbachhuber authored
154 $this->register_acm_post_type();
155
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
156 // Ad tags are only run on the frontend
157 if ( !is_admin() ) {
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
158 add_action( 'acm_tag', array( $this, 'action_acm_tag' ) );
ed5abd2 @danielbachhuber Better approach for tokenizing... load all of our url_vars into the a…
danielbachhuber authored
159 add_filter( 'acm_output_tokens', array( $this, 'filter_output_tokens' ), 5, 3 );
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
160 }
4da2b93 late night fixes
rinatkhaziev authored
161
881b460 @danielbachhuber This can just be in the init action
danielbachhuber authored
162 // Load all of our registered ad codes
163 $this->register_ad_codes( $this->get_ad_codes() );
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
164 }
165
166 /**
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
167 * Register our custom post type to store ad codes
168 *
3395e21 @danielbachhuber Remove unnecessary code
danielbachhuber authored
169 * @since 0.1
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
170 */
171 function register_acm_post_type() {
b2bb7a6 WP code standards
rinatkhaziev authored
172 register_post_type( $this->post_type, array( 'labels' => $this->post_type_labels, 'public' => false ) );
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
173 }
4da2b93 late night fixes
rinatkhaziev authored
174
5fefe94 @danielbachhuber Sanitize when we're directly handling user input, and only pass clean…
danielbachhuber authored
175 /**
176 * Handles all admin ajax requests: getting, updating, creating and deleting
177 *
178 * @since 0.1
179 */
9990e27 data from jqGrid was passed as string, but treated as array, added ty…
Rinat Khaziev authored
180 function ajax_handler() {
aea51a1 nonce & wp_ajax_
Rinat Khaziev authored
181 if ( ! isset( $_REQUEST['nonce'] ) || ! wp_verify_nonce( $_REQUEST['nonce'], 'acm_nonce' ) )
4da2b93 late night fixes
rinatkhaziev authored
182 return;
9990e27 data from jqGrid was passed as string, but treated as array, added ty…
Rinat Khaziev authored
183
3b064c0 @danielbachhuber Include a caps check when making AJAX requests too
danielbachhuber authored
184 if ( !current_user_can( $this->manage_ads_cap ) )
185 return;
186
aea51a1 nonce & wp_ajax_
Rinat Khaziev authored
187 switch( $_GET['acm-action'] ) {
188 case 'datasource':
189 $this->get_ad_codes_ajax();
190 break;
191 case 'datasource-conditionals':
192 $this->get_conditionals_ajax();
193 break;
194 case 'edit':
195 $this->ad_code_edit_actions();
196 break;
197 case 'edit-conditionals':
198 $this->conditionals_edit_actions();
199 break;
4da2b93 late night fixes
rinatkhaziev authored
200 }
aea51a1 nonce & wp_ajax_
Rinat Khaziev authored
201 return;
202 }
203
3f73c30 start of jqGrid implementation / basic ui
Rinat Khaziev authored
204 /**
205 * Returns json encoded ad code
206 * This is the datasource for jqGRID
c30c8f1 do not add ad code with no conditionals in the array of codes to disp…
Rinat Khaziev authored
207 *
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
208 */
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
209 function get_ad_codes_ajax() {
3f73c30 start of jqGrid implementation / basic ui
Rinat Khaziev authored
210 // These are params that should be managed via UI
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
211 /**
212 * NB!
213 * $response is an object with following properties
214 * $response->page = current page
215 * $response->total = total pages
216 * $response->record = count of rows
c30c8f1 do not add ad code with no conditionals in the array of codes to disp…
Rinat Khaziev authored
217 * $response->rows = nested array of assoc arrays
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
218 */
3f73c30 start of jqGrid implementation / basic ui
Rinat Khaziev authored
219 $response;
220 if ( isset( $_GET[ 'acm-action' ] ) && $_GET[ 'acm-action'] == 'datasource' ) {
e68e295 supply offset for get_posts in get_posts_ajax, otherwise pagination i…
Rinat Khaziev authored
221 $response->page = isset( $_GET[ 'acm-grid-page' ] ) ? sanitize_key( $_GET[ 'acm-grid-page' ] ) : 1 ;
222 $query_args = array();
223
224 // We need to pass offset to get_ad_codes offset for jqGrid to work correctly
225 if ( 1 < $response->page )
226 $query_args['offset'] = ( $response->page - 1 ) * intval( $_GET['rows'] );
227
228 $ad_codes = $this->get_ad_codes( $query_args ) ;
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
229 // prepare data in jqGrid specific format
230 $pass = array();
231 foreach ( $ad_codes as $ad_code ) {
232 $pass[] = array(
b83d510 UI cleanup
Rinat Khaziev authored
233 'id' => $ad_code['post_id'],
8a1e904 expand default tag_ids for
Rinat Khaziev authored
234 'site_name' => $ad_code[ 'url_vars' ][ 'site_name' ] ,
235 'zone1' => $ad_code[ 'url_vars' ][ 'zone1' ],
b2bb7a6 WP code standards
rinatkhaziev authored
236 'act' => '',
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
237 );
3f73c30 start of jqGrid implementation / basic ui
Rinat Khaziev authored
238 }
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
239 $response->rows = $pass;
e68e295 supply offset for get_posts in get_posts_ajax, otherwise pagination i…
Rinat Khaziev authored
240 $count_object = wp_count_posts( $this->post_type );
241 $total_pages = ceil ( $count_object->publish / $_GET['rows'] );
242 $response->total = $total_pages;
243 $response->records = $count_object->publish;
3f73c30 start of jqGrid implementation / basic ui
Rinat Khaziev authored
244 $this->print_json( $response );
245 }
246 return;
247 }
4da2b93 late night fixes
rinatkhaziev authored
248
249
8a1e904 expand default tag_ids for
Rinat Khaziev authored
250 /**
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
251 * Get the ad codes stored in our custom post type
8a1e904 expand default tag_ids for
Rinat Khaziev authored
252 *
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
253 * @todo This is too DFP specific. Abstract it
8a1e904 expand default tag_ids for
Rinat Khaziev authored
254 */
e68e295 supply offset for get_posts in get_posts_ajax, otherwise pagination i…
Rinat Khaziev authored
255 function get_ad_codes( $query_args = array() ) {
8a1e904 expand default tag_ids for
Rinat Khaziev authored
256 $ad_codes_formatted = array();
e68e295 supply offset for get_posts in get_posts_ajax, otherwise pagination i…
Rinat Khaziev authored
257 $allowed_query_params = apply_filters( 'acm_allowed_get_posts_args', array( 'offset' ) );
258
aaa1f0d @danielbachhuber Increase the number of ad codes queried to 50 and make it filterable
danielbachhuber authored
259 $args = array(
260 'post_type' => $this->post_type,
261 'numberposts' => apply_filters( 'acm_ad_code_count', 50 ),
262 );
e68e295 supply offset for get_posts in get_posts_ajax, otherwise pagination i…
Rinat Khaziev authored
263
264 foreach ( (array) $query_args as $query_key => $query_value ) {
265 if ( ! in_array( $query_key, $allowed_query_params ) ) {
266 unset( $query_args[$query_key] );
267 } else {
b889a23 @danielbachhuber sanitize_text_field() isn't necessary here... we should be passing sa…
danielbachhuber authored
268 $args[$query_key] = $query_value;
e68e295 supply offset for get_posts in get_posts_ajax, otherwise pagination i…
Rinat Khaziev authored
269 }
270 }
271
aaa1f0d @danielbachhuber Increase the number of ad codes queried to 50 and make it filterable
danielbachhuber authored
272 $ad_codes = get_posts( $args );
8a1e904 expand default tag_ids for
Rinat Khaziev authored
273 foreach ( $ad_codes as $ad_code_cpt ) {
274 $ad_codes_formatted[] = array(
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
275 'conditionals' => $this->get_conditionals( $ad_code_cpt->ID ),
276 'url_vars' => array(
277 'site_name' => get_post_meta( $ad_code_cpt->ID, 'site_name', true ),
278 'zone1' => get_post_meta( $ad_code_cpt->ID, 'zone1', true ),
279 ),
280 'post_id' => $ad_code_cpt->ID
281 );
8a1e904 expand default tag_ids for
Rinat Khaziev authored
282 }
283 return $ad_codes_formatted;
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
284 }
4da2b93 late night fixes
rinatkhaziev authored
285
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
286 function get_conditionals_ajax() {
aea51a1 nonce & wp_ajax_
Rinat Khaziev authored
287 if ( 0 !== intval( $_GET[ 'id' ] ) ) {
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
288 $conditionals = $this->get_conditionals( intval( $_GET[ 'id' ] ) );
9990e27 data from jqGrid was passed as string, but treated as array, added ty…
Rinat Khaziev authored
289 $response;
290 foreach ( $conditionals as $index => $item ) {
291 if ( is_array( $item['arguments'] ) ) {
292 $item['arguments'] = implode(";", $item['arguments'] );
293 }
b2bb7a6 WP code standards
rinatkhaziev authored
294 $response->rows[] = $item;
9990e27 data from jqGrid was passed as string, but treated as array, added ty…
Rinat Khaziev authored
295 }
9c8abe6 UI
Rinat Khaziev authored
296 $count = count( $response->rows );
c30c8f1 do not add ad code with no conditionals in the array of codes to disp…
Rinat Khaziev authored
297 $total_pages = ceil ( $count / $_GET['rows'] );
9c8abe6 UI
Rinat Khaziev authored
298
9990e27 data from jqGrid was passed as string, but treated as array, added ty…
Rinat Khaziev authored
299 $response->page = isset( $_GET['acm-grid-page'] ) ? sanitize_text_field( $_GET['acm-grid-page'] ) : 1 ;
9c8abe6 UI
Rinat Khaziev authored
300 $response->total = $total_pages;
301 $response->records = $count;
4da2b93 late night fixes
rinatkhaziev authored
302 $this->print_json( $response );
303 }
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
304 }
305
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
306 /**
307 * Get the conditional values for an ad code
308 */
4da2b93 late night fixes
rinatkhaziev authored
309 function get_conditionals( $ad_code_id ) {
5fefe94 @danielbachhuber Sanitize when we're directly handling user input, and only pass clean…
danielbachhuber authored
310 return get_post_meta( $ad_code_id, 'conditionals', true );
9c8abe6 UI
Rinat Khaziev authored
311 }
b2bb7a6 WP code standards
rinatkhaziev authored
312
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
313 /**
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
314 * Handles AJAX Create, Update, Delete actions for Ad Codes
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
315 */
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
316 function ad_code_edit_actions() {
5fefe94 @danielbachhuber Sanitize when we're directly handling user input, and only pass clean…
danielbachhuber authored
317 // Noncing happens in $this->ajax_handler()
aea51a1 nonce & wp_ajax_
Rinat Khaziev authored
318 if ( ! empty( $_POST ) ) {
b2bb7a6 WP code standards
rinatkhaziev authored
319 //this is jqGrid param
76440ee @danielbachhuber Sanitize values when creating or editing ad codes or conditionals
danielbachhuber authored
320 $ad_code_vals = array(
321 'site_name' => sanitize_text_field( $_POST['site_name'] ),
322 'zone1' => sanitize_text_field( $_POST['zone1'] ),
323 );
b2bb7a6 WP code standards
rinatkhaziev authored
324 switch ( $_POST[ 'oper' ] ) {
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
325 case 'add':
76440ee @danielbachhuber Sanitize values when creating or editing ad codes or conditionals
danielbachhuber authored
326 $this->create_ad_code( $ad_code_vals );
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
327 break;
328 case 'edit':
0f72d9b ad codes/conditionals edit actions bugfix
Rinat Khaziev authored
329 $this->edit_ad_code( intval( $_POST[ 'id' ] ), $ad_code_vals );
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
330 break;
331 case 'del':
5fefe94 @danielbachhuber Sanitize when we're directly handling user input, and only pass clean…
danielbachhuber authored
332 $this->delete_ad_code( intval( $_POST[ 'id' ] ) );
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
333 break;
334 }
335 exit; // exit, jqGrid sends another request to fetch new data
336 }
337 return;
338 }
b2bb7a6 WP code standards
rinatkhaziev authored
339
c982fb7 update UI to match presentation logic
Rinat Khaziev authored
340 function conditionals_edit_actions() {
aea51a1 nonce & wp_ajax_
Rinat Khaziev authored
341 if ( ! empty( $_POST ) ) {
76440ee @danielbachhuber Sanitize values when creating or editing ad codes or conditionals
danielbachhuber authored
342 $conditional_vals = array(
343 'function' => sanitize_key( $_POST['function'] ),
9990e27 data from jqGrid was passed as string, but treated as array, added ty…
Rinat Khaziev authored
344 //arguments from jqGrid are passed as string, need to check arguments type before choosing the way to sanitize the value
345 'arguments' => is_array( $_POST['arguments'] ) ? array_map( 'sanitize_text_field', $_POST['arguments'] ) : sanitize_text_field( $_POST['arguments'] ),
76440ee @danielbachhuber Sanitize values when creating or editing ad codes or conditionals
danielbachhuber authored
346 );
b2bb7a6 WP code standards
rinatkhaziev authored
347 switch ( $_POST[ 'oper' ] ) {
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
348 case 'add':
76440ee @danielbachhuber Sanitize values when creating or editing ad codes or conditionals
danielbachhuber authored
349 $result = $this->create_conditional( intval( $_GET['id'] ), $conditional_vals );
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
350 break;
351 case 'edit':
0f72d9b ad codes/conditionals edit actions bugfix
Rinat Khaziev authored
352 $conditional_vals['id'] = intval( $_POST['id'] ); // we need this for edit action to work correctly
76440ee @danielbachhuber Sanitize values when creating or editing ad codes or conditionals
danielbachhuber authored
353 $result = $this->edit_conditional( intval( $_GET['id'] ), $conditional_vals, true );
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
354 break;
355 case 'del':
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
356 // That's confusing: $_GET['id'] refers to CPT ID, $_POST['id'] refers to indices that should be
4da2b93 late night fixes
rinatkhaziev authored
357 // removed from array of conditionals
76440ee @danielbachhuber Sanitize values when creating or editing ad codes or conditionals
danielbachhuber authored
358 $result = $this->delete_conditional( intval( $_GET['id'] ), intval( $_POST[ 'id' ] ), true );
b2bb7a6 WP code standards
rinatkhaziev authored
359 break;
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
360 }
24e610a fixed conditional edit logic
Rinat Khaziev authored
361 exit($result);
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
362 }
363 return;
364 }
b2bb7a6 WP code standards
rinatkhaziev authored
365
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
366 /**
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
367 * Create a new ad code in the database
368 *
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
369 * @uses register_ad_code()
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
370 *
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
371 * @todo validation / nonce
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
372 *
4da2b93 late night fixes
rinatkhaziev authored
373 * @param array $ad_code
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
374 */
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
375 function create_ad_code( $ad_code = array() ) {
376 if ( $ad_code['site_name'] && $ad_code['zone1'] ) {
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
377 $acm_post = array(
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
378 'post_title' => $ad_code['site_name'] .'-' . $ad_code['zone1'],
379 'post_status' => 'publish',
380 'comment_status' => 'closed',
381 'ping_status' => 'closed',
382 'post_type' => $this->post_type,
383 );
b2bb7a6 WP code standards
rinatkhaziev authored
384 if ( ! is_wp_error( $acm_inserted_post_id = wp_insert_post( $acm_post, true ) ) ) {
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
385 update_post_meta( $acm_inserted_post_id, 'site_name', $ad_code[ 'site_name' ] );
386 update_post_meta( $acm_inserted_post_id, 'zone1', $ad_code[ 'zone1' ] );
b2bb7a6 WP code standards
rinatkhaziev authored
387 }
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
388 }
389 return;
390 }
b2bb7a6 WP code standards
rinatkhaziev authored
391
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
392 /**
393 * Update an existing ad code
394 */
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
395 function edit_ad_code( $ad_code_id, $ad_code = array() ) {
5fefe94 @danielbachhuber Sanitize when we're directly handling user input, and only pass clean…
danielbachhuber authored
396 if ( 0 !== $ad_code_id && $ad_code['site_name'] && $ad_code['zone1'] ) {
397 update_post_meta( $ad_code_id, 'site_name', $ad_code['site_name'] );
398 update_post_meta( $ad_code_id, 'zone1', $ad_code['zone1'] );
0f72d9b ad codes/conditionals edit actions bugfix
Rinat Khaziev authored
399 }
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
400 return;
401 }
402
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
403 /**
404 * Delete an existing ad code
405 */
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
406 function delete_ad_code( $ad_code_id ) {
5fefe94 @danielbachhuber Sanitize when we're directly handling user input, and only pass clean…
danielbachhuber authored
407 if ( 0 !== $ad_code_id )
408 wp_delete_post( $ad_code_id , true ); //force delete post
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
409 return;
410 }
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
411 /**
412 * Create conditional
413 *
414 * @param int $ad_code_id id of our CPT post
415 * @param array $conditional to add
416 *
417 * @return void ???
418 */
419 function create_conditional( $ad_code_id, $conditional ) {
5fefe94 @danielbachhuber Sanitize when we're directly handling user input, and only pass clean…
danielbachhuber authored
420 if ( 0 !== $ad_code_id && !empty( $conditional ) ) {
69b18fa fixed conditional create logic
Rinat Khaziev authored
421 $existing_conditionals = get_post_meta( $ad_code_id, 'conditionals', true );
c982fb7 update UI to match presentation logic
Rinat Khaziev authored
422 if ( ! is_array( $existing_conditionals ) ) {
423 $existing_conditionals = array();
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
424 }
c982fb7 update UI to match presentation logic
Rinat Khaziev authored
425 $existing_conditionals[] = array(
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
426 'function' => $conditional[ 'function' ],
9990e27 data from jqGrid was passed as string, but treated as array, added ty…
Rinat Khaziev authored
427 'arguments' => explode(';', $conditional[ 'arguments' ] ), // @todo filterize explode character?
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
428 );
8a1e904 expand default tag_ids for
Rinat Khaziev authored
429 update_post_meta( $ad_code_id, 'conditionals', $existing_conditionals );
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
430 }
431 return;
432 }
4da2b93 late night fixes
rinatkhaziev authored
433
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
434 /**
435 * Update conditional
436 *
437 * @param int $ad_code_id id of our CPT post
438 * @param array $conditional
439 *
440 */
24e610a fixed conditional edit logic
Rinat Khaziev authored
441 function edit_conditional( $ad_code_id, $conditional, $from_ajax = false ) {
5fefe94 @danielbachhuber Sanitize when we're directly handling user input, and only pass clean…
danielbachhuber authored
442 if ( 0 !== $ad_code_id && !empty( $conditional ) ) {
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
443 $existing_conditionals = (array) get_post_meta( $ad_code_id, 'conditionals', true );
24e610a fixed conditional edit logic
Rinat Khaziev authored
444 if ( $from_ajax && isset( $conditional ['id'] ) ) { // jqGrid starts with one, PHP starts with 0
445 $conditional['id']--;
446 }
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
447 foreach ( $existing_conditionals as $conditional_index => $existing_conditional ) {
24e610a fixed conditional edit logic
Rinat Khaziev authored
448 // $id is not an actual unique ID, but rather index of conditional in array of them
449 if ( isset( $conditional['id'] ) && $conditional['id'] === $conditional_index ) {
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
450 $existing_conditionals[ $conditional_index ] = array(
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
451 'function' => $conditional[ 'function' ],
452 'arguments' => (array) $conditional[ 'arguments' ],
453 );
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
454 }
455 }
24e610a fixed conditional edit logic
Rinat Khaziev authored
456 return update_post_meta( $ad_code_id, 'conditionals', array_values($existing_conditionals) );
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
457 }
458 return;
459 }
4da2b93 late night fixes
rinatkhaziev authored
460
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
461 /**
462 * This is a bit tricky as we really don't use any ID for conditionals
463 * To remove conditional we need to specify array index
464 *
465 * @param int $ad_code_id
466 * @param string $conditional_indices string of comma separated indices
467 */
468 function delete_conditional( $ad_code_id, $conditional_indices = '', $from_ajax = false ) {
5fefe94 @danielbachhuber Sanitize when we're directly handling user input, and only pass clean…
danielbachhuber authored
469 if ( 0 !== $ad_code_id ) {
56f59a7 decouple AJAX actions from actual CRUD methods
Rinat Khaziev authored
470 $existing_conditionals = get_post_meta( $ad_code_id, 'conditionals', true );
471 $ids_to_delete = explode(',', $conditional_indices ); //
472 foreach ($ids_to_delete as $index_to_delete ) {
473 if ( $from_ajax ) { // jqGrid starts with one, PHP starts with 0
474 $index_to_delete--;
475 }
4da2b93 late night fixes
rinatkhaziev authored
476 unset( $existing_conditionals[ $index_to_delete ] );
477 }
24e610a fixed conditional edit logic
Rinat Khaziev authored
478 update_post_meta( $ad_code_id, 'conditionals', array_values( $existing_conditionals ) ); //array_values to keep indices consistent
b2bb7a6 WP code standards
rinatkhaziev authored
479 }
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
480 return;
481 }
482
483 /**
484 * encode as json any given $data
485 */
3f73c30 start of jqGrid implementation / basic ui
Rinat Khaziev authored
486 function print_json( $data = array() ) {
487 header( 'Content-type: application/json;' );
488 echo json_encode( $data );
489 exit;
490 }
3020fef @danielbachhuber Move Ad Code Manager page under the Tools menu, and only print JS hea…
danielbachhuber authored
491
475678f remove hardcode in acm.js
Rinat Khaziev authored
492 /**
493 * Print our vars as JS
494 */
495 function post_admin_header() {
3020fef @danielbachhuber Move Ad Code Manager page under the Tools menu, and only print JS hea…
danielbachhuber authored
496
497 if ( !isset( $_GET['page'] ) || $_GET['page'] != $this->plugin_slug )
498 return;
499
c982fb7 update UI to match presentation logic
Rinat Khaziev authored
500 $conditionals_parsed = array();
501 foreach ( $this->whitelisted_conditionals as $conditional )
4da2b93 late night fixes
rinatkhaziev authored
502 $conditionals_parsed[] = $conditional . ':' . ucfirst( str_replace('_', ' ', $conditional ) );
475678f remove hardcode in acm.js
Rinat Khaziev authored
503 ?>
504 <script type="text/javascript">
3e05b73 making the list of usable conditions filterable with acm_conditions …
Rinat Khaziev authored
505 var acm_url = '<?php echo esc_js( admin_url( 'admin.php?page=' . $this->plugin_slug ) ) ?>';
c982fb7 update UI to match presentation logic
Rinat Khaziev authored
506 var acm_conditionals = '<?php echo esc_js( implode( ';', $conditionals_parsed ) )?>';
aea51a1 nonce & wp_ajax_
Rinat Khaziev authored
507 var acm_ajax_nonce = '<?php echo esc_js( wp_create_nonce('acm_nonce') ) ?>';
475678f remove hardcode in acm.js
Rinat Khaziev authored
508 </script>
509 <?php
510 }
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
511
3020fef @danielbachhuber Move Ad Code Manager page under the Tools menu, and only print JS hea…
danielbachhuber authored
512 /**
513 * Hook in our submenu page to the navigation
514 */
515 function action_admin_menu() {
3b064c0 @danielbachhuber Include a caps check when making AJAX requests too
danielbachhuber authored
516 add_submenu_page( 'tools.php', $this->title, $this->title, $this->manage_ads_cap, $this->plugin_slug, array( &$this, 'admin_view_controller' ) );
3f73c30 start of jqGrid implementation / basic ui
Rinat Khaziev authored
517 }
b2bb7a6 WP code standards
rinatkhaziev authored
518
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
519 /**
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
520 * Print the admin interface for managing the ad codes
521 *
3f73c30 start of jqGrid implementation / basic ui
Rinat Khaziev authored
522 * @todo remove html to views
523 */
524 function admin_view_controller() {
525 ?>
b83d510 UI cleanup
Rinat Khaziev authored
526 <div class="acm-ui-wrapper">
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
527 <h2>Ad Code Manager</h2>
b83d510 UI cleanup
Rinat Khaziev authored
528
feecb59 UI cleanup: added conditionals help (copy-paste from codex)
Rinat Khaziev authored
529 <p>Quick start note: Create an ad code, then click on the row and start adding <a href="javascript:;" id="conditionals-help-toggler">conditionals</a>.</p>
530
531 <div id="conditionals-help" class="hidden">
532 <strong>Note:</strong> this is not full list of conditional tags, you can always check out <a href="http://codex.wordpress.org/Conditional_Tags" class="external text">Codex page</a>.
533
0a75221 @danielbachhuber Fix links and temporarily untag v0.1.3
danielbachhuber authored
534 <dl><dt> <tt><a href="http://codex.wordpress.org/Function_Reference/is_home" class="external text" title="http://codex.wordpress.org/Function_Reference/is_home">is_home()</a></tt>&nbsp;</dt><dd> When the main blog page is being displayed. This is the page which shows the time based blog content of your site, so if you've set a static Page for the Front Page (see below), then this will only be true on the Page which you set as the "Posts page" in <a href="http://codex.wordpress.org/Administration_Panels" title="Administration Panels" class="mw-redirect">Administration</a> &gt; <a href="http://codex.wordpress.org/Administration_Panels#Reading" title="Administration Panels" class="mw-redirect">Settings</a> &gt; <a href="http://codex.wordpress.org/Settings_Reading_SubPanel" title="Settings Reading SubPanel" class="mw-redirect">Reading</a>.
feecb59 UI cleanup: added conditionals help (copy-paste from codex)
Rinat Khaziev authored
535 </dd></dl>
0a75221 @danielbachhuber Fix links and temporarily untag v0.1.3
danielbachhuber authored
536 <dl><dt> <tt><a href="http://codex.wordpress.org/Function_Reference/is_front_page" class="external text" title="http://codex.wordpress.org/Function_Reference/is_front_page">is_front_page()</a></tt>&nbsp;</dt><dd> When the front of the site is displayed, whether it is posts or a <a href="http://codex.wordpress.org/Pages" title="Pages">Page</a>. Returns true when the main blog page is being displayed and the '<a href="http://codex.wordpress.org/Administration_Panels#Reading" title="Administration Panels" class="mw-redirect">Settings</a> &gt; <a href="http://codex.wordpress.org/Settings_Reading_SubPanel" title="Settings Reading SubPanel" class="mw-redirect">Reading</a> -&gt;Front page displays' is set to "Your latest posts", <b>or</b> when '<a href="http://codex.wordpress.org/Administration_Panels#Reading" title="Administration Panels" class="mw-redirect">Settings</a> &gt; <a href="http://codex.wordpress.org/Settings_Reading_SubPanel" title="Settings Reading SubPanel" class="mw-redirect">Reading</a> -&gt;Front page displays' is set to "A static page" and the "Front Page" value is the current <a href="/Pages" title="Pages">Page</a> being displayed.
feecb59 UI cleanup: added conditionals help (copy-paste from codex)
Rinat Khaziev authored
537 </dd></dl>
538 <dl><dt> <tt><a href="http://codex.wordpress.org/Function_Reference/is_category" class="external text" title="http://codex.wordpress.org/Function_Reference/is_category">is_category()</a></tt>&nbsp;</dt><dd> When any Category archive page is being displayed.
539 </dd><dt> <tt>is_category( '9' )</tt>&nbsp;</dt><dd> When the archive page for Category 9 is being displayed.
540 </dd><dt> <tt>is_category( 'Stinky Cheeses' )</tt>&nbsp;</dt><dd> When the archive page for the Category with Name "Stinky Cheeses" is being displayed.
541 </dd><dt> <tt>is_category( 'blue-cheese' )</tt>&nbsp;</dt><dd> When the archive page for the Category with Category Slug "blue-cheese" is being displayed.
542 </dd><dt> <tt>is_category( array( 9, 'blue-cheese', 'Stinky Cheeses' ) )</tt>&nbsp;</dt><dd> Returns true when the category of posts being displayed is either term_ID 9, or <i>slug</i> "blue-cheese", or <i>name</i> "Stinky Cheeses".
543 </dd><dt> <tt>in_category( '5' )</tt>&nbsp;</dt><dd> Returns true if the current post is <b>in</b> the specified category id. <a href="http://codex.wordpress.org/Template_Tags/in_category" class="external text" title="http://codex.wordpress.org/Template_Tags/in_category">read more</a>
544 </dd></dl>
545 <dl><dt> <tt><a href="http://codex.wordpress.org/Function_Reference/is_tag" class="external text" title="http://codex.wordpress.org/Function_Reference/is_tag">is_tag()</a></tt>&nbsp;</dt><dd> When any Tag archive page is being displayed.
546 </dd><dt> <tt>is_tag( 'mild' )</tt>&nbsp;</dt><dd> When the archive page for tag with the slug of 'mild' is being displayed.
547 </dd><dt> <tt>is_tag( array( 'sharp', 'mild', 'extreme' ) )</tt>&nbsp;</dt><dd> Returns true when the tag archive being displayed has a slug of either "sharp", "mild", or "extreme".
548 </dd><dt> <tt>has_tag()</tt>&nbsp;</dt><dd> When the current post has a tag. Must be used inside The Loop.
549 </dd><dt> <tt>has_tag( 'mild' )</tt>&nbsp;</dt><dd> When the current post has the tag 'mild'.
550 </dd><dt> <tt>has_tag( array( 'sharp', 'mild', 'extreme' ) )</tt>&nbsp;</dt><dd> When the current post has any of the tags in the array.
551 </dd></dl>
552 </div>
b83d510 UI cleanup
Rinat Khaziev authored
553
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
554 <table id="acm-codes-list"></table>
555 <div id="acm-codes-pager"></div>
2b607c1 create, read, update, delete logic for ad codes and conditions. Fully…
Rinat Khaziev authored
556
b83d510 UI cleanup
Rinat Khaziev authored
557 <div class="acm-conditionals-wrapper hidden">
558 <table id="acm-codes-conditionals-list"></table>
559 <div id="acm-codes-conditionals-pager"></div>
560 </div>
561 </div>
3f73c30 start of jqGrid implementation / basic ui
Rinat Khaziev authored
562 <?php
563 }
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
564
8d29d6f assets for UI
Rinat Khaziev authored
565 /**
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
566 * Register scripts and styles
8d29d6f assets for UI
Rinat Khaziev authored
567 *
568 */
569 function register_scripts_and_styles() {
41a1171 check against global
Rinat Khaziev authored
570 global $pagenow;
3020fef @danielbachhuber Move Ad Code Manager page under the Tools menu, and only print JS hea…
danielbachhuber authored
571
572 // Only load this on the proper page
573 if ( 'tools.php' != $pagenow || !isset( $_GET['page'] ) || $_GET['page'] != $this->plugin_slug )
574 return;
575
576 wp_enqueue_style( 'acm-jquery-ui-theme', AD_CODE_MANAGER_URL . '/common/css/jquery-ui-1.8.17.custom.css' );
577 wp_enqueue_style( 'acm-jqgrid', AD_CODE_MANAGER_URL . '/common/css/ui.jqgrid.css' );
578 wp_enqueue_script( 'acm-jqgrid-locale-en', AD_CODE_MANAGER_URL . '/common/js/grid.locale-en.js', array( 'jquery', 'jquery-ui-core' ) );
579 wp_enqueue_script( 'acm-jqgrid', AD_CODE_MANAGER_URL . '/common/js/jquery.jqGrid.min.js', array( 'jquery', 'jquery-ui-core' ) );
580 wp_enqueue_script( 'acm', AD_CODE_MANAGER_URL . '/common/js/acm.js', array( 'jquery', 'jquery-ui-core' ) );
8d29d6f assets for UI
Rinat Khaziev authored
581 }
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
582
583 /**
584 * Register an ad tag with the plugin so it can be used
585 * on the frontend of the site
586 *
721b720 @danielbachhuber Moar cleanup
danielbachhuber authored
587 * @since 0.1
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
588 *
589 * @param string $tag Ad tag for this instance of code
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
590 * @param string $url Script URL for ad code
591 * @param array $conditionals WordPress-style conditionals for where this code should be displayed
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
592 * @param int $priority What priority this registration runs at
593 * @param array $url_vars Replace tokens in $script with these values
594 * @return bool|WP_Error $success Whether we were successful in registering the ad tag
595 */
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
596 function register_ad_code( $tag, $url, $conditionals = array(), $url_vars = array() ) {
597
f449381 @danielbachhuber Include a method for validating our script URLs against a whitelist s…
danielbachhuber authored
598 // Run $url aganist a whitelist to make sure it's a safe URL
599 if ( !$this->validate_script_url( $url ) )
600 return;
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
601
602 // @todo Sanitize the conditionals against our possible set of conditionals so that users
f449381 @danielbachhuber Include a method for validating our script URLs against a whitelist s…
danielbachhuber authored
603 // can't just run arbitrary functions. These are whitelisted on execution of the ad code so we're fine for now
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
604
605 // @todo Sanitize all of the other input
606
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
607 // Save the ad code to our set of ad codes
608 $this->ad_codes[$tag][] = array(
609 'url' => $url,
610 'conditionals' => $conditionals,
611 'url_vars' => $url_vars,
612 );
613 }
614
615 /**
616 * Register an array of ad tags with the plugin
617 *
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
618 * @since 0.1
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
619 *
620 * @param array $ad_codes An array of ad tags
621 */
622 function register_ad_codes( $ad_codes = array() ) {
becf72f formatting
Rinat Khaziev authored
623 foreach( (array)$ad_codes as $key => $ad_code ) {
5164301 code cleanup
rinatkhaziev authored
624
becf72f formatting
Rinat Khaziev authored
625 $default = array(
8a1e904 expand default tag_ids for
Rinat Khaziev authored
626 'tag' => '',
627 'url' => '',
628 'conditionals' => array(),
629 'url_vars' => array(),
630 );
becf72f formatting
Rinat Khaziev authored
631 $ad_code = array_merge( $default, $ad_code );
01c371e merge fix
Rinat Khaziev authored
632
ed5abd2 @danielbachhuber Better approach for tokenizing... load all of our url_vars into the a…
danielbachhuber authored
633 foreach ( (array)$this->ad_tag_ids as $default_tag ) {
51b4444 @danielbachhuber Include descriptions for what each filter does at the code level
danielbachhuber authored
634 /**
635 * Configuration filter: acm_default_url
636 * If you don't specify a URL for your ad code when registering it in
637 * the WordPress admin or at a code level, you can simply apply it with
638 * a custom filter defined.
639 */
b17a67c rename filter to acm_default_url
Rinat Khaziev authored
640 $this->register_ad_code( $default_tag['tag'], apply_filters( 'acm_default_url', $ad_code['url'] ), $ad_code['conditionals'], array_merge( $default_tag['url_vars'], $ad_code['url_vars'] ) );
becf72f formatting
Rinat Khaziev authored
641 }
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
642 }
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
643 }
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
644
645 /**
646 * Display the ad code based on what's registered
647 * and complicated sorting logic
648 *
649 * @uses do_action( 'acm_tag, 'your_tag_id' )
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
650 *
651 * @todo implement prioritization. currently, we just pull the first registered ad meeting criteria
652 *
653 * @param string $tag_id Unique ID for the ad tag
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
654 */
655 function action_acm_tag( $tag_id ) {
a35d1e8 skeleton CRUD actions, implemented inline cell editing for jqGrid
rinatkhaziev authored
656
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
657 // If there aren't any ad codes, it's not worth it for us to do anything.
658 if ( !isset( $this->ad_codes[$tag_id] ) )
659 return;
660
661 // Run our ad codes through all of the conditionals to make sure we should
662 // be displaying it
663 $display_codes = array();
664 foreach( (array)$this->ad_codes[$tag_id] as $ad_code ) {
4da2b93 late night fixes
rinatkhaziev authored
665
f65977c do not add ad code with no conditionals in the array of codes to disp…
Rinat Khaziev authored
666 // If the ad code doesn't have any conditionals and logical_operator set to "AND",
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
667 // we should add it to the display list
668 if ( empty( $ad_code['conditionals'] ) ) {
f65977c do not add ad code with no conditionals in the array of codes to disp…
Rinat Khaziev authored
669 if ( $this->logical_operator == 'AND' ) {
670 $display_codes[] = $ad_code;
671 }
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
672 continue;
673 }
ad3064f Revert "debugging"
Rinat Khaziev authored
674
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
675 $include = true;
676 foreach( $ad_code['conditionals'] as $conditional ) {
677 // If the conditional was passed as an array, then we have a complex rule
678 // Otherwise, we have a function name and expect rue
679 if ( is_array( $conditional ) ) {
680 $cond_func = $conditional['function'];
681 if ( !empty( $conditional['arguments'] ) )
682 $cond_args = $conditional['arguments'];
683 else
684 $cond_args = array();
685 if ( isset( $conditional['result'] ) )
686 $cond_result = $conditional['result'];
687 else
688 $cond_result = true;
689 } else {
690 $cond_func = $conditional;
691 $cond_args = array();
692 $cond_result = true;
693 }
694
695 // Special trick: include '!' in front of the function name to reverse the result
696 if ( 0 === strpos( $cond_func, '!' ) ) {
697 $cond_func = ltrim( $cond_func, '!' );
698 $cond_result = false;
699 }
4da2b93 late night fixes
rinatkhaziev authored
700
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
701 // Don't run the conditional if the conditional function doesn't exist or
702 // isn't in our whitelist
703 if ( !function_exists( $cond_func ) || !in_array( $cond_func, $this->whitelisted_conditionals ) )
704 continue;
705
706 // Run our conditional and use any arguments that were passed
51b4444 @danielbachhuber Include descriptions for what each filter does at the code level
danielbachhuber authored
707 if ( !empty( $cond_args ) ) {
708 /**
709 * Configuration filter: acm_conditional_args
710 * For certain conditionals (has_tag, has_category), you might need to
711 * pass additional arguments.
712 */
24e610a fixed conditional edit logic
Rinat Khaziev authored
713 $result = call_user_func_array( $cond_func, apply_filters( 'acm_conditional_args', $cond_args, $cond_func ) );
51b4444 @danielbachhuber Include descriptions for what each filter does at the code level
danielbachhuber authored
714 } else {
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
715 $result = call_user_func( $cond_func );
51b4444 @danielbachhuber Include descriptions for what each filter does at the code level
danielbachhuber authored
716 }
5164301 code cleanup
rinatkhaziev authored
717
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
718 // If our results don't match what we need, don't include this ad code
719 if ( $cond_result !== $result )
720 $include = false;
45e0fbf fixed issue with not being set to true if there's matching conditional
Rinat Khaziev authored
721 else
722 $include = true;
ad3064f Revert "debugging"
Rinat Khaziev authored
723
4da2b93 late night fixes
rinatkhaziev authored
724 //
1d4983e making OR default logical operator, but allow users to filter it
Rinat Khaziev authored
725 // If we have matching conditional and $this->logical_operator equals OR just break from the loop and do not try to evaluate others
726 if ( $include && $this->logical_operator == 'OR' )
db564ce immediately break from foreach conditional loop if we have at least o…
Rinat Khaziev authored
727 break;
4da2b93 late night fixes
rinatkhaziev authored
728
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
729 }
730
731 // If we're supposed to include the ad code even after we've run the conditionals,
732 // let's do it
733 if ( $include )
734 $display_codes[] = $ad_code;
735
736 }
4da2b93 late night fixes
rinatkhaziev authored
737
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
738 // Don't do anything if we've ended up with no ad codes
739 if ( empty( $display_codes ) )
740 return;
4da2b93 late night fixes
rinatkhaziev authored
741
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
742 // @todo possibly complicated logic for determining which
743 // script is executed while factoring in:
799b6ca @danielbachhuber s/ad tag/ad code/
danielbachhuber authored
744 // - priority against other ad codes
0f72d9b ad codes/conditionals edit actions bugfix
Rinat Khaziev authored
745
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
746 $code_to_display = $display_codes[0];
747
f449381 @danielbachhuber Include a method for validating our script URLs against a whitelist s…
danielbachhuber authored
748 // Run $url aganist a whitelist to make sure it's a safe URL
749 if ( !$this->validate_script_url( $code_to_display['url'] ) )
750 return;
751
51b4444 @danielbachhuber Include descriptions for what each filter does at the code level
danielbachhuber authored
752 /**
753 * Configuration filter: acm_output_html
754 * Support multiple ad formats ( e.g. Javascript ad tags, or simple HTML tags )
755 * by adjusting the HTML rendered for a given ad tag.
756 */
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
757 $output_html = apply_filters( 'acm_output_html', $this->output_html, $tag_id );
758
ed5abd2 @danielbachhuber Better approach for tokenizing... load all of our url_vars into the a…
danielbachhuber authored
759 // Parse the output and replace any tokens we have left. But first, load the script URL
760 $output_html = str_replace( '%url%', $code_to_display['url'], $output_html );
51b4444 @danielbachhuber Include descriptions for what each filter does at the code level
danielbachhuber authored
761 /**
762 * Configuration filter: acm_output_tokens
763 * Register output tokens depending on the needs of your setup. Tokens are the
764 * keys to be replaced in your script URL.
765 */
ed5abd2 @danielbachhuber Better approach for tokenizing... load all of our url_vars into the a…
danielbachhuber authored
766 $output_tokens = apply_filters( 'acm_output_tokens', $this->output_tokens, $tag_id, $code_to_display );
767 foreach( (array)$output_tokens as $token => $val ) {
768 $output_html = str_replace( $token, $val, $output_html );
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
769 }
01c371e merge fix
Rinat Khaziev authored
770
3c58222 @danielbachhuber Basic logic for registering a new ad code with a tag, and then presen…
danielbachhuber authored
771 // Print the ad code
772 echo $output_html;
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
773 }
774
ed5abd2 @danielbachhuber Better approach for tokenizing... load all of our url_vars into the a…
danielbachhuber authored
775 /**
776 * Filter the output tokens used in $this->action_acm_tag to include our URL vars
777 *
678c6a9 @danielbachhuber General cleanup on comments and formatting
danielbachhuber authored
778 * @since 0.1
ed5abd2 @danielbachhuber Better approach for tokenizing... load all of our url_vars into the a…
danielbachhuber authored
779 *
780 * @return array $output Placeholder tokens to be replaced with their values
781 */
782 function filter_output_tokens( $output_tokens, $tag_id, $code_to_display ) {
783 if ( !isset( $code_to_display['url_vars'] ) || !is_array( $code_to_display['url_vars'] ) )
784 return $output_tokens;
785
786 foreach( $code_to_display['url_vars'] as $url_var => $val ) {
787 $new_key = '%' . $url_var . '%';
788 $output_tokens[$new_key] = $val;
789 }
5164301 code cleanup
rinatkhaziev authored
790
ed5abd2 @danielbachhuber Better approach for tokenizing... load all of our url_vars into the a…
danielbachhuber authored
791 return $output_tokens;
792 }
793
f449381 @danielbachhuber Include a method for validating our script URLs against a whitelist s…
danielbachhuber authored
794 /**
795 * Ensure the URL being used passes our whitelist check
796 *
797 * @since 0.1
798 * @see https://gist.github.com/1623788
799 */
800 function validate_script_url( $url ) {
801 $domain = parse_url( $url, PHP_URL_HOST );
802
803 // Check if we match the domain exactly
804 if ( in_array( $domain, $this->whitelisted_script_urls ) )
805 return true;
806
807 $valid = false;
808
809 foreach( $this->whitelisted_script_urls as $whitelisted_domain ) {
810 $whitelisted_domain = '.' . $whitelisted_domain; // Prevent things like 'evilsitetime.com'
811 if( strpos( $domain, $whitelisted_domain ) === ( strlen( $domain ) - strlen( $whitelisted_domain ) ) ) {
812 $valid = true;
813 break;
814 }
815 }
816 return $valid;
817 }
818
7e0674e @danielbachhuber Initial commit: skeleton of the plugin
danielbachhuber authored
819 }
820 global $ad_code_manager;
821 $ad_code_manager = new Ad_Code_Manager();
Something went wrong with that request. Please try again.