PluginProbe
Timed Content / 2.7
Timed Content v2.7
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 | timed-content.php +1490 -2292 2.502.7 View file →
@@ -1,2293 +1,1491 @@
1 -<?php
2 -/*
3 -Plugin Name: Timed Content
4 -Text Domain: timed-content
5 -Domain Path: /lang
6 -Plugin URI: http://wordpress.org/plugins/timed-content/
7 -Description: Plugin to show or hide portions of a Page or Post based on specific date/time characteristics. These actions can either be processed either server-side or client-side, depending on the desired effect.
8 -Author: K. Tough, Arno Welzel
9 -Version: 2.50
10 -Author URI: http://wordpress.org/plugins/timed-content/
11 -*/
12 -defined('ABSPATH') or die();
13 -
14 -include 'lib/customFieldsInterface.php';
15 -
16 -define('TIMED_CONTENT_VERSION', '2.50');
17 -define('TIMED_CONTENT_SLUG', 'timed-content');
18 -define('TIMED_CONTENT_PLUGIN_URL', plugins_url() . '/' . TIMED_CONTENT_SLUG);
19 -define('TIMED_CONTENT_SHORTCODE_CLIENT', 'timed-content-client');
20 -define('TIMED_CONTENT_SHORTCODE_SERVER', 'timed-content-server');
21 -define('TIMED_CONTENT_SHORTCODE_RULE', 'timed-content-rule');
22 -define('TIMED_CONTENT_TIME_ZERO', '1970-01-01 00:00:00 +000'); // Start of Unix Epoch (32 bit)
23 -define('TIMED_CONTENT_TIME_END', '2038-01-19 03:14:06 +000'); // End of Unix Epoch (32 bit)
24 -define('TIMED_CONTENT_RULE_TYPE', 'timed_content_rule');
25 -define('TIMED_CONTENT_RULE_POSTMETA_PREFIX', TIMED_CONTENT_RULE_TYPE . '_');
26 -define('TIMED_CONTENT_CSS', TIMED_CONTENT_PLUGIN_URL . '/css/timed-content.css');
27 -define('TIMED_CONTENT_CSS_DASHICONS', TIMED_CONTENT_PLUGIN_URL . '/css/dashicons/style.css');
28 -define('TIMED_CONTENT_JQUERY_UI_CSS', TIMED_CONTENT_PLUGIN_URL . '/css/jqueryui/1.10.3/themes/smoothness/jquery-ui.css');
29 -define('TIMED_CONTENT_JQUERY_UI_TIMEPICKER_JS', TIMED_CONTENT_PLUGIN_URL . '/js/jquery-ui-timepicker-0.3.3/jquery.ui.timepicker.js');
30 -define('TIMED_CONTENT_JQUERY_UI_TIMEPICKER_CSS', TIMED_CONTENT_PLUGIN_URL . '/js/jquery-ui-timepicker-0.3.3/jquery.ui.timepicker.css');
31 -define('TIMED_CONTENT_DATE_FORMAT_OUTPUT', 'Y-m-d H:i O');
32 -
33 -/**
34 - * Class timedContentPlugin
35 - *
36 - * @package TimedContent
37 - */
38 -class timedContentPlugin
39 -{
40 - var $rule_freq_array;
41 - var $rule_days_array;
42 - var $rule_ordinal_array;
43 - var $rule_ordinal_days_array;
44 - var $rule_occurrence_custom_fields;
45 - var $rule_pattern_custom_fields;
46 - var $rule_recurrence_custom_fields;
47 - var $rule_exceptions_custom_fields;
48 -
49 - var $meridiem;
50 - var $show_period;
51 - var $show_period_labels;
52 - var $show_leading_zero;
53 -
54 - var $jquery_ui_datetime_datepicker_i18n;
55 - var $jquery_ui_datetime_timepicker_i18n;
56 -
57 - /**
58 - * Constructor
59 - */
60 - function __construct()
61 - {
62 - add_filter('timed_content_filter', 'convert_smilies');
63 - add_filter('timed_content_filter', 'convert_chars');
64 - add_filter('timed_content_filter', 'prepend_attachment');
65 - add_filter('timed_content_filter', 'do_shortcode');
66 - add_filter('manage_' . TIMED_CONTENT_RULE_TYPE . '_posts_columns', array($this, 'addDescColumnHead'));
67 - add_filter('pre_get_posts', array($this, 'timedContentPreGetPosts'));
68 - add_filter('post_updated_messages', array($this, 'timedContentRuleUpdatedMessages'), 1);
69 -
70 - add_action('plugins_loaded', array($this, 'i18nInit'), 1);
71 - add_action('init', array($this, 'init'), 2);
72 - add_action('wp_head', array($this, 'addHeaderCode'), 1);
73 - add_action('manage_' . TIMED_CONTENT_RULE_TYPE . '_posts_custom_column', array($this, 'addDescColumnContent'), 10, 2);
74 - add_action('admin_enqueue_scripts', array($this, 'addAdminHeaderCode'), 1);
75 - add_action('admin_init', array($this, 'setTinyMCEPluginVars'), 1);
76 - add_action('admin_init', array($this, 'initTinyMCEPlugin'), 2);
77 - add_action('wp_ajax_timedContentPluginGetTinyMCEDialog', array($this, 'timedContentPluginGetTinyMCEDialog'), 1);
78 - add_action('wp_ajax_timedContentPluginGetRulePeriodsAjax', array($this, 'timedContentPluginGetRulePeriodsAjax'), 1);
79 - add_action('wp_ajax_timedContentPluginGetScheduleDescriptionAjax', array($this, 'timedContentPluginGetScheduleDescriptionAjax'), 1);
80 - add_action('dashboard_glance_items', array($this, 'addRulesCount'));
81 - add_action('admin_head', array($this, 'addPostTypeIcons'), 1);
82 -
83 - add_shortcode(TIMED_CONTENT_SHORTCODE_CLIENT, array($this, 'clientShowHTML'));
84 - add_shortcode(TIMED_CONTENT_SHORTCODE_SERVER, array($this, 'serverShowHTML'));
85 - add_shortcode(TIMED_CONTENT_SHORTCODE_RULE, array($this, 'rulesShowHTML'));
86 - }
87 -
88 - /**
89 - * Initialise plugin
90 - */
91 - function init()
92 - {
93 - global $wp_locale;
94 -
95 - $this->rule_freq_array = array(
96 - 0 => __('hourly', 'timed-content'),
97 - 1 => __('daily', 'timed-content'),
98 - 2 => __('weekly', 'timed-content'),
99 - 3 => __('monthly', 'timed-content'),
100 - 4 => __('yearly', 'timed-content')
101 - );
102 -
103 - $this->rule_days_array = array(
104 - 0 => __('Sunday', 'timed-content'),
105 - 1 => __('Monday', 'timed-content'),
106 - 2 => __('Tuesday', 'timed-content'),
107 - 3 => __('Wednesday', 'timed-content'),
108 - 4 => __('Thursday', 'timed-content'),
109 - 5 => __('Friday', 'timed-content'),
110 - 6 => __('Saturday', 'timed-content')
111 - );
112 -
113 - $this->rule_ordinal_array = array(
114 - 0 => __('first', 'timed-content'),
115 - 1 => __('second', 'timed-content'),
116 - 2 => __('third', 'timed-content'),
117 - 3 => __('fourth', 'timed-content'),
118 - 4 => __('last', 'timed-content')
119 - );
120 -
121 - $this->rule_ordinal_days_array = array(
122 - 0 => __('Sunday', 'timed-content'),
123 - 1 => __('Monday', 'timed-content'),
124 - 2 => __('Tuesday', 'timed-content'),
125 - 3 => __('Wednesday', 'timed-content'),
126 - 4 => __('Thursday', 'timed-content'),
127 - 5 => __('Friday', 'timed-content'),
128 - 6 => __('Saturday', 'timed-content'),
129 - 7 => __('day', 'timed-content')
130 - );
131 -
132 - $this->jquery_ui_datetime_datepicker_i18n = array(
133 - "closeText" => _x( "Done", "jQuery UI Datepicker Close label", "timed-content" ), // Display text for close link
134 - "prevText" => _x( "Prev", "jQuery UI Datepicker Previous label", "timed-content" ), // Display text for previous month link
135 - "nextText" => _x( "Next", "jQuery UI Datepicker Next label", "timed-content" ), // Display text for next month link
136 - "currentText" => _x( "Today", "jQuery UI Datepicker Today label", "timed-content" ), // Display text for current month link
137 - "weekHeader" => _x( "Wk", "jQuery UI Datepicker Week label", "timed-content" ), // Column header for week of the year
138 - // Replace the text indices for the following arrays with 0-based arrays
139 - "monthNames" => $this->stripArrayIndices( $wp_locale->month ), // Names of months for drop-down and formatting
140 - "monthNamesShort" => $this->stripArrayIndices( $wp_locale->month_abbrev ), // For formatting
141 - "dayNames" => $this->stripArrayIndices( $wp_locale->weekday ), // For formatting
142 - "dayNamesShort" => $this->stripArrayIndices( $wp_locale->weekday_abbrev ), // For formatting
143 - "dayNamesMin" => $this->stripArrayIndices( $wp_locale->weekday_initial ), // Column headings for days starting at Sunday
144 - "dateFormat" => 'yy-mm-dd',
145 - "firstDay" => get_option( 'start_of_week' ),
146 - "isRTL" => $wp_locale->is_rtl(),
147 - "showMonthAfterYear" => false, // True if the year select precedes month, false for month then year
148 - "yearSuffix" => '' // Additional text to append to the year in the month headers
149 - );
150 -
151 - $tf = get_option( 'time_format' );
152 - if ( false !== strpos( $tf, "A") ) {
153 - $this->meridiem = array($wp_locale->meridiem['AM'], $wp_locale->meridiem['PM']);
154 - $this->show_period = true;
155 - $this->show_period_labels = true;
156 - $this->show_leading_zero = false;
157 - } elseif ( false !== strpos( $tf, "a") ) {
158 - $this->meridiem = array($wp_locale->meridiem['am'], $wp_locale->meridiem['pm']);
159 - $this->show_period = true;
160 - $this->show_period_labels = true;
161 - $this->show_leading_zero = false;
162 - } else {
163 - $this->meridiem = array('', '');
164 - $this->show_period = false;
165 - $this->show_period_labels = false;
166 - $this->show_leading_zero = true;
167 - }
168 -
169 - $this->jquery_ui_datetime_timepicker_i18n = array(
170 - "hourText" => _x( "Hour", "jQuery UI Timepicker 'Hour' label", "timed-content" ),
171 - "minuteText" => _x( "Minute", "jQuery UI Timepicker 'Minute' label", "timed-content" ),
172 - "timeSeparator" => _x( ":", "jQuery UI Datepicker: Character used to separate hours and minutes in translated language", 'timed-content' ),
173 - "closeButtonText" => _x( "Done", "jQuery UI Timepicker 'Done' label", "timed-content" ),
174 - "nowButtonText" => _x( "Now", "jQuery UI Timepicker 'Now' label", "timed-content" ),
175 - "deselectButtonText" => _x( "Deselect", "jQuery UI Timepicker 'Deselect' label", "timed-content" ),
176 - "amPmText" => array('', ''),
177 - "showPeriod" => false,
178 - "showPeriodLabels" => false,
179 - "showLeadingZero" => false,
180 - "timeFormat" => 'G:i'
181 - );
182 -
183 - $this->timedContentRuleTypeInit();
184 - $this->setupCustomFields();
185 - }
186 -
187 - /**
188 - * Creates the Timed Content Rule post type and registers it with Wordpress
189 - */
190 - function timedContentRuleTypeInit()
191 - {
192 - $labels = array(
193 - 'name' => _x( 'Timed Content rules', 'post type general name', 'timed-content' ),
194 - 'singular_name' => _x( 'Timed Content rule', 'post type singular name', 'timed-content' ),
195 - 'add_new' => _x( 'Add new', 'Menu item/button label on Timed Content Rules admin page',
196 - 'timed-content' ),
197 - 'add_new_item' => __( 'Add new Timed Content rule', 'timed-content' ),
198 - 'edit_item' => __( 'Edit Timed Content rule', 'timed-content' ),
199 - 'new_item' => __( 'New Timed Content rule', 'timed-content' ),
200 - 'view_item' => __( 'View Timed Content rule', 'timed-content' ),
201 - 'search_items' => __( 'Search Timed Content rules', 'timed-content' ),
202 - 'not_found' => __( 'No Timed Content rules found', 'timed-content' ),
203 - 'not_found_in_trash' => __( 'No Timed Content rules found in trash', 'timed-content' ),
204 - 'parent_item_colon' => '',
205 - 'menu_name' => _x( 'Timed Content rules', 'post type general name', 'timed-content' )
206 - );
207 - $args = array(
208 - 'labels' => $labels,
209 - 'description' => __( 'Create regular schedules to show or hide selected content in a page or post.',
210 - 'timed-content' ),
211 - 'public' => false,
212 - 'publicly_queryable' => false,
213 - 'exclude_from_search' => false,
214 - 'show_ui' => true,
215 - 'show_in_menu' => true,
216 - 'show_in_nav_menus' => true,
217 - 'show_in_admin_bar' => true,
218 - 'query_var' => false,
219 - 'rewrite' => false,
220 - 'capability_type' => 'post',
221 - 'has_archive' => false,
222 - 'hierarchical' => false,
223 - 'menu_position' => 5,
224 - 'supports' => array( 'title' )
225 - );
226 - register_post_type( TIMED_CONTENT_RULE_TYPE, $args );
227 - }
228 -
229 -
230 - /**
231 - * Fix for date_i18n() as suggested in https://core.trac.wordpress.org/ticket/25768
232 - *
233 - * Modified from the original patch to use the currently set timezone from PHP,
234 - * like PHP's date(), and to make the code more readable.
235 - *
236 - * @param $j
237 - * @param $req_format
238 - * @param bool $i
239 - * @param bool $gmt
240 - *
241 - * @return bool|string
242 - */
243 - function fix_date_i18n($j, $req_format, $i = false, $gmt = false)
244 - {
245 - global $wp_locale;
246 - global $post;
247 -
248 - $timestamp = $i;
249 -
250 - // get current timestamp if $i is false
251 - if (false === $timestamp) {
252 - if ($gmt) {
253 - $timestamp = time();
254 - } else {
255 - $timestamp = current_time( 'timestamp' );
256 - }
257 -
258 - // use debug parameter if current user is allowed to edit the post
259 - if (isset( $_GET['tctest'] ) && current_user_can("edit_post", $post->post_id)) {
260 - $dt = DateTime::createFromFormat('Y-m-d H:i:s', $_GET['tctest']);
261 - if ($dt != false) {
262 - $timestamp = $dt->getTimestamp();
263 - }
264 - }
265 - }
266 -
267 - // get components of the date (timestamp) as array
268 - $date_components = getdate($timestamp);
269 -
270 - // numeric representation of a month, with leading zeros
271 - $date_month = $wp_locale->get_month($date_components['mon']);
272 - $date_month_abbrev = $wp_locale->get_month_abbrev($date_month);
273 - // numeric representation of the day of the week
274 - $date_weekday = $wp_locale->get_weekday($date_components['wday']);
275 - $date_weekday_abbrev = $wp_locale->get_weekday_abbrev($date_weekday);
276 - // get if hour is Ante meridiem or Post meridiem
277 - $meridiem = $date_components['hours'] >= 12 ? 'pm' : 'am';
278 - // lowercase Ante meridiem and Post meridiem hours
279 - $date_meridiem = $wp_locale->get_meridiem($meridiem);
280 - // uppercase Ante meridiem and Post meridiem
281 - $date_meridiem_capital = $wp_locale->get_meridiem(strtoupper($meridiem));
282 -
283 - // escape literals
284 - $date_weekday_abbrev = backslashit($date_weekday_abbrev);
285 - $date_month = backslashit($date_month);
286 - $date_weekday = backslashit($date_weekday);
287 - $date_month_abbrev = backslashit($date_month_abbrev);
288 - $date_meridiem = backslashit($date_meridiem);
289 - $date_meridiem_capital = backslashit($date_meridiem_capital);
290 -
291 - // the translated format string
292 - $translated_date_format_string = '';
293 - // the 2 arrays map a format literal to its translation (e. g. 'F' to the escaped month translation)
294 - $translate_formats = array('D', 'F', 'l', 'M', 'a', 'A', 'c', 'r');
295 - $translations = array(
296 - $date_weekday_abbrev, // D
297 - $date_month, // F
298 - $date_weekday, // l
299 - $date_month_abbrev, // M
300 - $date_meridiem, // a
301 - $date_meridiem_capital, // A
302 - 'Y-m-d\TH:i:sP', // c
303 - sprintf( '%s, d %s Y H:i:s O', $date_weekday_abbrev, $date_month_abbrev ), // r
304 - );
305 -
306 - // find each format literal that needs translation and replace it by its translation
307 - // respects the escaping
308 - // iterate $req_format from ending to beginning
309 - for ( $i = strlen( $req_format ) - 1; $i > - 1; $i -- ) {
310 - // test if current char is format literal that needs translation
311 - $translate_formats_index = array_search( $req_format[ $i ], $translate_formats );
312 -
313 - if ( $translate_formats_index !== false ) {
314 - // counts the slashes (the escape char) in front of the current char
315 - $slashes_counter = 0;
316 -
317 - // count all slashes left-hand side of the current char
318 - for ( $j = $i - 1; $j > - 1; $j -- ) {
319 - if ( $req_format[ $j ] == '\\' ) {
320 - $slashes_counter ++;
321 - } else {
322 - break;
323 - }
324 - }
325 -
326 - // number of slashes is even
327 - if ( $slashes_counter % 2 == 0 ) // current char is not escaped, therefore it is a format literal
328 - {
329 - $translated_date_format_string = $translations[ $translate_formats_index ] . $translated_date_format_string;
330 - } else // current char is escaped, therefore it is not a format literal, just add it unchanged
331 - {
332 - $translated_date_format_string = $req_format[ $i ] . $translated_date_format_string;
333 - }
334 - } else // current char is no a format literal, just add it unchanged
335 - {
336 - $translated_date_format_string = $req_format[ $i ] . $translated_date_format_string;
337 - }
338 - }
339 -
340 - $req_format = $translated_date_format_string;
341 -
342 - if ($gmt) {
343 - // get GMT date string
344 - $date_formatted = gmdate( $req_format, $timestamp );
345 - } else {
346 - // get Wordpress time zone
347 - // $timezone_string = get_option('timezone_string');
348 - // Haha, just kidding. Let's get the currently set timezone, as God and Rasmus intended
349 - $timezone_string = date_default_timezone_get();
350 -
351 - if ($timezone_string) {
352 - // create time zone object
353 - $timezone_object = timezone_open( $timezone_string );
354 - // create date object from time zone object
355 - $local_date_object = date_create( null, $timezone_object );
356 - // set time and date of $local_date_object to $timestamp
357 - $date_components = isset( $date_components ) ? $date_components : getdate( $timestamp );
358 - date_date_set( $local_date_object, $date_components['year'], $date_components['mon'],
359 - $date_components['mday'] );
360 - date_time_set( $local_date_object, $date_components['hours'], $date_components['minutes'],
361 - $date_components['seconds'] );
362 - // format date according to the Wordpress time zone
363 - $date_formatted = date_format( $local_date_object, $req_format );
364 - } else {
365 - // fall back if no Wordpress time zone set
366 - $date_formatted = date( $req_format, $i );
367 - }
368 - }
369 -
370 - return $date_formatted;
371 - }
372 -
373 - /**
374 - * Filter to change sort order to title
375 - *
376 - * @param array $messages Array of currently defined messages for post types
377 - *
378 - * @return mixed Array of messages with appropriate messages for Timed Content Rules added in
379 - */
380 - function timedContentPreGetPosts($query)
381 - {
382 - if ( $query->is_admin ) {
383 - if ( $query->get( 'post_type' ) == TIMED_CONTENT_RULE_TYPE ) {
384 - $query->set( 'orderby', 'title' );
385 - $query->set( 'order', 'ASC' );
386 - }
387 - }
388 -
389 - return $query;
390 - }
391 -
392 - /**
393 - * Filter to customize CRUD messages for Timed Content Rules
394 - *
395 - * @param array $messages Array of currently defined messages for post types
396 - *
397 - * @return mixed Array of messages with appropriate messages for Timed Content Rules added in
398 - */
399 - function timedContentRuleUpdatedMessages($messages)
400 - {
401 - global $post;
402 -
403 - /* translators: date and time format to activate rule. http://ca2.php.net/manual/en/function.date.php*/
404 - $post_date = date_i18n( __( 'M j, Y @ G:i', 'timed-content' ), strtotime( $post->post_date ) );
405 -
406 - $messages[ TIMED_CONTENT_RULE_TYPE ] = array(
407 - 0 => '', // Unused. Messages start at index 1.
408 - 1 => __( 'Timed Content Rule updated.', 'timed-content' ),
409 - 2 => __( 'Custom field updated.', 'timed-content' ),
410 - 3 => __( 'Custom field deleted.', 'timed-content' ),
411 - 4 => __( 'Timed Content Rule updated.', 'timed-content' ),
412 - /* translators: %s: date and time of the revision */
413 - 5 => isset( $_GET['revision'] ) ? sprintf( __( 'Timed Content Rule restored to revision from %s',
414 - 'timed-content' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
415 - 6 => __( 'Timed Content Rule published.', 'timed-content' ),
416 - 7 => __( 'Timed Content Rule saved.', 'timed-content' ),
417 - 8 => __( 'Timed Content Rule submitted.', 'timed-content' ),
418 - /* translators: %s: date and time to activate rule. */
419 - 9 => sprintf( __( 'Timed Content Rule scheduled for: %s.', 'timed-content' ),
420 - "<strong>" . $post_date . "</strong>" ),
421 - 10 => __( 'Timed Content Rule draft updated.', 'timed-content' )
422 - );
423 -
424 - return $messages;
425 - }
426 -
427 - function __datetimeToEnglish( $date, $time = "" )
428 - {
429 - $months = array(
430 - "January",
431 - "February",
432 - "March",
433 - "April",
434 - "May",
435 - "June",
436 - "July",
437 - "August",
438 - "September",
439 - "October",
440 - "November",
441 - "December"
442 - );
443 - $monthsI18N = array(
444 - __( "January", 'timed-content' ),
445 - __( "February", 'timed-content' ),
446 - __( "March", 'timed-content' ),
447 - __( "April", 'timed-content' ),
448 - __( "May", 'timed-content' ),
449 - __( "June", 'timed-content' ),
450 - __( "July", 'timed-content' ),
451 - __( "August", 'timed-content' ),
452 - __( "September", 'timed-content' ),
453 - __( "October", 'timed-content' ),
454 - __( "November", 'timed-content' ),
455 - __( "December", 'timed-content' )
456 - );
457 - $english_date = str_replace( $monthsI18N, $months, $date );
458 -
459 - return $english_date . " " . $time;
460 - }
461 -
462 - /**
463 - * Advances a date by a set number of days
464 - *
465 - * @param int $current UNIX timestamp of the date before incrementing
466 - * @param int $interval_multiplier Number of days to advance
467 - *
468 - * @return int Unix timestamp of the new date
469 - */
470 - function __getNextDay( $current, $interval_multiplier )
471 - {
472 - return strtotime( $interval_multiplier . " day", $current );
473 - }
474 -
475 - /**
476 - * Advances a date/time by a set number of hours
477 - *
478 - * @param int $current UNIX timestamp of the date/time before incrementing
479 - * @param int $interval_multiplier Number of hours to advance
480 - *
481 - * @return int Unix timestamp of the new date/time
482 - */
483 - function __getNextHour( $current, $interval_multiplier )
484 - {
485 - return strtotime( $interval_multiplier . " hour", $current );
486 - }
487 -
488 - /**
489 - * Advances a date/time by a set number of weeks
490 - *
491 - * Advances a date/time by a set number of weeks. If given an array of days of the week, this function will
492 - * advance the date/time to the next day in that array in the jumped-to week. Use this function if you're
493 - * repeating an action on specific days of the week (i.e., on Weekdays, Tuesdays and Thursdays, etc.).
494 - *
495 - * @param int $current UNIX timestamp of the date before incrementing
496 - * @param int $interval_multiplier Number of weeks to advance
497 - * @param array $days Array of integers symbolizing the days of the week to
498 - * repeat on (0 - Sunday, 1 - Monday, ..., 6 - Saturday).
499 - *
500 - * @return int Unix timestamp of the new date
501 - */
502 - function __getNextWeek( $current, $interval_multiplier, $days = array() )
503 - {
504 - // If $days is empty, advance $interval_multiplier weeks from $current and return the timestamp
505 - if ( empty( $days ) ) {
506 - return strtotime( $interval_multiplier . " week", $current );
507 - }
508 -
509 - // Otherwise, set up an array combining the days of the week to repeat on and the current day
510 - // (keys and values of the array will be the same, and the array is sorted)
511 - $currentDayOfWeekIndex = date( "w", $current );
512 - $days = array_merge( array( $currentDayOfWeekIndex ), $days );
513 - $days = array_unique( $days );
514 - $days = array_values( $days );
515 - sort( $days );
516 - $daysOfWeek = array_combine( $days, $days );
517 -
518 - // If the current day is the last one of the days of the week to repeat on, jump ahead to
519 - // the next week to be repeating on and get the earliest day in the array
520 - if ( $currentDayOfWeekIndex == max( $daysOfWeek ) ) {
521 - $pattern = ( ( 7 - $currentDayOfWeekIndex ) + ( 7 * ( $interval_multiplier - 1 ) ) + ( min( array_keys( $daysOfWeek ) ) ) ) . " day";
522 - } // Otherwise, cycle through the array until we find the next day to repeat on
523 - else {
524 - $nextDayOfWeekIndex = $currentDayOfWeekIndex;
525 - do {
526 - } while ( ! isset( $daysOfWeek[ ++ $nextDayOfWeekIndex ] ) );
527 - $pattern = ( $nextDayOfWeekIndex - $currentDayOfWeekIndex ) . " day";
528 - }
529 -
530 - return strtotime( $pattern, $current );
531 - }
532 -
533 - /**
534 - * Advances a date by a set number of months
535 - *
536 - * Advances a date by a set number of months. When the date of the first active period lies
537 - * on the 29th, 30th, or 31st of the month, this function will return a date on the the last day
538 - * of the month for those months not containing those days.
539 - *
540 - * @param int $current UNIX timestamp of the date before incrementing
541 - * @param int $start UNIX timestamp of the first active period's date
542 - * @param int $interval_multiplier Number of months to advance
543 - *
544 - * @return int Unix timestamp of the new date
545 - */
546 - function __getNextMonth( $current, $start, $interval_multiplier )
547 - {
548 - // For most days in the month, it's pretty easy. Get the day of month of the starting date.
549 - $startDay = date( "j", $start );
550 -
551 - // If it's before or on the 28th, just jump the number of months and be done with it.
552 - if ( $startDay <= 28 ) {
553 - return strtotime( $interval_multiplier . " month", $current );
554 - }
555 -
556 - // If it's on the 29th, 30th, or 31st, it gets tricky. Some months don't have those days - so on those
557 - // months we need to repeat on the last day of the month instead, but we also need to jump back to the
558 - // correct day the following month. Let's say we want to repeat something on the 31st every month: this
559 - // is what we expect to see for a pattern:
560 - //
561 - // .
562 - // .
563 - // .
564 - // December 31st
565 - // January 31st
566 - // February 28th
567 - // March 31st
568 - // April 30th
569 - // .
570 - // .
571 - // .
572 - //
573 - // Unfortunately, PHP relative date handling isn't that smart (add "+1 month" to January 31st, and you
574 - // end up in March), so we'll have to figure it out ourselves by figuring out how many days to jump instead.
575 -
576 - // We'll need to calculate this for each interval and return the timestamp after the last jump.
577 - $temp_current = $current;
578 - for ( $i = 0; $i < $interval_multiplier; $i ++ ) {
579 - // The pattern for jumping will be different in each interval.
580 - /** @noinspection PhpUnusedLocalVariableInspection */
581 - $temp_pattern = "";
582 -
583 - // Get the month number of the current date.
584 - //$currentMonth = date( "n", $temp_current );
585 -
586 - // Get the number of days in the month of the current date.
587 - $lastDayThisMonth = date( "t", strtotime( "this month", $temp_current ) );
588 -
589 - // Get the number of days for the next month relative to the current date .
590 - // Subtract 3 days from the next month to counter known month skipping bugs in PHP's relative date
591 - // handling, that being the difference between the shortest possible month (non-leap February - 28 days)
592 - // and the longest (Jan., Mar., May, Jul., Aug., Oct., Dec. - 31 days). This may be fixed in PHP 5.3.x
593 - // but this should be backwards-compatible anyway.
594 - $lastDayNextMonth = date( "t", strtotime( "-3 day next month", $temp_current ) );
595 -
596 - // If the current month is longer than next month, follow this block
597 - if ( $lastDayThisMonth > $lastDayNextMonth ) {
598 - // If we're repeating on the last day of this month, jump the number of days next month
599 - if ( $startDay == $lastDayThisMonth ) {
600 - $temp_pattern = $lastDayNextMonth . " days";
601 - }
602 - // If the start day doesn't exist in the next month (i.e., no "31st" in June), jump the
603 - // number of days next month plus the difference between the start day and the number of days this month
604 - elseif ( $startDay > $lastDayNextMonth ) {
605 - $temp_pattern = ( $lastDayThisMonth + $lastDayNextMonth - $startDay ) . " days";
606 - } // Otherwise, jump ahead the number of days in this month
607 - else {
608 - $temp_pattern = $lastDayThisMonth . " days";
609 - }
610 - } // Or, if the current month is shorter than next month
611 - elseif ( $lastDayThisMonth < $lastDayNextMonth ) {
612 - // If the start day doesn't exist in this month (i.e., no "31st" in June), jump the
613 - // number of days next month plus the difference between the start day and the number of days this month
614 - if ( $startDay >= $lastDayThisMonth ) {
615 - $temp_pattern = $startDay . " days";
616 - } // Otherwise, jump ahead the number of days in this month
617 - else {
618 - $temp_pattern = $lastDayThisMonth . " days";
619 - }
620 - } // If the current month and next month are equally long, jumping by "1 month" is fine
621 - else {
622 - $temp_pattern = "1 month";
623 - }
624 -
625 - $temp_current = strtotime( $temp_pattern, $temp_current );
626 - }
627 -
628 - return $temp_current;
629 -
630 - }
631 -
632 - /**
633 - * Advances a date to the 'n'th weekday of the next month (eg., first Wednesday, third Monday, last Friday, etc.).
634 - *
635 - * NB: if $ordinal is set to '4' and $day is set to '7', it wil return the last day of the month.
636 - *
637 - * @param int $current UNIX timestamp of the date before incrementing
638 - * @param int $ordinal Integer symbolizing the ordinal (0 - first, 1 - second, 2 - third, 3 - fourth, 4 - last)
639 - * @param int $day Integers symbolizing the days of the week to repeat on
640 - * (0 - Sunday, 1 - Monday, ..., 6 - Saturday, 7 - day).
641 - *
642 - * @return int Unix timestamp of the new date
643 - */
644 - function __getNthWeekdayOfMonth( $current, $ordinal, $day )
645 - {
646 - // First, get the month/year we need to work with
647 - $the_month = date( "F", $current );
648 - $the_year = date( "Y", $current );
649 - $lastDayThisMonth = date( "t", $current );
650 -
651 - // Get the time for the $current timestamp
652 - $current_time = date( "g:i A", $current );
653 - $the_day = "";
654 -
655 - if ( $day == 7 ) { // If $day is "day of the month", get the day of month based on the ordinal
656 - switch ( $ordinal ) {
657 - case 0 :
658 - $the_day = "1";
659 - break; // First day of the month //
660 - case 1 :
661 - $the_day = "2";
662 - break; // Second day of the month //
663 - case 2 :
664 - $the_day = "3";
665 - break; // Third day of the month //
666 - case 3 :
667 - $the_day = "4";
668 - break; // Fourth day of the month //
669 - case 4 :
670 - $the_day = $lastDayThisMonth;
671 - break; // Last day of the month //
672 - default :
673 - $the_day = "1";
674 - break;
675 - }
676 - } else { // If $day is one of the days of the week...
677 - $day_range = array();
678 - switch ( $ordinal ) { // ...get a 7-day range based on the ordinal...
679 - case 0 :
680 - $day_range = range( 1, 7 );
681 - break; // First 7 days of the month //
682 - case 1 :
683 - $day_range = range( 8, 14 );
684 - break; // Second 7 days of the month //
685 - case 2 :
686 - $day_range = range( 15, 21 );
687 - break; // Third 7 days of the month //
688 - case 3 :
689 - $day_range = range( 22, 28 );
690 - break; // Fourth 7 days of the month //
691 - case 4 :
692 - $day_range = range( $lastDayThisMonth - 6, $lastDayThisMonth );
693 - break; // Last 7 days of the month //
694 - default :
695 - $day_range = range( 1, 7 );
696 - break;
697 - }
698 - foreach ( $day_range as $a_day ) { // ...and find the matching weekday in that range.
699 - if ( $day == date( "w", strtotime( $the_month . " " . $a_day . ", " . $the_year ) ) ) {
700 - $the_day = $a_day;
701 - break;
702 - }
703 - }
704 - }
705 -
706 - // Build the date string for the correct day and return its timestamp
707 - $pattern = $the_month . " " . $the_day . ", " . $the_year . ", " . $current_time;
708 -
709 - return strtotime( $pattern );
710 -
711 - }
712 -
713 - /**
714 - * Advances a date by a set number of years
715 - *
716 - * @param int $current UNIX timestamp of the date before incrementing
717 - * @param int $interval_multiplier Number of years to advance
718 - *
719 - * @return int Unix timestamp of the new date
720 - */
721 - function __getNextYear( $current, $interval_multiplier )
722 - {
723 - return strtotime( $interval_multiplier . " year", $current );
724 - }
725 -
726 - /**
727 - * Validates the various Timed Content Rule parameters and returns a series of error messages.
728 - *
729 - * @param $args Array of Timed Content Rule parameters
730 - *
731 - * @return array Array of error messages
732 - */
733 - function __validate( $args )
734 - {
735 - $errors = array();
736 -
737 - $instance_start = DateTime::createFromFormat('Y-m-d', $args['instance_start']['date']);
738 - if($instance_start != false) {
739 - $instance_start = $instance_start->getTimestamp();
740 - }
741 - $instance_end= DateTime::createFromFormat('Y-m-d', $args['instance_end']['date']);
742 - if($instance_end != false) {
743 - $instance_end = $instance_end->getTimestamp();
744 - }
745 - $end_date = DateTime::createFromFormat('Y-m-d', $args['end_date']);
746 - if($end_date != false) {
747 - $end_date = $end_date->getTimestamp();
748 - }
749 -
750 - if ($args['instance_start']['date'] == "") {
751 - $errors[] = __( "Starting date must not be empty.", 'timed-content' );
752 - }
753 - if ($args['instance_start']['time'] == "") {
754 - $errors[] = __("Starting time must not be empty.", 'timed-content');
755 - }
756 - if ($args['instance_end']['date'] == "") {
757 - $errors[] = __("Ending date must not be empty.", 'timed-content');
758 - }
759 - if ($args['instance_end']['time'] == "") {
760 - $errors[] = __("Ending time must not be empty.", 'timed-content');
761 - }
762 - if ($args['interval_multiplier'] == "") {
763 - $errors[] = __("Number of recurrences must not be empty.", 'timed-content');
764 - }
765 - if (! is_numeric($args['interval_multiplier'])) {
766 - $errors[] = __("Number of recurrences must be a number.", 'timed-content');
767 - }
768 - if (($args['num_repeat'] == "") && ($args['recurr_type'] == "recurrence_duration_num_repeat")) {
769 - $errors[] = __("Number of repetitions must not be empty.", 'timed-content');
770 - }
771 - if ((! is_numeric($args['num_repeat'])) && ($args['recurr_type'] == "recurrence_duration_num_repeat")) {
772 - $errors[] = __("Number of repetitions must be a number.", 'timed-content');
773 - }
774 - if (($args['end_date'] == "") && ($args['recurr_type'] == "recurrence_duration_end_date")) {
775 - $errors[] = __("End date must not be empty.", 'timed-content');
776 - }
777 - if (false === $args['instance_start']) {
778 - $errors[] = __("Starting date/time must be valid.", 'timed-content');
779 - }
780 - if (false === $args['instance_end']) {
781 - $errors[] = __("Ending date/time must be valid.", 'timed-content');
782 - }
783 - if ($instance_start > $instance_end) {
784 - $errors[] = __("Starting date/time must be before ending date/time.", 'timed-content');
785 - }
786 - if (($instance_end > $end_date) && ($args['recurr_type'] == "recurrence_duration_end_date")) {
787 - $errors[] = __("Recurrence end date must be after ending date/time.", 'timed-content');
788 - }
789 -
790 - return $errors;
791 - }
792 -
793 - /**
794 - * Calculates the active periods for a Timed Content Rule
795 - *
796 - * @param $args Array of Timed Content Rule parameters
797 - *
798 - * @return array Array of active periods. Each value in the array describes an active period as an array itself
799 - * with "start" and "end" keys and values that are either UNIX timestamps or human-readable dates,
800 - * based on whether $args['human_readable'] is set to true or false.
801 - */
802 - function __getRulePeriods( $args )
803 - {
804 - $active_periods = array();
805 - $period_count = 0;
806 -
807 - $human_readable = $args['human_readable'];
808 - $freq = $args['freq'];
809 - $timezone = $args['timezone'];
810 - $recurr_type = $args['recurr_type'];
811 - $num_repeat = intval( $args['num_repeat'] );
812 - $end_date = $args['end_date'];
813 - $days_of_week = $args['days_of_week'];
814 - $interval_multiplier = $args['interval_multiplier'];
815 - $instance_start_date = $args['instance_start']['date'];
816 - $instance_start_time = $args['instance_start']['time'];
817 - $instance_end_date = $args['instance_end']['date'];
818 - $instance_end_time = $args['instance_end']['time'];
819 - $monthly_pattern = $args['monthly_pattern'];
820 - $monthly_pattern_ord = $args['monthly_pattern_ord'];
821 - $monthly_pattern_day = $args['monthly_pattern_day'];
822 - $exceptions_dates = $args['exceptions_dates'];
823 - //print_r($days_of_week);
824 -
825 - add_filter( 'date_i18n', array( &$this, "fix_date_i18n" ), 10, 4 );
826 - $temp_tz = date_default_timezone_get();
827 - date_default_timezone_set( $timezone );
828 - $right_now_t = current_time( 'timestamp', 1 );
829 -
830 - // use debug parameter if current user is allowed to edit the post
831 - if ( isset( $_GET['tctest'] ) && current_user_can( "edit_post", $post->post_id ) ) {
832 - $dt = DateTime::createFromFormat( 'Y-m-d H:i:s', $_GET['tctest'] );
833 - if ( $dt != false ) {
834 - $right_now_t = $dt->getTimestamp();
835 - }
836 - }
837 -
838 - $instance_start = strtotime( $this->__datetimeToEnglish( $instance_start_date,
839 - $instance_start_time ) . " " . $timezone ); // Beginning of first occurrence
840 - $instance_end = strtotime( $this->__datetimeToEnglish( $instance_end_date,
841 - $instance_end_time ) . " " . $timezone ); // End of first occurrence
842 - $current = $instance_start;
843 - $end_current = $instance_end;
844 -
845 - if ( $recurr_type == "recurrence_duration_num_repeat" ) {
846 - $last_occurrence_start = strtotime( TIMED_CONTENT_TIME_END );
847 - } else {
848 - $last_occurrence_start = strtotime( $this->__datetimeToEnglish( $end_date,
849 - $instance_start_time ) . " " . $timezone );
850 - }
851 -
852 - if ( $human_readable == true ) {
853 - $active_periods[ $period_count ]["start"] = date_i18n( TIMED_CONTENT_DATE_FORMAT_OUTPUT, $current );
854 - $active_periods[ $period_count ]["end"] = date_i18n( TIMED_CONTENT_DATE_FORMAT_OUTPUT, $end_current );
855 - if ( $right_now_t < $current ) {
856 - $active_periods[ $period_count ]["status"] = "upcoming";
857 - $active_periods[ $period_count ]["time"] = sprintf( _x( '%s from now.',
858 - 'Human readable time difference', 'timed-content' ),
859 - human_time_diff( $right_now_t, $current ) );
860 - } elseif ( ( $current <= $right_now_t ) && ( $right_now_t <= $end_current ) ) {
861 - $active_periods[ $period_count ]["status"] = "active";
862 - $active_periods[ $period_count ]["time"] = __( "Right now!", 'timed-content' );
863 - } else {
864 - $active_periods[ $period_count ]["status"] = "expired";
865 - $active_periods[ $period_count ]["time"] = sprintf( _x( '%s ago.',
866 - 'Human readable time difference', 'timed-content' ),
867 - human_time_diff( $end_current, $right_now_t ) );
868 - }
869 - } else {
870 - $active_periods[ $period_count ]["start"] = $current;
871 - $active_periods[ $period_count ]["end"] = $end_current;
872 - }
873 - $period_count ++;
874 -
875 - if ( $recurr_type == "recurrence_duration_end_date" ) {
876 - $loop_test = "return ( \$current < \$last_occurrence_start );";
877 - } else {
878 - $loop_test = "return ( \$period_count <= \$num_repeat );";
879 - }
880 -
881 - while ( eval ( $loop_test ) ) {
882 - $temp_current = "";
883 - if ( $freq == 0 ) {
884 - $current = $this->__getNextHour( $current, $interval_multiplier );
885 - } elseif ( $freq == 1 ) {
886 - $current = $this->__getNextDay( $current, $interval_multiplier );
887 - } elseif ( $freq == 2 ) {
888 - $current = $this->__getNextWeek( $current, $interval_multiplier, $days_of_week );
889 - } elseif ( $freq == 3 ) {
890 - $current = $this->__getNextMonth( $current, $instance_start, $interval_multiplier );
891 - $temp_current = $current;
892 - if ( $monthly_pattern == "yes" ) {
893 - $current = $this->__getNthWeekdayOfMonth( $current, $monthly_pattern_ord,
894 - $monthly_pattern_day );
895 - } else {
896 - $current = $temp_current;
897 - }
898 - } elseif ( $freq == 4 ) {
899 - $current = $this->__getNextYear( $current, $interval_multiplier );
900 - }
901 -
902 - $exception_period = false;
903 - if ( is_array( $exceptions_dates ) ) {
904 - foreach ( $exceptions_dates as $date ) {
905 - if ( ( $current >= $date ) && ( $current < strtotime( "+1 day", $date ) ) ) {
906 - $exception_period = true;
907 - break;
908 - }
909 - }
910 - }
911 -
912 - if ( ( eval ( $loop_test ) ) && ( ! ( $exception_period ) ) ) {
913 - $end_current = $current + ( $instance_end - $instance_start );
914 - if ( $human_readable == true ) {
915 - $active_periods[ $period_count ]["start"] = date_i18n( TIMED_CONTENT_DATE_FORMAT_OUTPUT, $current );
916 - $active_periods[ $period_count ]["end"] = date_i18n( TIMED_CONTENT_DATE_FORMAT_OUTPUT, $end_current );
917 - if ( $right_now_t < $current ) {
918 - $active_periods[ $period_count ]["status"] = "upcoming";
919 - $active_periods[ $period_count ]["time"] = sprintf( _x( '%s from now.',
920 - 'Human readable time difference', 'timed-content' ),
921 - human_time_diff( $current, $right_now_t ) );
922 - } elseif ( ( $current <= $right_now_t ) && ( $right_now_t <= $end_current ) ) {
923 - $active_periods[ $period_count ]["status"] = "active";
924 - $active_periods[ $period_count ]["time"] = __( "Right now!", 'timed-content' );
925 - } else {
926 - $active_periods[ $period_count ]["status"] = "expired";
927 - $active_periods[ $period_count ]["time"] = sprintf( _x( '%s ago.',
928 - 'Human readable time difference', 'timed-content' ),
929 - human_time_diff( $end_current, $right_now_t ) );
930 - }
931 - } else {
932 - $active_periods[ $period_count ]["start"] = $current;
933 - $active_periods[ $period_count ]["end"] = $end_current;
934 - }
935 - if ( ! ( $exception_period ) ) {
936 - $period_count ++;
937 - }
938 - }
939 -
940 - }
941 - date_default_timezone_set( $temp_tz );
942 - remove_filter( 'date_i18n', array( &$this, "fix_date_i18n" ), 10, 4 );
943 -
944 - return $active_periods;
945 - }
946 -
947 - /**
948 - * Wrapper for calling timedContentPlugin::__getRulePeriods() by the ID of a Timed Content Rule
949 - *
950 - * @param int $ID ID of the Timed Content Rule
951 - * @param bool $human_readable If true, the active periods are returned as a human-readable date
952 - * as defined by the constant TIMED_CONTENT_DT_FORMAT_OUTPUT otherwise,
953 - * they are returned as UNIX timestamps.
954 - *
955 - * @return array Array of active periods
956 - */
957 - function getRulePeriodsById( $ID, $human_readable = false )
958 - {
959 - if ( TIMED_CONTENT_RULE_TYPE != get_post_type( $ID ) ) {
960 - return array();
961 - }
962 -
963 - $prefix = TIMED_CONTENT_RULE_POSTMETA_PREFIX;
964 - $args = array();
965 -
966 - $args['human_readable'] = (bool) $human_readable;
967 - $args['freq'] = get_post_meta( $ID, $prefix . 'frequency', true );
968 - $args['timezone'] = get_post_meta( $ID, $prefix . 'timezone', true );
969 - $args['recurr_type'] = get_post_meta( $ID, $prefix . 'recurrence_duration', true );
970 - $args['num_repeat'] = get_post_meta( $ID, $prefix . 'recurrence_duration_num_repeat', true );
971 - $args['end_date'] = get_post_meta( $ID, $prefix . 'recurrence_duration_end_date', true );
972 - $args['days_of_week'] = get_post_meta( $ID, $prefix . 'weekly_days_of_week_to_repeat', true );
973 - if ( $args['freq'] == 0 ) {
974 - $args['interval_multiplier'] = get_post_meta( $ID, $prefix . 'hourly_num_of_hours', true );
975 - }
976 - if ( $args['freq'] == 1 ) {
977 - $args['interval_multiplier'] = get_post_meta( $ID, $prefix . 'daily_num_of_days', true );
978 - }
979 - if ( $args['freq'] == 2 ) {
980 - $args['interval_multiplier'] = get_post_meta( $ID, $prefix . 'weekly_num_of_weeks', true );
981 - }
982 - if ( $args['freq'] == 3 ) {
983 - $args['interval_multiplier'] = get_post_meta( $ID, $prefix . 'monthly_num_of_months', true );
984 - }
985 - if ( $args['freq'] == 4 ) {
986 - $args['interval_multiplier'] = get_post_meta( $ID, $prefix . 'yearly_num_of_years', true );
987 - }
988 - $args['instance_start'] = get_post_meta( $ID, $prefix . 'instance_start', true );
989 - $args['instance_end'] = get_post_meta( $ID, $prefix . 'instance_end', true );
990 - $args['monthly_pattern'] = get_post_meta( $ID, $prefix . 'monthly_nth_weekday_of_month', true );
991 - $args['monthly_pattern_ord'] = get_post_meta( $ID, $prefix . 'monthly_nth_weekday_of_month_nth', true );
992 - $args['monthly_pattern_day'] = get_post_meta( $ID, $prefix . 'monthly_nth_weekday_of_month_weekday', true );
993 - $args['exceptions_dates'] = get_post_meta( $ID, $prefix . 'exceptions_dates', true );
994 -
995 - $args = $this->convertDateTimeParametersToISO($args);
996 -
997 - return $this->__getRulePeriods( $args );
998 - }
999 -
1000 - /**
1001 - * Wrapper for calling timedContentPlugin::__getRulePeriods() based on the contents of the form fields
1002 - * of the Add Timed Content Rule and Edit Timed Content Rule screens. Output is sent to output as JSON
1003 - */
1004 - function timedContentPluginGetRulePeriodsAjax()
1005 - {
1006 - if ( current_user_can( 'edit_posts' ) || current_user_can( 'edit_pages' ) ) {
1007 - $prefix = TIMED_CONTENT_RULE_POSTMETA_PREFIX;
1008 - $args = array();
1009 -
1010 - $args['human_readable'] = ( ( ( isset( $_POST[ $prefix . 'human_readable' ] ) ) && ( $_POST[ $prefix . 'human_readable' ] == 'true' ) ) ? (bool) $_POST[ $prefix . 'human_readable' ] : false );
1011 - $args['freq'] = $_POST[ $prefix . 'frequency' ];
1012 - $args['timezone'] = $_POST[ $prefix . 'timezone' ];
1013 - $args['recurr_type'] = $_POST[ $prefix . 'recurrence_duration' ];
1014 - $args['num_repeat'] = $_POST[ $prefix . 'recurrence_duration_num_repeat' ];
1015 - $args['end_date'] = $_POST[ $prefix . 'recurrence_duration_end_date' ];
1016 - $args['days_of_week'] = ( isset( $_POST[ $prefix . 'weekly_days_of_week_to_repeat' ] ) ? $_POST[ $prefix . 'weekly_days_of_week_to_repeat' ] : array() );
1017 - $args['interval_multiplier'] = $_POST[ $prefix . 'interval_multiplier' ];
1018 - $args['instance_start'] = $_POST[ $prefix . 'instance_start' ];
1019 - $args['instance_end'] = $_POST[ $prefix . 'instance_end' ];
1020 - $args['monthly_pattern'] = $_POST[ $prefix . 'monthly_nth_weekday_of_month' ];
1021 - $args['monthly_pattern_ord'] = $_POST[ $prefix . 'monthly_nth_weekday_of_month_nth' ];
1022 - $args['monthly_pattern_day'] = $_POST[ $prefix . 'monthly_nth_weekday_of_month_weekday' ];
1023 - $args['exceptions_dates'] = ( isset( $_POST[ $prefix . 'exceptions_dates' ] ) ? $_POST[ $prefix . 'exceptions_dates' ] : array() );
1024 -
1025 - $response = json_encode( $this->__getRulePeriods( $args ) );
1026 -
1027 - // response output
1028 - header( "Content-Type: application/json" );
1029 - echo $response;
1030 - }
1031 - die();
1032 -
1033 - }
1034 -
1035 - /**
1036 - * Returns a human-readable description of a Timed Content Rule
1037 - *
1038 - * @param $args Array of Timed Content Rule parameters
1039 - *
1040 - * @return string Schedule description or warning, if the rule may not work properly
1041 - */
1042 - function __getScheduleDescription( $args )
1043 - {
1044 - $interval_multiplier = 1;
1045 - $desc = "";
1046 -
1047 - $errors = $this->__validate( $args );
1048 - if ( $errors ) {
1049 - $messages = "<div class=\"tcr-warning\">\n";
1050 - $messages .= "<p class=\"heading\">" . __( "Warning!", 'timed-content' ) . "</p>\n";
1051 - $messages .= "<p>" . __( "Some problems have been detected. Although you can still publish this rule, it may not work the way you expect.", 'timed-content' ) . "</p>\n";
1052 - $messages .= "<ul>\n";
1053 - foreach ( $errors as $error ) {
1054 - $messages .= " <li>" . $error . "</li>\n";
1055 - }
1056 - $messages .= "</ul>\n";
1057 - $messages .= "<p>" . __( "Check that all of the conditions for this rule are correct, and use <b>Show projected dates/times</b> to ensure your rule is working properly.", 'timed-content' ) . "</p>\n";
1058 - $messages .= "</div>\n";
1059 -
1060 - return $messages;
1061 - }
1062 -
1063 - if ( $args['action'] ) {
1064 - $action = __( "Show the content", 'timed-content' );
1065 - } else {
1066 - $action = __( "Hide the content", 'timed-content' );
1067 - }
1068 - $freq = $args['freq'];
1069 - $timezone = $args['timezone'];
1070 - $recurr_type = $args['recurr_type'];
1071 - $num_repeat = intval( $args['num_repeat'] );
1072 - $end_date = $args['end_date'];
1073 - $days_of_week = $args['days_of_week'];
1074 - $interval_multiplier = $args['interval_multiplier'];
1075 - $instance_start_date = $args['instance_start']['date'];
1076 - $instance_start_time = $args['instance_start']['time'];
1077 - $instance_end_date = $args['instance_end']['date'];
1078 - $instance_end_time = $args['instance_end']['time'];
1079 - $monthly_pattern = $args['monthly_pattern'];
1080 - $monthly_pattern_ord = $args['monthly_pattern_ord'];
1081 - $monthly_pattern_day = $args['monthly_pattern_day'];
1082 - $exceptions_dates = $args['exceptions_dates'];
1083 -
1084 - $desc = sprintf( _x( '%1$s on %2$s @ %3$s until %4$s @ %5$s.',
1085 - 'Perform action (%1$s) from date/time of first active period (%2$s @ %3$s) until date/time of last active period (%4$s @ %5$s).',
1086 - 'timed-content' ), $action, $instance_start_date, $instance_start_time, $instance_end_date,
1087 - $instance_end_time );
1088 -
1089 - if ( $freq == 0 ) {
1090 - $desc .= "<br />" . sprintf( _n( 'Repeat this action every hour.', 'Repeat this action every %d hours.',
1091 - $interval_multiplier, 'timed-content' ), $interval_multiplier );
1092 - } elseif ( $freq == 1 ) {
1093 - $desc .= "<br />" . sprintf( _n( 'Repeat this action every day.', 'Repeat this action every %d days.',
1094 - $interval_multiplier, 'timed-content' ), $interval_multiplier );
1095 - } elseif ( $freq == 2 ) {
1096 - if ( ( $days_of_week ) && ( is_array( $days_of_week ) ) ) {
1097 - $days = array();
1098 - $days_list = "";
1099 - foreach ( $days_of_week as $v ) {
1100 - $days[] = $this->rule_days_array[ $v ];
1101 - }
1102 - switch ( count( $days ) ) {
1103 - case 1:
1104 - $days_list = sprintf( _x( '%1$s', 'List of one weekday', 'timed-content' ), $days[0] );
1105 - break;
1106 - case 2:
1107 - $days_list = sprintf( _x( '%1$s and %2$s', 'List of two weekdays', 'timed-content' ),
1108 - $days[0], $days[1] );
1109 - break;
1110 - case 3:
1111 - $days_list = sprintf( _x( '%1$s, %2$s and %3$s', 'List of three weekdays',
1112 - 'timed-content' ), $days[0], $days[1], $days[2] );
1113 - break;
1114 - case 4:
1115 - $days_list = sprintf( _x( '%1$s, %2$s, %3$s and %4$s', 'List of four weekdays',
1116 - 'timed-content' ), $days[0], $days[1], $days[2], $days[3] );
1117 - break;
1118 - case 5:
1119 - $days_list = sprintf( _x( '%1$s, %2$s, %3$s, %4$s and %5$s', 'List of five weekdays',
1120 - 'timed-content' ), $days[0], $days[1], $days[2], $days[3], $days[4] );
1121 - break;
1122 - case 6:
1123 - $days_list = sprintf( _x( '%1$s, %2$s, %3$s, %4$s, %5$s and %6$s', 'List of six weekdays',
1124 - 'timed-content' ), $days[0], $days[1], $days[2], $days[3], $days[4], $days[5] );
1125 - break;
1126 - case 7:
1127 - $days_list = sprintf( _x( '%1$s, %2$s, %3$s, %4$s, %5$s, %6$s and %7$s',
1128 - 'List of all weekdays', 'timed-content' ), $days[0], $days[1], $days[2], $days[3],
1129 - $days[4], $days[5], $days[6] );
1130 - break;
1131 - }
1132 - if ( $interval_multiplier == 1 ) {
1133 - $desc .= "<br />" . sprintf( _x( 'Repeat this action every week on %s.',
1134 - 'List the weekdays to repeat the rule when frequency is every week. %s is the list of weekdays.',
1135 - 'timed-content' ), $days_list );
1136 - } else {
1137 - $desc .= "<br />" . sprintf( _x( 'Repeat this action every %1$d weeks on %2$s.',
1138 - 'List the weekdays to repeat the rule when frequency is every %1$d weeks. %2$s is the list of weekdays.',
1139 - 'timed-content' ), $interval_multiplier, $days_list );
1140 - }
1141 - } else {
1142 - $desc .= "<br />" . sprintf( _n( 'Repeat this action every week.',
1143 - 'Repeat this action every %d weeks.', $interval_multiplier, 'timed-content' ),
1144 - $interval_multiplier );
1145 - }
1146 -
1147 - } elseif ( $freq == 3 ) {
1148 - if ( $monthly_pattern == "yes" ) {
1149 - if ( $interval_multiplier == 1 ) {
1150 - $desc .= "<br />" . sprintf( _x( 'Repeat this action every month on the %1$s %2$s of the month.',
1151 - "Example: 'Repeat this action every month on the second Friday of the month.'",
1152 - 'timed-content' ), $this->rule_ordinal_array[ $monthly_pattern_ord ],
1153 - $this->rule_ordinal_days_array[ $monthly_pattern_day ] );
1154 - } else {
1155 - $desc .= "<br />" . sprintf( _x( 'Repeat this action every %1$d months on the %2$s %3$s of the month.',
1156 - "Example: 'Repeat this action every 2 months on the second Friday of the month.'",
1157 - 'timed-content' ), $interval_multiplier,
1158 - $this->rule_ordinal_array[ $monthly_pattern_ord ],
1159 - $this->rule_ordinal_days_array[ $monthly_pattern_day ] );
1160 - }
1161 - } else {
1162 - $desc .= "<br />" . sprintf( _n( 'Repeat this action every month.',
1163 - 'Repeat this action every %d months.', $interval_multiplier, 'timed-content' ),
1164 - $interval_multiplier );
1165 - }
1166 - } elseif ( $freq == 4 ) {
1167 - $desc .= "<br />" . sprintf( _n( 'Repeat this action every year.', 'Repeat this action every %d years.',
1168 - $interval_multiplier, 'timed-content' ), $interval_multiplier );
1169 - }
1170 -
1171 - if ( $recurr_type == "recurrence_duration_num_repeat" ) {
1172 - $desc .= "<br />" . sprintf( _n( 'This rule will be active for one recurrence.',
1173 - 'This rule will be active for %d recurrences.', $num_repeat, 'timed-content' ), $num_repeat );
1174 - } elseif ( $recurr_type == "recurrence_duration_end_date" ) {
1175 - $desc .= "<br />" . sprintf( __( 'This rule will be active until %s.', 'timed-content' ), $end_date );
1176 - }
1177 -
1178 - if ( ( $exceptions_dates ) && ( is_array( $exceptions_dates ) ) ) {
1179 - sort( $exceptions_dates, SORT_NUMERIC );
1180 - $exceptions_dates = array_unique( $exceptions_dates );
1181 - if ( $exceptions_dates[0] == 0 ) {
1182 - array_shift( $exceptions_dates );
1183 - }
1184 - if ( ! empty( $exceptions_dates ) ) {
1185 - $desc .= "<br />" . sprintf( __( 'This rule will be inactive on the following dates: %s.',
1186 - 'timed-content' ), join( ", ", $exceptions_dates ) );
1187 - }
1188 - }
1189 -
1190 - $desc .= "<br />" . sprintf( __( 'All times are in the %s timezone.', 'timed-content' ), $timezone );
1191 -
1192 - return $desc;
1193 - }
1194 -
1195 - /**
1196 - * Wrapper for calling timedContentPlugin::__getScheduleDescription() by the ID of a Timed Content Rule
1197 - *
1198 - * @param int $ID ID of the Timed Content Rule
1199 - *
1200 - * @return string
1201 - */
1202 - function getScheduleDescriptionById( $ID )
1203 - {
1204 - $defaults = array();
1205 -
1206 - foreach ( $this->rule_occurrence_custom_fields as $field ) {
1207 - $defaults[ $field['name'] ] = $field['default'];
1208 - }
1209 - foreach ( $this->rule_pattern_custom_fields as $field ) {
1210 - $defaults[ $field['name'] ] = $field['default'];
1211 - }
1212 - foreach ( $this->rule_recurrence_custom_fields as $field ) {
1213 - $defaults[ $field['name'] ] = $field['default'];
1214 - }
1215 - foreach ( $this->rule_exceptions_custom_fields as $field ) {
1216 - $defaults[ $field['name'] ] = $field['default'];
1217 - }
1218 -
1219 - $prefix = TIMED_CONTENT_RULE_POSTMETA_PREFIX;
1220 - $args = array();
1221 -
1222 - $args['action'] = ( false === get_post_meta( $ID, $prefix . 'action',
1223 - true ) ? $defaults['action'] : get_post_meta( $ID, $prefix . 'action', true ) );
1224 - $args['freq'] = ( false === get_post_meta( $ID, $prefix . 'frequency',
1225 - true ) ? $defaults['frequency'] : get_post_meta( $ID, $prefix . 'frequency', true ) );
1226 - $args['timezone'] = ( false === get_post_meta( $ID, $prefix . 'timezone',
1227 - true ) ? $defaults['timezone'] : get_post_meta( $ID, $prefix . 'timezone', true ) );
1228 - $args['recurr_type'] = ( false === get_post_meta( $ID, $prefix . 'recurrence_duration',
1229 - true ) ? $defaults['recurrence_duration'] : get_post_meta( $ID, $prefix . 'recurrence_duration',
1230 - true ) );
1231 - $args['num_repeat'] = ( false === get_post_meta( $ID, $prefix . 'recurrence_duration_num_repeat',
1232 - true ) ? $defaults['recurrence_duration_num_repeat'] : get_post_meta( $ID,
1233 - $prefix . 'recurrence_duration_num_repeat', true ) );
1234 - $args['end_date'] = ( false === get_post_meta( $ID, $prefix . 'recurrence_duration_end_date',
1235 - true ) ? $defaults['recurrence_duration_end_date'] : get_post_meta( $ID,
1236 - $prefix . 'recurrence_duration_end_date', true ) );
1237 - $args['days_of_week'] = ( false === get_post_meta( $ID, $prefix . 'weekly_days_of_week_to_repeat',
1238 - true ) ? $defaults['weekly_days_of_week_to_repeat'] : get_post_meta( $ID,
1239 - $prefix . 'weekly_days_of_week_to_repeat', true ) );
1240 - if ( $args['freq'] == 0 ) {
1241 - $args['interval_multiplier'] = ( false === get_post_meta( $ID, $prefix . 'hourly_num_of_hours',
1242 - true ) ? $defaults['hourly_num_of_hours'] : get_post_meta( $ID, $prefix . 'hourly_num_of_hours',
1243 - true ) );
1244 - }
1245 - if ( $args['freq'] == 1 ) {
1246 - $args['interval_multiplier'] = ( false === get_post_meta( $ID, $prefix . 'daily_num_of_days',
1247 - true ) ? $defaults['daily_num_of_days'] : get_post_meta( $ID, $prefix . 'daily_num_of_days',
1248 - true ) );
1249 - }
1250 - if ( $args['freq'] == 2 ) {
1251 - $args['interval_multiplier'] = ( false === get_post_meta( $ID, $prefix . 'weekly_num_of_weeks',
1252 - true ) ? $defaults['weekly_num_of_weeks'] : get_post_meta( $ID, $prefix . 'weekly_num_of_weeks',
1253 - true ) );
1254 - }
1255 - if ( $args['freq'] == 3 ) {
1256 - $args['interval_multiplier'] = ( false === get_post_meta( $ID, $prefix . 'monthly_num_of_months',
1257 - true ) ? $defaults['monthly_num_of_months'] : get_post_meta( $ID, $prefix . 'monthly_num_of_months',
1258 - true ) );
1259 - }
1260 - if ( $args['freq'] == 4 ) {
1261 - $args['interval_multiplier'] = ( false === get_post_meta( $ID, $prefix . 'yearly_num_of_years',
1262 - true ) ? $defaults['yearly_num_of_years'] : get_post_meta( $ID, $prefix . 'yearly_num_of_years',
1263 - true ) );
1264 - }
1265 - $args['instance_start'] = ( false === get_post_meta( $ID, $prefix . 'instance_start',
1266 - true ) ? $defaults['instance_start'] : get_post_meta( $ID, $prefix . 'instance_start', true ) );
1267 - $args['instance_end'] = ( false === get_post_meta( $ID, $prefix . 'instance_end',
1268 - true ) ? $defaults['instance_end'] : get_post_meta( $ID, $prefix . 'instance_end', true ) );
1269 - $args['monthly_pattern'] = ( false === get_post_meta( $ID, $prefix . 'monthly_nth_weekday_of_month',
1270 - true ) ? $defaults['monthly_nth_weekday_of_month'] : get_post_meta( $ID,
1271 - $prefix . 'monthly_nth_weekday_of_month', true ) );
1272 - $args['monthly_pattern_ord'] = ( false === get_post_meta( $ID, $prefix . 'monthly_nth_weekday_of_month_nth',
1273 - true ) ? $defaults['monthly_nth_weekday_of_month_nth'] : get_post_meta( $ID,
1274 - $prefix . 'monthly_nth_weekday_of_month_nth', true ) );
1275 - $args['monthly_pattern_day'] = ( false === get_post_meta( $ID,
1276 - $prefix . 'monthly_nth_weekday_of_month_weekday',
1277 - true ) ? $defaults['monthly_nth_weekday_of_month_weekday'] : get_post_meta( $ID,
1278 - $prefix . 'monthly_nth_weekday_of_month_weekday', true ) );
1279 - $args['exceptions_dates'] = ( false === get_post_meta( $ID, $prefix . 'exceptions_dates',
1280 - true ) ? $defaults['exceptions_dates'] : get_post_meta( $ID, $prefix . 'exceptions_dates', true ) );
1281 -
1282 - $args = $this->convertDateTimeParametersToISO( $args );
1283 -
1284 - return $this->__getScheduleDescription( $args );
1285 - }
1286 -
1287 - /**
1288 - * Wrapper for calling timedContentPlugin::__getRulePeriods() based on the contents of the form fields
1289 - * of the Add Timed Content Rule and Edit Timed Content Rule screens. Output is sent to output as plain text
1290 - */
1291 - function timedContentPluginGetScheduleDescriptionAjax()
1292 - {
1293 - if ( current_user_can( 'edit_posts' ) || current_user_can( 'edit_pages' ) ) {
1294 - $prefix = TIMED_CONTENT_RULE_POSTMETA_PREFIX;
1295 - $args = array();
1296 -
1297 - $args['action'] = $_POST[ $prefix . 'action' ];
1298 - $args['freq'] = $_POST[ $prefix . 'frequency' ];
1299 - $args['timezone'] = $_POST[ $prefix . 'timezone' ];
1300 - $args['recurr_type'] = $_POST[ $prefix . 'recurrence_duration' ];
1301 - $args['num_repeat'] = $_POST[ $prefix . 'recurrence_duration_num_repeat' ];
1302 - $args['end_date'] = $_POST[ $prefix . 'recurrence_duration_end_date' ];
1303 - $args['days_of_week'] = ( isset( $_POST[ $prefix . 'weekly_days_of_week_to_repeat' ] ) ? $_POST[ $prefix . 'weekly_days_of_week_to_repeat' ] : array() );
1304 - $args['interval_multiplier'] = $_POST[ $prefix . 'interval_multiplier' ];
1305 - $args['instance_start'] = $_POST[ $prefix . 'instance_start' ];
1306 - $args['instance_end'] = $_POST[ $prefix . 'instance_end' ];
1307 - $args['monthly_pattern'] = $_POST[ $prefix . 'monthly_nth_weekday_of_month' ];
1308 - $args['monthly_pattern_ord'] = $_POST[ $prefix . 'monthly_nth_weekday_of_month_nth' ];
1309 - $args['monthly_pattern_day'] = $_POST[ $prefix . 'monthly_nth_weekday_of_month_weekday' ];
1310 - $args['exceptions_dates'] = ( isset( $_POST[ $prefix . 'exceptions_dates' ] ) ? $_POST[ $prefix . 'exceptions_dates' ] : array() );
1311 -
1312 - $response = $this->__getScheduleDescription( $args );
1313 -
1314 - // response output
1315 - header( "Content-Type: text/plain" );
1316 - echo $response;
1317 - }
1318 - die();
1319 - }
1320 -
1321 - /**
1322 - * Processes the [timed-content-client] shortcode.
1323 - *
1324 - * @param array $atts Shortcode attributes
1325 - * @param null $content Content inside the shortcode
1326 - *
1327 - * @return string Processed output
1328 - */
1329 - function clientShowHTML( $atts, $content = null )
1330 - {
1331 - $show_attr = "";
1332 - $hide_attr = "";
1333 - extract( shortcode_atts( array( 'show' => '0:00:000', 'hide' => '0:00:000', 'display' => 'div' ), $atts ) );
1334 -
1335 - // Initialize show/hide arguments
1336 - $s_min = 0;
1337 - $s_sec = 0;
1338 - $s_fade = 0;
1339 - $h_min = 0;
1340 - $h_sec = 0;
1341 - $h_fade = 0;
1342 - @list( $s_min, $s_sec, $s_fade ) = explode( ":", $show );
1343 - @list( $h_min, $h_sec, $h_fade ) = explode( ":", $hide );
1344 -
1345 - if ( ( (int) $s_min + (int) $s_sec ) > 0 ) {
1346 - $show_attr = "_show_" . $s_min . "_" . $s_sec . "_" . $s_fade;
1347 - }
1348 - if ( ( (int) $h_min + (int) $h_sec ) > 0 ) {
1349 - $hide_attr = "_hide_" . $h_min . "_" . $h_sec . "_" . $h_fade;
1350 - }
1351 -
1352 - $the_class = TIMED_CONTENT_SHORTCODE_CLIENT . $show_attr . $hide_attr;
1353 - $the_tag = ( $display == "div" ? "div" : "span" );
1354 -
1355 - $the_filter = "timed_content_filter";
1356 - $the_filter = apply_filters( "timed_content_filter_override", $the_filter );
1357 -
1358 - $the_HTML = "<"
1359 - . $the_tag
1360 - . " class='"
1361 - . $the_class
1362 - . "'"
1363 - . ( ( $show_attr != "" ) ? " style='display: none;'" : "" ) . ">"
1364 - . str_replace( ']]>', ']]&gt;', apply_filters( $the_filter, $content ) )
1365 - . "</" . $the_tag . ">";
1366 -
1367 - return $the_HTML;
1368 - }
1369 -
1370 - /**
1371 - * Processes the [timed-content-server] shortcode.
1372 - *
1373 - * @param array $atts Shortcode attributes
1374 - * @param null $content Content inside the shortcode
1375 - *
1376 - * @return string Processed output
1377 - */
1378 - function serverShowHTML( $atts, $content = null )
1379 - {
1380 - global $post;
1381 - extract( shortcode_atts( array(
1382 - 'show' => TIMED_CONTENT_TIME_ZERO,
1383 - 'hide' => TIMED_CONTENT_TIME_END,
1384 - 'debug' => 'false'
1385 - ), $atts ) );
1386 -
1387 - $pos = strrpos( $show, ' ' );
1388 - if ( $pos !== false ) {
1389 - $show_time = substr( $show, 0, $pos );
1390 - $show_tz = substr( $show, $pos + 1 );
1391 - } else {
1392 - $show_time = $show;
1393 - $show_tz = date_default_timezone_get();
1394 - }
1395 -
1396 - // Try to parse date as ISO first
1397 - $show_dt = DateTime::createFromFormat( 'Y-m-d G:i', $show_time, new DateTimeZone( $show_tz ) );
1398 - if ($show_dt === false) {
1399 - $show_dt = DateTime::createFromFormat('m/d/Y G:i', $show_time, new DateTimeZone($show_tz));
1400 - }
1401 -
1402 - if ( $show_dt !== false ) {
1403 - $show_t = $show_dt->getTimeStamp();
1404 - } else {
1405 - $show_t = 0;
1406 - }
1407 -
1408 - $pos = strrpos( $hide, ' ' );
1409 - if ( $pos !== false ) {
1410 - $hide_time = substr( $hide, 0, $pos );
1411 - $hide_tz = substr( $hide, $pos + 1 );
1412 - } else {
1413 - $hide_time = $hide;
1414 - $hide_tz = date_default_timezone_get();
1415 - }
1416 -
1417 - // Try to parse date as ISO first
1418 - $hide_dt = DateTime::createFromFormat( 'Y-m-d H:i:s', $hide_time, new DateTimeZone( $show_tz ) );
1419 - if ($hide_dt === false) {
1420 - $hide_dt = DateTime::createFromFormat( 'm/d/Y G:i', $hide_time, new DateTimeZone( $hide_tz ) );
1421 - }
1422 - if ( $hide_dt !== false ) {
1423 - $hide_t = $hide_dt->getTimeStamp();
1424 - } else {
1425 - $hide_t = 0;
1426 - }
1427 -
1428 - $right_now_t = current_time( 'timestamp', 1 );
1429 - $debug_message = "";
1430 -
1431 - // use debug parameter if current user is allowed to edit the post
1432 - if ( isset( $_GET['tctest'] ) && current_user_can( "edit_post", $post->post_id ) ) {
1433 - $dt = DateTime::createFromFormat( 'Y-m-d H:i:s', $_GET['tctest'] );
1434 - if ( $dt != false ) {
1435 - $right_now_t = $dt->getTimestamp();
1436 - }
1437 - }
1438 -
1439 - $the_filter = "timed_content_filter";
1440 - $the_filter = apply_filters( "timed_content_filter_override", $the_filter );
1441 -
1442 - if ( ( $debug == "true" ) && ( current_user_can( "edit_post", $post->post_id ) ) ) {
1443 - add_filter( 'date_i18n', array( &$this, "fix_date_i18n" ), 10, 4 );
1444 - $temp_tz = date_default_timezone_get();
1445 - date_default_timezone_set( get_option( 'timezone_string' ) );
1446 -
1447 - $right_now = date_i18n( TIMED_CONTENT_DATE_FORMAT_OUTPUT, $right_now_t );
1448 -
1449 - if ( $show_t > $right_now_t ) {
1450 - $show_diff_str = sprintf( _x( '%s from now.', 'Human readable time difference', 'timed-content' ),
1451 - human_time_diff( $show_t, $right_now_t ) );
1452 - } else {
1453 - $show_diff_str = sprintf( _x( '%s ago.', 'Human readable time difference', 'timed-content' ),
1454 - human_time_diff( $show_t, $right_now_t ) );
1455 - }
1456 - if ( $hide_t > $right_now_t ) {
1457 - $hide_diff_str = sprintf( _x( '%s from now.', 'Human readable time difference', 'timed-content' ),
1458 - human_time_diff( $hide_t, $right_now_t ) );
1459 - } else {
1460 - $hide_diff_str = sprintf( _x( '%s ago.', 'Human readable time difference', 'timed-content' ),
1461 - human_time_diff( $hide_t, $right_now_t ) );
1462 - }
1463 -
1464 - $debug_message = "<div class=\"tcr-warning\">\n";
1465 - $debug_message .= "<p class=\"heading\">" . _x( "Notice", "Noun", 'timed-content' ) . "</p>\n";
1466 - $debug_message .= "<p>" . sprintf( __( 'Debugging has been turned on for a %1$s shortcode on this Post/Page. Only website users who are currently logged in and can edit this Post/Page will see this. To turn off this message, remove the %2$s attribute from the shortcode.',
1467 - 'timed-content' ), "<code>[timed-content-server]</code>", "<code>debug</code>" ) . "</p>\n";
1468 -
1469 - if ( $show == TIMED_CONTENT_TIME_ZERO ) {
1470 - $debug_message .= "<p>" . sprintf( __( 'The %s attribute is not set.', 'timed-content' ),
1471 - "<code>show</code>" ) . "</p>\n";
1472 - } else {
1473 - $debug_message .= "<p>" . sprintf( __( 'The %s attribute is currently set to', 'timed-content' ),
1474 - "<code>show</code>" ) . ": " . $show . ",<br />\n "
1475 - . __( 'The Timed Content plugin thinks the intended date/time is',
1476 - 'timed-content' ) . ": " . date_i18n( TIMED_CONTENT_DATE_FORMAT_OUTPUT, $show_t )
1477 - . " (" . $show_diff_str . ")</p>\n";
1478 - }
1479 -
1480 - if ( $hide == TIMED_CONTENT_TIME_END ) {
1481 - $debug_message .= "<p>" . sprintf( __( 'The %s attribute is not set.', 'timed-content' ),
1482 - "<code>hide</code>" ) . "</p>\n";
1483 - } else {
1484 - $debug_message .= "<p>" . sprintf( __( 'The %s attribute is currently set to', 'timed-content' ),
1485 - "<code>hide</code>" ) . ": " . $hide . ",<br />\n"
1486 - . __( 'The Timed Content plugin thinks the intended date/time is',
1487 - 'timed-content' ) . ": " . date_i18n( TIMED_CONTENT_DATE_FORMAT_OUTPUT, $hide_t )
1488 - . " (" . $hide_diff_str . ").</p>\n";
1489 - }
1490 -
1491 - $debug_message .= "<p>" . __( 'Current date:',
1492 - 'timed-content' ) . "&nbsp;" . $right_now . "<br />\n";
1493 - $debug_message .= __( 'Content filter:', 'timed-content' ) . "&nbsp;" . $the_filter . "</p>\n";
1494 - $debug_message .= "<p>" . _x( 'Content:', "Noun", 'timed-content' ) . "&nbsp;" . $content . "</p>\n";
1495 -
1496 - $debug_message .= "</div>\n";
1497 -
1498 - date_default_timezone_set( $temp_tz );
1499 - remove_filter( 'date_i18n', array( &$this, "fix_date_i18n" ), 10, 4 );
1500 - }
1501 -
1502 -
1503 - if ( ( $show_t <= $right_now_t ) && ( $right_now_t <= $hide_t ) ) {
1504 - do_action( "timed_content_server_show", $post->ID, $show, $hide, $content );
1505 -
1506 - return $debug_message . str_replace( ']]>', ']]&gt;', apply_filters( $the_filter, $content ) ) . "\n";
1507 - } else {
1508 - do_action( "timed_content_server_hide", $post->ID, $show, $hide, $content );
1509 -
1510 - return $debug_message . "\n";
1511 - }
1512 -
1513 - }
1514 -
1515 - /**
1516 - * Processes the [timed-content-rule] shortcode.
1517 - *
1518 - * @param array $atts Shortcode attributes
1519 - * @param null $content Content inside the shortcode
1520 - *
1521 - * @return string Processed output
1522 - */
1523 - function rulesShowHTML( $atts, $content = null )
1524 - {
1525 - global $post;
1526 - extract( shortcode_atts( array( 'id' => 0 ), $atts ) );
1527 - if ( ! is_numeric( $id ) ) {
1528 - $page = get_page_by_title( $id, OBJECT, TIMED_CONTENT_RULE_TYPE );
1529 - if ( $page == null ) {
1530 - return;
1531 - }
1532 - $id = $page->ID;
1533 - }
1534 - if ( TIMED_CONTENT_RULE_TYPE != get_post_type( $id ) ) {
1535 - return;
1536 - }
1537 -
1538 - $prefix = TIMED_CONTENT_RULE_POSTMETA_PREFIX;
1539 - $right_now_t = current_time( 'timestamp', 1 );
1540 - $rule_is_active = false;
1541 -
1542 - // use debug parameter if current user is allowed to edit the post
1543 - if ( isset( $_GET['tctest'] ) && current_user_can( "edit_post", $post->post_id ) ) {
1544 - $dt = DateTime::createFromFormat( 'Y-m-d H:i:s', $_GET['tctest'] );
1545 - if ( $dt != false ) {
1546 - $right_now_t = $dt->getTimestamp();
1547 - }
1548 - }
1549 -
1550 - $active_periods = $this->getRulePeriodsById( $id, false );
1551 - $action_is_show = (bool) get_post_meta( $id, $prefix . 'action', true );
1552 -
1553 - foreach ( $active_periods as $period ) {
1554 - if ( ( $period['start'] <= $right_now_t ) && ( $right_now_t <= $period['end'] ) ) {
1555 - $rule_is_active = true;
1556 - break;
1557 - }
1558 - }
1559 -
1560 - $the_filter = "timed_content_filter";
1561 - $the_filter = apply_filters( "timed_content_filter_override", $the_filter );
1562 -
1563 - if ( ( ( $rule_is_active == true ) && ( $action_is_show == true ) ) || ( ( $rule_is_active == false ) && ( $action_is_show == false ) ) ) {
1564 - do_action( "timed_content_rule_show", $post->ID, $id, $content );
1565 -
1566 - return str_replace( ']]>', ']]&gt;', apply_filters( $the_filter, $content ) );
1567 - } else {
1568 - do_action( "timed_content_rule_hide", $post->ID, $id, $content );
1569 -
1570 - return "";
1571 - }
1572 - }
1573 -
1574 - /**
1575 - * Enqueues the JavaScript code necessary for the functionality of the [timed-content-client] shortcode.
1576 - */
1577 - function addHeaderCode()
1578 - {
1579 - if ( ! is_admin() ) {
1580 - wp_enqueue_style( 'timed-content-css', TIMED_CONTENT_CSS, false, TIMED_CONTENT_VERSION );
1581 - wp_enqueue_script( 'timed-content_js', TIMED_CONTENT_PLUGIN_URL . '/js/timed-content.js',
1582 - array( 'jquery' ), TIMED_CONTENT_VERSION );
1583 - }
1584 - }
1585 -
1586 - /**
1587 - * Enqueues the CSS code necessary for custom icons for the Timed Content Rules management screens
1588 - * and the TinyMCE editor. Echo'd to output.
1589 - */
1590 - function addPostTypeIcons()
1591 - {
1592 - wp_enqueue_style( 'timed-content-dashicons', TIMED_CONTENT_CSS_DASHICONS, false, TIMED_CONTENT_VERSION );
1593 - ?>
1594 - <style type="text/css" media="screen">
1595 - #adminmenu #menu-posts-<?php echo TIMED_CONTENT_RULE_TYPE; ?>.menu-icon-post div.wp-menu-image:before {
1596 - font-family: 'timed-content-dashicons' !important;
1597 - content: '\e601';
1598 - }
1599 -
1600 - #dashboard_right_now li.<?php echo TIMED_CONTENT_RULE_TYPE; ?>-count a:before {
1601 - font-family: 'timed-content-dashicons' !important;
1602 - content: '\e601';
1603 - }
1604 -
1605 - .mce-i-timed_content:before {
1606 - font: 400 24px/1 'timed-content-dashicons' !important;
1607 - padding: 0;
1608 - vertical-align: top;
1609 - margin-left: -2px;
1610 - padding-right: 2px;
1611 - content: '\e601';
1612 - }
1613 - </style>
1614 - <?php
1615 - }
1616 -
1617 - /**
1618 - * Enqueues the JavaScript code necessary for the functionality of the Timed Content Rules management screens.
1619 - */
1620 - function addAdminHeaderCode()
1621 - {
1622 - if ( ( isset( $_GET['post_type'] ) && $_GET['post_type'] == TIMED_CONTENT_RULE_TYPE )
1623 - || ( isset( $post_type ) && $post_type == TIMED_CONTENT_RULE_TYPE )
1624 - || ( isset( $_GET['post'] ) && get_post_type( $_GET['post'] ) == TIMED_CONTENT_RULE_TYPE ) ) {
1625 - wp_enqueue_style( 'thickbox' );
1626 - wp_enqueue_style( 'timed-content-css', TIMED_CONTENT_CSS, false, TIMED_CONTENT_VERSION );
1627 - // Enqueue the JavaScript file that manages the meta box UI
1628 - wp_enqueue_script( 'timed-content-admin_js', TIMED_CONTENT_PLUGIN_URL . '/js/timed-content-admin.js',
1629 - array( 'jquery' ), TIMED_CONTENT_VERSION );
1630 - // Enqueue the JavaScript file that makes AJAX requests
1631 - wp_enqueue_script( 'timed-content-ajax_js', TIMED_CONTENT_PLUGIN_URL . '/js/timed-content-ajax.js',
1632 - array( 'jquery', 'thickbox' ), TIMED_CONTENT_VERSION );
1633 -
1634 - // Set up local variables used in the Admin JavaScript file
1635 - wp_localize_script( 'timed-content-admin_js', 'timedContentRuleAdmin', array(
1636 - 'no_exceptions_label' => __( "- No exceptions set -", 'timed-content' )
1637 - ) );
1638 -
1639 - // Set up local variables used in the AJAX JavaScript file
1640 - wp_localize_script( 'timed-content-ajax_js', 'timedContentRuleAjax', array(
1641 - 'ajaxurl' => admin_url( 'admin-ajax.php' ),
1642 - 'start_label' => _x( 'Start',
1643 - 'Scheduled Dates/Times dialog - Beginning of active period table header', 'timed-content' ),
1644 - 'end_label' => _x( 'End',
1645 - 'Scheduled Dates/Times dialog - End of active period table header', 'timed-content' ),
1646 - 'dialog_label' => _x( 'Scheduled dates/times',
1647 - 'Scheduled Dates/Times dialog - dialog header', 'timed-content' ),
1648 - 'button_loading_label' => __( 'Calculating dates/times', 'timed-content' ),
1649 - 'button_finished_label' => __( 'Show projected dates/times', 'timed-content' ),
1650 - 'dialog_width' => 800,
1651 - 'dialog_height' => 500,
1652 - 'error' => __( "Error", 'timed-content' ),
1653 - 'error_desc' => __( "Something unexpected has happened along the way. The specific details are below:",
1654 - 'timed-content' )
1655 - ) );
1656 - }
1657 - }
1658 -
1659 - /**
1660 - * Initializes the TinyMCE plugin bundled with this Wordpress plugin
1661 - *
1662 - * @return void
1663 - */
1664 - function initTinyMCEPlugin()
1665 - {
1666 - if ( ( ! current_user_can( 'edit_posts' ) ) && ( ! current_user_can( 'edit_pages' ) ) ) {
1667 - return;
1668 - }
1669 -
1670 - // Add only in Rich Editor mode
1671 - if ( get_user_option( 'rich_editing' ) == 'true' ) {
1672 - add_filter( "mce_external_plugins", array( &$this, "addTimedContentTinyMCEPlugin" ) );
1673 - add_filter( "mce_buttons", array( &$this, "registerTinyMCEButton" ) );
1674 - }
1675 - }
1676 -
1677 - /**
1678 - * Sets up variables to use in the TinyMCE plugin's plugin.js.
1679 - *
1680 - * @return void
1681 - */
1682 - function setTinyMCEPluginVars()
1683 - {
1684 - global $wp_version;
1685 - if ( ( ! current_user_can( 'edit_posts' ) ) && ( ! current_user_can( 'edit_pages' ) ) ) {
1686 - return;
1687 - }
1688 -
1689 - // Add only in Rich Editor mode
1690 - if ( get_user_option( 'rich_editing' ) == 'true' ) {
1691 - if ( version_compare( $wp_version, "3.8", "<" ) ) {
1692 - $image = "/clock.gif";
1693 - } else {
1694 - $image = "";
1695 - }
1696 - wp_localize_script( 'editor',
1697 - 'timedContentAdminTinyMCEOptions',
1698 - array(
1699 - 'version' => TIMED_CONTENT_VERSION,
1700 - 'desc' => __( "Add Timed Content shortcodes", 'timed-content' ),
1701 - 'image' => $image
1702 - ) );
1703 - }
1704 - }
1705 -
1706 - /**
1707 - * Sets up the button for the associated TinyMCE plugin for use in the editor menubar.
1708 - *
1709 - * @param array $buttons Array of menu buttons already registered with TinyMCE
1710 - *
1711 - * @return array The array of TinyMCE menu buttons with ours now loaded in as well
1712 - */
1713 - function registerTinyMCEButton( $buttons )
1714 - {
1715 - array_push( $buttons, "|", "timed_content" );
1716 -
1717 - return $buttons;
1718 - }
1719 -
1720 - /**
1721 - * Loads the associated TinyMCE plugin into TinyMCE's plugin array
1722 - *
1723 - * @param array $plugin_array Array of plugins already registered with TinyMCE
1724 - *
1725 - * @return array The array of TinyMCE plugins with ours now loaded in as well
1726 - */
1727 - function addTimedContentTinyMCEPlugin( $plugin_array )
1728 - {
1729 - $plugin_array['timed_content'] = TIMED_CONTENT_PLUGIN_URL . "/tinymce_plugin/plugin.js";
1730 -
1731 - return $plugin_array;
1732 - }
1733 -
1734 - /**
1735 - * Generates JavaScript array of objects describing Timed Content rules. Used in the dialog box created by
1736 - * timedContentPlugin::timedContentPluginGetTinyMCEDialog().
1737 - *
1738 - * @return string JavaScript array describing the Timed Content rules
1739 - */
1740 - function __getRulesJS()
1741 - {
1742 - $the_js = "var rules = [\n";
1743 - $args = array(
1744 - 'post_type' => TIMED_CONTENT_RULE_TYPE,
1745 - 'posts_per_page' => - 1,
1746 - 'post_status' => 'publish'
1747 - );
1748 - $the_rules = get_posts( $args );
1749 - foreach ( $the_rules as $rule ) {
1750 - $desc = $this->getScheduleDescriptionById( $rule->ID );
1751 - $desc = str_replace('<br />', ' ', $desc);
1752 - // Only add a rule if there's no errors or warnings
1753 - if ( false === strpos( $desc, "tcr-warning" ) ) {
1754 - $the_js .= " { 'ID': " . $rule->ID . ", 'title': '" . esc_js( ( ( strlen( $rule->post_title ) > 0 ) ? $rule->post_title : _x( "(no title)",
1755 - "No Timed Content Rule title",
1756 - "timed-content" ) ) ) . "', 'desc': '" . esc_js( $desc ) . "' },\n";
1757 - }
1758 - }
1759 - if ( empty( $the_rules ) ) {
1760 - $the_js .= " { 'ID': -999, 'title': ' ---- ', 'desc': '" . __( 'No Timed Content Rules found',
1761 - 'timed-content' ) . "' }\n";
1762 - }
1763 -
1764 - $the_js .= "];\n";
1765 -
1766 - return $the_js;
1767 - }
1768 -
1769 - /**
1770 - * Display a dialog box for this plugin's associated TinyMCE plugin. Called from TinyMCE via AJAX.
1771 - *
1772 - * @return void
1773 - */
1774 - function timedContentPluginGetTinyMCEDialog()
1775 - {
1776 - wp_enqueue_style( TIMED_CONTENT_SLUG . '-jquery-ui-css', TIMED_CONTENT_JQUERY_UI_CSS );
1777 - wp_enqueue_script( 'jquery-ui-datepicker' );
1778 - wp_register_style( TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-css',
1779 - TIMED_CONTENT_JQUERY_UI_TIMEPICKER_CSS );
1780 - wp_enqueue_style( TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-css' );
1781 - wp_register_script( TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-js', TIMED_CONTENT_JQUERY_UI_TIMEPICKER_JS,
1782 - array( 'jquery', 'jquery-ui-datepicker' ), TIMED_CONTENT_VERSION );
1783 - wp_enqueue_script( TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-js' );
1784 - if ( ! ( wp_script_is( TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js', 'registered' ) ) ) {
1785 - wp_register_script( TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js',
1786 - TIMED_CONTENT_PLUGIN_URL . "/js/timed-content-datetime-i18n.js",
1787 - array( 'jquery', 'jquery-ui-datepicker', TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-js' ),
1788 - TIMED_CONTENT_VERSION );
1789 - wp_enqueue_script( TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js' );
1790 - wp_localize_script( TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js', 'TimedContentJQDatepickerI18n',
1791 - $this->jquery_ui_datetime_datepicker_i18n );
1792 - wp_localize_script( TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js', 'TimedContentJQTimepickerI18n',
1793 - $this->jquery_ui_datetime_timepicker_i18n );
1794 - }
1795 -
1796 - ob_start();
1797 - include( "tinymce_plugin/dialog.php" );
1798 - $content = ob_get_contents();
1799 - ob_end_clean();
1800 - echo $content;
1801 - die();
1802 - }
1803 -
1804 - /**
1805 - * Adds support for i18n (internationalization)
1806 - *
1807 - * @return void
1808 - */
1809 - function i18nInit()
1810 - {
1811 - $plugin_dir = basename( dirname( __FILE__ ) ) . "/lang/";
1812 - load_plugin_textdomain( 'timed-content', false, $plugin_dir );
1813 - }
1814 -
1815 - /**
1816 - * Add custom columns to the Timed Content Rules overview page
1817 - *
1818 - * @return void
1819 - */
1820 - function addDescColumnHead( $defaults )
1821 - {
1822 - unset( $defaults['date'] );
1823 - $defaults['description'] = __( 'Description', 'timed-content' );
1824 - $defaults['shortcode'] = __( 'Shortcode', 'timed-content' );
1825 -
1826 - return $defaults;
1827 - }
1828 -
1829 - /**
1830 - * Display content associated with custom columns on the Timed Content rules overview page
1831 - *
1832 - * @param $column_name Name of the column to be displayed
1833 - * @param $post_ID ID of the Timed Content Rule being listed
1834 - */
1835 - function addDescColumnContent( $column_name, $post_ID )
1836 - {
1837 - if ( $column_name == 'shortcode' ) {
1838 - echo '<code>[' . TIMED_CONTENT_SHORTCODE_RULE . ' id="' . $post_ID . '"]...[/' . TIMED_CONTENT_SHORTCODE_RULE . ']</code>';
1839 - }
1840 - if ( $column_name == 'description' ) {
1841 - $desc = $this->getScheduleDescriptionById( $post_ID );
1842 - if ( $desc ) {
1843 - echo '<em>' . $desc . '</em>';
1844 - }
1845 - }
1846 - }
1847 -
1848 - /**
1849 - * Display a count of Timed Content rules in the Dashboard's Right Now widget
1850 - *
1851 - * @return void
1852 - */
1853 - function addRulesCount() {
1854 - if ( ! post_type_exists( TIMED_CONTENT_RULE_TYPE ) ) {
1855 - return;
1856 - }
1857 -
1858 - $num_posts = wp_count_posts( TIMED_CONTENT_RULE_TYPE );
1859 - $num = number_format_i18n( $num_posts->publish );
1860 - $text = _n( 'Timed Content rule', 'Timed Content rules', intval( $num_posts->publish ),
1861 - 'timed-content' );
1862 - if ( current_user_can( 'edit_posts' ) || current_user_can( 'edit_pages' ) ) {
1863 - echo "<a href='edit.php?post_type=" . TIMED_CONTENT_RULE_TYPE . "'>"
1864 - . '<li class="' . TIMED_CONTENT_RULE_TYPE . '-count">'
1865 - . $num
1866 - . ' '
1867 - . $text
1868 - . '</a></li>';
1869 - }
1870 -
1871 - if ( $num_posts->pending > 0 ) {
1872 - $num = number_format_i18n( $num_posts->pending );
1873 - $text = _n( 'Timed Content rule pending', 'Timed Content rules pending', intval( $num_posts->pending ),
1874 - 'timed-content' );
1875 - if ( current_user_can( 'edit_posts' ) || current_user_can( 'edit_pages' ) ) {
1876 - echo "<a href='edit.php?post_status=pending&post_type=" . TIMED_CONTENT_RULE_TYPE . "'>"
1877 - . '<li class="' . TIMED_CONTENT_RULE_TYPE . '-count">'
1878 - . $num
1879 - . ' '
1880 - . $text
1881 - . '</a></li>';
1882 - }
1883 - }
1884 - }
1885 -
1886 - /**
1887 - * Setup custom fields for Timed Content rules
1888 - *
1889 - * @return void
1890 - */
1891 - function setupCustomFields()
1892 - {
1893 - global $post;
1894 -
1895 - $now_t = current_time( "timestamp" );
1896 - $post_id = ( isset( $_GET['post'] ) && ( TIMED_CONTENT_RULE_TYPE === get_post_type( $_GET['post'] ) ) ? intval( $_GET['post'] ) : intval( 0 ) );
1897 - $timed_content_rules_exceptions_dates = ( "" === get_post_meta( $post_id, TIMED_CONTENT_RULE_POSTMETA_PREFIX . "exceptions_dates", true ) ? array() : get_post_meta( $post_id, TIMED_CONTENT_RULE_POSTMETA_PREFIX . "exceptions_dates", true ) );
1898 - if ( empty( $timed_content_rules_exceptions_dates ) )
1899 - $timed_content_rules_exceptions_dates_array = array( "0" => __( "- No exceptions set -", 'timed-content' ) );
1900 - else {
1901 - sort( $timed_content_rules_exceptions_dates, SORT_NUMERIC );
1902 - $timed_content_rules_exceptions_dates = array_unique( $timed_content_rules_exceptions_dates );
1903 - $formatted_dates = array();
1904 - foreach ( $timed_content_rules_exceptions_dates as $a_date ) {
1905 - $a_date_idx = $a_date * 1000;
1906 - $formatted_dates[$a_date_idx] = date('Y-m-d', $a_date);
1907 - }
1908 - $timed_content_rules_exceptions_dates_array = array_combine($timed_content_rules_exceptions_dates, $formatted_dates);
1909 - }
1910 -
1911 - $this->rule_occurrence_custom_fields = array(
1912 - array(
1913 - "name" => "action",
1914 - "display" => "block",
1915 - "title" => __( "Action", 'timed-content' ),
1916 - "description" => __( "Sets the action to be performed when the rule is active.", 'timed-content' ),
1917 - "type" => "radio",
1918 - "values" => array(1 => __( "Show the content", 'timed-content' ),
1919 - 0 => __( "Hide the content", 'timed-content' ) ),
1920 - "default" => 1,
1921 - "scope" => array(TIMED_CONTENT_RULE_TYPE ),
1922 - "capability" => "edit_posts"
1923 - ),
1924 - array(
1925 - "name" => "instance_start",
1926 - "display" => "block",
1927 - "title" => __( "Starting date/time", 'timed-content' ),
1928 - "description" => __( "Sets the date and time for the beginning of the first active period for this rule.", 'timed-content' ),
1929 - "type" => "datetime",
1930 - "default" => array("date" => date_i18n( get_option('date_format'), strtotime( "+1 hour", $now_t ) ),
1931 - "time" => date_i18n( get_option('time_format'), strtotime( "+1 hour", $now_t ) ) ),
1932 - "scope" => array(TIMED_CONTENT_RULE_TYPE ),
1933 - "capability" => "edit_posts"
1934 - ),
1935 - array(
1936 - "name" => "instance_end",
1937 - "display" => "block",
1938 - "title" => __( "Ending date/time", 'timed-content' ),
1939 - "description" => __( "Sets the date and time for the end of the first active period for this rule.", 'timed-content' ),
1940 - "type" => "datetime",
1941 - "default" => array("date" => date_i18n( get_option('date_format'), strtotime( "+2 hour", $now_t ) ),
1942 - "time" => date_i18n( get_option('time_format'), strtotime( "+2 hour", $now_t ) ) ),
1943 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
1944 - "capability" => "edit_posts"
1945 - ),
1946 - array(
1947 - "name" => "timezone",
1948 - "display" => "block",
1949 - "title" => __( "Timezone", 'timed-content' ),
1950 - "description" => __( "Select the timezone you wish to use for this rule.", 'timed-content' ),
1951 - "type" => "timezone-list",
1952 - "default" => get_option( 'timezone_string' ),
1953 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
1954 - "capability" => "edit_posts"
1955 - )
1956 - );
1957 -
1958 - $this->rule_pattern_custom_fields = array(
1959 - array(
1960 - "name" => "frequency",
1961 - "display" => "block",
1962 - "title" => __( "Frequency", 'timed-content' ),
1963 - "description" => __( "Sets the frequency at which the action should be repeated.", 'timed-content' ),
1964 - "type" => "list",
1965 - "default" => "1",
1966 - "values" => $this->rule_freq_array,
1967 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
1968 - "capability" => "edit_posts"
1969 - ),
1970 - array(
1971 - "name" => "hourly_num_of_hours",
1972 - "display" => "none",
1973 - "title" => __( "Number of recurrences", 'timed-content' ),
1974 - "description" => __( "Repeat this action every X hours.", 'timed-content' ),
1975 - "type" => "number",
1976 - "default" => "1",
1977 - "min" => "1",
1978 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
1979 - "capability" => "edit_posts"
1980 - ),
1981 - array(
1982 - "name" => "daily_num_of_days",
1983 - "display" => "none",
1984 - "title" => __( "Number of recurrences", 'timed-content' ),
1985 - "description" => __( "Repeat this action every X days.", 'timed-content' ),
1986 - "type" => "number",
1987 - "default" => "1",
1988 - "min" => "1",
1989 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
1990 - "capability" => "edit_posts"
1991 - ),
1992 - array(
1993 - "name" => "weekly_num_of_weeks",
1994 - "display" => "none",
1995 - "title" => __( "Number of recurrences", 'timed-content' ),
1996 - "description" => __( "Repeat this action every X weeks.", 'timed-content' ),
1997 - "type" => "number",
1998 - "default" => "1",
1999 - "min" => "1",
2000 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
2001 - "capability" => "edit_posts"
2002 - ),
2003 - array(
2004 - "name" => "weekly_days_of_week_to_repeat",
2005 - "display" => "none",
2006 - "title" => __( "Repeat on the following days", 'timed-content' ),
2007 - "description" => __( "Repeat this action on these days of the week <strong>instead</strong> of the day of week the starting date/time falls on.", 'timed-content' ),
2008 - "type" => "checkbox-list",
2009 - "default" => array(),
2010 - "values" => $this->rule_days_array,
2011 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
2012 - "capability" => "edit_posts"
2013 - ),
2014 - array(
2015 - "name" => "monthly_num_of_months",
2016 - "display" => "none",
2017 - "title" => __( "Number of recurrences", 'timed-content' ),
2018 - "description" => __( "Repeat this action every X months.", 'timed-content' ),
2019 - "type" => "number",
2020 - "default" => "1",
2021 - "min" => "1",
2022 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
2023 - "capability" => "edit_posts"
2024 - ),
2025 - array(
2026 - "name" => "monthly_nth_weekday_of_month",
2027 - "display" => "none",
2028 - "title" => __( "Repeat on a specific weekday of the month", 'timed-content' ),
2029 - "description" => __( "Repeat this action on a specific weekday of the month (for example, \"every third Tuesday\"). Check this box to select a pattern below.", 'timed-content' ),
2030 - "type" => "checkbox",
2031 - "default" => "no",
2032 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
2033 - "capability" => "edit_posts"
2034 - ),
2035 - array(
2036 - "name" => "monthly_nth_weekday_of_month_nth",
2037 - "display" => "none",
2038 - "title" => __( "Weekday ordinal", 'timed-content' ),
2039 - "description" => __( "Select a value for week of the month (for example \"first\", \"second\", etc.).", 'timed-content' ),
2040 - "type" => "list",
2041 - "default" => 0,
2042 - "values" => $this->rule_ordinal_array,
2043 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
2044 - "capability" => "edit_posts"
2045 - ),
2046 - array(
2047 - "name" => "monthly_nth_weekday_of_month_weekday",
2048 - "display" => "none",
2049 - "title" => __( "Day of the week", 'timed-content' ),
2050 - "description" => __( "Select the day of week.", 'timed-content' ),
2051 - "type" => "list",
2052 - "default" => 0,
2053 - "values" => $this->rule_ordinal_days_array,
2054 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
2055 - "capability" => "edit_posts"
2056 - ),
2057 - array(
2058 - "name" => "yearly_num_of_years",
2059 - "display" => "none",
2060 - "title" => __( "Number of recurrences", 'timed-content' ),
2061 - "description" => __( "Repeat this action every X years.", 'timed-content' ),
2062 - "type" => "number",
2063 - "default" => "1",
2064 - "min" => "1",
2065 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
2066 - "capability" => "edit_posts"
2067 - )
2068 - );
2069 -
2070 - $this->rule_recurrence_custom_fields = array(
2071 - array(
2072 - "name" => "recurrence_duration",
2073 - "display" => "block",
2074 - "title" => __( "How often to repeat this action", 'timed-content' ),
2075 - "description" => "",
2076 - "type" => "radio",
2077 - "values" => array("recurrence_duration_end_date" => __( "Keep repeating until a given date", 'timed-content' ),
2078 - "recurrence_duration_num_repeat" => __( "Repeat a set number of times", 'timed-content' ) ),
2079 - "default" => "recurrence_duration_end_date",
2080 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
2081 - "capability" => "edit_posts"
2082 - ),
2083 - array(
2084 - "name" => "recurrence_duration_end_date",
2085 - "display" => "none",
2086 - "title" => __( "End Date", 'timed-content' ),
2087 - "description" => __( "Using the settings above, repeat this action until this date.", 'timed-content' ),
2088 - "type" => "date",
2089 - "default" => date_i18n( get_option('date_format'), strtotime( "+1 year", $now_t ) ),
2090 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
2091 - "capability" => "edit_posts"
2092 - ),
2093 - array(
2094 - "name" => "recurrence_duration_num_repeat",
2095 - "display" => "none",
2096 - "title" => __( "Number of repetitions", 'timed-content' ),
2097 - "description" => __( "Using the settings above, repeat this action this many times.", 'timed-content' ),
2098 - "type" => "number",
2099 - "default" => "1",
2100 - "min" => "1",
2101 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
2102 - "capability" => "edit_posts"
2103 - )
2104 - );
2105 -
2106 - $exceptions_dates_picker_on_select = <<<FUNC
2107 -onSelect: function (dateText, inst) {
2108 - //alert(dateText);
2109 - jQuery("#timed_content_rule_exceptions_dates option[value='0']" ).remove();
2110 - jQuery("#timed_content_rule_exceptions_dates").append( '<option value="' + parseInt(Date.parse(dateText) / 1000) + '">' + dateText + '</option>' );
2111 - jQuery(this).val("");
2112 - jQuery(this).trigger("change");
2113 - },
2114 -FUNC;
2115 -
2116 - $this->rule_exceptions_custom_fields = array(
2117 - array(
2118 - "name" => "exceptions_dates_picker",
2119 - "display" => "block",
2120 - "title" => __( "Add exception date:", 'timed-content' ),
2121 - "description" => __( "Select a date to add to the exception dates list.", 'timed-content' ),
2122 - "type" => "date",
2123 - "default" => "",
2124 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
2125 - "capability" => "edit_posts",
2126 - "custom_functions" => $exceptions_dates_picker_on_select
2127 - ),
2128 - array(
2129 - "name" => "exceptions_dates",
2130 - "display" => "block",
2131 - "title" => __( "Exception dates list", 'timed-content' ),
2132 - "description" => __( "Dates that this Timed Content rule will not be active. Double-click on a date to remove it from the list.", 'timed-content' ),
2133 - "type" => "menu",
2134 - "values" => $timed_content_rules_exceptions_dates_array,
2135 - "size" => "10",
2136 - "default" => array(),
2137 - "scope" => array( TIMED_CONTENT_RULE_TYPE ),
2138 - "capability" => "edit_posts"
2139 - )
2140 - );
2141 -
2142 - $scf = new customFieldsInterface( "timed_content_rule_schedule",
2143 - __( 'Rule description/schedule', 'timed-content' ),
2144 - "<div id=\"schedule_desc\" style=\"font-style: italic; overflow-y: auto;\">"
2145 - . ( isset( $_GET['post'] ) && ( TIMED_CONTENT_RULE_TYPE === get_post_type( $_GET['post'] ) ) ? $this->getScheduleDescriptionById( intval( $_GET['post'] ) ) : $this->getScheduleDescriptionById( intval( 0 ) ) )
2146 - . "</div>"
2147 - . "<div id=\"tcr-dialogHolder\" style=\"display:none;\"></div>"
2148 - . "<div style=\"padding-top: 10px;\"><input type=\"button\" class=\"button button-primary\" id=\"timed_content_rule_test\" value=\"" . __( 'Show projected dates/times',
2149 - 'timed-content' ) . "\" /></div>",
2150 - TIMED_CONTENT_RULE_POSTMETA_PREFIX,
2151 - array( TIMED_CONTENT_RULE_TYPE ),
2152 - array(),
2153 - $this->jquery_ui_datetime_datepicker_i18n,
2154 - $this->jquery_ui_datetime_timepicker_i18n);
2155 - $ocf = new customFieldsInterface( "timed_content_rule_initial_event",
2156 - __( 'Action/Initial Event', 'timed-content' ),
2157 - __( 'Set the action to be taken and when it should first run.', 'timed-content' ),
2158 - TIMED_CONTENT_RULE_POSTMETA_PREFIX,
2159 - array( TIMED_CONTENT_RULE_TYPE ),
2160 - $this->rule_occurrence_custom_fields,
2161 - $this->jquery_ui_datetime_datepicker_i18n,
2162 - $this->jquery_ui_datetime_timepicker_i18n);
2163 - $pcf = new customFieldsInterface( "timed_content_rule_recurrence",
2164 - __( 'Repeating Pattern', 'timed-content' ),
2165 - __( 'Set how often the action should repeat.', 'timed-content' ),
2166 - TIMED_CONTENT_RULE_POSTMETA_PREFIX,
2167 - array( TIMED_CONTENT_RULE_TYPE ),
2168 - $this->rule_pattern_custom_fields,
2169 - $this->jquery_ui_datetime_datepicker_i18n,
2170 - $this->jquery_ui_datetime_timepicker_i18n );
2171 - $rcf = new customFieldsInterface( "timed_content_rule_stop_condition",
2172 - __( 'Stopping Condition', 'timed-content' ),
2173 - __( 'Set how long or how many times the action should occur.', 'timed-content' ),
2174 - TIMED_CONTENT_RULE_POSTMETA_PREFIX,
2175 - array( TIMED_CONTENT_RULE_TYPE ),
2176 - $this->rule_recurrence_custom_fields,
2177 - $this->jquery_ui_datetime_datepicker_i18n,
2178 - $this->jquery_ui_datetime_timepicker_i18n );
2179 - $ecf = new customFieldsInterface( "timed_content_rule_exceptions",
2180 - __( 'Exceptions', 'timed-content' ),
2181 - __( 'Set up any exceptions to this Timed Content Rule.', 'timed-content' ),
2182 - TIMED_CONTENT_RULE_POSTMETA_PREFIX,
2183 - array( TIMED_CONTENT_RULE_TYPE ),
2184 - $this->rule_exceptions_custom_fields,
2185 - $this->jquery_ui_datetime_datepicker_i18n,
2186 - $this->jquery_ui_datetime_timepicker_i18n );
2187 - }
2188 -
2189 - /**
2190 - * Strips indices from an array
2191 - *
2192 - * @param $ArrayToStrip
2193 - *
2194 - * @return array Processed array
2195 - */
2196 - function stripArrayIndices($ArrayToStrip)
2197 - {
2198 - foreach ($ArrayToStrip as $objArrayItem) {
2199 - $NewArray[] = $objArrayItem;
2200 - }
2201 -
2202 - return $NewArray;
2203 - }
2204 -
2205 - /**
2206 - * Convert a PHP date format to the format required by jQuery
2207 - *
2208 - * @param string $sFormat Format as used in PHP
2209 - *
2210 - * @return mixed Format as used in jQuery
2211 - */
2212 - function dateFormatPhpToJs($sFormat)
2213 - {
2214 - return str_replace(
2215 - array('d', 'j', 'l', 'm', 'n', 'F', 'Y'),
2216 - array('dd', 'd', 'DD', 'mm', 'm', 'MM', 'yy'),
2217 - $sFormat
2218 - );
2219 - }
2220 -
2221 - /**
2222 - * Convert dates and times to ISO format if needed
2223 - *
2224 - * @param array $args Existing date and time values
2225 - *
2226 - * @return array Converted date values in ISO format
2227 - */
2228 - function convertDateTimeParametersToISO($args)
2229 - {
2230 - $date_parsed = date_create_from_format('Y-m-d', $args['instance_start']['date']);
2231 - if ($date_parsed === false) {
2232 - $date_source = strtotime($this->__datetimeToEnglish($args['instance_start']['date']));
2233 - $args['instance_start']['date'] = strftime('%Y-%m-%d', $date_source);
2234 - }
2235 -
2236 - $date_parsed = date_create_from_format('Y-m-d', $args['instance_end']['date']);
2237 - if ($date_parsed === false) {
2238 - $date_source = strtotime($this->__datetimeToEnglish($args['instance_end']['date']));
2239 - $args['instance_end']['date'] = strftime('%Y-%m-%d', $date_source);
2240 - }
2241 -
2242 - $args['instance_start']['time'] = $this->convertTimeToISO($args['instance_start']['time']);
2243 -
2244 - $args['instance_end']['time'] = $this->convertTimeToISO($args['instance_end']['time']);
2245 -
2246 - $date_parsed = date_create_from_format('Y-m-d', $args['end_date']);
2247 - if ($date_parsed === false) {
2248 - $date_source = strtotime($this->__datetimeToEnglish($args['end_date']));
2249 - $args['end_date'] = strftime('%Y-%m-%d', $date_source);
2250 - }
2251 -
2252 - if( is_array($args['exceptions_dates'])) {
2253 - foreach ($args['exceptions_dates'] as $key => $value) {
2254 - $date_parsed = date_create_from_format('Y-m-d', $value);
2255 - if ($date_parsed === false) {
2256 - $date_source = strtotime($this->__datetimeToEnglish($args['end_date']));
2257 - $args['exceptions_dates'][$key] = strftime('%Y-%m-%d', $date_source);
2258 - }
2259 - }
2260 - }
2261 -
2262 - return $args;
2263 - }
2264 -
2265 - /**
2266 - * Convert time to ISO format if needed
2267 - *
2268 - * @param string $time Existing time value
2269 - *
2270 - * @return string Converted time values in ISO format
2271 - */
2272 - function convertTimeToISO($time) {
2273 - if (strpos($time, 'AM') !== false) {
2274 - $time_base = trim(substr($time, 0, strlen($time)-2));
2275 - $time_dt = date_create_from_format('G:i', $time_base);
2276 - if($time_dt !== false) {
2277 - $time = strftime('%H:%M', $time_dt->getTimestamp());
2278 - }
2279 - } else if (strpos($time, 'PM') !== false) {
2280 - $time_base = trim(substr($time, 0, strlen($time)-2));
2281 - $time_dt = date_create_from_format('G:i', $time_base);
2282 - if($time_dt !== false) {
2283 - $time = strftime('%H:%M', $time_dt->getTimestamp() + 43200);
2284 - }
2285 - }
2286 -
2287 - return $time;
2288 - }
2289 -}
2290 -
2291 -// Initialize plugin
2292 -$timedContentPluginInstance = new timedContentPlugin();
1 +<?php
2 +/*
3 +Plugin Name: Timed Content
4 +Text Domain: timed-content
5 +Domain Path: /lang
6 +Plugin URI: http://wordpress.org/plugins/timed-content/
7 +Description: Plugin to show or hide portions of a Page or Post based on specific date/time characteristics. These actions can either be processed either server-side or client-side, depending on the desired effect.
8 +Author: K. Tough, Arno Welzel
9 +Version: 2.7
10 +Author URI: http://wordpress.org/plugins/timed-content/
11 +*/
12 +if ( !class_exists( "timedContentPlugin" ) ) {
13 +
14 + define( "TIMED_CONTENT_VERSION", "2.7" );
15 + define( "TIMED_CONTENT_SLUG", "timed-content" );
16 + define( "TIMED_CONTENT_PLUGIN_URL", plugins_url() . '/' . TIMED_CONTENT_SLUG );
17 + define( "TIMED_CONTENT_CLIENT_TAG", "timed-content-client" );
18 + define( "TIMED_CONTENT_SERVER_TAG", "timed-content-server" );
19 + define( "TIMED_CONTENT_RULE_TAG", "timed-content-rule" );
20 + define( "TIMED_CONTENT_ZERO_TIME", "1970-Jan-01 00:00:00 +000" ); // Start of Unix Epoch
21 + define( "TIMED_CONTENT_END_TIME", "2038-Jan-19 03:14:07 +000" ); // End of Unix Epoch
22 + define( "TIMED_CONTENT_RULE_TYPE", "timed_content_rule" );
23 + define( "TIMED_CONTENT_RULE_POSTMETA_PREFIX", TIMED_CONTENT_RULE_TYPE . "_" );
24 + define( "TIMED_CONTENT_CSS", TIMED_CONTENT_PLUGIN_URL . "/css/timed-content.css" );
25 + define( "TIMED_CONTENT_CSS_DASHICONS", TIMED_CONTENT_PLUGIN_URL . "/css/ca-aliencyborg-dashicons/style.css" );
26 + // Required for styling the jQuery UI Datepicker and jQuery UI Timepicker
27 + define( "TIMED_CONTENT_JQUERY_UI_CSS", TIMED_CONTENT_PLUGIN_URL . "/css/jqueryui/1.10.3/themes/smoothness/jquery-ui.css" );
28 + define( "TIMED_CONTENT_JQUERY_UI_TIMEPICKER_JS", TIMED_CONTENT_PLUGIN_URL . "/js/jquery-ui-timepicker-0.3.3/jquery.ui.timepicker.js" );
29 + define( "TIMED_CONTENT_JQUERY_UI_TIMEPICKER_CSS", TIMED_CONTENT_PLUGIN_URL . "/js/jquery-ui-timepicker-0.3.3/jquery.ui.timepicker.css" );
30 +
31 +
32 + /**
33 + * Class timedContentPlugin
34 + *
35 + * Class that contains all of the functions required to run the plugin. This cuts down on
36 + * the possibility of name collisions with other plugins.
37 + */
38 + class timedContentPlugin {
39 +
40 + function __construct() {
41 + //constructor
42 +
43 + }
44 +
45 + function timedContentPlugin() {
46 + self::__construct();
47 +
48 + }
49 +
50 + /** https://core.trac.wordpress.org/ticket/25768
51 + *
52 + * Modified from the original patch to use the currently set
53 + * timezone from PHP, like PHP's date(), and to make the code
54 + * more readable.
55 + *
56 + * @param $j
57 + * @param $req_format
58 + * @param bool $i
59 + * @param bool $gmt
60 + * @return bool|string
61 + */
62 + function fix_date_i18n($j, $req_format, $i = false, $gmt = false)
63 + {
64 + /* @var $wp_locale WP_Locale */
65 + global $wp_locale;
66 + $timestamp = $i;
67 +
68 + // get current timestamp if $i is false
69 + if (false === $timestamp)
70 + {
71 + if ($gmt)
72 + $timestamp = time();
73 + else
74 + $timestamp = current_time('timestamp');
75 + }
76 +
77 +
78 + // get components of the date (timestamp) as array
79 + $date_components = getdate($timestamp);
80 +
81 + // numeric representation of a month, with leading zeros
82 + $date_month = $wp_locale->get_month($date_components['mon']);
83 + $date_month_abbrev = $wp_locale->get_month_abbrev($date_month);
84 + // numeric representation of the day of the week
85 + $date_weekday = $wp_locale->get_weekday($date_components['wday']);
86 + $date_weekday_abbrev = $wp_locale->get_weekday_abbrev($date_weekday);
87 + // get if hour is Ante meridiem or Post meridiem
88 + $meridiem = $date_components['hours'] >= 12 ? 'pm' : 'am';
89 + // lowercase Ante meridiem and Post meridiem hours
90 + $date_meridiem = $wp_locale->get_meridiem($meridiem);
91 + // uppercase Ante meridiem and Post meridiem
92 + $date_meridiem_capital = $wp_locale->get_meridiem(strtoupper($meridiem));
93 +
94 + // escape literals
95 + $date_weekday_abbrev = backslashit($date_weekday_abbrev);
96 + $date_month = backslashit($date_month);
97 + $date_weekday = backslashit($date_weekday);
98 + $date_month_abbrev = backslashit($date_month_abbrev);
99 + $date_meridiem = backslashit($date_meridiem);
100 + $date_meridiem_capital = backslashit($date_meridiem_capital);
101 +
102 + // the translated format string
103 + $translated_date_format_string = '';
104 + // the 2 arrays map a format literal to its translation (e. g. 'F' to the escaped month translation)
105 + $translate_formats = array('D', 'F', 'l', 'M', 'a', 'A', 'c', 'r');
106 + $translations = array(
107 + $date_weekday_abbrev, // D
108 + $date_month, // F
109 + $date_weekday, // l
110 + $date_month_abbrev, // M
111 + $date_meridiem, // a
112 + $date_meridiem_capital, // A
113 + 'Y-m-d\TH:i:sP', // c
114 + sprintf('%s, d %s Y H:i:s O', $date_weekday_abbrev, $date_month_abbrev), // r
115 + );
116 +
117 + // find each format literal that needs translation and replace it by its translation
118 + // respects the escaping
119 + // iterate $req_format from ending to beginning
120 + for ($i = strlen($req_format) - 1; $i > -1; $i--)
121 + {
122 + // test if current char is format literal that needs translation
123 + $translate_formats_index = array_search($req_format[$i], $translate_formats);
124 +
125 + if ($translate_formats_index !== false)
126 + {
127 + // counts the slashes (the escape char) in front of the current char
128 + $slashes_counter = 0;
129 +
130 + // count all slashes left-hand side of the current char
131 + for ($j = $i - 1; $j > -1; $j--)
132 + {
133 + if ($req_format[$j] == '\\')
134 + $slashes_counter++;
135 + else
136 + break;
137 + }
138 +
139 + // number of slashes is even
140 + if ($slashes_counter % 2 == 0)
141 + // current char is not escaped, therefore it is a format literal
142 + $translated_date_format_string = $translations[$translate_formats_index] . $translated_date_format_string;
143 + else
144 + // current char is escaped, therefore it is not a format literal, just add it unchanged
145 + $translated_date_format_string = $req_format[$i] . $translated_date_format_string;
146 + }
147 + else
148 + // current char is no a format literal, just add it unchanged
149 + $translated_date_format_string = $req_format[$i] . $translated_date_format_string;
150 + }
151 +
152 + $req_format = $translated_date_format_string;
153 +
154 + if ($gmt)
155 + // get GMT date string
156 + $date_formatted = gmdate($req_format, $timestamp);
157 + else
158 + {
159 + // get Wordpress time zone
160 + // $timezone_string = get_option('timezone_string');
161 + // Haha, just kidding. Let's get the currently set timezone, as God and Rasmus intended
162 + $timezone_string = date_default_timezone_get();
163 +
164 + if ($timezone_string)
165 + {
166 + // create time zone object
167 + $timezone_object = timezone_open($timezone_string);
168 + // create date object from time zone object
169 + $local_date_object = date_create(null, $timezone_object);
170 + // set time and date of $local_date_object to $timestamp
171 + $date_components = isset($date_components) ? $date_components : getdate($timestamp);
172 + date_date_set($local_date_object, $date_components['year'], $date_components['mon'], $date_components['mday']);
173 + date_time_set($local_date_object, $date_components['hours'], $date_components['minutes'], $date_components['seconds']);
174 + // format date according to the Wordpress time zone
175 + $date_formatted = date_format($local_date_object, $req_format);
176 + }
177 + else
178 + {
179 + // fall back if no Wordpress time zone set
180 + $date_formatted = date($req_format, $i);
181 + }
182 + }
183 +
184 + return $date_formatted;
185 + }
186 +
187 + /**
188 + * Creates the Timed Content Rule post type and registers it with Wordpress
189 + *
190 + */
191 + function timedContentRuleTypeInit()
192 + {
193 + $labels = array(
194 + 'name' => _x( 'Timed Content Rules', 'post type general name', 'timed-content' ),
195 + 'singular_name' => _x( 'Timed Content Rule', 'post type singular name', 'timed-content' ),
196 + 'add_new' => _x( 'Add New', 'Menu item/button label on Timed Content Rules admin page', 'timed-content' ),
197 + 'add_new_item' => __( 'Add New Timed Content Rule', 'timed-content' ),
198 + 'edit_item' => __( 'Edit Timed Content Rule', 'timed-content' ),
199 + 'new_item' => __( 'New Timed Content Rule', 'timed-content' ),
200 + 'view_item' => __( 'View Timed Content Rule', 'timed-content' ),
201 + 'search_items' => __( 'Search Timed Content Rules', 'timed-content' ),
202 + 'not_found' => __( 'No Timed Content Rules found', 'timed-content' ),
203 + 'not_found_in_trash' => __( 'No Timed Content Rules found in Trash', 'timed-content' ),
204 + 'parent_item_colon' => '',
205 + 'menu_name' => _x( 'Timed Content Rules', 'post type general name', 'timed-content' )
206 + );
207 + $args = array(
208 + 'labels' => $labels,
209 + 'description' => __( 'Create regular schedules to show or hide selected content in a Page or Post.', 'timed-content' ),
210 + 'public' => false,
211 + 'publicly_queryable' => false,
212 + 'exclude_from_search' => false,
213 + 'show_ui' => true,
214 + 'show_in_menu' => true,
215 + 'show_in_nav_menus' => true,
216 + 'show_in_admin_bar' => true,
217 + 'query_var' => false,
218 + 'rewrite' => false,
219 + 'capability_type' => 'post',
220 + 'has_archive' => false,
221 + 'hierarchical' => false,
222 + 'menu_position' => 5,
223 + 'supports' => array( 'title' )
224 + );
225 + register_post_type( TIMED_CONTENT_RULE_TYPE, $args );
226 + }
227 +
228 + /**
229 + * Filter to customize CRUD messages for Timed Content Rules
230 + *
231 + * @param array $messages Array of currently defined messages for post types
232 + * @return mixed Array of messages with appropriate messages for Timed Content Rules added in
233 + */
234 + function timedContentRuleUpdatedMessages( $messages ) {
235 + global $post;
236 +
237 + /* translators: date and time format to activate rule. http://ca2.php.net/manual/en/function.date.php*/
238 + $post_date = date_i18n( __( 'M j, Y @ G:i', 'timed-content' ), strtotime( $post->post_date ) );
239 +
240 + $messages[TIMED_CONTENT_RULE_TYPE] = array(
241 + 0 => '', // Unused. Messages start at index 1.
242 + 1 => __( 'Timed Content Rule updated.', 'timed-content' ),
243 + 2 => __( 'Custom field updated.', 'timed-content' ),
244 + 3 => __( 'Custom field deleted.', 'timed-content' ),
245 + 4 => __( 'Timed Content Rule updated.', 'timed-content' ),
246 + /* translators: %s: date and time of the revision */
247 + 5 => isset( $_GET['revision'] ) ? sprintf( __( 'Timed Content Rule restored to revision from %s', 'timed-content' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
248 + 6 => __( 'Timed Content Rule published.', 'timed-content' ),
249 + 7 => __( 'Timed Content Rule saved.', 'timed-content' ),
250 + 8 => __( 'Timed Content Rule submitted.', 'timed-content' ),
251 + /* translators: %s: date and time to activate rule. */
252 + 9 => sprintf( __( 'Timed Content Rule scheduled for: %s.' , 'timed-content' ), "<strong>" . $post_date . "</strong>" ),
253 + 10 => __( 'Timed Content Rule draft updated.', 'timed-content' )
254 + );
255 +
256 + return $messages;
257 + }
258 +
259 + function __datetimeToEnglish( $date, $time = "" ) {
260 + $months = array( "January",
261 + "February",
262 + "March",
263 + "April",
264 + "May",
265 + "June",
266 + "July",
267 + "August",
268 + "September",
269 + "October",
270 + "November",
271 + "December" );
272 + $monthsI18N = array( __( "January", 'timed-content' ),
273 + __( "February", 'timed-content' ),
274 + __( "March", 'timed-content' ),
275 + __( "April", 'timed-content' ),
276 + __( "May", 'timed-content' ),
277 + __( "June", 'timed-content' ),
278 + __( "July", 'timed-content' ),
279 + __( "August", 'timed-content' ),
280 + __( "September", 'timed-content' ),
281 + __( "October", 'timed-content' ),
282 + __( "November", 'timed-content' ),
283 + __( "December", 'timed-content' ) );
284 + $english_date = str_replace( $monthsI18N, $months, $date );
285 + return $english_date . " " . $time;
286 + }
287 +
288 + /**
289 + * Advances a date/time by a set number of days
290 + *
291 + * @param int $current UNIX timestamp of the date/time before incrementing
292 + * @param int $interval_multiplier Number of days to advance
293 + * @return int Unix timestamp of the new date/time
294 + */
295 + function __getNextDay( $current, $interval_multiplier ) {
296 + return strtotime( $interval_multiplier . " day", $current );
297 + }
298 +
299 + /**
300 + * Advances a date/time by a set number of hours
301 + *
302 + * @param int $current UNIX timestamp of the date/time before incrementing
303 + * @param int $interval_multiplier Number of hours to advance
304 + * @return int Unix timestamp of the new date/time
305 + */
306 + function __getNextHour( $current, $interval_multiplier ) {
307 + return strtotime( $interval_multiplier . " hour", $current );
308 + }
309 +
310 + /**
311 + * Advances a date/time by a set number of weeks
312 + *
313 + * Advances a date/time by a set number of weeks. If given an array of days of the week, this function will
314 + * advance the date/time to the next day in that array in the jumped-to week. Use this function if you're
315 + * repeating an action on specific days of the week (i.e., on Weekdays, Tuesdays and Thursdays, etc.).
316 + *
317 + * @param int $current UNIX timestamp of the date/time before incrementing
318 + * @param int $interval_multiplier Number of weeks to advance
319 + * @param array $days Array of integers symbolizing the days of the week to
320 + * repeat on (0 - Sunday, 1 - Monday, ..., 6 - Saturday).
321 + * @return int Unix timestamp of the new date/time
322 + */
323 + function __getNextWeek( $current, $interval_multiplier, $days = array() ) {
324 + // If $days is empty, advance $interval_multiplier weeks from $current and return the timestamp
325 + if ( empty( $days ) ) return strtotime( $interval_multiplier . " week", $current );
326 +
327 + // Otherwise, set up an array combining the days of the week to repeat on and the current day
328 + // (keys and values of the array will be the same, and the array is sorted)
329 + $currentDayOfWeekIndex = date( "w", $current );
330 + $days = array_merge( array( $currentDayOfWeekIndex ), $days );
331 + $days = array_unique( $days );
332 + $days = array_values( $days );
333 + sort( $days );
334 + $daysOfWeek = array_combine( $days, $days );
335 +
336 + // If the current day is the last one of the days of the week to repeat on, jump ahead to
337 + // the next week to be repeating on and get the earliest day in the array
338 + if ( $currentDayOfWeekIndex == max( $daysOfWeek ) )
339 + $pattern = ( ( 7 - $currentDayOfWeekIndex ) + ( 7 * ( $interval_multiplier - 1 ) ) + ( min( array_keys( $daysOfWeek ) ) ) ) . " day";
340 + // Otherwise, cycle through the array until we find the next day to repeat on
341 + else {
342 + $nextDayOfWeekIndex = $currentDayOfWeekIndex;
343 + do {} while ( !isset( $daysOfWeek[++$nextDayOfWeekIndex] ) );
344 + $pattern = ( $nextDayOfWeekIndex - $currentDayOfWeekIndex ) . " day";
345 + }
346 + return strtotime( $pattern, $current );
347 + }
348 +
349 + /**
350 + * Advances a date/time by a set number of months
351 + *
352 + * Advances a date/time by a set number of months. When the date/time of the first active period lies
353 + * on the 29th, 30th, or 31st of the month, this function will return a date/time on the the last day
354 + * of the month for those months not containing those days.
355 + *
356 + * @param int $current UNIX timestamp of the date/time before incrementing
357 + * @param int $start UNIX timestamp of the first active period's date/time
358 + * @param int $interval_multiplier Number of months to advance
359 + * @return int Unix timestamp of the new date/time
360 + */
361 + function __getNextMonth( $current, $start, $interval_multiplier ) {
362 +
363 + // For most days in the month, it's pretty easy. Get the day of month of the starting date.
364 + $startDay = date( "j", $start );
365 +
366 + // If it's before or on the 28th, just jump the number of months and be done with it.
367 + if ( $startDay <= 28 )
368 + return strtotime( $interval_multiplier . " month", $current );
369 +
370 + // If it's on the 29th, 30th, or 31st, it gets tricky. Some months don't have those days - so on those
371 + // months we need to repeat on the last day of the month instead, but we also need to jump back to the
372 + // correct day the following month. Let's say we want to repeat something on the 31st every month: this
373 + // is what we expect to see for a pattern:
374 + //
375 + // .
376 + // .
377 + // .
378 + // December 31st
379 + // January 31st
380 + // February 28th
381 + // March 31st
382 + // April 30th
383 + // .
384 + // .
385 + // .
386 + //
387 + // Unfortunately, PHP relative date handling isn't that smart (add "+1 month" to January 31st, and you
388 + // end up in March), so we'll have to figure it out ourselves by figuring out how many days to jump instead.
389 +
390 + // We'll need to calculate this for each interval and return the timestamp after the last jump.
391 + $temp_current = $current;
392 + for ( $i = 0; $i < $interval_multiplier; $i++ ) {
393 + // The pattern for jumping will be different in each interval.
394 + /** @noinspection PhpUnusedLocalVariableInspection */
395 + $temp_pattern = "";
396 +
397 + // Get the month number of the current date.
398 + //$currentMonth = date( "n", $temp_current );
399 +
400 + // Get the number of days in the month of the current date.
401 + $lastDayThisMonth = date( "t", strtotime( "this month", $temp_current ) );
402 +
403 + // Get the number of days for the next month relative to the current date .
404 + // Subtract 3 days from the next month to counter known month skipping bugs in PHP's relative date
405 + // handling, that being the difference between the shortest possible month (non-leap February - 28 days)
406 + // and the longest (Jan., Mar., May, Jul., Aug., Oct., Dec. - 31 days). This may be fixed in PHP 5.3.x
407 + // but this should be backwards-compatible anyway.
408 + $lastDayNextMonth = date( "t", strtotime( "-3 day next month", $temp_current ) );
409 +
410 + // If the current month is longer than next month, follow this block
411 + if ( $lastDayThisMonth > $lastDayNextMonth ) {
412 + // If we're repeating on the last day of this month, jump the number of days next month
413 + if ( $startDay == $lastDayThisMonth )
414 + $temp_pattern = $lastDayNextMonth . " days";
415 + // If the start day doesn't exist in the next month (i.e., no "31st" in June), jump the
416 + // number of days next month plus the difference between the start day and the number of days this month
417 + elseif ( $startDay > $lastDayNextMonth )
418 + $temp_pattern = ( $lastDayThisMonth + $lastDayNextMonth - $startDay ). " days";
419 + // Otherwise, jump ahead the number of days in this month
420 + else
421 + $temp_pattern = $lastDayThisMonth . " days";
422 + }
423 + // Or, if the current month is shorter than next month
424 + elseif ( $lastDayThisMonth < $lastDayNextMonth ) {
425 + // If the start day doesn't exist in this month (i.e., no "31st" in June), jump the
426 + // number of days next month plus the difference between the start day and the number of days this month
427 + if ( $startDay >= $lastDayThisMonth )
428 + $temp_pattern = $startDay . " days";
429 + // Otherwise, jump ahead the number of days in this month
430 + else
431 + $temp_pattern = $lastDayThisMonth . " days";
432 + }
433 + // If the current month and next month are equally long, jumping by "1 month" is fine
434 + else
435 + $temp_pattern = "1 month";
436 +
437 + $temp_current = strtotime( $temp_pattern, $temp_current );
438 + }
439 + return $temp_current;
440 +
441 + }
442 +
443 + /**
444 + * Advances a date/time to the 'n'th weekday of the next month (eg., first Wednesday, third Monday, last Friday, etc.).
445 + *
446 + * NB: if $ordinal is set to '4' and $day is set to '7', it wil return the last day of the month.
447 + *
448 + * @param int $current UNIX timestamp of the date/time before incrementing
449 + * @param int $ordinal Integer symbolizing the ordinal (0 - first, 1 - second, 2 - third, 3 - fourth, 4 - last)
450 + * @param int $day integers symbolizing the days of the week to
451 + * repeat on (0 - Sunday, 1 - Monday, ..., 6 - Saturday, 7 - day).
452 + * @return int Unix timestamp of the new date/time
453 + */
454 + function __getNthWeekdayOfMonth( $current, $ordinal, $day ) {
455 +
456 + // First, get the month/year we need to work with
457 + $the_month = date( "F", $current );
458 + $the_year = date( "Y", $current );
459 + $lastDayThisMonth = date( "t", $current );
460 +
461 + // Get the time for the $current timestamp
462 + $current_time = date( "g:i A", $current );
463 + $the_day = "";
464 +
465 + if ( $day == 7 ) { // If $day is "day of the month", get the day of month based on the ordinal
466 + switch ( $ordinal ) {
467 + case 0 : $the_day = "1"; break; // First day of the month //
468 + case 1 : $the_day = "2"; break; // Second day of the month //
469 + case 2 : $the_day = "3"; break; // Third day of the month //
470 + case 3 : $the_day = "4"; break; // Fourth day of the month //
471 + case 4 : $the_day = $lastDayThisMonth; break; // Last day of the month //
472 + default : $the_day = "1"; break;
473 + }
474 + } else { // If $day is one of the days of the week...
475 + $day_range = array();
476 + switch ( $ordinal ) { // ...get a 7-day range based on the ordinal...
477 + case 0 : $day_range = range( 1, 7 ); break; // First 7 days of the month //
478 + case 1 : $day_range = range( 8, 14 ); break; // Second 7 days of the month //
479 + case 2 : $day_range = range( 15, 21 ); break; // Third 7 days of the month //
480 + case 3 : $day_range = range( 22, 28 ); break; // Fourth 7 days of the month //
481 + case 4 : $day_range = range( $lastDayThisMonth - 6, $lastDayThisMonth ); break; // Last 7 days of the month //
482 + default : $day_range = range( 1, 7 ); break;
483 + }
484 + foreach ( $day_range as $a_day ) { // ...and find the matching weekday in that range.
485 + if ( $day == date( "w", strtotime( $the_month . " " . $a_day . ", " . $the_year ) ) ) {
486 + $the_day = $a_day;
487 + break;
488 + }
489 + }
490 + }
491 +
492 + // Build the date/time string for the correct day and return its timestamp
493 + $pattern = $the_month . " " . $the_day . ", " . $the_year . ", " . $current_time;
494 + return strtotime( $pattern );
495 +
496 + }
497 +
498 + /**
499 + * Advances a date/time by a set number of years
500 + *
501 + * @param int $current UNIX timestamp of the date/time before incrementing
502 + * @param int $interval_multiplier Number of years to advance
503 + * @return int Unix timestamp of the new date/time
504 + */
505 + function __getNextYear( $current, $interval_multiplier ) {
506 + return strtotime( $interval_multiplier . " year", $current );
507 + }
508 +
509 + /**
510 + * Validates the various Timed Content Rule parameters and returns a series of error messages.
511 + *
512 + * @param $args Array of Timed Content Rule parameters
513 + * @return array Array of error messages
514 + */
515 + function __validate( $args ) {
516 + $errors = array();
517 +
518 + $instance_start = strtotime( $this->__datetimeToEnglish( $args['instance_start']['date'], $args['instance_start']['time'] ) . ' ' . $args['timezone'] );
519 + $instance_end = strtotime( $this->__datetimeToEnglish( $args['instance_end']['date'], $args['instance_end']['time'] ) . ' ' . $args['timezone'] );
520 + $end_date = strtotime( $this->__datetimeToEnglish( $args['end_date'], $args['instance_start']['time'] ) . ' ' . $args['timezone'] );
521 +
522 + if ( $args['instance_start']['date'] == "" )
523 + $errors[] = __( "Date in Starting Date/Time must not be empty.", 'timed-content' );
524 + if ( $args['instance_start']['time'] == "" )
525 + $errors[] = __( "Time in Starting Date/Time must not be empty.", 'timed-content' );
526 + if ( $args['instance_end']['date'] == "" )
527 + $errors[] = __( "Date in Ending Date/Time must not be empty.", 'timed-content' );
528 + if ( $args['instance_end']['time'] == "" )
529 + $errors[] = __( "Time in Ending Date/Time must not be empty.", 'timed-content' );
530 + if ( $args['interval_multiplier'] == "" )
531 + $errors[] = __( "Repeat How Often? must not be empty.", 'timed-content' );
532 + if ( !is_numeric( $args['interval_multiplier'] ) )
533 + $errors[] = __( "Repeat How Often? must be a number.", 'timed-content' );
534 + if ( ( $args['num_repeat'] == "" ) && ( $args['recurr_type'] == "recurrence_duration_num_repeat" ) )
535 + $errors[] = __( "Repeat How Many Times? must not be empty.", 'timed-content' );
536 + if ( ( !is_numeric( $args['num_repeat'] ) ) && ( $args['recurr_type'] == "recurrence_duration_num_repeat" ) )
537 + $errors[] = __( "Repeat How Many Times? must be a number.", 'timed-content' );
538 + if ( ( $args['end_date'] == "" ) && ( $args['recurr_type'] == "recurrence_duration_end_date" ) )
539 + $errors[] = __( "End Date must not be empty.", 'timed-content' );
540 + if ( false === $instance_start )
541 + $errors[] = __( "Starting Date/Time must be valid.", 'timed-content' );
542 + if ( false === $instance_end )
543 + $errors[] = __( "Ending Date/Time must be valid.", 'timed-content' );
544 + if ( $instance_start > $instance_end )
545 + $errors[] = __( "Starting Date/Time must be before Ending Date/Time.", 'timed-content' );
546 + if ( ( $instance_end > $end_date ) && ( $args['recurr_type'] == "recurrence_duration_end_date" ) )
547 + $errors[] = __( "End Date must be after Ending Date/Time.", 'timed-content' );
548 +
549 + return $errors;
550 + }
551 +
552 + /**
553 + * Calculates the active periods for a Timed Content Rule
554 + *
555 + * @param $args Array of Timed Content Rule parameters
556 + * @return array Array of active periods. Each value in the array describes an active period as
557 + * an array itself with "start" and "end" keys and values that are either UNIX
558 + * timestamps or human-readable dates, based on whether $args['human_readable']
559 + * is set to true or false.
560 + */
561 + function __getRulePeriods( $args ) {
562 + $active_periods = array();
563 + $period_count = 0;
564 +
565 + $human_readable = $args['human_readable'];
566 + $freq = $args['freq'];
567 + $timezone = $args['timezone'];
568 + $recurr_type = $args['recurr_type'];
569 + $num_repeat = intval( $args['num_repeat'] );
570 + $end_date = $args['end_date'];
571 + $days_of_week = $args['days_of_week'];
572 + $interval_multiplier = $args['interval_multiplier'];
573 + $instance_start_date = $args['instance_start']['date'];
574 + $instance_start_time = $args['instance_start']['time'];
575 + $instance_end_date = $args['instance_end']['date'];
576 + $instance_end_time = $args['instance_end']['time'];
577 + $monthly_pattern = $args['monthly_pattern'];
578 + $monthly_pattern_ord = $args['monthly_pattern_ord'];
579 + $monthly_pattern_day = $args['monthly_pattern_day'];
580 + $exceptions_dates = $args['exceptions_dates'];
581 + //print_r($days_of_week);
582 +
583 + add_filter('date_i18n', array( &$this, "fix_date_i18n" ), 10, 4);
584 + $temp_tz = date_default_timezone_get();
585 + date_default_timezone_set( $timezone );
586 + $right_now_t = current_time( 'timestamp', 1 );
587 +
588 + $instance_start = strtotime( $this->__datetimeToEnglish( $instance_start_date, $instance_start_time ) . " " . $timezone ); // Beginning of first occurrence
589 + $instance_end = strtotime( $this->__datetimeToEnglish( $instance_end_date, $instance_end_time ) . " " . $timezone ); // End of first occurrence
590 + $current = $instance_start;
591 + $end_current = $instance_end;
592 +
593 + if ( $recurr_type == "recurrence_duration_num_repeat" )
594 + $last_occurrence_start = strtotime( TIMED_CONTENT_END_TIME );
595 + else
596 + $last_occurrence_start = strtotime( $this->__datetimeToEnglish( $end_date, $instance_start_time ) . " " . $timezone );
597 +
598 + if ( $human_readable == true ) {
599 + $active_periods[$period_count]["start"] = date_i18n( TIMED_CONTENT_DT_FORMAT, $current );
600 + $active_periods[$period_count]["end"] = date_i18n( TIMED_CONTENT_DT_FORMAT, $end_current );
601 + if ( $right_now_t < $current ) {
602 + $active_periods[$period_count]["status"] = "upcoming";
603 + $active_periods[$period_count]["time"] = sprintf( _x( '%s from now.', 'Human readable time difference', 'timed-content' ), human_time_diff( $right_now_t, $current ) );
604 + } elseif ( ( $current <= $right_now_t ) && ( $right_now_t <= $end_current ) ) {
605 + $active_periods[$period_count]["status"] = "active";
606 + $active_periods[$period_count]["time"] = __( "Right now!", 'timed-content' );
607 + } else {
608 + $active_periods[$period_count]["status"] = "expired";
609 + $active_periods[$period_count]["time"] = sprintf( _x( '%s ago.', 'Human readable time difference', 'timed-content' ), human_time_diff( $end_current, $right_now_t ) );
610 + }
611 + } else {
612 + $active_periods[$period_count]["start"] = $current;
613 + $active_periods[$period_count]["end"] = $end_current;
614 + }
615 + $period_count++;
616 +
617 + if ( $recurr_type == "recurrence_duration_end_date" )
618 + $loop_test = "return ( \$current < \$last_occurrence_start );";
619 + else
620 + $loop_test = "return ( \$period_count <= \$num_repeat );";
621 +
622 + while ( eval ( $loop_test ) ) {
623 + $temp_current = "";
624 + if ( $freq == 0 )
625 + $current = $this->__getNextHour( $current, $interval_multiplier );
626 + elseif ( $freq == 1 )
627 + $current = $this->__getNextDay( $current, $interval_multiplier );
628 + elseif ( $freq == 2 )
629 + $current = $this->__getNextWeek( $current, $interval_multiplier, $days_of_week );
630 + elseif ( $freq == 3 ) {
631 + $current = $this->__getNextMonth( $current, $instance_start, $interval_multiplier );
632 + $temp_current = $current;
633 + if ( $monthly_pattern == "yes" )
634 + $current = $this->__getNthWeekdayOfMonth( $current, $monthly_pattern_ord, $monthly_pattern_day );
635 + else
636 + $current = $temp_current;
637 + } elseif ( $freq == 4 )
638 + $current = $this->__getNextYear( $current, $interval_multiplier );
639 +
640 + $exception_period = false;
641 + if ( is_array( $exceptions_dates ) ) {
642 + foreach ($exceptions_dates as $date) {
643 + if (($current >= $date) && ($current < strtotime("+1 day", $date))) {
644 + $exception_period = true;
645 + break;
646 + }
647 + }
648 + }
649 +
650 + if ( ( eval ( $loop_test ) ) && ( !($exception_period) ) ) {
651 + $end_current = $current + ( $instance_end - $instance_start );
652 + if ( $human_readable == true ) {
653 + $active_periods[$period_count]["start"] = date_i18n( TIMED_CONTENT_DT_FORMAT, $current );
654 + $active_periods[$period_count]["end"] = date_i18n( TIMED_CONTENT_DT_FORMAT, $end_current );
655 + if ( $right_now_t < $current ) {
656 + $active_periods[$period_count]["status"] = "upcoming";
657 + $active_periods[$period_count]["time"] = sprintf( _x( '%s from now.', 'Human readable time difference', 'timed-content' ), human_time_diff( $current, $right_now_t ) );
658 + } elseif ( ( $current <= $right_now_t ) && ( $right_now_t <= $end_current ) ) {
659 + $active_periods[$period_count]["status"] = "active";
660 + $active_periods[$period_count]["time"] = __( "Right now!", 'timed-content' );
661 + } else {
662 + $active_periods[$period_count]["status"] = "expired";
663 + $active_periods[$period_count]["time"] = sprintf( _x( '%s ago.', 'Human readable time difference', 'timed-content' ), human_time_diff( $end_current, $right_now_t ) );
664 + }
665 + } else {
666 + $active_periods[$period_count]["start"] = $current;
667 + $active_periods[$period_count]["end"] = $end_current;
668 + }
669 + if ( !($exception_period) )
670 + $period_count++;
671 + }
672 +
673 + }
674 + date_default_timezone_set( $temp_tz );
675 + remove_filter('date_i18n', array( &$this, "fix_date_i18n" ), 10, 4);
676 + return $active_periods;
677 + }
678 +
679 + /**
680 + * Wrapper for calling timedContentPlugin::__getRulePeriods() by the ID of a Timed Content Rule
681 + *
682 + * @param int $ID ID of the Timed Content Rule
683 + * @param bool $human_readable If true, the active periods are returned as a human-readable date/time
684 + * as defined by the constant TIMED_CONTENT_DT_FORMAT; otherwise, they are
685 + * returned as UNIX timestamps.
686 + * @return array Array of active periods
687 + */
688 + function getRulePeriodsById( $ID, $human_readable = false ) {
689 + if ( TIMED_CONTENT_RULE_TYPE != get_post_type( $ID ) )
690 + return array();
691 +
692 + $prefix = TIMED_CONTENT_RULE_POSTMETA_PREFIX;
693 + $args = array();
694 +
695 + $args['human_readable'] = (bool) $human_readable;
696 + $args['freq'] = get_post_meta( $ID, $prefix . 'frequency', true );
697 + $args['timezone'] = get_post_meta( $ID, $prefix . 'timezone', true );
698 + $args['recurr_type'] = get_post_meta( $ID, $prefix . 'recurrence_duration', true );
699 + $args['num_repeat'] = get_post_meta( $ID, $prefix . 'recurrence_duration_num_repeat', true );
700 + $args['end_date'] = get_post_meta( $ID, $prefix . 'recurrence_duration_end_date', true );
701 + $args['days_of_week'] = get_post_meta( $ID, $prefix . 'weekly_days_of_week_to_repeat', true );
702 + if ( $args['freq'] == 0 ) $args['interval_multiplier'] = get_post_meta( $ID, $prefix . 'hourly_num_of_hours', true );
703 + if ( $args['freq'] == 1 ) $args['interval_multiplier'] = get_post_meta( $ID, $prefix . 'daily_num_of_days', true );
704 + if ( $args['freq'] == 2 ) $args['interval_multiplier'] = get_post_meta( $ID, $prefix . 'weekly_num_of_weeks', true );
705 + if ( $args['freq'] == 3 ) $args['interval_multiplier'] = get_post_meta( $ID, $prefix . 'monthly_num_of_months', true );
706 + if ( $args['freq'] == 4 ) $args['interval_multiplier'] = get_post_meta( $ID, $prefix . 'yearly_num_of_years', true );
707 + $args['instance_start'] = get_post_meta( $ID, $prefix . 'instance_start', true );
708 + $args['instance_end'] = get_post_meta( $ID, $prefix . 'instance_end', true );
709 + $args['monthly_pattern'] = get_post_meta( $ID, $prefix . 'monthly_nth_weekday_of_month', true );
710 + $args['monthly_pattern_ord'] = get_post_meta( $ID, $prefix . 'monthly_nth_weekday_of_month_nth', true );
711 + $args['monthly_pattern_day'] = get_post_meta( $ID, $prefix . 'monthly_nth_weekday_of_month_weekday', true );
712 + $args['exceptions_dates'] = get_post_meta( $ID, $prefix . 'exceptions_dates', true );
713 +
714 + return $this->__getRulePeriods( $args );
715 +
716 + }
717 +
718 + /**
719 + * Wrapper for calling timedContentPlugin::__getRulePeriods() based on the contents of the form fields
720 + * of the Add Timed Content Rule and Edit Timed Content Rule screens. Output is sent to output as JSON
721 + */
722 + function timedContentPluginGetRulePeriodsAjax() {
723 + if ( current_user_can( 'edit_posts' ) || current_user_can( 'edit_pages' ) ) {
724 + $prefix = TIMED_CONTENT_RULE_POSTMETA_PREFIX;
725 + $args = array();
726 +
727 + $args['human_readable'] = ( ( ( isset( $_POST[$prefix . 'human_readable'] ) ) && ( $_POST[$prefix . 'human_readable'] == 'true' ) ) ? (bool)$_POST[$prefix . 'human_readable'] : false );
728 + $args['freq'] = $_POST[$prefix . 'frequency'];
729 + $args['timezone'] = $_POST[$prefix . 'timezone'];
730 + $args['recurr_type'] = $_POST[$prefix . 'recurrence_duration'];
731 + $args['num_repeat'] = $_POST[$prefix . 'recurrence_duration_num_repeat'];
732 + $args['end_date'] = $_POST[$prefix . 'recurrence_duration_end_date'];
733 + $args['days_of_week'] = ( isset( $_POST[$prefix . 'weekly_days_of_week_to_repeat'] ) ? $_POST[$prefix . 'weekly_days_of_week_to_repeat'] : array() );
734 + $args['interval_multiplier'] = $_POST[$prefix . 'interval_multiplier'];
735 + $args['instance_start'] = $_POST[$prefix . 'instance_start'];
736 + $args['instance_end'] = $_POST[$prefix . 'instance_end'];
737 + $args['monthly_pattern'] = $_POST[$prefix . 'monthly_nth_weekday_of_month'];
738 + $args['monthly_pattern_ord'] = $_POST[$prefix . 'monthly_nth_weekday_of_month_nth'];
739 + $args['monthly_pattern_day'] = $_POST[$prefix . 'monthly_nth_weekday_of_month_weekday'];
740 + $args['exceptions_dates'] = ( isset( $_POST[$prefix . 'exceptions_dates'] ) ? $_POST[$prefix . 'exceptions_dates'] : array() );
741 +
742 + $response = json_encode( $this->__getRulePeriods( $args ) );
743 +
744 + // response output
745 + header( "Content-Type: application/json" );
746 + echo $response;
747 + }
748 + die();
749 +
750 + }
751 +
752 + /**
753 + * Returns a human-readable description of a Timed Content Rule
754 + *
755 + * @param $args Array of Timed Content Rule parameters
756 + * @return string
757 + */
758 + function __getScheduleDescription( $args ) {
759 + include("lib/Arrays_Definitions.php");
760 +
761 + $interval_multiplier = 1;
762 + $desc = "";
763 +
764 + $errors = $this->__validate( $args );
765 + if ( $errors ) {
766 + $messages = "<div class=\"tcr-warning\">\n";
767 + $messages .= "<p class=\"heading\">" . __( "Warning!", 'timed-content' ) . "</p>\n";
768 + $messages .= "<p>" . __( "Some problems have been detected. Although you can still publish this rule, it may not work the way you expect.", 'timed-content' ) . "</p>\n";
769 + $messages .= "<ul>\n";
770 + foreach ( $errors as $error )
771 + $messages .= " <li>" . $error . "</li>\n";
772 + $messages .= "</ul>\n";
773 + $messages .= "<p>" . __( "Check that all of the conditions for this rule are correct, and use Show Projected Dates/Times to ensure your rule is working properly.", 'timed-content' ) . "</p>\n";
774 + $messages .= "</div>\n";
775 + return $messages;
776 + }
777 +
778 + if ( $args['action'] )
779 + $action = __( "Show the content", 'timed-content' );
780 + else
781 + $action = __( "Hide the content", 'timed-content' );
782 + $freq = $args['freq'];
783 + $timezone = $args['timezone'];
784 + $recurr_type = $args['recurr_type'];
785 + $num_repeat = intval( $args['num_repeat'] );
786 + $end_date = $args['end_date'];
787 + $days_of_week = $args['days_of_week'];
788 + $interval_multiplier = $args['interval_multiplier'];
789 + $instance_start_date = $args['instance_start']['date'];
790 + $instance_start_time = $args['instance_start']['time'];
791 + $instance_end_date = $args['instance_end']['date'];
792 + $instance_end_time = $args['instance_end']['time'];
793 + $monthly_pattern = $args['monthly_pattern'];
794 + $monthly_pattern_ord = $args['monthly_pattern_ord'];
795 + $monthly_pattern_day = $args['monthly_pattern_day'];
796 + $exceptions_dates = $args['exceptions_dates'];
797 +
798 + $desc = sprintf( _x( '%1$s on %2$s @ %3$s until %4$s @ %5$s.', 'Perform action (%1$s) from date/time of first active period (%2$s @ %3$s) until date/time of last active period (%4$s @ %5$s).', 'timed-content' ), $action, $instance_start_date, $instance_start_time, $instance_end_date, $instance_end_time );
799 +
800 + if ( $freq == 0 )
801 + $desc .= "&nbsp;" . sprintf( _n( 'Repeat this action every hour.', 'Repeat this action every %d hours.', $interval_multiplier, 'timed-content' ), $interval_multiplier );
802 + elseif ( $freq == 1 )
803 + $desc .= "&nbsp;" . sprintf( _n( 'Repeat this action every day.', 'Repeat this action every %d days.', $interval_multiplier, 'timed-content' ), $interval_multiplier );
804 + elseif ( $freq == 2 ) {
805 + if ( ( $days_of_week ) && ( is_array( $days_of_week ) ) ) {
806 + $days = array(); $days_list = "";
807 + foreach ( $days_of_week as $v )
808 + $days[] = $timed_content_rule_days_array[$v];
809 + switch ( count( $days ) ) {
810 + case 1: $days_list = sprintf( _x( '%1$s', 'List of one weekday', 'timed-content' ), $days[0] ); break;
811 + case 2: $days_list = sprintf( _x( '%1$s and %2$s', 'List of two weekdays', 'timed-content' ), $days[0], $days[1] ); break;
812 + case 3: $days_list = sprintf( _x( '%1$s, %2$s, and %3$s', 'List of three weekdays', 'timed-content' ), $days[0], $days[1], $days[2] ); break;
813 + case 4: $days_list = sprintf( _x( '%1$s, %2$s, %3$s, and %4$s', 'List of four weekdays', 'timed-content' ), $days[0], $days[1], $days[2], $days[3] ); break;
814 + case 5: $days_list = sprintf( _x( '%1$s, %2$s, %3$s, %4$s, and %5$s', 'List of five weekdays', 'timed-content' ), $days[0], $days[1], $days[2], $days[3], $days[4] ); break;
815 + case 6: $days_list = sprintf( _x( '%1$s, %2$s, %3$s, %4$s, %5$s, and %6$s', 'List of six weekdays', 'timed-content' ), $days[0], $days[1], $days[2], $days[3], $days[4], $days[5] ); break;
816 + case 7: $days_list = sprintf( _x( '%1$s, %2$s, %3$s, %4$s, %5$s, %6$s, and %7$s', 'List of all weekdays', 'timed-content' ), $days[0], $days[1], $days[2], $days[3], $days[4], $days[5], $days[6] ); break;
817 + }
818 + if ( $interval_multiplier == 1 )
819 + $desc .= "&nbsp;" . sprintf( _x( 'Repeat this action every week on %s.', 'List the weekdays to repeat the rule when frequency is every week. %s is the list of weekdays.', 'timed-content' ), $days_list );
820 + else
821 + $desc .= "&nbsp;" . sprintf( _x( 'Repeat this action every %1$d weeks on %2$s.', 'List the weekdays to repeat the rule when frequency is every %1$d weeks. %2$s is the list of weekdays.', 'timed-content' ), $interval_multiplier, $days_list );
822 + } else
823 + $desc .= "&nbsp;" . sprintf( _n( 'Repeat this action every week.', 'Repeat this action every %d weeks.', $interval_multiplier, 'timed-content' ), $interval_multiplier );
824 +
825 + } elseif ( $freq == 3 ) {
826 + if ( $monthly_pattern == "yes" ) {
827 + if ( $interval_multiplier == 1 )
828 + $desc .= "&nbsp;" . sprintf( _x( 'Repeat this action every month on the %1$s %2$s of the month.', "Example: 'Repeat this action every month on the second Friday of the month.'", 'timed-content' ), $timed_content_rule_ordinal_array[$monthly_pattern_ord], $timed_content_rule_ordinal_days_array[$monthly_pattern_day] );
829 + else
830 + $desc .= "&nbsp;" . sprintf( _x( 'Repeat this action every %1$d months on the %2$s %3$s of the month.', "Example: 'Repeat this action every 2 months on the second Friday of the month.'", 'timed-content' ), $interval_multiplier, $timed_content_rule_ordinal_array[$monthly_pattern_ord], $timed_content_rule_ordinal_days_array[$monthly_pattern_day] );
831 + } else
832 + $desc .= "&nbsp;" . sprintf( _n( 'Repeat this action every month.', 'Repeat this action every %d months.', $interval_multiplier, 'timed-content' ), $interval_multiplier );
833 + } elseif ( $freq == 4 )
834 + $desc .= "&nbsp;" . sprintf( _n( 'Repeat this action every year.', 'Repeat this action every %d years.', $interval_multiplier, 'timed-content' ), $interval_multiplier );
835 +
836 + if ( $recurr_type == "recurrence_duration_num_repeat" )
837 + $desc .= "&nbsp;" . sprintf( _n( 'This rule will be active for 1 repetition.', 'This rule will be active for %d repetitions.', $num_repeat, 'timed-content' ), $num_repeat );
838 + elseif ( $recurr_type == "recurrence_duration_end_date" )
839 + $desc .= "&nbsp;" . sprintf( __( 'This rule will be active until %s.', 'timed-content' ), $end_date );
840 +
841 + if ( ( $exceptions_dates ) && ( is_array( $exceptions_dates ) ) ) {
842 + sort( $exceptions_dates, SORT_NUMERIC );
843 + $exceptions_dates = array_unique( $exceptions_dates );
844 + if ( $exceptions_dates[0] == 0 )
845 + array_shift( $exceptions_dates );
846 + if ( !empty( $exceptions_dates ) ) {
847 + $formatted_dates = array();
848 + foreach ( $exceptions_dates as $a_date )
849 + $formatted_dates[] = date( _x( "F j, Y" , "Date format for schedule description", 'timed-content' ), $a_date );
850 + $desc .= "&nbsp;" . sprintf( __( 'This rule will be inactive on the following dates: %s.', 'timed-content' ), join( ", ", $formatted_dates ) );
851 + }
852 + }
853 +
854 + $desc .= "&nbsp;" . sprintf( __( 'All times are in the %s timezone.', 'timed-content' ), $timezone );
855 + return $desc;
856 + }
857 +
858 + /**
859 + * Wrapper for calling timedContentPlugin::__getScheduleDescription() by the ID of a Timed Content Rule
860 + *
861 + * @param int $ID ID of the Timed Content Rule
862 + * @return string
863 + */
864 + function getScheduleDescriptionById( $ID ) {
865 + global $timed_content_rule_occurrence_custom_fields,
866 + $timed_content_rule_pattern_custom_fields,
867 + $timed_content_rule_recurrence_custom_fields,
868 + $timed_content_rule_exceptions_custom_fields;
869 + $defaults = array();
870 +
871 + foreach ( $timed_content_rule_occurrence_custom_fields as $field ) {
872 + $defaults[$field['name']] = $field['default'];
873 + }
874 + foreach ( $timed_content_rule_pattern_custom_fields as $field ) {
875 + $defaults[$field['name']] = $field['default'];
876 + }
877 + foreach ( $timed_content_rule_recurrence_custom_fields as $field ) {
878 + $defaults[$field['name']] = $field['default'];
879 + }
880 + foreach ( $timed_content_rule_exceptions_custom_fields as $field ) {
881 + $defaults[$field['name']] = $field['default'];
882 + }
883 +
884 + $prefix = TIMED_CONTENT_RULE_POSTMETA_PREFIX;
885 + $args = array();
886 +
887 + $args['action'] = ( false === get_post_meta( $ID, $prefix . 'action', true ) ? $defaults['action'] : get_post_meta( $ID, $prefix . 'action', true ) );
888 + $args['freq'] = ( false === get_post_meta( $ID, $prefix . 'frequency', true ) ? $defaults['frequency'] : get_post_meta( $ID, $prefix . 'frequency', true ) );
889 + $args['timezone'] = ( false === get_post_meta( $ID, $prefix . 'timezone', true ) ? $defaults['timezone'] : get_post_meta( $ID, $prefix . 'timezone', true ) );
890 + $args['recurr_type'] = ( false === get_post_meta( $ID, $prefix . 'recurrence_duration', true ) ? $defaults['recurrence_duration'] : get_post_meta( $ID, $prefix . 'recurrence_duration', true ) );
891 + $args['num_repeat'] = ( false === get_post_meta( $ID, $prefix . 'recurrence_duration_num_repeat', true ) ? $defaults['recurrence_duration_num_repeat'] : get_post_meta( $ID, $prefix . 'recurrence_duration_num_repeat', true ) );
892 + $args['end_date'] = ( false === get_post_meta( $ID, $prefix . 'recurrence_duration_end_date', true ) ? $defaults['recurrence_duration_end_date'] : get_post_meta( $ID, $prefix . 'recurrence_duration_end_date', true ) );
893 + $args['days_of_week'] = ( false === get_post_meta( $ID, $prefix . 'weekly_days_of_week_to_repeat', true ) ? $defaults['weekly_days_of_week_to_repeat'] : get_post_meta( $ID, $prefix . 'weekly_days_of_week_to_repeat', true ) );
894 + if ( $args['freq'] == 0 ) $args['interval_multiplier'] = ( false === get_post_meta( $ID, $prefix . 'hourly_num_of_hours', true ) ? $defaults['hourly_num_of_hours'] : get_post_meta( $ID, $prefix . 'hourly_num_of_hours', true ) );
895 + if ( $args['freq'] == 1 ) $args['interval_multiplier'] = ( false === get_post_meta( $ID, $prefix . 'daily_num_of_days', true ) ? $defaults['daily_num_of_days'] : get_post_meta( $ID, $prefix . 'daily_num_of_days', true ) );
896 + if ( $args['freq'] == 2 ) $args['interval_multiplier'] = ( false === get_post_meta( $ID, $prefix . 'weekly_num_of_weeks', true ) ? $defaults['weekly_num_of_weeks'] : get_post_meta( $ID, $prefix . 'weekly_num_of_weeks', true ) );
897 + if ( $args['freq'] == 3 ) $args['interval_multiplier'] = ( false === get_post_meta( $ID, $prefix . 'monthly_num_of_months', true ) ? $defaults['monthly_num_of_months'] : get_post_meta( $ID, $prefix . 'monthly_num_of_months', true ) );
898 + if ( $args['freq'] == 4 ) $args['interval_multiplier'] = ( false === get_post_meta( $ID, $prefix . 'yearly_num_of_years', true ) ? $defaults['yearly_num_of_years'] : get_post_meta( $ID, $prefix . 'yearly_num_of_years', true ) );
899 + $args['instance_start'] = ( false === get_post_meta( $ID, $prefix . 'instance_start', true ) ? $defaults['instance_start'] : get_post_meta( $ID, $prefix . 'instance_start', true ) );
900 + $args['instance_end'] = ( false === get_post_meta( $ID, $prefix . 'instance_end', true ) ? $defaults['instance_end'] : get_post_meta( $ID, $prefix . 'instance_end', true ) );
901 + $args['monthly_pattern'] = ( false === get_post_meta( $ID, $prefix . 'monthly_nth_weekday_of_month', true ) ? $defaults['monthly_nth_weekday_of_month'] : get_post_meta( $ID, $prefix . 'monthly_nth_weekday_of_month', true ) );
902 + $args['monthly_pattern_ord'] = ( false === get_post_meta( $ID, $prefix . 'monthly_nth_weekday_of_month_nth', true ) ? $defaults['monthly_nth_weekday_of_month_nth'] : get_post_meta( $ID, $prefix . 'monthly_nth_weekday_of_month_nth', true ) );
903 + $args['monthly_pattern_day'] = ( false === get_post_meta( $ID, $prefix . 'monthly_nth_weekday_of_month_weekday', true ) ? $defaults['monthly_nth_weekday_of_month_weekday'] : get_post_meta( $ID, $prefix . 'monthly_nth_weekday_of_month_weekday', true ) );
904 + $args['exceptions_dates'] = ( false === get_post_meta( $ID, $prefix . 'exceptions_dates', true ) ? $defaults['exceptions_dates'] : get_post_meta( $ID, $prefix . 'exceptions_dates', true ) );
905 +
906 + return $this->__getScheduleDescription( $args );
907 +
908 + }
909 +
910 + /**
911 + * Wrapper for calling timedContentPlugin::__getRulePeriods() based on the contents of the form fields
912 + * of the Add Timed Content Rule and Edit Timed Content Rule screens. Output is sent to output as plain text
913 + */
914 + function timedContentPluginGetScheduleDescriptionAjax() {
915 + if ( current_user_can( 'edit_posts' ) || current_user_can( 'edit_pages' ) ) {
916 + $prefix = TIMED_CONTENT_RULE_POSTMETA_PREFIX;
917 + $args = array();
918 +
919 + $args['action'] = $_POST[$prefix . 'action'];
920 + $args['freq'] = $_POST[$prefix . 'frequency'];
921 + $args['timezone'] = $_POST[$prefix . 'timezone'];
922 + $args['recurr_type'] = $_POST[$prefix . 'recurrence_duration'];
923 + $args['num_repeat'] = $_POST[$prefix . 'recurrence_duration_num_repeat'];
924 + $args['end_date'] = $_POST[$prefix . 'recurrence_duration_end_date'];
925 + $args['days_of_week'] = ( isset( $_POST[$prefix . 'weekly_days_of_week_to_repeat'] ) ? $_POST[$prefix . 'weekly_days_of_week_to_repeat'] : array() );
926 + $args['interval_multiplier'] = $_POST[$prefix . 'interval_multiplier'];
927 + $args['instance_start'] = $_POST[$prefix . 'instance_start'];
928 + $args['instance_end'] = $_POST[$prefix . 'instance_end'];
929 + $args['monthly_pattern'] = $_POST[$prefix . 'monthly_nth_weekday_of_month'];
930 + $args['monthly_pattern_ord'] = $_POST[$prefix . 'monthly_nth_weekday_of_month_nth'];
931 + $args['monthly_pattern_day'] = $_POST[$prefix . 'monthly_nth_weekday_of_month_weekday'];
932 + $args['exceptions_dates'] = ( isset( $_POST[$prefix . 'exceptions_dates'] ) ? $_POST[$prefix . 'exceptions_dates'] : array() );
933 +
934 + $response = $this->__getScheduleDescription( $args );
935 +
936 + // response output
937 + header( "Content-Type: text/plain" );
938 + echo $response;
939 + }
940 + die();
941 + }
942 +
943 + /**
944 + * Processes the [timed-content-client] shortcode.
945 + *
946 + * @param array $atts
947 + * @param null $content
948 + * @return string
949 + */
950 + function clientShowHTML( $atts, $content = null ) {
951 + $show_attr = "";
952 + $hide_attr = "";
953 + extract( shortcode_atts( array( 'show' => '0:00:000' , 'hide' => '0:00:000' , 'display' => 'div' ), $atts ) );
954 +
955 + // Initialize show/hide arguments
956 + $s_min = 0; $s_sec = 0; $s_fade = 0;
957 + $h_min = 0; $h_sec = 0; $h_fade = 0;
958 + @list( $s_min, $s_sec, $s_fade ) = explode( ":", $show );
959 + @list( $h_min, $h_sec, $h_fade ) = explode( ":", $hide );
960 +
961 + if ( ( (int)$s_min + (int)$s_sec ) > 0 )
962 + $show_attr = "_show_" . $s_min . "_" . $s_sec . "_" . $s_fade;
963 + if ( ( (int)$h_min + (int)$h_sec ) > 0 )
964 + $hide_attr = "_hide_" . $h_min . "_" . $h_sec . "_" . $h_fade;
965 +
966 + $the_class = TIMED_CONTENT_CLIENT_TAG . $show_attr . $hide_attr ;
967 + $the_tag = ( $display == "div" ? "div" : "span" );
968 +
969 + $the_filter = "timed_content_filter";
970 + $the_filter = apply_filters( "timed_content_filter_override", $the_filter );
971 +
972 + $the_HTML = "<"
973 + . $the_tag
974 + . " class='"
975 + . $the_class
976 + . "'"
977 + . ( ( $show_attr != "" ) ? " style='display: none;'" : "" ) .">"
978 + . str_replace( ']]>', ']]&gt;', apply_filters( $the_filter, $content ) )
979 + . "</" . $the_tag . ">";
980 +
981 + return $the_HTML;
982 + }
983 +
984 + /**
985 + * Processes the [timed-content-server] shortcode.
986 + *
987 + * @param array $atts
988 + * @param null $content
989 + * @return string
990 + */
991 + function serverShowHTML( $atts, $content = null ) {
992 + global $post;
993 + extract( shortcode_atts( array( 'show' => TIMED_CONTENT_ZERO_TIME , 'hide' => TIMED_CONTENT_END_TIME, 'debug' => 'false' ), $atts ) );
994 + $show_t = strtotime( $this->__datetimeToEnglish( $show ) );
995 + $hide_t = strtotime( $this->__datetimeToEnglish( $hide ) );
996 + $right_now_t = current_time( 'timestamp', 1 );
997 + $debug_message = "";
998 +
999 + $the_filter = "timed_content_filter";
1000 + $the_filter = apply_filters( "timed_content_filter_override", $the_filter );
1001 +
1002 + if ( ( $debug == "true" ) && ( current_user_can( "edit_post", $post->post_id ) ) ) {
1003 + add_filter('date_i18n', array( &$this, "fix_date_i18n" ), 10, 4);
1004 + $temp_tz = date_default_timezone_get();
1005 + date_default_timezone_set( get_option( 'timezone_string' ) );
1006 +
1007 + $right_now = date_i18n( TIMED_CONTENT_DT_FORMAT, $right_now_t );
1008 +
1009 + if ( $show_t > $right_now_t )
1010 + $show_diff_str = sprintf( _x( '%s from now.', 'Human readable time difference', 'timed-content' ), human_time_diff( $show_t, $right_now_t ) );
1011 + else
1012 + $show_diff_str = sprintf( _x( '%s ago.', 'Human readable time difference', 'timed-content' ), human_time_diff( $show_t, $right_now_t ) );
1013 + if ( $hide_t > $right_now_t )
1014 + $hide_diff_str = sprintf( _x( '%s from now.', 'Human readable time difference', 'timed-content' ), human_time_diff( $hide_t, $right_now_t ) );
1015 + else
1016 + $hide_diff_str = sprintf( _x( '%s ago.', 'Human readable time difference', 'timed-content' ), human_time_diff( $hide_t, $right_now_t ) );
1017 +
1018 + $debug_message = "<div class=\"tcr-warning\">\n";
1019 + $debug_message .= "<p class=\"heading\">" . _x( "Notice", "Noun", 'timed-content' ) . "</p>\n";
1020 + $debug_message .= "<p>" . sprintf( __( 'Debugging has been turned on for a %1$s shortcode on this Post/Page. Only website users who are currently logged in and can edit this Post/Page will see this. To turn off this message, remove the %2$s attribute from the shortcode.', 'timed-content' ), "<code>[timed-content-server]</code>" , "<code>debug</code>" ) . "</p>\n";
1021 +
1022 + if ( $show == TIMED_CONTENT_ZERO_TIME )
1023 + $debug_message .= "<p>" . sprintf( __( 'The %s attribute is not set.', 'timed-content' ), "<code>show</code>" ) . "</p>\n";
1024 + else
1025 + $debug_message .= "<p>" . sprintf( __( 'The %s attribute is currently set to', 'timed-content' ), "<code>show</code>" ) . ": " . $show . ",<br />\n "
1026 + . __( 'The Timed Content plugin thinks the intended date/time is', 'timed-content') . ": " . date_i18n( TIMED_CONTENT_DT_FORMAT, $show_t )
1027 + . " (" . $show_diff_str . ")</p>\n";
1028 +
1029 + if ( $hide == TIMED_CONTENT_END_TIME )
1030 + $debug_message .= "<p>" . sprintf( __( 'The %s attribute is not set.' , 'timed-content' ), "<code>hide</code>" ) . "</p>\n";
1031 + else
1032 + $debug_message .= "<p>" . sprintf( __( 'The %s attribute is currently set to', 'timed-content' ), "<code>hide</code>" ) . ": " . $hide . ",<br />\n"
1033 + . __( 'The Timed Content plugin thinks the intended date/time is', 'timed-content') . ": " . date_i18n( TIMED_CONTENT_DT_FORMAT, $hide_t )
1034 + . " (" . $hide_diff_str . ").</p>\n";
1035 +
1036 + $debug_message .= "<p>" . __( 'Current Date/Time:', 'timed-content') . "&nbsp;" . $right_now . "<br />\n";
1037 + $debug_message .= __( 'Content Filter:', 'timed-content') . "&nbsp;" . $the_filter . "</p>\n";
1038 + $debug_message .= "<p>" . _x( 'Content:', "Noun", 'timed-content') . "&nbsp;" . $content . "</p>\n";
1039 +
1040 + $debug_message .= "</div>\n";
1041 +
1042 + date_default_timezone_set( $temp_tz );
1043 + remove_filter('date_i18n', array( &$this, "fix_date_i18n" ), 10, 4);
1044 + }
1045 +
1046 +
1047 + if ( ( $show_t <= $right_now_t ) && ( $right_now_t <= $hide_t ) ) {
1048 + do_action("timed_content_server_show", $post->ID, $show, $hide, $content);
1049 + return $debug_message . str_replace(']]>', ']]&gt;', apply_filters($the_filter, $content)) . "\n";
1050 + } else {
1051 + do_action("timed_content_server_hide", $post->ID, $show, $hide, $content);
1052 + return $debug_message . "\n";
1053 + }
1054 +
1055 + }
1056 +
1057 + /**
1058 + * Processes the [timed-content-rule] shortcode.
1059 + *
1060 + * @param array $atts
1061 + * @param null $content
1062 + * @return string
1063 + */
1064 + function rulesShowHTML( $atts, $content = null ) {
1065 + global $post;
1066 + extract( shortcode_atts( array( 'id' => 0 ), $atts ) );
1067 + if ( !is_numeric( $id ) ) {
1068 + $page = get_page_by_title( $id, OBJECT, TIMED_CONTENT_RULE_TYPE );
1069 + if ( $page == null ) return;
1070 + $id = $page->ID;
1071 + }
1072 + if ( TIMED_CONTENT_RULE_TYPE != get_post_type( $id ) ) return;
1073 +
1074 + $prefix = TIMED_CONTENT_RULE_POSTMETA_PREFIX;
1075 + $right_now_t = current_time( 'timestamp', 1 );
1076 + $rule_is_active = false;
1077 +
1078 + $active_periods = $this->getRulePeriodsById( $id, false );
1079 + $action_is_show = (bool) get_post_meta( $id, $prefix . 'action', true );
1080 +
1081 + foreach ( $active_periods as $period ) {
1082 + if ( ( $period['start'] <= $right_now_t ) && ( $right_now_t <= $period['end'] ) ) {
1083 + $rule_is_active = true;
1084 + break;
1085 + }
1086 + }
1087 +
1088 + $the_filter = "timed_content_filter";
1089 + $the_filter = apply_filters( "timed_content_filter_override", $the_filter );
1090 +
1091 + if ( ( ( $rule_is_active == true ) && ( $action_is_show == true ) ) || ( ( $rule_is_active == false ) && ( $action_is_show == false ) ) ) {
1092 + do_action("timed_content_rule_show", $post->ID, $id, $content);
1093 + return str_replace(']]>', ']]&gt;', apply_filters($the_filter, $content));
1094 + } else {
1095 + do_action("timed_content_rule_hide", $post->ID, $id, $content);
1096 + return "";
1097 + }
1098 + }
1099 +
1100 + /**
1101 + * Enqueues the JavaScript code necessary for the functionality of the [timed-content-client] shortcode.
1102 + */
1103 + function addHeaderCode() {
1104 + if ( ! is_admin() ) {
1105 + wp_enqueue_style( 'timed-content-css', TIMED_CONTENT_CSS, false, TIMED_CONTENT_VERSION );
1106 + wp_enqueue_script( 'timed-content_js', TIMED_CONTENT_PLUGIN_URL . '/js/timed-content.js', array( 'jquery' ), TIMED_CONTENT_VERSION );
1107 + }
1108 + }
1109 +
1110 + /**
1111 + * Enqueues the CSS code necessary for custom icons for the Timed Content Rules management screens for WP 3.7.1 and under. Echo'd to output.
1112 + */
1113 + function addPostTypeIcons37() {
1114 + ?>
1115 + <style type="text/css" media="screen">
1116 + #menu-posts-<?php echo TIMED_CONTENT_RULE_TYPE; ?> .wp-menu-image {
1117 + background: url(<?php echo TIMED_CONTENT_PLUGIN_URL; ?>/img/clock_icon.png) no-repeat 6px 6px !important;
1118 + }
1119 + #menu-posts-<?php echo TIMED_CONTENT_RULE_TYPE; ?>:hover .wp-menu-image, #menu-posts-<?php echo TIMED_CONTENT_RULE_TYPE; ?>.wp-has-current-submenu .wp-menu-image {
1120 + background-position: -22px 6px !important;
1121 + }
1122 + #icon-edit.icon32-posts-<?php echo TIMED_CONTENT_RULE_TYPE; ?> {background: url(<?php echo TIMED_CONTENT_PLUGIN_URL; ?>/img/clock_32x32.png) no-repeat;}
1123 + </style>
1124 + <?php
1125 + }
1126 +
1127 + /**
1128 + * Enqueues the CSS code necessary for custom icons for the Timed Content Rules management screens
1129 + * and the TinyMCE editor. Echo'd to output.
1130 + */
1131 + function addPostTypeIcons() {
1132 + wp_enqueue_style( 'ca-aliencyborg-dashicons', TIMED_CONTENT_CSS_DASHICONS, false, TIMED_CONTENT_VERSION );
1133 + ?>
1134 + <style type="text/css" media="screen">
1135 + #adminmenu #menu-posts-<?php echo TIMED_CONTENT_RULE_TYPE; ?>.menu-icon-post div.wp-menu-image:before {
1136 + font-family: 'ca-aliencyborg-dashicons' !important;
1137 + content: '\e601';
1138 + }
1139 + #dashboard_right_now li.<?php echo TIMED_CONTENT_RULE_TYPE; ?>-count a:before {
1140 + font-family: 'ca-aliencyborg-dashicons' !important;
1141 + content: '\e601';
1142 + }
1143 + .mce-i-timed_content:before {
1144 + font: 400 24px/1 'ca-aliencyborg-dashicons' !important;
1145 + padding: 0;
1146 + vertical-align: top;
1147 + margin-left: -2px;
1148 + padding-right: 2px;
1149 + content: '\e601';
1150 + }
1151 + </style>
1152 +<?php
1153 + }
1154 +
1155 + /**
1156 + * Enqueues the JavaScript code necessary for the functionality of the Timed Content Rules management screens.
1157 + */
1158 + function addAdminHeaderCode() {
1159 + if ( ( isset( $_GET['post_type'] ) && $_GET['post_type'] == TIMED_CONTENT_RULE_TYPE )
1160 + || ( isset( $post_type ) && $post_type == TIMED_CONTENT_RULE_TYPE )
1161 + || ( isset( $_GET['post'] ) && get_post_type( $_GET['post'] ) == TIMED_CONTENT_RULE_TYPE ) ) {
1162 + wp_enqueue_style( 'thickbox' );
1163 + wp_enqueue_style( 'timed-content-css', TIMED_CONTENT_CSS, false, TIMED_CONTENT_VERSION );
1164 + // Enqueue the JavaScript file that manages the meta box UI
1165 + wp_enqueue_script( 'timed-content-admin_js', TIMED_CONTENT_PLUGIN_URL . '/js/timed-content-admin.js', array( 'jquery' ), TIMED_CONTENT_VERSION );
1166 + // Enqueue the JavaScript file that makes AJAX requests
1167 + wp_enqueue_script( 'timed-content-ajax_js', TIMED_CONTENT_PLUGIN_URL . '/js/timed-content-ajax.js', array( 'jquery', 'thickbox' ), TIMED_CONTENT_VERSION );
1168 +
1169 + // Set up local variables used in the Admin JavaScript file
1170 + wp_localize_script( 'timed-content-admin_js', 'timedContentRuleAdmin', array(
1171 + 'no_exceptions_label' => __( "- No exceptions set -", 'timed-content' ) ) );
1172 +
1173 + // Set up local variables used in the AJAX JavaScript file
1174 + wp_localize_script( 'timed-content-ajax_js', 'timedContentRuleAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ),
1175 + 'start_label' => _x( 'Start', 'Scheduled Dates/Times dialog - Beginning of active period table header', 'timed-content' ),
1176 + 'end_label' => _x( 'End', 'Scheduled Dates/Times dialog - End of active period table header', 'timed-content' ),
1177 + 'dialog_label' => _x( 'Scheduled Dates/Times', 'Scheduled Dates/Times dialog - dialog header', 'timed-content' ),
1178 + 'button_loading_label' => __( 'Calculating Dates/Times', 'timed-content' ),
1179 + 'button_finished_label' => __( 'Show Projected Dates/Times', 'timed-content' ),
1180 + 'dialog_width' => 800,
1181 + 'dialog_height' => 500,
1182 + 'error' => __( "Error", 'timed-content' ),
1183 + 'error_desc' => __( "Something unexpected has happened along the way. The specific details are below:", 'timed-content' ) ) );
1184 + }
1185 + }
1186 +
1187 + /**
1188 + * Initializes the TinyMCE plugin bundled with this Wordpress plugin
1189 + */
1190 + function initTinyMCEPlugin() {
1191 + if ( ( ! current_user_can( 'edit_posts' ) ) && ( ! current_user_can( 'edit_pages' ) ) )
1192 + return;
1193 +
1194 + // Add only in Rich Editor mode
1195 + if ( get_user_option( 'rich_editing' ) == 'true' ) {
1196 + add_filter( "mce_external_plugins", array( &$this, "addTimedContentTinyMCEPlugin" ) );
1197 + add_filter( "mce_buttons", array( &$this, "registerTinyMCEButton" ) );
1198 + }
1199 + }
1200 +
1201 + /**
1202 + * Sets up variables to use in the TinyMCE plugin's plugin.js.
1203 + *
1204 + */
1205 + function setTinyMCEPluginVars() {
1206 + global $wp_version;
1207 + if ( ( ! current_user_can( 'edit_posts' ) ) && ( ! current_user_can( 'edit_pages' ) ) )
1208 + return;
1209 +
1210 + // Add only in Rich Editor mode
1211 + if ( get_user_option( 'rich_editing' ) == 'true' ) {
1212 + if ( version_compare( $wp_version, "3.8", "<" ) )
1213 + $image = "/clock.gif";
1214 + else
1215 + $image = "";
1216 + wp_localize_script( 'editor',
1217 + 'timedContentAdminTinyMCEOptions',
1218 + array( 'version' => TIMED_CONTENT_VERSION,
1219 + 'desc' => __( "Add Timed Content shortcodes", 'timed-content' ),
1220 + 'image' => $image ) );
1221 + }
1222 + }
1223 +
1224 + /**
1225 + * Sets up the button for the associated TinyMCE plugin for use in the editor menubar.
1226 + * @param array $buttons Array of menu buttons already registered with TinyMCE
1227 + * @return array The array of TinyMCE menu buttons with ours now loaded in as well
1228 + */
1229 + function registerTinyMCEButton( $buttons ) {
1230 + array_push( $buttons, "|", "timed_content" );
1231 + return $buttons;
1232 + }
1233 +
1234 + /**
1235 + * Loads the associated TinyMCE plugin into TinyMCE's plugin array
1236 + *
1237 + * @param array $plugin_array Array of plugins already registered with TinyMCE
1238 + * @return array The array of TinyMCE plugins with ours now loaded in as well
1239 + */
1240 + function addTimedContentTinyMCEPlugin( $plugin_array ) {
1241 + $plugin_array['timed_content'] = TIMED_CONTENT_PLUGIN_URL . "/tinymce_plugin/plugin.js";
1242 + return $plugin_array;
1243 + }
1244 +
1245 + /**
1246 + * Generates JavaScript array of objects describing Timed Content Rules. Used in the dialog box created by
1247 + * timedContentPlugin::timedContentPluginGetTinyMCEDialog().
1248 + *
1249 + * @return string
1250 + */
1251 + function __getRulesJS() {
1252 + $the_js = "var rules = [\n";
1253 + $args = array( 'post_type' => TIMED_CONTENT_RULE_TYPE, 'posts_per_page' => -1, 'post_status' => 'publish' );
1254 + $the_rules = get_posts( $args );
1255 + foreach ( $the_rules as $rule ) {
1256 + $desc = $this->getScheduleDescriptionById( $rule->ID );
1257 + // Only add a rule if there's no errors or warnings
1258 + if ( false === strpos( $desc, "tcr-warning" ) )
1259 + $the_js .= " { 'ID': " . $rule->ID . ", 'title': '" . esc_js( ( ( strlen( $rule->post_title ) > 0 ) ? $rule->post_title : _x( "(no title)", "No Timed Content Rule title", "timed-content" ) ) ) . "', 'desc': '" . esc_js( $desc ) . "' },\n";
1260 + }
1261 + if ( empty( $the_rules ) )
1262 + $the_js .= " { 'ID': -999, 'title': ' ---- ', 'desc': '" . __( 'No Timed Content Rules found', 'timed-content' ) . "' }\n";
1263 +
1264 + $the_js .= "];\n";
1265 + return $the_js;
1266 + }
1267 + /**
1268 + * Display a dialog box for this plugin's associated TinyMCE plugin. Called from TinyMCE via AJAX.
1269 + *
1270 + */
1271 + function timedContentPluginGetTinyMCEDialog() {
1272 + include("lib/jquery-ui-datetime-i18n.php");
1273 +
1274 + wp_enqueue_style(TIMED_CONTENT_SLUG . '-jquery-ui-css', TIMED_CONTENT_JQUERY_UI_CSS);
1275 + wp_enqueue_script('jquery-ui-datepicker');
1276 + wp_register_style(TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-css', TIMED_CONTENT_JQUERY_UI_TIMEPICKER_CSS);
1277 + wp_enqueue_style(TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-css');
1278 + wp_register_script(TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-js', TIMED_CONTENT_JQUERY_UI_TIMEPICKER_JS, array('jquery', 'jquery-ui-datepicker'), TIMED_CONTENT_VERSION);
1279 + wp_enqueue_script(TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-js');
1280 + if (!(wp_script_is(TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js', 'registered'))) {
1281 + wp_register_script(TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js', TIMED_CONTENT_PLUGIN_URL . "/js/content-protector-datetime-i18n.js", array('jquery', 'jquery-ui-datepicker', TIMED_CONTENT_SLUG . '-jquery-ui-timepicker-js'), TIMED_CONTENT_VERSION);
1282 + wp_enqueue_script(TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js');
1283 + wp_localize_script(TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js', 'TimedContentJQDatepickerI18n', $jquery_ui_datetime_datepicker_i18n);
1284 + wp_localize_script(TIMED_CONTENT_SLUG . '-jquery-ui-datetime-i18n-js', 'TimedContentJQTimepickerI18n', $jquery_ui_datetime_timepicker_i18n);
1285 + }
1286 +
1287 + ob_start();
1288 + include( "tinymce_plugin/dialog.php" );
1289 + $content = ob_get_contents();
1290 + ob_end_clean();
1291 + echo $content;
1292 + die();
1293 + }
1294 +
1295 + /**
1296 + * Adds support for i18n (internationalization)
1297 + *
1298 + */
1299 + function i18nInit() {
1300 + $plugin_dir = basename( dirname( __FILE__ ) ) . "/lang/";
1301 + load_plugin_textdomain( 'timed-content', false, $plugin_dir );
1302 + }
1303 +
1304 + /**
1305 + * Add custom columns to the Timed Content Rules overview page
1306 + *
1307 + */
1308 + function addDescColumnHead( $defaults ) {
1309 + unset( $defaults['date'] );
1310 + $defaults['description'] = __( 'Description', 'timed-content' );
1311 + $defaults['shortcode'] = __( 'Shortcode', 'timed-content' );
1312 + return $defaults;
1313 + }
1314 +
1315 + /**
1316 + * Display content associated with custom columns on the Timed Content Rules overview page
1317 + *
1318 + * @param $column_name Name of the column to be displayed
1319 + * @param $post_ID ID of the Timed Content Rule being listed
1320 + */
1321 + function addDescColumnContent( $column_name, $post_ID ) {
1322 + if ( $column_name == 'shortcode' ) {
1323 + echo '<code>[' . TIMED_CONTENT_RULE_TAG . ' id="' . $post_ID . '"]...[/' . TIMED_CONTENT_RULE_TAG . ']</code>';
1324 + }
1325 + if ( $column_name == 'description' ) {
1326 + $desc = $this->getScheduleDescriptionById( $post_ID );
1327 + if ( $desc ) {
1328 + echo '<em>' . $desc . '</em>';
1329 + }
1330 + }
1331 + }
1332 +
1333 + /**
1334 + * Display a count of Timed Content Rules in the Dashboard's Right Now widget for Wordpress versions 3.7.1 and below
1335 + *
1336 + */
1337 + function addRulesCount37() {
1338 + if ( !post_type_exists( TIMED_CONTENT_RULE_TYPE ) ) {
1339 + return;
1340 + }
1341 +
1342 + $num_posts = wp_count_posts( TIMED_CONTENT_RULE_TYPE );
1343 + $num = number_format_i18n( $num_posts->publish );
1344 + $text = _n( 'Timed Content Rule', 'Timed Content Rules', intval( $num_posts->publish ), 'timed-content' );
1345 + if ( current_user_can( 'edit_posts' ) || current_user_can( 'edit_pages' ) ) {
1346 + $num = "<a href='edit.php?post_type=" . TIMED_CONTENT_RULE_TYPE . "'>" . $num . "</a>";
1347 + $text = "<a href='edit.php?post_type=" . TIMED_CONTENT_RULE_TYPE . "'>" . $text . "</a>";
1348 + }
1349 + echo '<tr>';
1350 + echo '<td class="first b b-' . TIMED_CONTENT_RULE_TYPE . '">' . $num . '</td>';
1351 + echo '<td class="t ' . TIMED_CONTENT_RULE_TYPE . '">' . $text . '</td>';
1352 + echo '</tr>';
1353 +
1354 + if ( $num_posts->pending > 0 ) {
1355 + $num = number_format_i18n( $num_posts->pending );
1356 + $text = _n( 'Timed Content Rule Pending', 'Timed Content Rules Pending', intval( $num_posts->pending ), 'timed-content' );
1357 + if ( current_user_can( 'edit_posts' ) || current_user_can( 'edit_pages' ) ) {
1358 + $num = "<a href='edit.php?post_status=pending&post_type=" . TIMED_CONTENT_RULE_TYPE . "'>" . $num . "</a>";
1359 + $text = "<a href='edit.php?post_status=pending&post_type=" . TIMED_CONTENT_RULE_TYPE . "'>" . $text . "</a>";
1360 + }
1361 + echo '<tr>';
1362 + echo '<td class="first b b-' . TIMED_CONTENT_RULE_TYPE . '">' . $num . '</td>';
1363 + echo '<td class="t ' . TIMED_CONTENT_RULE_TYPE . '">' . $text . '</td>';
1364 + echo '</tr>';
1365 + }
1366 + }
1367 +
1368 + /**
1369 + * Display a count of Timed Content Rules in the Dashboard's Right Now widget
1370 + *
1371 + */
1372 + function addRulesCount() {
1373 + if ( !post_type_exists( TIMED_CONTENT_RULE_TYPE ) ) {
1374 + return;
1375 + }
1376 +
1377 + $num_posts = wp_count_posts( TIMED_CONTENT_RULE_TYPE );
1378 + $num = number_format_i18n( $num_posts->publish );
1379 + $text = _n( 'Timed Content Rule', 'Timed Content Rules', intval( $num_posts->publish ), 'timed-content' );
1380 + if ( current_user_can( 'edit_posts' ) || current_user_can( 'edit_pages' ) )
1381 + echo "<a href='edit.php?post_type=" . TIMED_CONTENT_RULE_TYPE . "'>"
1382 + . '<li class="' . TIMED_CONTENT_RULE_TYPE . '-count">'
1383 + . $num
1384 + . ' '
1385 + . $text
1386 + . '</a></li>';
1387 +
1388 + if ( $num_posts->pending > 0 ) {
1389 + $num = number_format_i18n( $num_posts->pending );
1390 + $text = _n( 'Timed Content Rule Pending', 'Timed Content Rules Pending', intval( $num_posts->pending ), 'timed-content' );
1391 + if ( current_user_can( 'edit_posts' ) || current_user_can( 'edit_pages' ) )
1392 + echo "<a href='edit.php?post_status=pending&post_type=" . TIMED_CONTENT_RULE_TYPE . "'>"
1393 + . '<li class="' . TIMED_CONTENT_RULE_TYPE . '-count">'
1394 + . $num
1395 + . ' '
1396 + . $text
1397 + . '</a></li>';
1398 + }
1399 + }
1400 +
1401 + function setUpCustomFields() {
1402 + require_once( "lib/customFields-settings.php" );
1403 + require_once( "lib/customFieldsInterface.php" );
1404 +
1405 + $scf = new customFieldsInterface( "timed_content_rule_schedule",
1406 + __( 'Rule Description/Schedule', 'timed-content' ),
1407 + "<div id=\"schedule_desc\" style=\"font-style: italic;\">"
1408 + . ( isset( $_GET['post'] ) && ( TIMED_CONTENT_RULE_TYPE === get_post_type( $_GET['post'] ) ) ? $this->getScheduleDescriptionById( intval( $_GET['post'] ) ) : $this->getScheduleDescriptionById( intval( 0 ) ) )
1409 + . "</div>"
1410 + . "<div id=\"tcr-dialogHolder\" style=\"display:none;\"></div>"
1411 + . "<div style=\"padding-top: 10px;\"><input type=\"button\" class=\"button button-primary\" id=\"timed_content_rule_test\" value=\"" . __( 'Show Projected Dates/Times', 'timed-content' ) . "\" /></div>",
1412 + TIMED_CONTENT_RULE_POSTMETA_PREFIX,
1413 + array( TIMED_CONTENT_RULE_TYPE ),
1414 + array() );
1415 + $ocf = new customFieldsInterface( "timed_content_rule_initial_event",
1416 + __( 'Action/Initial Event', 'timed-content' ),
1417 + __( 'Set the action to be taken and when it should first run.', 'timed-content' ),
1418 + TIMED_CONTENT_RULE_POSTMETA_PREFIX,
1419 + array( TIMED_CONTENT_RULE_TYPE ),
1420 + $timed_content_rule_occurrence_custom_fields );
1421 + $pcf = new customFieldsInterface( "timed_content_rule_recurrence",
1422 + __( 'Repeating Pattern', 'timed-content' ),
1423 + __( 'Set how often the action should repeat.', 'timed-content' ),
1424 + TIMED_CONTENT_RULE_POSTMETA_PREFIX,
1425 + array( TIMED_CONTENT_RULE_TYPE ),
1426 + $timed_content_rule_pattern_custom_fields );
1427 + $rcf = new customFieldsInterface( "timed_content_rule_stop_condition",
1428 + __( 'Stopping Condition', 'timed-content' ),
1429 + __( 'Set how long or how many times the action should occur.', 'timed-content' ),
1430 + TIMED_CONTENT_RULE_POSTMETA_PREFIX,
1431 + array( TIMED_CONTENT_RULE_TYPE ),
1432 + $timed_content_rule_recurrence_custom_fields );
1433 + $ecf = new customFieldsInterface( "timed_content_rule_exceptions",
1434 + __( 'Exceptions', 'timed-content' ),
1435 + __( 'Set up any exceptions to this Timed Content Rule.', 'timed-content' ),
1436 + TIMED_CONTENT_RULE_POSTMETA_PREFIX,
1437 + array( TIMED_CONTENT_RULE_TYPE ),
1438 + $timed_content_rule_exceptions_custom_fields );
1439 +
1440 + // Initially loaded at the top; defining this constant here means it can get i18n'd
1441 + /* translators: date/time format for debugging messages. http://ca2.php.net/manual/en/function.date.php */
1442 + define( "TIMED_CONTENT_DT_FORMAT", __( "l, F jS, Y, g:i A T" , 'timed-content' ) );
1443 +
1444 + }
1445 +
1446 + }
1447 +
1448 +} //End Class timedContentPlugin
1449 +
1450 +// Initialize plugin
1451 +if ( class_exists( "timedContentPlugin" ) ) {
1452 + $timedContentPluginInstance = new timedContentPlugin();
1453 +}
1454 +
1455 +// Actions and Filters
1456 +if ( isset( $timedContentPluginInstance ) ) {
1457 + global $wp_version;
1458 +
1459 + add_filter('timed_content_filter', 'wptexturize');
1460 + add_filter('timed_content_filter', 'convert_smilies');
1461 + add_filter('timed_content_filter', 'convert_chars');
1462 + add_filter('timed_content_filter', 'wpautop');
1463 + add_filter('timed_content_filter', 'prepend_attachment');
1464 + add_filter('timed_content_filter', 'do_shortcode');
1465 +
1466 + add_action( "plugins_loaded", array( &$timedContentPluginInstance, "i18nInit" ), 1 );
1467 + add_action( "init", array( &$timedContentPluginInstance, "timedContentRuleTypeInit" ), 2 );
1468 + add_action( "init", array( &$timedContentPluginInstance, "setUpCustomFields" ), 2 );
1469 + add_action( "wp_head", array( &$timedContentPluginInstance, "addHeaderCode" ), 1 );
1470 + add_filter( "manage_" . TIMED_CONTENT_RULE_TYPE . "_posts_columns", array( &$timedContentPluginInstance, "addDescColumnHead" ) );
1471 + add_action( "manage_" . TIMED_CONTENT_RULE_TYPE . "_posts_custom_column", array( &$timedContentPluginInstance, "addDescColumnContent" ), 10, 2);
1472 + add_action( "admin_enqueue_scripts", array( &$timedContentPluginInstance, "addAdminHeaderCode" ), 1 );
1473 + add_action( "admin_init", array( &$timedContentPluginInstance, "setTinyMCEPluginVars" ), 1 );
1474 + add_action( "admin_init", array( &$timedContentPluginInstance, "initTinyMCEPlugin" ), 2 );
1475 + add_action( 'wp_ajax_timedContentPluginGetTinyMCEDialog', array( &$timedContentPluginInstance, "timedContentPluginGetTinyMCEDialog" ), 1 );
1476 + add_action( 'wp_ajax_timedContentPluginGetRulePeriodsAjax', array( &$timedContentPluginInstance, "timedContentPluginGetRulePeriodsAjax" ), 1 );
1477 + add_action( 'wp_ajax_timedContentPluginGetScheduleDescriptionAjax', array( &$timedContentPluginInstance, "timedContentPluginGetScheduleDescriptionAjax" ), 1 );
1478 + add_filter( "post_updated_messages", array( &$timedContentPluginInstance, "timedContentRuleUpdatedMessages" ), 1 );
1479 + if ( version_compare( $wp_version, "3.8", ">=" ) ) {
1480 + add_action( "dashboard_glance_items", array( &$timedContentPluginInstance, "addRulesCount" ) );
1481 + add_action( "admin_head", array( &$timedContentPluginInstance, "addPostTypeIcons" ), 1 );
1482 + } else {
1483 + add_action( "right_now_content_table_end", array( &$timedContentPluginInstance, "addRulesCount37" ) );
1484 + add_action( "admin_head", array( &$timedContentPluginInstance, "addPostTypeIcons37" ), 1 );
1485 + }
1486 +
1487 + add_shortcode( TIMED_CONTENT_CLIENT_TAG, array( &$timedContentPluginInstance, "clientShowHTML" ), 1 );
1488 + add_shortcode( TIMED_CONTENT_SERVER_TAG, array( &$timedContentPluginInstance, "serverShowHTML" ), 1 );
1489 + add_shortcode( TIMED_CONTENT_RULE_TAG, array( &$timedContentPluginInstance, "rulesShowHTML" ), 1 );
1490 +}
2293 1491 ?>