/** * Logs access capability times. * * @package s2Member\CCAPS * @since 140514 * * @attaches-to ``add_action('added_user_meta')`` * @attaches-to ``add_action('updated_user_meta')`` * @attaches-to ``add_action('deleted_user_meta')`` (indirectly) * * @param integer $meta_id Meta row ID in database. * @param integer $object_id User ID. * @param string $meta_key Meta key. * @param mixed $meta_value Meta value. */ public static function log_access_cap_times($meta_id, $object_id, $meta_key, $meta_value) { $wpdb = $GLOBALS['wpdb']; /** @var $wpdb \wpdb For IDEs. */ if (strpos($meta_key, 'capabilities') === FALSE || $meta_key !== $wpdb->get_blog_prefix() . 'capabilities') { return; } // Not updating caps. $user_id = (int) $object_id; $user = new WP_User($user_id); if (!$user->ID || !$user->exists()) { return; } // Not a valid user. $caps['prev'] = !empty(self::$prev_caps_by_user[$user_id]) ? self::$prev_caps_by_user[$user_id] : array(); self::$prev_caps_by_user = array(); // Reset this in case `get_user_caps_before_update()` doesn't run somehow. $caps['now'] = is_array($meta_value) ? $meta_value : array(); $role_objects = $GLOBALS['wp_roles']->role_objects; foreach ($caps as &$_caps_prev_now) { foreach (array_intersect(array_keys($_caps_prev_now), array_keys($role_objects)) as $_role) { if ($_caps_prev_now[$_role]) { // If the cap (i.e., the role) is enabled; merge its caps. $_caps_prev_now = array_merge($_caps_prev_now, $role_objects[$_role]->capabilities); } } $_s2_caps_prev_now = array(); foreach ($_caps_prev_now as $_cap => $_enabled) { if (strpos($_cap, 'access_s2member_') === 0) { $_s2_caps_prev_now[substr($_cap, 16)] = $_enabled; } } $_caps_prev_now = $_s2_caps_prev_now; } unset($_s2_caps_prev_now, $_caps_prev_now, $_role, $_cap, $_enabled); $ac_times = get_user_option('s2member_access_cap_times', $user_id); if (!is_array($ac_times)) { $ac_times = array(); } if (!isset(self::$log_time)) { self::$log_time = (double) time(); } foreach ($caps['prev'] as $_cap => $_was_enabled) { if ($_was_enabled && empty($caps['now'][$_cap])) { $ac_times[number_format(self::$log_time += 0.0001, 4, '.', '')] = '-' . $_cap; } } unset($_cap, $_was_enabled); foreach ($caps['now'] as $_cap => $_now_enabled) { if ($_now_enabled && empty($caps['prev'][$_cap])) { $ac_times[number_format(self::$log_time += 0.0001, 4, '.', '')] = $_cap; } } unset($_cap, $_now_enabled); update_user_option($user_id, 's2member_access_cap_times', $ac_times); }
function s2member_capability_times($user_id = NULL, $access_caps = array()) { if (!$user_id) { $user_id = get_current_user_id(); } return c_ws_plugin__s2member_access_cap_times::get_access_cap_times($user_id, $access_caps); }
/** * Conditional check for drip access. * * @since 140514 Enhancing `[s2Drip]` shortcode. * * @param string $access Required; conditional expression with access_s2member_ capabilities * (i.e., leveln, ccap_name), e.g., `level2` or `level3 and (ccap_music or ccap_videos)`. * Note that `and`, `or` MUST be used in place of `&&`, `||` due to sanitation routines. * The `$access` string may contain only `[A-Za-z0-9 _()]`. * * @param integer $from_day Optional. Defaults to `0`. Any value greater than or equal to `0`. * @param integer $to_day Optional. Defaults to `0`. Any value greater than or equal to `0`. * * @param null|integer $user_id Optional. A `NULL` value indicates the current user. * * @return boolean `TRUE` if user can `$access`; and dripping should occur; based on `$from_day` & `$to_day`. * * @triggers `E_USER_ERROR` if an invalid `$access` syntax is detected; with invalid chars. * @triggers `E_USER_ERROR` if an invalid `$access` syntax is detected; without any word chars. */ public static function user_can_access_drip($access, $from_day = 0, $to_day = 0, $user_id = NULL) { $drip = FALSE; $access = trim((string) $access); $from_day = self::$from_day = (int) $from_day; $to_day = self::$to_day = (int) $to_day; if (!isset($user_id)) { $user_id = get_current_user_id(); } $user_id = self::$user_id = (int) $user_id; if (user_can($user_id, 'administrator')) { $drip = TRUE; } else { if ($access && $user_id) { if (!is_array($all_access_cap_times = self::$all_access_cap_times = c_ws_plugin__s2member_access_cap_times::get_access_cap_times($user_id))) { $all_access_cap_times = self::$all_access_cap_times = array(); } $access_expression = strtolower($access); // e.g., 'level1 and ccap_music' $access_expression = trim(preg_replace('/[^a-z0-9 _()]/', '', $access_expression, -1, $invalid_chars)); $access_expression = str_replace(array(' and ', ' or '), array(' && ', ' || '), $access_expression); if ($invalid_chars) { trigger_error('Syntax error: invalid chars. Please use only `A-Za-z0-9 _()` in the `access` parameter of s2Drip.', E_USER_ERROR); } if (!$access_expression || !preg_match('/\\w+/', $access_expression)) { trigger_error('Syntax error: no word chars in `access` parameter of s2Drip. Valid example: `level1 and ccap_music`.', E_USER_ERROR); } $access_expression = preg_replace_callback('/\\w+/', 'c_ws_plugin__s2member_pro_user_drip_access::_user_can_access_drip_cb', $access_expression); $drip = eval('return (' . $access_expression . ');'); } } return apply_filters('ws_plugin__s2member_pro_user_can_access_drip', $drip, get_defined_vars()); }
/** * Calculate Auto-EOT Time, based on `user_id`, `period1`, `period3`, `last_payment_time`, or an optional `eotper`. * * Used by s2Member's built-in Auto-EOT System, and also by its IPN routines. * `last_payment_time` can be forced w/ ``$lpt`` *(i.e., for delayed eots)*. * * @package s2Member\Utilities * @since 3.5 * * @param int|string $user_id Optional. A WordPress User ID. * * @param string $period1 Optional. First Intial "Period Term" *( i.e., `0 D` )*. * Only used when ``$user_id`` is passed in. * * @param string $period3 Optional. Regular "Period Term" *( i.e., `1 M` )*. * Only used when ``$user_id`` is passed in. * * @param string $eotper Optional. A Fixed "Period Term" *( i.e., `1 M` )*. * This replaces ``$period1`` / ``$period3``. * Not used when ``$user_id`` is passed in. * Only when ``$user_id`` is not passed in. * * @param int $lpt Optional. Force feed the Last Payment Time. * Only used when ``$user_id`` is passed in. * * @param int $ext Optional. Existing EOT Time for the User. * Always considered; even when ``$user_id`` is not passed in. * But only when ``$GLOBALS['WS_PLUGIN__']['s2member']['o']['eot_time_ext_behavior'] === 'extend'``. * * @return int Unix timestamp indicating the EOT Time calculated by this routine. */ public static function auto_eot_time($user_id = 0, $period1 = '', $period3 = '', $eotper = '', $lpt = 0, $ext = 0) { $eot_grace_time = (int) $GLOBALS['WS_PLUGIN__']['s2member']['o']['eot_grace_time']; $eot_grace_time = (int) apply_filters('ws_plugin__s2member_eot_grace_time', $eot_grace_time); $p1_time = $p3_time = $eot_time = $auto_eot_time = 0; // Intialize. if ($user_id && ($user = new WP_User($user_id)) && $user->ID) { $registration_time = strtotime($user->user_registered); $last_payment_time = get_user_option('s2member_last_payment_time', $user_id); $last_payment_time = (int) $lpt ? (int) $lpt : (int) $last_payment_time; $last_paid_access_cap_time = 0; // Initialize the last access cap time. if ($access_cap_times = c_ws_plugin__s2member_access_cap_times::get_access_cap_times($user_id)) { foreach (array_reverse($access_cap_times, TRUE) as $_time => $_cap) { if (strpos($_cap, '-') !== 0 && $_cap !== 'level0') { $last_paid_access_cap_time = (int) $_time; break; // Got what we need; stop here. } } } unset($_time, $_cap); // Housekeeping. if ($period1 = trim(strtoupper($period1))) { list($num, $span) = preg_split('/ /', $period1, 2); $days = 0; // Days start at 0. if (is_numeric($num) && !is_numeric($span)) { $days = $span === 'D' ? 1 : $days; $days = $span === 'W' ? 7 : $days; $days = $span === 'M' ? 30 : $days; $days = $span === 'Y' ? 365 : $days; } $p1_days = (int) $num * (int) $days; $p1_time = $p1_days * 86400; } if ($period3 = trim(strtoupper($period3))) { list($num, $span) = preg_split('/ /', $period3, 2); $days = 0; // Days start at 0. if (is_numeric($num) && !is_numeric($span)) { $days = $span === 'D' ? 1 : $days; $days = $span === 'W' ? 7 : $days; $days = $span === 'M' ? 30 : $days; $days = $span === 'Y' ? 365 : $days; } $p3_days = (int) $num * (int) $days; $p3_time = $p3_days * 86400; } if (!$last_payment_time) { // No last payment time; i.e., has paid nothing yet? $auto_eot_time = ($last_paid_access_cap_time ? $last_paid_access_cap_time : $registration_time) + $p1_time + $eot_grace_time; } else { if ($p1_time && $last_payment_time <= ($last_paid_access_cap_time ? $last_paid_access_cap_time : $registration_time) + $p1_time) { $auto_eot_time = $last_payment_time + $p1_time + $eot_grace_time; } else { $auto_eot_time = $last_payment_time + $p3_time + $eot_grace_time; } } } else { if ($eotper) { if ($eotper = trim(strtoupper($eotper))) { list($num, $span) = preg_split('/ /', $eotper, 2); $days = 0; // Days start at 0. if (is_numeric($num) && !is_numeric($span)) { $days = $span === 'D' ? 1 : $days; $days = $span === 'W' ? 7 : $days; $days = $span === 'M' ? 30 : $days; $days = $span === 'Y' ? 365 : $days; } $eot_days = (int) $num * (int) $days; $eot_time = $eot_days * 86400; } $auto_eot_time = strtotime('now') + $eot_time + $eot_grace_time; } } if ($ext && $GLOBALS['WS_PLUGIN__']['s2member']['o']['eot_time_ext_behavior'] === 'extend') { if ((int) $ext > strtotime('now')) { // Existing EOT Time must be in the future. $auto_eot_time = $auto_eot_time + ((int) $ext - strtotime('now')); } } return $auto_eot_time <= 0 ? strtotime('now') : $auto_eot_time; }