PluginProbe
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions / trunk
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions vtrunk
260909 260829 260814 260805 110710 110731 110812 110815 110912 110913 110915 110926 110927 111002 111003 111011 111017 111029 111105 111206 111216 111220 120213 120219 120301 All 187 releases
s2member / src / includes / classes / utils-time.inc.php

utils-time.inc.php in s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions trunk, at src/includes/classes/utils-time.inc.php

388 lines 18.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // @codingStandardsIgnoreFile
3 /**
4 * Time utilities.
5 *
6 * Copyright: © 2009-2011
7 * {@link http://websharks-inc.com/ WebSharks, Inc.}
8 * (coded in the USA)
9 *
10 * Released under the terms of the GNU General Public License.
11 * You should have received a copy of the GNU General Public License,
12 * along with this software. In the main directory, see: /licensing/
13 * If not, see: {@link http://www.gnu.org/licenses/}.
14 *
15 * @package s2Member\Utilities
16 * @since 3.5
17 */
18 if(!defined('WPINC')) // MUST have WordPress.
19 exit('Do not access this file directly.');
20
21 if(!class_exists('c_ws_plugin__s2member_utils_time'))
22 {
23 /**
24 * Time utilities.
25 *
26 * @package s2Member\Utilities
27 * @since 3.5
28 */
29 class c_ws_plugin__s2member_utils_time
30 {
31 /**
32 * Determines the difference between two timestamps.
33 *
34 * Returns the difference in a human readable format.
35 * Supports: minutes, hours, days, weeks, months, and years. This is an improvement on WordPress ``human_time_diff()``.
36 * This returns an "approximate" time difference. Rounded to nearest minute, hour, day, week, month, year.
37 *
38 * @package s2Member\Utilities
39 * @since 3.5
40 *
41 * @param int $from Beginning timestamp to start from.
42 * @param int $to Ending timestamp to stop at.
43 * @param string $round_via Rounding type.
44 *
45 * @return string Human readable difference between ``$from`` and ``$to``.
46 */
47 public static function approx_time_difference($from = 0, $to = 0, $round_via = 'round')
48 {
49 $from = !$from ? time() : (int)$from;
50 $to = !$to ? time() : (int)$to;
51 $since = ''; // Initialize.
52
53 if(($difference = abs($to - $from)) < 3600)
54 {
55 if($round_via === 'floor') {
56 $m = (int)floor($difference / 60);
57 } elseif ($round_via === 'ceil') {
58 $m = (int)ceil($difference / 60);
59 } else {
60 $m = (int)round($difference / 60);
61 }
62 $since = ($m < 1) ? _x('less than a minute', 's2member-front', 's2member') : $since;
63 $since = ($m === 1) ? _x('about 1 minute', 's2member-front', 's2member') : $since;
64 $since = ($m > 1) ? sprintf(_nx('about %s minute', 'about %s minutes', $m, 's2member-front', 's2member'), $m) : $since;
65 $since = ($m >= 60) ? _x('about 1 hour', 's2member-front', 's2member') : $since;
66 }
67 else if($difference >= 3600 && $difference < 86400)
68 {
69 if($round_via === 'floor') {
70 $h = (int)floor($difference / 3600);
71 } elseif ($round_via === 'ceil') {
72 $h = (int)ceil($difference / 3600);
73 } else {
74 $h = (int)round($difference / 3600);
75 }
76 $since = ($h === 1) ? _x('about 1 hour', 's2member-front', 's2member') : $since;
77 $since = ($h > 1) ? sprintf(_nx('about %s hour', 'about %s hours', $h, 's2member-front', 's2member'), $h) : $since;
78 $since = ($h >= 24) ? _x('about 1 day', 's2member-front', 's2member') : $since;
79 }
80 else if($difference >= 86400 && $difference < 604800)
81 {
82 if($round_via === 'floor') {
83 $d = (int)floor($difference / 86400);
84 } elseif ($round_via === 'ceil') {
85 $d = (int)ceil($difference / 86400);
86 } else {
87 $d = (int)round($difference / 86400);
88 }
89 $since = ($d === 1) ? _x('about 1 day', 's2member-front', 's2member') : $since;
90 $since = ($d > 1) ? sprintf(_nx('about %s day', 'about %s days', $d, 's2member-front', 's2member'), $d) : $since;
91 $since = ($d >= 7) ? _x('about 1 week', 's2member-front', 's2member') : $since;
92 }
93 else if($difference >= 604800 && $difference < 2592000)
94 {
95 if($round_via === 'floor') {
96 $w = (int)floor($difference / 604800);
97 } elseif ($round_via === 'ceil') {
98 $w = (int)ceil($difference / 604800);
99 } else {
100 $w = (int)round($difference / 604800);
101 }
102 $since = ($w === 1) ? _x('about 1 week', 's2member-front', 's2member') : $since;
103 $since = ($w > 1) ? sprintf(_nx('about %s week', 'about %s weeks', $w, 's2member-front', 's2member'), $w) : $since;
104 $since = ($w >= 4) ? _x('about 1 month', 's2member-front', 's2member') : $since;
105 }
106 else if($difference >= 2592000 && $difference < 31556926)
107 {
108 if($round_via === 'floor') {
109 $m = (int)floor($difference / 2592000);
110 } elseif ($round_via === 'ceil') {
111 $m = (int)ceil($difference / 2592000);
112 } else {
113 $m = (int)round($difference / 2592000);
114 }
115 $since = ($m === 1) ? _x('about 1 month', 's2member-front', 's2member') : $since;
116 $since = ($m > 1) ? sprintf(_nx('about %s month', 'about %s months', $m, 's2member-front', 's2member'), $m) : $since;
117 $since = ($m >= 12) ? _x('about 1 year', 's2member-front', 's2member') : $since;
118 }
119 else if($difference >= 31556926) // Years.
120 {
121 if($round_via === 'floor') {
122 $y = (int)floor($difference / 31556926);
123 } elseif ($round_via === 'ceil') {
124 $y = (int)ceil($difference / 31556926);
125 } else {
126 $y = (int)round($difference / 31556926);
127 }
128 $since = ($y === 1) ? _x('about 1 year', 's2member-front', 's2member') : $since;
129 $since = ($y > 1) ? sprintf(_nx('about %s year', 'about %s years', $y, 's2member-front', 's2member'), $y) : $since;
130 }
131 return $since;
132 }
133
134 /**
135 * Calculate Auto-EOT Time, based on `user_id`, `period1`, `period3`, `last_payment_time`, or an optional `eotper`.
136 *
137 * Used by s2Member's built-in Auto-EOT System, and also by its IPN routines.
138 * `last_payment_time` can be forced w/ ``$lpt`` *(i.e., for delayed eots)*.
139 *
140 * @package s2Member\Utilities
141 * @since 3.5
142 *
143 * @param int|string $user_id Optional. A WordPress User ID.
144 *
145 * @param string $period1 Optional. First Intial "Period Term" *( i.e., `0 D` )*.
146 * Only used when ``$user_id`` is passed in.
147 *
148 * @param string $period3 Optional. Regular "Period Term" *( i.e., `1 M` )*.
149 * Only used when ``$user_id`` is passed in.
150 *
151 * @param string $eotper Optional. A Fixed "Period Term" *( i.e., `1 M` )*.
152 * This replaces ``$period1`` / ``$period3``.
153 * Not used when ``$user_id`` is passed in.
154 * Only when ``$user_id`` is not passed in.
155 *
156 * @param int $lpt Optional. Force feed the Last Payment Time.
157 * Only used when ``$user_id`` is passed in.
158 *
159 * @param int $ext Optional. Existing EOT Time for the User.
160 * Always considered; even when ``$user_id`` is not passed in.
161 * But only when ``$GLOBALS['WS_PLUGIN__']['s2member']['o']['eot_time_ext_behavior'] === 'extend'``.
162 *
163 * @return int Unix timestamp indicating the EOT Time calculated by this routine.
164 */
165 public static function auto_eot_time($user_id = 0, $period1 = '', $period3 = '', $eotper = '', $lpt = 0, $ext = 0)
166 {
167 $eot_grace_time = (int)$GLOBALS['WS_PLUGIN__']['s2member']['o']['eot_grace_time'];
168 $eot_grace_time = (int)apply_filters('ws_plugin__s2member_eot_grace_time', $eot_grace_time);
169 $p1_time = $p3_time = $eot_time = $auto_eot_time = 0; // Intialize.
170
171 if($user_id && ($user = new WP_User ($user_id)) && $user->ID)
172 {
173 $registration_time = strtotime($user->user_registered);
174 $last_payment_time = get_user_option('s2member_last_payment_time', $user_id);
175 $free_trial_expired_time = (int)get_user_option('s2member_free_trial_expired_time', $user_id);
176 $last_payment_time = (int)$lpt ? (int)$lpt : (int)$last_payment_time;
177 $last_paid_access_cap_time = 0; // Initialize the last access cap time.
178
179 if(($access_cap_times = c_ws_plugin__s2member_access_cap_times::get_access_cap_times($user_id))) {
180 foreach(array_reverse($access_cap_times, TRUE) as $_time => $_cap) {
181 if(strpos($_cap, '-') !== 0 && $_cap !== 'level0') {
182 $last_paid_access_cap_time = (int)$_time;
183 break; // Got what we need; stop here.
184 }
185 } // unset($_time, $_cap); // Housekeeping.
186 }
187 if(($period1 = trim(strtoupper($period1))))
188 {
189 list($num, $span) = preg_split('/ /', $period1, 2);
190
191 $days = 0; // Days start at 0.
192
193 if(is_numeric($num) && !is_numeric($span))
194 {
195 $days = ($span === 'D') ? 1 : $days;
196 $days = ($span === 'W') ? 7 : $days;
197 $days = ($span === 'M') ? 30 : $days;
198 $days = ($span === 'Y') ? 365 : $days;
199 }
200 $p1_days = (int)$num * (int)$days;
201 $p1_time = $p1_days * 86400;
202 }
203 if(($period3 = trim(strtoupper($period3))))
204 {
205 list($num, $span) = preg_split('/ /', $period3, 2);
206
207 $days = 0; // Days start at 0.
208
209 if(is_numeric($num) && !is_numeric($span))
210 {
211 $days = ($span === 'D') ? 1 : $days;
212 $days = ($span === 'W') ? 7 : $days;
213 $days = ($span === 'M') ? 30 : $days;
214 $days = ($span === 'Y') ? 365 : $days;
215 }
216 $p3_days = (int)$num * (int)$days;
217 $p3_time = $p3_days * 86400;
218 }
219 if(!$last_payment_time && !$free_trial_expired_time)
220 $auto_eot_time = ($last_paid_access_cap_time ? $last_paid_access_cap_time : $registration_time) + $p1_time + $eot_grace_time;
221
222 else if($p1_time && max($last_payment_time, $free_trial_expired_time) <= ($last_paid_access_cap_time ? $last_paid_access_cap_time : $registration_time) + $p1_time)
223 $auto_eot_time = max($last_payment_time, $free_trial_expired_time) + $p1_time + $eot_grace_time;
224
225 else $auto_eot_time = max($last_payment_time, $free_trial_expired_time) + $p3_time + $eot_grace_time;
226 }
227 else if($eotper) // Otherwise, if we have a specific EOT period; calculate from today.
228 {
229 if(($eotper = trim(strtoupper($eotper))))
230 {
231 list($num, $span) = preg_split('/ /', $eotper, 2);
232
233 $days = 0; // Days start at 0.
234
235 if(is_numeric($num) && !is_numeric($span))
236 {
237 $days = ($span === 'D') ? 1 : $days;
238 $days = ($span === 'W') ? 7 : $days;
239 $days = ($span === 'M') ? 30 : $days;
240 $days = ($span === 'Y') ? 365 : $days;
241 }
242 $eot_days = (int)$num * (int)$days;
243 $eot_time = $eot_days * 86400;
244 }
245 $auto_eot_time = strtotime('now') + $eot_time + $eot_grace_time;
246 }
247 if($ext && $GLOBALS['WS_PLUGIN__']['s2member']['o']['eot_time_ext_behavior'] === 'extend')
248 if((int)$ext > strtotime('now')) // Existing EOT Time must be in the future.
249 $auto_eot_time = $auto_eot_time + ((int)$ext - strtotime('now'));
250
251 return $auto_eot_time <= 0 ? strtotime('now') : $auto_eot_time;
252 }
253
254 /**
255 * Converts a Term `[D,W,M,Y,L,Day,Week,Month,Year,Lifetime]` into `Daily`, `Weekly`, `Monthly`, `Yearly`, `Lifetime`.
256 *
257 * Can also handle "Period Term" combinations. Where the Period will be stripped automatically before conversion.
258 *
259 * For example, `1 D`, would become, just `Daily`. Another example, `3 Y` would become `Yearly`; and `1 L`, would become `Lifetime`.
260 * Recurring examples: `2 W`, becomes `Bi-Weekly`, `3 M` becomes `Quarterly`, and `2 M` becomes `Bi-Monthly`.
261 *
262 * @package s2Member\Utilities
263 * @since 3.5
264 *
265 * @param string $term_or_period_term A Term, or a "Period Term" combination.
266 * @param string $directive Optional. One of `recurring|singular|plural`. Defaults to `recurring`.
267 *
268 * @return string|bool A Term Cycle *( i.e., `Daily`, `Weekly`, `Monthly`, `Yearly`, `Lifetime`, etc. )*, else false on failure.
269 *
270 * @todo Add support here for fixed recurring payments configured through `rrt=""`.
271 */
272 public static function term_cycle($term_or_period_term = '', $directive = 'recurring')
273 {
274 $term_cycle_key = trim(strtoupper(preg_replace('/^(.+?) /', '', $term_or_period_term)));
275
276 if($term_cycle_key && $directive === 'recurring') // recurring = Daily, Weekly, Bi-Weekly, Monthly, Bi-Monthly, Quarterly, Yearly, Lifetime.
277 {
278 $paypal_term_cycles = array('D' => _x('Daily', 's2member-front', 's2member'), 'W' => _x('Weekly', 's2member-front', 's2member'), 'M' => _x('Monthly', 's2member-front', 's2member'), 'Y' => _x('Yearly', 's2member-front', 's2member'), 'L' => _x('Lifetime', 's2member-front', 's2member'), 'DAY' => _x('Daily', 's2member-front', 's2member'), 'WEEK' => _x('Weekly', 's2member-front', 's2member'), 'MONTH' => _x('Monthly', 's2member-front', 's2member'), 'YEAR' => _x('Yearly', 's2member-front', 's2member'), 'Lifetime' => _x('Lifetime', 's2member-front', 's2member'));
279
280 $term_cycle = isset ($paypal_term_cycles[$term_cycle_key]) ? $paypal_term_cycles[$term_cycle_key] : FALSE;
281
282 $term_cycle = (strtoupper($term_or_period_term) === '2 W') ? _x('Bi-Weekly', 's2member-front', 's2member') : $term_cycle;
283 $term_cycle = (strtoupper($term_or_period_term) === '2 M') ? _x('Bi-Monthly', 's2member-front', 's2member') : $term_cycle;
284 $term_cycle = (strtoupper($term_or_period_term) === '3 M') ? _x('Quarterly', 's2member-front', 's2member') : $term_cycle;
285 $term_cycle = (strtoupper($term_or_period_term) === '6 M') ? _x('Semi-Yearly', 's2member-front', 's2member') : $term_cycle;
286 }
287 else if($term_cycle_key && $directive === 'singular') // singular = Day, Week, Month, Year, Lifetime.
288 {
289 $paypal_term_cycles = array('D' => _x('Day', 's2member-front', 's2member'), 'W' => _x('Week', 's2member-front', 's2member'), 'M' => _x('Month', 's2member-front', 's2member'), 'Y' => _x('Year', 's2member-front', 's2member'), 'L' => _x('Lifetime', 's2member-front', 's2member'), 'DAY' => _x('Day', 's2member-front', 's2member'), 'WEEK' => _x('Week', 's2member-front', 's2member'), 'MONTH' => _x('Month', 's2member-front', 's2member'), 'YEAR' => _x('Year', 's2member-front', 's2member'), 'Lifetime' => _x('Lifetime', 's2member-front', 's2member'));
290
291 $term_cycle = isset ($paypal_term_cycles[$term_cycle_key]) ? $paypal_term_cycles[$term_cycle_key] : FALSE;
292 }
293 else if($term_cycle_key && $directive === 'plural') // plural = Days, Weeks, Months, Years, Lifetimes.
294 {
295 $paypal_term_cycles = array('D' => _x('Days', 's2member-front', 's2member'), 'W' => _x('Weeks', 's2member-front', 's2member'), 'M' => _x('Months', 's2member-front', 's2member'), 'Y' => _x('Years', 's2member-front', 's2member'), 'L' => _x('Lifetimes', 's2member-front', 's2member'), 'DAY' => _x('Days', 's2member-front', 's2member'), 'WEEK' => _x('Weeks', 's2member-front', 's2member'), 'MONTH' => _x('Months', 's2member-front', 's2member'), 'YEAR' => _x('Years', 's2member-front', 's2member'), 'Lifetime' => _x('Lifetimes', 's2member-front', 's2member'));
296
297 $term_cycle = isset ($paypal_term_cycles[$term_cycle_key]) ? $paypal_term_cycles[$term_cycle_key] : FALSE;
298 }
299 return (!empty($term_cycle)) ? $term_cycle : FALSE;
300 }
301
302 /**
303 * Converts a 'Period Term', and Recurring flag.
304 *
305 * Returns a full Term explanation *(lowercase)*.
306 * Example: `2 months`.
307 *
308 * @package s2Member\Utilities
309 * @since 3.5
310 *
311 * @param string $period_term A "Period Term" combination.
312 * @param bool|int|string $recurring Defaults to false. If true, the ``$period_term`` is recurring. Can also be the string `0|1|BN`.
313 *
314 * @return string Verbose *(lowercase)* Period Term description *( i.e., `weekly`, `every 3 weeks`, `lifetime`, `3 months`, `1 month`, etc. )*.
315 *
316 * @todo Add support here for fixed recurring payments configured through `rrt=""`.
317 */
318 public static function period_term($period_term = '', $recurring = FALSE)
319 {
320 list ($period, $term) = preg_split('/ /', ($period_term = strtoupper($period_term)), 2);
321 $recurring = (is_string($recurring) && strtoupper($recurring) === 'BN') ? (int)0 : (int)$recurring;
322
323 $cycle_recurring = c_ws_plugin__s2member_utils_time::term_cycle($period_term, 'recurring');
324 $cycle_singular = c_ws_plugin__s2member_utils_time::term_cycle($period_term, 'singular');
325 $cycle_plural = c_ws_plugin__s2member_utils_time::term_cycle($period_term, 'plural');
326
327 if($recurring && in_array($period_term, array('1 D', '1 W', '2 W', '1 M', '2 M', '3 M', '6 M', '1 Y')))
328 $period_term = strtolower($cycle_recurring); // Results in an "ly" ending.
329
330 else if($recurring) // Otherwise, it's recurring; but NOT an "ly" ending.
331 /* translators: Each cycle ( i.e., `each day/week/month` or `every 2 days/weeks/months`, etc. ). Cycles are translated elsewhere. */
332 $period_term = strtolower(sprintf(_nx('each %2$s', 'every %1$s %3$s', $period, 's2member-front', 's2member'), $period, $cycle_singular, $cycle_plural));
333
334 else if(strtoupper($term) === 'L') // One-payment for lifetime access.
335 $period_term = strtolower(_x('lifetime', 's2member-front', 's2member')); // Life.
336
337 else // Otherwise, this is NOT recurring. Results in X days/weeks/months/years/lifetime.
338 /* translators: Membership cycle ( i.e., `1 day/week/month` or `2 days/weeks/months`, etc. ). Most of this is translated elsewhere. */
339 $period_term = strtolower(sprintf(_nx('%1$s %2$s', '%1$s %3$s', $period, 's2member-front', 's2member'), $period, $cycle_singular, $cycle_plural));
340
341 return $period_term; // Return converted value.
342 }
343
344 /**
345 * Converts a Billing Amount, Period Term, and Recurring flag.
346 *
347 * Returns a full Billing Term explanation.
348 * Example: `1.00 for 2 months`.
349 *
350 * @package s2Member\Utilities
351 * @since 3.5
352 *
353 * @param int|string $amount A numeric amount, usually in US dollars.
354 * @param string $period_term A "Period Term" combo, with space separation.
355 * @param bool|int|string $recurring Defaults to false. If true, the ``$period_term`` is recurring. Can also be the string `0|1|BN`.
356 *
357 * @return string Verbose *(lowercase)* Amount Period Term description *( i.e., `1.00`, `1.00 / monthly`, `1.00 every 3 months`, `1.00 for 1 month`, `1.00 for 3 months`, etc. )*.
358 *
359 * @todo Add support here for fixed recurring payments configured through `rrt=""`.
360 */
361 public static function amount_period_term($amount = 0, $period_term = '', $recurring = FALSE)
362 {
363 list ($period, $term) = preg_split('/ /', ($period_term = strtoupper($period_term)), 2);
364 $recurring = (is_string($recurring) && strtoupper($recurring) === 'BN') ? (int)0 : (int)$recurring;
365
366 $cycle_recurring = c_ws_plugin__s2member_utils_time::term_cycle($period_term, 'recurring');
367 $cycle_singular = c_ws_plugin__s2member_utils_time::term_cycle($period_term, 'singular');
368 $cycle_plural = c_ws_plugin__s2member_utils_time::term_cycle($period_term, 'plural');
369
370 if($recurring && in_array($period_term, array('1 D', '1 W', '2 W', '1 M', '2 M', '3 M', '6 M', '1 Y')))
371 $amount_period_term = number_format($amount, 2, '.', '').' / '.strtolower($cycle_recurring);
372
373 else if($recurring) // Otherwise, it's recurring; but NOT an "ly" ending.
374 /* translators: Each cycle ( i.e., `each day/week/month` or `every 2 days/weeks/months`, etc. ). Cycles are translated elsewhere. */
375 $amount_period_term = number_format($amount, 2, '.', '').' '.strtolower(sprintf(_nx('each %2$s', 'every %1$s %3$s', $period, 's2member-front', 's2member'), $period, $cycle_singular, $cycle_plural));
376
377 else if(strtoupper($term) === 'L') // One-payment for lifetime access.
378 $amount_period_term = number_format($amount, 2, '.', ''); // Price.
379
380 else // Otherwise, this is NOT recurring. Results in 0.00 for X days/weeks/months/years/lifetime.
381 /* translators: Cycle ( i.e., `for 1 day/week/month` or `for 2 days/weeks/months`, etc. ). Most of this is translated elsewhere. */
382 $amount_period_term = number_format($amount, 2, '.', '').' '.strtolower(sprintf(_nx('for %1$s %2$s', 'for %1$s %3$s', $period, 's2member-front', 's2member'), $period, $cycle_singular, $cycle_plural));
383
384 return $amount_period_term; // Return converted value.
385 }
386 }
387 }
388