PluginProbe
Timed Content / 2.75
Timed Content v2.75
2.99 trunk 1.0 1.1 1.2 2.0 2.1 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.10 2.11 2.12 2.15 2.2 2.3 2.3.1 2.4 2.5 2.5.1 2.50 2.51 2.52 All 67 releases
← All changes | lib/class-customfieldsinterface.php +618 -616 trunk2.75 View file →
@@ -1,616 +1,618 @@
1 -<?php
2 -
3 -class CustomFieldsInterface {
4 - /**
5 - * @var string $handle The handle for the box containing the custom fields
6 - */
7 - var $handle = '';
8 - /**
9 - * @var string $label The label for the box containing the custom fields
10 - */
11 - var $label = '';
12 - /**
13 - * @var string $desc The description/introduction for the box containing the custom fields
14 - */
15 - var $desc = '';
16 - /**
17 - * @var string $prefix The prefix for storing custom fields in the postmeta table
18 - */
19 - var $prefix = '';
20 - /**
21 - * @var array $post_types An array of public custom post types, plus the standard "post" and "page" - add the custom types you want to include here
22 - */
23 - var $post_types = array();
24 - /**
25 - * @var array $custom_fields Defines the custom fields available
26 - */
27 - var $custom_fields = array();
28 - /**
29 - * @var array $jquery_ui_datetime_datepicker_i18n Array for jQuery datepicker UI localization
30 - */
31 - var $jquery_ui_datetime_datepicker_i18n;
32 - /**
33 - * @var array $jquery_ui_datetime_timepicker_i18n Array for jQuery timepicker UI localization
34 - */
35 - var $jquery_ui_datetime_timepicker_i18n;
36 -
37 - /**
38 - * @var string $rule_description_as_html Description of the rule as HTML
39 - */
40 - var $rule_description_as_html;
41 -
42 - /**
43 - * Constructor
44 - */
45 - function __construct( $handle, $label, $desc, $prefix, $post_types, $custom_fields, $jquery_ui_datetime_datepicker_i18n, $jquery_ui_datetime_timepicker_i18n, $rule_description_as_html = '' ) {
46 - $this->handle = $handle;
47 - $this->label = $label;
48 - $this->desc = $desc;
49 - $this->prefix = $prefix;
50 - $this->post_types = $post_types;
51 - $this->custom_fields = $custom_fields;
52 - $this->jquery_ui_datetime_datepicker_i18n = $jquery_ui_datetime_datepicker_i18n;
53 - $this->jquery_ui_datetime_timepicker_i18n = $jquery_ui_datetime_timepicker_i18n;
54 - $this->rule_description_as_html = $rule_description_as_html;
55 -
56 - add_action( 'admin_menu', array( &$this, 'create_custom_fields' ) );
57 - add_action( 'save_post', array( &$this, 'save_custom_fields' ), 1, 2 );
58 - // Comment this line out if you want to keep default custom fields meta box
59 - add_action( 'do_meta_boxes', array( &$this, 'remove_default_custom_fields' ), 10, 3 );
60 - }
61 -
62 - // Inspired by http://ca1.php.net/manual/en/function.timezone-identifiers-list.php#79284
63 - static function generate_timezone_select_options( $default_tz ) {
64 - $timezone_identifiers = timezone_identifiers_list();
65 - sort( $timezone_identifiers );
66 - $current_continent = '';
67 - $options_list = '';
68 -
69 - foreach ( $timezone_identifiers as $timezone_identifier ) {
70 - list( $continent, ) = explode( '/', $timezone_identifier, 2 );
71 - if ( in_array(
72 - $continent,
73 - array(
74 - 'Africa',
75 - 'America',
76 - 'Antarctica',
77 - 'Arctic',
78 - 'Asia',
79 - 'Atlantic',
80 - 'Australia',
81 - 'Europe',
82 - 'Indian',
83 - 'Pacific',
84 - ),
85 - true
86 - ) ) {
87 - list(, $city) = explode( '/', $timezone_identifier, 2 );
88 - if ( strlen( $current_continent ) === 0 ) {
89 - // Start first continent optgroup
90 - $options_list .= '<optgroup label=\'' . $continent . '\'>';
91 - } elseif ( $current_continent !== $continent ) {
92 - // End old optgroup and start new continent optgroup
93 - $options_list .= '</optgroup><optgroup label=\'' . $continent . '\'>';
94 - }
95 - // Timezone
96 - $options_list .= '<option' .
97 - ( ( $timezone_identifier === $default_tz ) ? ' selected=\'selected\'' : '' ) .
98 - ' value=\'' . $timezone_identifier . '\'>' .
99 - str_replace( '_', ' ', $city ) . '</option>';
100 - }
101 - $current_continent = $continent;
102 - }
103 - $options_list .= '</optgroup>'; // End last continent optgroup
104 -
105 - return $options_list;
106 - }
107 -
108 - /**
109 - * Remove the default Custom Fields meta box
110 - */
111 - function remove_default_custom_fields( $type, $context, $post ) {
112 - foreach ( array( 'normal', 'advanced', 'side' ) as $context ) {
113 - foreach ( $this->post_types as $post_type ) {
114 - remove_meta_box( 'postcustom', $post_type, $context );
115 - }
116 - }
117 - }
118 -
119 - /**
120 - * Create the new Custom Fields meta box
121 - */
122 - function create_custom_fields() {
123 - // Only enqueue scripts if we're dealing with 'timed-content-rule' pages
124 - foreach ( $this->post_types as $a_post_type ) {
125 - if ( ( isset( $_GET['post_type'] ) && $_GET['post_type'] === $a_post_type )
126 - || ( isset( $post_type ) && $post_type === $a_post_type )
127 - || ( isset( $_GET['post'] ) && get_post_type( $_GET['post'] ) === $a_post_type ) ) {
128 -
129 - wp_enqueue_style( 'wp-color-picker' );
130 - wp_enqueue_script( 'wp-color-picker' );
131 - wp_enqueue_script( 'jquery-ui-spinner' );
132 -
133 - wp_enqueue_style( TIMED_CONTENT_SLUG . '-jquery-ui-css', TIMED_CONTENT_JQUERY_UI_CSS );
134 - wp_enqueue_script( 'jquery-ui-datepicker' );
135 - wp_register_style(
136 - TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-css',
137 - TIMED_CONTENT_JQUERY_UI_TIMEPICKER_CSS
138 - );
139 - wp_enqueue_style( TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-css' );
140 - wp_register_script(
141 - TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-js',
142 - TIMED_CONTENT_JQUERY_UI_TIMEPICKER_JS,
143 - array( 'jquery', 'jquery-ui-datepicker' ),
144 - TIMED_CONTENT_VERSION
145 - );
146 - wp_enqueue_script( TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-js' );
147 - if ( ! ( wp_script_is( TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js', 'registered' ) ) ) {
148 - wp_register_script(
149 - TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js',
150 - TIMED_CONTENT_PLUGIN_URL . '/js/timed-content-datetime-i18n.js',
151 - array( 'jquery', 'jquery-ui-datepicker', TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-js' ),
152 - TIMED_CONTENT_VERSION
153 - );
154 - wp_enqueue_script( TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js' );
155 - wp_localize_script(
156 - TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js',
157 - 'TimedContentJQDatepickerI18n',
158 - $this->jquery_ui_datetime_datepicker_i18n
159 - );
160 - wp_localize_script(
161 - TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js',
162 - 'TimedContentJQTimepickerI18n',
163 - $this->jquery_ui_datetime_timepicker_i18n
164 - );
165 - }
166 -
167 - if ( function_exists( 'add_meta_box' ) ) {
168 - add_meta_box(
169 - $this->handle,
170 - $this->label,
171 - array( &$this, 'display_custom_fields' ),
172 - $a_post_type,
173 - 'normal',
174 - 'high'
175 - );
176 - }
177 - }
178 - }
179 - }
180 -
181 - /**
182 - * Display the new Custom Fields meta box
183 - */
184 - function display_custom_fields() {
185 - global $post;
186 -
187 - if ( '' !== $this->rule_description_as_html ) {
188 - // If there is a rule description, then use this as we are not allowed to use generated
189 - // HTML code as variable without escaping or sanitizing but we need the button element
190 -
191 - echo '<div id="schedule_desc" style="font-style: italic; overflow-y: auto;">';
192 - echo wp_kses_post( $this->rule_description_as_html );
193 - echo '</div>';
194 - echo '<div id="tcr-dialogHolder" style="display:none;"></div>';
195 - echo '<div style="padding-top: 10px;">';
196 - echo '<input type="button" class="button button-primary" id="timed_content_rule_test" value="' .
197 - __( 'Show projected dates/times', 'timed-content' ) .
198 - '" />';
199 - echo '</div>';
200 - } else {
201 - // Otherwise output the description as text
202 -
203 - echo '<p>' . esc_html( $this->desc ) . '</p>';
204 - }
205 - echo '<div class="form-wrap">';
206 - wp_nonce_field( $this->handle, $this->handle . '_wpnonce', false, true );
207 - foreach ( $this->custom_fields as $custom_field ) {
208 - // Check scope
209 - $scope = $custom_field['scope'];
210 - $output = false;
211 - foreach ( $scope as $scope_item ) {
212 - switch ( $scope_item ) {
213 - default:
214 - if ( $post->post_type === $scope_item ) {
215 - $output = true;
216 - }
217 - break;
218 - }
219 - if ( $output ) {
220 - break;
221 - }
222 - }
223 - // Check capability
224 - if ( ! current_user_can( $custom_field['capability'], $post->ID ) ) {
225 - $output = false;
226 - }
227 - // Output if allowed
228 - if ( $output ) {
229 - $field_name = $this->prefix . $custom_field['name'];
230 - $field_title = $custom_field['title'];
231 - echo '<div class="form-field form-required"';
232 - echo ' id="' . esc_attr( $field_name ) . '_div"';
233 - echo ' style="display: ' . esc_attr( $custom_field['display'] ) . '">';
234 - switch ( $custom_field['type'] ) {
235 - case 'radio':
236 - $checked_value = get_post_meta(
237 - $post->ID,
238 - $field_name,
239 - true
240 - );
241 - if ( '' === $checked_value || false === $checked_value ) {
242 - $checked_value = $custom_field['default'];
243 - }
244 - echo '<strong>' . esc_html( $field_title ) . '</strong><br />';
245 - foreach ( $custom_field['values'] as $value => $label ) {
246 - echo '<input type="radio" name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '_' . esc_attr( $value ) . '" value="' . esc_attr( $value ) . '"';
247 - if ( $checked_value === $value || intval( $checked_value ) === $value ) {
248 - echo ' checked="checked"';
249 - }
250 - echo ' /><label for="' . esc_attr( $field_name ) . '_' . esc_attr( $value ) . '" style="display: inline;">' . esc_html( $label ) . '</label><br />';
251 - }
252 - break;
253 - case 'menu':
254 - echo '<label for="' . esc_attr( $field_name ) . '" style="display:inline;"><strong>' . esc_html( $field_title ) . '</strong></label><br />';
255 - if ( sizeof( $custom_field['values'] ) === 0 ) {
256 - echo '<em>' . __( 'This menu is empty.', 'timed-content' ) . '</em>';
257 - } else {
258 - $selected_value = ( '' === get_post_meta(
259 - $post->ID,
260 - $field_name,
261 - true
262 - ) ? $custom_field['default'] : get_post_meta(
263 - $post->ID,
264 - $field_name,
265 - true
266 - ) );
267 - echo '<select name="' . esc_attr( $field_name ) . '[]" id="' . esc_attr( $field_name ) . '" style="width: auto; height: auto; padding: 3px;" size="' . esc_attr( $custom_field['size'] ) . '" multiple="multiple">';
268 - foreach ( $custom_field['values'] as $value => $label ) {
269 - echo '<option value="' . esc_attr( $value ) . '"';
270 - if ( $selected_value === $value || intval( $selected_value ) === $value ) {
271 - echo ' selected="selected"';
272 - }
273 - echo '>' . esc_html( $label ) . '</option>';
274 - }
275 - echo '</select>';
276 - }
277 - break;
278 - case 'list':
279 - // list
280 - echo '<label for="' . esc_attr( $field_name ) . '" style="display:inline;"><strong>' . esc_html( $field_title ) . '</strong></label><br />';
281 - if ( sizeof( $custom_field['values'] ) === 0 ) {
282 - echo '<em>' . __( 'This menu is empty.', 'timed-content' ) . '</em>';
283 - } else {
284 - $selected_value = ( '' === get_post_meta(
285 - $post->ID,
286 - $field_name,
287 - true
288 - ) ? $custom_field['default'] : get_post_meta(
289 - $post->ID,
290 - $field_name,
291 - true
292 - ) );
293 - echo '<select name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" style="width: auto;">';
294 - foreach ( $custom_field['values'] as $value => $label ) {
295 - echo '<option value="' . esc_attr( $value ) . '"';
296 - if ( $selected_value === $value || intval( $selected_value ) === $value ) {
297 - echo ' selected="selected"';
298 - }
299 - echo '>' . esc_html( $label ) . '</option>';
300 - }
301 - echo '</select>';
302 - }
303 - break;
304 - case 'timezone-list':
305 - // timezone list
306 - $selected_value = get_post_meta(
307 - $post->ID,
308 - $field_name,
309 - true
310 - );
311 - if (empty($selected_value)) {
312 - $selected_value = wp_timezone_string();
313 - }
314 - echo '<label for="' . esc_attr( $field_name ) . '" style="display:inline;"><strong>' . esc_html( $field_title ) . '</strong></label><br />';
315 - echo '<select name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" style="width: auto;">';
316 - echo CustomFieldsInterface::generate_timezone_select_options( $selected_value );
317 - echo '</select>';
318 - break;
319 - case 'checkbox':
320 - // Checkbox
321 - $checked_value = ( '' === get_post_meta(
322 - $post->ID,
323 - $field_name,
324 - true
325 - ) ? $custom_field['default'] : get_post_meta(
326 - $post->ID,
327 - $field_name,
328 - true
329 - ) );
330 -
331 - echo '<label for="' . esc_attr( $field_name ) . '" style="display:inline;"><strong>' . esc_html( $field_title ) . '</strong><br />';
332 - echo '<input type="checkbox" name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" value="yes"';
333 - if ( 'yes' === $checked_value ) {
334 - echo ' checked="checked"';
335 - }
336 - echo ' />' . __( 'Yes', 'timed-content' ) . '</label>';
337 - break;
338 - case 'checkbox-list':
339 - // Checkbox list
340 - $checked_value = ( '' === get_post_meta(
341 - $post->ID,
342 - $field_name,
343 - true
344 - ) ? $custom_field['default'] : get_post_meta(
345 - $post->ID,
346 - $field_name,
347 - true
348 - ) );
349 -
350 - echo '<strong>' . esc_html( $field_title ) . '</strong><br />';
351 - if ( sizeof( $custom_field['values'] ) === 0 ) {
352 - echo '<em>' . __( 'This menu is empty.', 'timed-content' ) . '</em>';
353 - } else {
354 - foreach ( $custom_field['values'] as $value => $label ) {
355 - echo '<input type="checkbox" name="' . esc_attr( $field_name ) . '[]" id="' . esc_attr( $field_name ) . '_' . esc_attr( $value ) . '" value="' . esc_attr( $value ) . '"';
356 - if ( ( is_array( $checked_value ) ) && ( in_array(
357 - (string) $value,
358 - $checked_value,
359 - true
360 - ) ) ) {
361 - echo ' checked="checked"';
362 - }
363 - echo ' /><label for="' . esc_attr( $field_name ) . '_' . esc_attr( $value ) . '" style="display: inline;" >' . esc_html( $label ) . '</label><br />';
364 - }
365 - }
366 - break;
367 - case 'textarea':
368 - case 'wysiwyg':
369 - // Text area
370 - $value = ( '' === get_post_meta(
371 - $post->ID,
372 - $field_name,
373 - true
374 - ) ? $custom_field['default'] : get_post_meta(
375 - $post->ID,
376 - $field_name,
377 - true
378 - ) );
379 - echo '<label for="' . esc_attr( $field_name ) . '"><strong>' . esc_html( $field_title ) . '</strong></label><br />';
380 - echo '<textarea name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" columns="30" rows="3">' . esc_html( $value ) . '</textarea>';
381 - // WYSIWYG
382 - if ( 'wysiwyg' === $custom_field['type'] ) {
383 - echo '<script type="text/javascript">' . PHP_EOL;
384 - echo '//<![CDATA[' . PHP_EOL;
385 - echo 'jQuery(document).ready(function () {' . PHP_EOL;
386 - echo ' jQuery("' . esc_js( $field_name ) . '").addClass("mceEditor");' . PHP_EOL;
387 - echo ' if (typeof (tinyMCE) == "object" && typeof (tinyMCE.execCommand) == "function") {' . PHP_EOL;
388 - echo ' tinyMCE.execCommand("mceAddControl", false, "' . esc_js( $field_name ) . '");' . PHP_EOL;
389 - echo ' }' . PHP_EOL;
390 - echo '});' . PHP_EOL;
391 - echo '//]]>' . PHP_EOL;
392 - echo '</script>' . PHP_EOL;
393 - }
394 - break;
395 - case 'color-picker':
396 - $value = ( '' === get_post_meta(
397 - $post->ID,
398 - $field_name,
399 - true
400 - ) ? $custom_field['default'] : get_post_meta(
401 - $post->ID,
402 - $field_name,
403 - true
404 - ) );
405 - // Color picker using WP's built-in Iris jQuery plugin
406 - echo '<script type="text/javascript">' . PHP_EOL;
407 - echo '//<![CDATA[' . PHP_EOL;
408 - echo 'jQuery(document).ready(function () {' . PHP_EOL;
409 - echo ' var ' . esc_js( $field_name ) . 'Options = {' . PHP_EOL;
410 - echo ' defaultColor: false,' . PHP_EOL;
411 - echo ' hide: true,' . PHP_EOL;
412 - echo ' palettes: true' . PHP_EOL;
413 - echo ' };' . PHP_EOL;
414 - echo ' jQuery("#' . esc_js( $field_name ) . '").wpColorPicker(' . esc_js( $field_name ) . 'Options);' . PHP_EOL;
415 - echo '});' . PHP_EOL;
416 - echo '//]]>' . PHP_EOL;
417 - echo '</script>' . PHP_EOL;
418 - echo '<label for="' . esc_attr( $field_name ) . '"><strong>' . esc_html( $field_title ) . '</strong></label><br />';
419 - echo '<input type="text" name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" value="' . esc_attr( $value ) . '" size="7" maxlength="7" style="width: 100px;" />';
420 - break;
421 - case 'date':
422 - echo '<label for="' . esc_attr( $field_name ) . '" style="display:inline;"><strong>' . esc_html( $field_title ) . '</strong></label><br />';
423 - $value = ( '' === get_post_meta(
424 - $post->ID,
425 - $field_name,
426 - true
427 - ) ? $custom_field['default'] : get_post_meta(
428 - $post->ID,
429 - $field_name,
430 - true
431 - ) );
432 - // Date picker using WP's built-in Datepicker jQuery plugin
433 - echo '<script type="text/javascript">' . PHP_EOL;
434 - echo '//<![CDATA[' . PHP_EOL;
435 - echo 'jQuery(document).ready(function () {' . PHP_EOL;
436 - echo ' jQuery("#' . esc_js( $field_name ) . '").datepicker(' . PHP_EOL;
437 - echo ' {' . PHP_EOL;
438 - echo ' onSelect: function (dateText, inst) {' . PHP_EOL;
439 - echo ' jQuery("#timed_content_rule_exceptions_dates option[value=\'0\']").remove();' . PHP_EOL;
440 - echo ' jQuery("#timed_content_rule_exceptions_dates").append(\'<option value="\' + dateText + \'">\' + dateText + \'</option>\');' . PHP_EOL;
441 - echo ' jQuery(this).val("");' . PHP_EOL;
442 - echo ' jQuery(this).trigger("change");' . PHP_EOL;
443 - echo ' },' . PHP_EOL;
444 - echo ' changeMonth: true,' . PHP_EOL;
445 - echo ' changeYear: true' . PHP_EOL;
446 - echo ' }' . PHP_EOL;
447 - echo ' );' . PHP_EOL;
448 - echo '});' . PHP_EOL;
449 - echo '//]]>' . PHP_EOL;
450 - echo '</script>' . PHP_EOL;
451 - echo '<input type="text" name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" value="' . esc_attr( $value ) . '" style="width: 175px;" />';
452 - break;
453 - case 'datetime':
454 - echo '<span style="display:inline;"><strong>' . esc_html( $field_title ) . '</strong></span><br />';
455 - $value = ( '' === get_post_meta(
456 - $post->ID,
457 - $field_name,
458 - true
459 - ) ? $custom_field['default'] : get_post_meta(
460 - $post->ID,
461 - $field_name,
462 - true
463 - ) );
464 - foreach ( $value as $k => $v ) {
465 - $value[ $k ] = esc_html( $v );
466 - }
467 - // Date picker using WP's built-in Datepicker jQuery plugin
468 - // Time picker using jQuery UI Timepicker: http://fgelinas.com/code/timepicker
469 - echo '<script type="text/javascript">' . PHP_EOL;
470 - echo '//<![CDATA[' . PHP_EOL;
471 - echo 'jQuery(document).ready(function () {' . PHP_EOL;
472 - echo ' jQuery("#' . esc_js( $field_name ) . '_date").datepicker({' . PHP_EOL;
473 - echo ' changeMonth: true,' . PHP_EOL;
474 - echo ' changeYear: true' . PHP_EOL;
475 - echo ' });' . PHP_EOL;
476 - echo ' jQuery("#' . esc_js( $field_name ) . '_time").timepicker({' . PHP_EOL;
477 - echo ' defaultTime: \'now\'' . PHP_EOL;
478 - echo ' });' . PHP_EOL;
479 - echo '});' . PHP_EOL;
480 - echo '//]]>' . PHP_EOL;
481 - echo '</script>' . PHP_EOL;
482 - echo '<label for="' . esc_attr( $field_name ) . '_date" style="display:inline;"><em>' . _x(
483 - 'Date',
484 - 'Date field label',
485 - 'timed-content'
486 - ) . ':</em></label>';
487 - echo '<input type="text" name="' . esc_attr( $field_name ) . '[date]" id="' . esc_attr( $field_name ) . '_date" value="' . esc_attr( $value['date'] ) . '" style="width: 175px;" />';
488 - echo '<label for="' . esc_attr( $field_name ) . '_time" style="display:inline;"><em>' . _x(
489 - 'Time',
490 - 'Time field label',
491 - 'timed-content'
492 - ) . ":</em></label>\n";
493 - echo '<input type="text" name="' . esc_attr( $field_name ) . '[time]" id="' . esc_attr( $field_name ) . '_time" value="' . esc_attr( $value['time'] ) . '" style="width: 125px;" />';
494 - break;
495 - case 'number':
496 - $value = get_post_meta(
497 - $post->ID,
498 - $field_name,
499 - true
500 - );
501 - if ( '' === $value ) {
502 - $value = $custom_field['default'];
503 - } else {
504 - $value = intval( $value );
505 - }
506 - // Number picker using WP's built-in Spinner jQuery plugin
507 - echo '<script type="text/javascript">' . PHP_EOL;
508 - echo '//<![CDATA[' . PHP_EOL;
509 - echo 'jQuery(document).ready(function () {' . PHP_EOL;
510 - echo ' jQuery("#' . esc_js( $field_name ) . '").spinner({' . PHP_EOL;
511 - echo ' stop: function (event, ui) {' . PHP_EOL;
512 - echo ' jQuery(this).trigger("change");' . PHP_EOL;
513 - echo ' },' . PHP_EOL;
514 - if ( isset( $custom_field['min'] ) ) {
515 - echo ' min: ' . esc_js( $custom_field['min'] ) . ', ';
516 - }
517 - if ( isset( $custom_field['max'] ) ) {
518 - echo ' max: ' . esc_js( $custom_field['max'] ) . ', ';
519 - }
520 - echo ' });' . PHP_EOL;
521 - echo '});' . PHP_EOL;
522 - echo '//]]>' . PHP_EOL;
523 - echo '</script>' . PHP_EOL;
524 - echo '<label for="' . esc_attr( $field_name ) . '" style="display:inline;"><strong>' . esc_html( $field_title ) . '</strong></label><br />';
525 - echo '<input type="text" name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" value="' . esc_attr( $value ) . '" size="2" />';
526 - break;
527 - case 'hidden':
528 - $value = ( '' === get_post_meta(
529 - $post->ID,
530 - $field_name,
531 - true
532 - ) ? $custom_field['default'] : get_post_meta(
533 - $post->ID,
534 - $field_name,
535 - true
536 - ) );
537 - // Hidden field
538 - echo '<input type="hidden" name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" value="' . esc_attr( $value ) . ' />';
539 - break;
540 - default:
541 - $value = ( '' === get_post_meta(
542 - $post->ID,
543 - $field_name,
544 - true
545 - ) ? $custom_field['default'] : get_post_meta(
546 - $post->ID,
547 - $field_name,
548 - true
549 - ) );
550 - // Plain text field
551 - echo '<label for="' . esc_attr( $field_name ) . '"><strong>' . esc_html( $field_title ) . '</strong></label><br/>';
552 - echo '<input type="text" name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" value="' . esc_attr( $value ) . ' />';
553 - break;
554 - }
555 - if ( isset( $custom_field['description'] ) ) {
556 - echo '<p>' . esc_html( $custom_field['description'] ) . '</p>';
557 - }
558 - echo '</div>';
559 - }
560 - }
561 - echo '</div>';
562 - }
563 -
564 - /**
565 - * Save the new Custom Fields values
566 - */
567 - function save_custom_fields( $post_id, $post ) {
568 - // Only save if the user intends to save
569 - if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
570 - return;
571 - }
572 - // Make sure the Save request is coming from the right place
573 - if ( ! isset( $_POST[ $this->handle . '_wpnonce' ] ) || ! wp_verify_nonce(
574 - $_POST[ $this->handle . '_wpnonce' ],
575 - $this->handle
576 - ) ) {
577 - return;
578 - }
579 - // Make sure the user can edit this specific post
580 - if ( ! current_user_can( 'edit_post', $post_id ) ) {
581 - return;
582 - }
583 - // Make sure this meta box is associated with the right post types
584 - if ( ! in_array( $post->post_type, $this->post_types, true ) ) {
585 - return;
586 - }
587 - foreach ( $this->custom_fields as $custom_field ) {
588 - if ( current_user_can( $custom_field['capability'], $post_id ) ) {
589 - $field_name = $this->prefix . $custom_field['name'];
590 - if ( isset( $_POST[ $field_name ] ) ) {
591 - if ( is_array( $_POST[ $field_name ] ) ) {
592 - foreach ( $_POST[ $field_name ] as $k => $v ) {
593 - $_POST[ $field_name ][ $k ] = trim( sanitize_text_field( $v ) );
594 - }
595 - } else {
596 - $_POST[ $field_name ] = trim( sanitize_text_field( $_POST[ $field_name ] ) );
597 - }
598 - $value = $_POST[ $field_name ];
599 - // Auto-paragraphs for any WYSIWYG
600 - if ( 'wysiwyg' === $custom_field['type'] ) {
601 - $value = wpautop( $value );
602 - }
603 - if ( 'checkbox' === $custom_field['type'] ) {
604 - $value = 'yes';
605 - }
606 - if ( 'number' === $custom_field['type'] ) {
607 - $value = intval( $value );
608 - }
609 - update_post_meta( $post_id, $field_name, $value );
610 - } else {
611 - delete_post_meta( $post_id, $field_name );
612 - }
613 - }
614 - }
615 - }
616 -}
1 +<?php
2 +
3 +class CustomFieldsInterface {
4 + /**
5 + * @var string $handle The handle for the box containing the custom fields
6 + */
7 + var $handle = '';
8 + /**
9 + * @var string $label The label for the box containing the custom fields
10 + */
11 + var $label = '';
12 + /**
13 + * @var string $desc The description/introduction for the box containing the custom fields
14 + */
15 + var $desc = '';
16 + /**
17 + * @var string $prefix The prefix for storing custom fields in the postmeta table
18 + */
19 + var $prefix = '';
20 + /**
21 + * @var array $post_types An array of public custom post types, plus the standard "post" and "page" - add the custom types you want to include here
22 + */
23 + var $post_types = array();
24 + /**
25 + * @var array $custom_fields Defines the custom fields available
26 + */
27 + var $custom_fields = array();
28 + /**
29 + * @var array $jquery_ui_datetime_datepicker_i18n Array for jQuery datepicker UI localization
30 + */
31 + var $jquery_ui_datetime_datepicker_i18n;
32 + /**
33 + * @var array $jquery_ui_datetime_timepicker_i18n Array for jQuery timepicker UI localization
34 + */
35 + var $jquery_ui_datetime_timepicker_i18n;
36 +
37 + /**
38 + * @var string $rule_description_as_html Description of the rule as HTML
39 + */
40 + var $rule_description_as_html;
41 +
42 + /**
43 + * Constructor
44 + */
45 + function __construct( $handle, $label, $desc, $prefix, $post_types, $custom_fields, $jquery_ui_datetime_datepicker_i18n, $jquery_ui_datetime_timepicker_i18n, $rule_description_as_html = '' ) {
46 + $this->handle = $handle;
47 + $this->label = $label;
48 + $this->desc = $desc;
49 + $this->prefix = $prefix;
50 + $this->post_types = $post_types;
51 + $this->custom_fields = $custom_fields;
52 + $this->jquery_ui_datetime_datepicker_i18n = $jquery_ui_datetime_datepicker_i18n;
53 + $this->jquery_ui_datetime_timepicker_i18n = $jquery_ui_datetime_timepicker_i18n;
54 + $this->rule_description_as_html = $rule_description_as_html;
55 +
56 + add_action( 'admin_menu', array( &$this, 'create_custom_fields' ) );
57 + add_action( 'save_post', array( &$this, 'save_custom_fields' ), 1, 2 );
58 + // Comment this line out if you want to keep default custom fields meta box
59 + add_action( 'do_meta_boxes', array( &$this, 'remove_default_custom_fields' ), 10, 3 );
60 + }
61 +
62 + // Inspired by http://ca1.php.net/manual/en/function.timezone-identifiers-list.php#79284
63 + static function generate_timezone_select_options( $default_tz ) {
64 + $timezone_identifiers = timezone_identifiers_list();
65 + sort( $timezone_identifiers );
66 + $current_continent = '';
67 + $options_list = '';
68 +
69 + foreach ( $timezone_identifiers as $timezone_identifier ) {
70 + list( $continent, ) = explode( '/', $timezone_identifier, 2 );
71 + if ( in_array(
72 + $continent,
73 + array(
74 + 'Africa',
75 + 'America',
76 + 'Antarctica',
77 + 'Arctic',
78 + 'Asia',
79 + 'Atlantic',
80 + 'Australia',
81 + 'Europe',
82 + 'Indian',
83 + 'Pacific',
84 + ),
85 + true
86 + ) ) {
87 + list(, $city) = explode( '/', $timezone_identifier, 2 );
88 + if ( strlen( $current_continent ) === 0 ) {
89 + // Start first continent optgroup
90 + $options_list .= '<optgroup label=\'' . $continent . '\'>';
91 + } elseif ( $current_continent !== $continent ) {
92 + // End old optgroup and start new continent optgroup
93 + $options_list .= '</optgroup><optgroup label=\'' . $continent . '\'>';
94 + }
95 + // Timezone
96 + $options_list .= '<option' .
97 + ( ( $timezone_identifier === $default_tz ) ? ' selected=\'selected\'' : '' ) .
98 + ' value=\'' . $timezone_identifier . '\'>' .
99 + str_replace( '_', ' ', $city ) . '</option>';
100 + }
101 + $current_continent = $continent;
102 + }
103 + $options_list .= '</optgroup>'; // End last continent optgroup
104 +
105 + return $options_list;
106 + }
107 +
108 + /**
109 + * Remove the default Custom Fields meta box
110 + */
111 + function remove_default_custom_fields( $type, $context, $post ) {
112 + foreach ( array( 'normal', 'advanced', 'side' ) as $context ) {
113 + foreach ( $this->post_types as $post_type ) {
114 + remove_meta_box( 'postcustom', $post_type, $context );
115 + }
116 + }
117 + }
118 +
119 + /**
120 + * Create the new Custom Fields meta box
121 + */
122 + function create_custom_fields() {
123 + // Only enqueue scripts if we're dealing with 'timed-content-rule' pages
124 + foreach ( $this->post_types as $a_post_type ) {
125 + if ( ( isset( $_GET['post_type'] ) && $_GET['post_type'] === $a_post_type )
126 + || ( isset( $post_type ) && $post_type === $a_post_type )
127 + || ( isset( $_GET['post'] ) && get_post_type( $_GET['post'] ) === $a_post_type ) ) {
128 +
129 + wp_enqueue_style( 'wp-color-picker' );
130 + wp_enqueue_script( 'wp-color-picker' );
131 + wp_enqueue_script( 'jquery-ui-spinner' );
132 +
133 + wp_enqueue_style( TIMED_CONTENT_SLUG . '-jquery-ui-css', TIMED_CONTENT_JQUERY_UI_CSS );
134 + wp_enqueue_script( 'jquery-ui-datepicker' );
135 + wp_register_style(
136 + TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-css',
137 + TIMED_CONTENT_JQUERY_UI_TIMEPICKER_CSS
138 + );
139 + wp_enqueue_style( TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-css' );
140 + wp_register_script(
141 + TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-js',
142 + TIMED_CONTENT_JQUERY_UI_TIMEPICKER_JS,
143 + array( 'jquery', 'jquery-ui-datepicker' ),
144 + TIMED_CONTENT_VERSION
145 + );
146 + wp_enqueue_script( TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-js' );
147 + if ( ! ( wp_script_is( TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js', 'registered' ) ) ) {
148 + wp_register_script(
149 + TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js',
150 + TIMED_CONTENT_PLUGIN_URL . '/js/timed-content-datetime-i18n.js',
151 + array( 'jquery', 'jquery-ui-datepicker', TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-js' ),
152 + TIMED_CONTENT_VERSION
153 + );
154 + wp_enqueue_script( TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js' );
155 + wp_localize_script(
156 + TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js',
157 + 'TimedContentJQDatepickerI18n',
158 + $this->jquery_ui_datetime_datepicker_i18n
159 + );
160 + wp_localize_script(
161 + TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js',
162 + 'TimedContentJQTimepickerI18n',
163 + $this->jquery_ui_datetime_timepicker_i18n
164 + );
165 + }
166 +
167 + if ( function_exists( 'add_meta_box' ) ) {
168 + add_meta_box(
169 + $this->handle,
170 + $this->label,
171 + array( &$this, 'display_custom_fields' ),
172 + $a_post_type,
173 + 'normal',
174 + 'high'
175 + );
176 + }
177 + }
178 + }
179 + }
180 +
181 + /**
182 + * Display the new Custom Fields meta box
183 + */
184 + function display_custom_fields() {
185 + global $post;
186 +
187 + if ( '' !== $this->rule_description_as_html ) {
188 + // If there is a rule description, then use this as we are not allowed to use generated
189 + // HTML code as variable without escaping or sanitizing but we need the button element
190 +
191 + echo '<div id="schedule_desc" style="font-style: italic; overflow-y: auto;">';
192 + echo wp_kses_post( $this->rule_description_as_html );
193 + echo '</div>';
194 + echo '<div id="tcr-dialogHolder" style="display:none;"></div>';
195 + echo '<div style="padding-top: 10px;">';
196 + echo '<input type="button" class="button button-primary" id="timed_content_rule_test" value="' .
197 + __( 'Show projected dates/times', 'timed-content' ) .
198 + '" />';
199 + echo '</div>';
200 + } else {
201 + // Otherwise output the description as text
202 +
203 + echo '<p>' . esc_html( $this->desc ) . '</p>';
204 + }
205 + echo '<div class="form-wrap">';
206 + wp_nonce_field( $this->handle, $this->handle . '_wpnonce', false, true );
207 + foreach ( $this->custom_fields as $custom_field ) {
208 + // Check scope
209 + $scope = $custom_field['scope'];
210 + $output = false;
211 + foreach ( $scope as $scope_item ) {
212 + switch ( $scope_item ) {
213 + default:
214 + if ( $post->post_type === $scope_item ) {
215 + $output = true;
216 + }
217 + break;
218 + }
219 + if ( $output ) {
220 + break;
221 + }
222 + }
223 + // Check capability
224 + if ( ! current_user_can( $custom_field['capability'], $post->ID ) ) {
225 + $output = false;
226 + }
227 + // Output if allowed
228 + if ( $output ) {
229 + $field_name = $this->prefix . $custom_field['name'];
230 + $field_title = $custom_field['title'];
231 + echo '<div class="form-field form-required"';
232 + echo ' id="' . esc_attr( $field_name ) . '_div"';
233 + echo ' style="display: ' . esc_attr( $custom_field['display'] ) . '">';
234 + switch ( $custom_field['type'] ) {
235 + case 'radio':
236 + $checked_value = get_post_meta(
237 + $post->ID,
238 + $field_name,
239 + true
240 + );
241 + if ( '' === $checked_value || false === $checked_value ) {
242 + $checked_value = $custom_field['default'];
243 + }
244 + echo '<strong>' . esc_html( $field_title ) . '</strong><br />';
245 + foreach ( $custom_field['values'] as $value => $label ) {
246 + echo '<input type="radio" name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '_' . esc_attr( $value ) . '" value="' . esc_attr( $value ) . '"';
247 + if ( $checked_value === $value || intval( $checked_value ) === $value ) {
248 + echo ' checked="checked"';
249 + }
250 + echo ' /><label for="' . esc_attr( $field_name ) . '_' . esc_attr( $value ) . '" style="display: inline;">' . esc_html( $label ) . '</label><br />';
251 + }
252 + break;
253 + case 'menu':
254 + echo '<label for="' . esc_attr( $field_name ) . '" style="display:inline;"><strong>' . esc_html( $field_title ) . '</strong></label><br />';
255 + if ( sizeof( $custom_field['values'] ) === 0 ) {
256 + echo '<em>' . __( 'This menu is empty.', 'timed-content' ) . '</em>';
257 + } else {
258 + $selected_value = ( '' === get_post_meta(
259 + $post->ID,
260 + $field_name,
261 + true
262 + ) ? $custom_field['default'] : get_post_meta(
263 + $post->ID,
264 + $field_name,
265 + true
266 + ) );
267 + echo '<select name="' . esc_attr( $field_name ) . '[]" id="' . esc_attr( $field_name ) . '" style="width: auto; height: auto; padding: 3px;" size="' . esc_attr( $custom_field['size'] ) . '" multiple="multiple">';
268 + foreach ( $custom_field['values'] as $value => $label ) {
269 + echo '<option value="' . esc_attr( $value ) . '"';
270 + if ( $selected_value === $value || intval( $selected_value ) === $value ) {
271 + echo ' selected="selected"';
272 + }
273 + echo '>' . esc_html( $label ) . '</option>';
274 + }
275 + echo '</select>';
276 + }
277 + break;
278 + case 'list':
279 + // list
280 + echo '<label for="' . esc_attr( $field_name ) . '" style="display:inline;"><strong>' . esc_html( $field_title ) . '</strong></label><br />';
281 + if ( sizeof( $custom_field['values'] ) === 0 ) {
282 + echo '<em>' . __( 'This menu is empty.', 'timed-content' ) . '</em>';
283 + } else {
284 + $selected_value = ( '' === get_post_meta(
285 + $post->ID,
286 + $field_name,
287 + true
288 + ) ? $custom_field['default'] : get_post_meta(
289 + $post->ID,
290 + $field_name,
291 + true
292 + ) );
293 + echo '<select name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" style="width: auto;">';
294 + foreach ( $custom_field['values'] as $value => $label ) {
295 + echo '<option value="' . esc_attr( $value ) . '"';
296 + if ( $selected_value === $value || intval( $selected_value ) === $value ) {
297 + echo ' selected="selected"';
298 + }
299 + echo '>' . esc_html( $label ) . '</option>';
300 + }
301 + echo '</select>';
302 + }
303 + break;
304 + case 'timezone-list':
305 + // timezone list
306 + $selected_value = ( '' === get_post_meta(
307 + $post->ID,
308 + $field_name,
309 + true
310 + ) ? $custom_field['default'] : get_post_meta(
311 + $post->ID,
312 + $field_name,
313 + true
314 + ) );
315 +
316 + echo '<label for="' . esc_attr( $field_name ) . '" style="display:inline;"><strong>' . esc_html( $field_title ) . '</strong></label><br />';
317 + echo '<select name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" style="width: auto;">';
318 + echo CustomFieldsInterface::generate_timezone_select_options( $selected_value );
319 + echo '</select>';
320 + break;
321 + case 'checkbox':
322 + // Checkbox
323 + $checked_value = ( '' === get_post_meta(
324 + $post->ID,
325 + $field_name,
326 + true
327 + ) ? $custom_field['default'] : get_post_meta(
328 + $post->ID,
329 + $field_name,
330 + true
331 + ) );
332 +
333 + echo '<label for="' . esc_attr( $field_name ) . '" style="display:inline;"><strong>' . esc_html( $field_title ) . '</strong><br />';
334 + echo '<input type="checkbox" name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" value="yes"';
335 + if ( 'yes' === $checked_value ) {
336 + echo ' checked="checked"';
337 + }
338 + echo ' />' . __( 'Yes', 'timed-content' ) . '</label>';
339 + break;
340 + case 'checkbox-list':
341 + // Checkbox list
342 + $checked_value = ( '' === get_post_meta(
343 + $post->ID,
344 + $field_name,
345 + true
346 + ) ? $custom_field['default'] : get_post_meta(
347 + $post->ID,
348 + $field_name,
349 + true
350 + ) );
351 +
352 + echo '<strong>' . esc_html( $field_title ) . '</strong><br />';
353 + if ( sizeof( $custom_field['values'] ) === 0 ) {
354 + echo '<em>' . __( 'This menu is empty.', 'timed-content' ) . '</em>';
355 + } else {
356 + foreach ( $custom_field['values'] as $value => $label ) {
357 + echo '<input type="checkbox" name="' . esc_attr( $field_name ) . '[]" id="' . esc_attr( $field_name ) . '_' . esc_attr( $value ) . '" value="' . esc_attr( $value ) . '"';
358 + if ( ( is_array( $checked_value ) ) && ( in_array(
359 + (string) $value,
360 + $checked_value,
361 + true
362 + ) ) ) {
363 + echo ' checked="checked"';
364 + }
365 + echo ' /><label for="' . esc_attr( $field_name ) . '_' . esc_attr( $value ) . '" style="display: inline;" >' . esc_html( $label ) . '</label><br />';
366 + }
367 + }
368 + break;
369 + case 'textarea':
370 + case 'wysiwyg':
371 + // Text area
372 + $value = ( '' === get_post_meta(
373 + $post->ID,
374 + $field_name,
375 + true
376 + ) ? $custom_field['default'] : get_post_meta(
377 + $post->ID,
378 + $field_name,
379 + true
380 + ) );
381 + echo '<label for="' . esc_attr( $field_name ) . '"><strong>' . esc_html( $field_title ) . '</strong></label><br />';
382 + echo '<textarea name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" columns="30" rows="3">' . esc_html( $value ) . '</textarea>';
383 + // WYSIWYG
384 + if ( 'wysiwyg' === $custom_field['type'] ) {
385 + echo '<script type="text/javascript">' . PHP_EOL;
386 + echo '//<![CDATA[' . PHP_EOL;
387 + echo 'jQuery(document).ready(function () {' . PHP_EOL;
388 + echo ' jQuery("' . esc_js( $field_name ) . '").addClass("mceEditor");' . PHP_EOL;
389 + echo ' if (typeof (tinyMCE) == "object" && typeof (tinyMCE.execCommand) == "function") {' . PHP_EOL;
390 + echo ' tinyMCE.execCommand("mceAddControl", false, "' . esc_js( $field_name ) . '");' . PHP_EOL;
391 + echo ' }' . PHP_EOL;
392 + echo '});' . PHP_EOL;
393 + echo '//]]>' . PHP_EOL;
394 + echo '</script>' . PHP_EOL;
395 + }
396 + break;
397 + case 'color-picker':
398 + $value = ( '' === get_post_meta(
399 + $post->ID,
400 + $field_name,
401 + true
402 + ) ? $custom_field['default'] : get_post_meta(
403 + $post->ID,
404 + $field_name,
405 + true
406 + ) );
407 + // Color picker using WP's built-in Iris jQuery plugin
408 + echo '<script type="text/javascript">' . PHP_EOL;
409 + echo '//<![CDATA[' . PHP_EOL;
410 + echo 'jQuery(document).ready(function () {' . PHP_EOL;
411 + echo ' var ' . esc_js( $field_name ) . 'Options = {' . PHP_EOL;
412 + echo ' defaultColor: false,' . PHP_EOL;
413 + echo ' hide: true,' . PHP_EOL;
414 + echo ' palettes: true' . PHP_EOL;
415 + echo ' };' . PHP_EOL;
416 + echo ' jQuery("#' . esc_js( $field_name ) . '").wpColorPicker(' . esc_js( $field_name ) . 'Options);' . PHP_EOL;
417 + echo '});' . PHP_EOL;
418 + echo '//]]>' . PHP_EOL;
419 + echo '</script>' . PHP_EOL;
420 + echo '<label for="' . esc_attr( $field_name ) . '"><strong>' . esc_html( $field_title ) . '</strong></label><br />';
421 + echo '<input type="text" name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" value="' . esc_attr( $value ) . '" size="7" maxlength="7" style="width: 100px;" />';
422 + break;
423 + case 'date':
424 + echo '<label for="' . esc_attr( $field_name ) . '" style="display:inline;"><strong>' . esc_html( $field_title ) . '</strong></label><br />';
425 + $value = ( '' === get_post_meta(
426 + $post->ID,
427 + $field_name,
428 + true
429 + ) ? $custom_field['default'] : get_post_meta(
430 + $post->ID,
431 + $field_name,
432 + true
433 + ) );
434 + // Date picker using WP's built-in Datepicker jQuery plugin
435 + echo '<script type="text/javascript">' . PHP_EOL;
436 + echo '//<![CDATA[' . PHP_EOL;
437 + echo 'jQuery(document).ready(function () {' . PHP_EOL;
438 + echo ' jQuery("#' . esc_js( $field_name ) . '").datepicker(' . PHP_EOL;
439 + echo ' {' . PHP_EOL;
440 + echo ' onSelect: function (dateText, inst) {' . PHP_EOL;
441 + echo ' jQuery("#timed_content_rule_exceptions_dates option[value=\'0\']").remove();' . PHP_EOL;
442 + echo ' jQuery("#timed_content_rule_exceptions_dates").append(\'<option value="\' + dateText + \'">\' + dateText + \'</option>\');' . PHP_EOL;
443 + echo ' jQuery(this).val("");' . PHP_EOL;
444 + echo ' jQuery(this).trigger("change");' . PHP_EOL;
445 + echo ' },' . PHP_EOL;
446 + echo ' changeMonth: true,' . PHP_EOL;
447 + echo ' changeYear: true' . PHP_EOL;
448 + echo ' }' . PHP_EOL;
449 + echo ' );' . PHP_EOL;
450 + echo '});' . PHP_EOL;
451 + echo '//]]>' . PHP_EOL;
452 + echo '</script>' . PHP_EOL;
453 + echo '<input type="text" name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" value="' . esc_attr( $value ) . '" style="width: 175px;" />';
454 + break;
455 + case 'datetime':
456 + echo '<span style="display:inline;"><strong>' . esc_html( $field_title ) . '</strong></span><br />';
457 + $value = ( '' === get_post_meta(
458 + $post->ID,
459 + $field_name,
460 + true
461 + ) ? $custom_field['default'] : get_post_meta(
462 + $post->ID,
463 + $field_name,
464 + true
465 + ) );
466 + foreach ( $value as $k => $v ) {
467 + $value[ $k ] = esc_html( $v );
468 + }
469 + // Date picker using WP's built-in Datepicker jQuery plugin
470 + // Time picker using jQuery UI Timepicker: http://fgelinas.com/code/timepicker
471 + echo '<script type="text/javascript">' . PHP_EOL;
472 + echo '//<![CDATA[' . PHP_EOL;
473 + echo 'jQuery(document).ready(function () {' . PHP_EOL;
474 + echo ' jQuery("#' . esc_js( $field_name ) . '_date").datepicker({' . PHP_EOL;
475 + echo ' changeMonth: true,' . PHP_EOL;
476 + echo ' changeYear: true' . PHP_EOL;
477 + echo ' });' . PHP_EOL;
478 + echo ' jQuery("#' . esc_js( $field_name ) . '_time").timepicker({' . PHP_EOL;
479 + echo ' defaultTime: \'now\'' . PHP_EOL;
480 + echo ' });' . PHP_EOL;
481 + echo '});' . PHP_EOL;
482 + echo '//]]>' . PHP_EOL;
483 + echo '</script>' . PHP_EOL;
484 + echo '<label for="' . esc_attr( $field_name ) . '_date" style="display:inline;"><em>' . _x(
485 + 'Date',
486 + 'Date field label',
487 + 'timed-content'
488 + ) . ':</em></label>';
489 + echo '<input type="text" name="' . esc_attr( $field_name ) . '[date]" id="' . esc_attr( $field_name ) . '_date" value="' . esc_attr( $value['date'] ) . '" style="width: 175px;" />';
490 + echo '<label for="' . esc_attr( $field_name ) . '_time" style="display:inline;"><em>' . _x(
491 + 'Time',
492 + 'Time field label',
493 + 'timed-content'
494 + ) . ":</em></label>\n";
495 + echo '<input type="text" name="' . esc_attr( $field_name ) . '[time]" id="' . esc_attr( $field_name ) . '_time" value="' . esc_attr( $value['time'] ) . '" style="width: 125px;" />';
496 + break;
497 + case 'number':
498 + $value = get_post_meta(
499 + $post->ID,
500 + $field_name,
501 + true
502 + );
503 + if ( '' === $value ) {
504 + $value = $custom_field['default'];
505 + } else {
506 + $value = intval( $value );
507 + }
508 + // Number picker using WP's built-in Spinner jQuery plugin
509 + echo '<script type="text/javascript">' . PHP_EOL;
510 + echo '//<![CDATA[' . PHP_EOL;
511 + echo 'jQuery(document).ready(function () {' . PHP_EOL;
512 + echo ' jQuery("#' . esc_js( $field_name ) . '").spinner({' . PHP_EOL;
513 + echo ' stop: function (event, ui) {' . PHP_EOL;
514 + echo ' jQuery(this).trigger("change");' . PHP_EOL;
515 + echo ' },' . PHP_EOL;
516 + if ( isset( $custom_field['min'] ) ) {
517 + echo ' min: ' . esc_js( $custom_field['min'] ) . ', ';
518 + }
519 + if ( isset( $custom_field['max'] ) ) {
520 + echo ' max: ' . esc_js( $custom_field['max'] ) . ', ';
521 + }
522 + echo ' });' . PHP_EOL;
523 + echo '});' . PHP_EOL;
524 + echo '//]]>' . PHP_EOL;
525 + echo '</script>' . PHP_EOL;
526 + echo '<label for="' . esc_attr( $field_name ) . '" style="display:inline;"><strong>' . esc_html( $field_title ) . '</strong></label><br />';
527 + echo '<input type="text" name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" value="' . esc_attr( $value ) . '" size="2" />';
528 + break;
529 + case 'hidden':
530 + $value = ( '' === get_post_meta(
531 + $post->ID,
532 + $field_name,
533 + true
534 + ) ? $custom_field['default'] : get_post_meta(
535 + $post->ID,
536 + $field_name,
537 + true
538 + ) );
539 + // Hidden field
540 + echo '<input type="hidden" name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" value="' . esc_attr( $value ) . ' />';
541 + break;
542 + default:
543 + $value = ( '' === get_post_meta(
544 + $post->ID,
545 + $field_name,
546 + true
547 + ) ? $custom_field['default'] : get_post_meta(
548 + $post->ID,
549 + $field_name,
550 + true
551 + ) );
552 + // Plain text field
553 + echo '<label for="' . esc_attr( $field_name ) . '"><strong>' . esc_html( $field_title ) . '</strong></label><br/>';
554 + echo '<input type="text" name="' . esc_attr( $field_name ) . '" id="' . esc_attr( $field_name ) . '" value="' . esc_attr( $value ) . ' />';
555 + break;
556 + }
557 + if ( isset( $custom_field['description'] ) ) {
558 + echo '<p>' . esc_html( $custom_field['description'] ) . '</p>';
559 + }
560 + echo '</div>';
561 + }
562 + }
563 + echo '</div>';
564 + }
565 +
566 + /**
567 + * Save the new Custom Fields values
568 + */
569 + function save_custom_fields( $post_id, $post ) {
570 + // Only save if the user intends to save
571 + if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
572 + return;
573 + }
574 + // Make sure the Save request is coming from the right place
575 + if ( ! isset( $_POST[ $this->handle . '_wpnonce' ] ) || ! wp_verify_nonce(
576 + $_POST[ $this->handle . '_wpnonce' ],
577 + $this->handle
578 + ) ) {
579 + return;
580 + }
581 + // Make sure the user can edit this specific post
582 + if ( ! current_user_can( 'edit_post', $post_id ) ) {
583 + return;
584 + }
585 + // Make sure this meta box is associated with the right post types
586 + if ( ! in_array( $post->post_type, $this->post_types, true ) ) {
587 + return;
588 + }
589 + foreach ( $this->custom_fields as $custom_field ) {
590 + if ( current_user_can( $custom_field['capability'], $post_id ) ) {
591 + $field_name = $this->prefix . $custom_field['name'];
592 + if ( isset( $_POST[ $field_name ] ) ) {
593 + if ( is_array( $_POST[ $field_name ] ) ) {
594 + foreach ( $_POST[ $field_name ] as $k => $v ) {
595 + $_POST[ $field_name ][ $k ] = trim( sanitize_text_field( $v ) );
596 + }
597 + } else {
598 + $_POST[ $field_name ] = trim( sanitize_text_field( $_POST[ $field_name ] ) );
599 + }
600 + $value = $_POST[ $field_name ];
601 + // Auto-paragraphs for any WYSIWYG
602 + if ( 'wysiwyg' === $custom_field['type'] ) {
603 + $value = wpautop( $value );
604 + }
605 + if ( 'checkbox' === $custom_field['type'] ) {
606 + $value = 'yes';
607 + }
608 + if ( 'number' === $custom_field['type'] ) {
609 + $value = intval( $value );
610 + }
611 + update_post_meta( $post_id, $field_name, $value );
612 + } else {
613 + delete_post_meta( $post_id, $field_name );
614 + }
615 + }
616 + }
617 + }
618 +}