PluginProbe
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions / 260814
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions v260814
260917 260913 260909 260829 260814 260805 110710 110731 110812 110815 110912 110913 110915 110926 110927 111002 111003 111011 111017 111029 111105 111206 111216 111220 120213 All 189 releases
s2member / src / includes / classes / auto-eots.inc.php

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

332 lines 18.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // @codingStandardsIgnoreFile
3 /**
4 * s2Member's Auto-EOT System *(EOT = End Of Term)*.
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\Auto_EOT_System
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_auto_eots'))
22 {
23 /**
24 * s2Member's Auto-EOT System *(EOT = End Of Term)*.
25 *
26 * @package s2Member\Auto_EOT_System
27 * @since 3.5
28 */
29 class c_ws_plugin__s2member_auto_eots
30 {
31 /**
32 * Adds a scheduled task for s2Member's Auto-EOT System.
33 *
34 * @package s2Member\Auto_EOT_System
35 * @since 3.5
36 *
37 * @return bool True if able to add Auto-EOT System schedule, else false.
38 */
39 public static function add_auto_eot_system()
40 {
41 do_action('ws_plugin__s2member_before_add_auto_eot_system', get_defined_vars());
42
43 if(!c_ws_plugin__s2member_auto_eots::delete_auto_eot_system())
44 {
45 return apply_filters('ws_plugin__s2member_add_auto_eot_system', FALSE, get_defined_vars());
46 }
47 else if(function_exists('wp_cron') /* Otherwise, we can schedule? */)
48 {
49 wp_schedule_event(time(), 'every10m', 'ws_plugin__s2member_auto_eot_system__schedule');
50
51 return apply_filters('ws_plugin__s2member_add_auto_eot_system', TRUE, get_defined_vars());
52 }
53 else // Otherwise, it would appear that WP-Cron is not available.
54 {
55 return apply_filters('ws_plugin__s2member_add_auto_eot_system', FALSE, get_defined_vars());
56 }
57 }
58
59 /**
60 * Deletes all scheduled tasks for s2Member's Auto-EOT System.
61 *
62 * @package s2Member\Auto_EOT_System
63 * @since 3.5
64 *
65 * @return bool True if able to delete Auto-EOT System schedule, else false.
66 */
67 public static function delete_auto_eot_system()
68 {
69 do_action('ws_plugin__s2member_before_delete_auto_eot_system', get_defined_vars());
70
71 if(function_exists('wp_cron') /* Is `wp_cron()` even available? */)
72 {
73 wp_clear_scheduled_hook('ws_plugin__s2member_auto_eot_system__schedule' /* Since v3.0.3. */);
74
75 return apply_filters('ws_plugin__s2member_delete_auto_eot_system', TRUE, get_defined_vars());
76 }
77 else // Otherwise, it would appear that WP-Cron is not available.
78 {
79 return apply_filters('ws_plugin__s2member_delete_auto_eot_system', FALSE, get_defined_vars());
80 }
81 }
82
83 /**
84 * Processed by WP_Cron; this handles Auto-EOTs *(EOT = End Of Term)*.
85 *
86 * If you have a HUGE userbase, increase the max EOTs per process.
87 * But NOTE, this runs ``$per_process`` *(per Blog)* on a Multisite Network.
88 * To increase, use: ``add_filter ('ws_plugin__s2member_auto_eot_system_per_process');``.
89 *
90 * This function makes an important Hook available: `ws_plugin__s2member_after_auto_eot_system`.
91 * This Hook is used by some of s2Member Pro's Gateway integrations; allowing CRON processing
92 * to run for important communications; which poll Payment Gateway APIs for possible EOTs.
93 *
94 * @package s2Member\Auto_EOT_System
95 * @since 3.5
96 *
97 * @param int $per_process Number of database records to process each time.
98 * Can also be Filtered with `ws_plugin__s2member_auto_eot_system_per_process`.
99 *
100 * @return null
101 */
102 public static function auto_eot_system($per_process = 6)
103 {
104 global $wpdb;
105 /** @var $wpdb \wpdb */
106 global $current_site, $current_blog;
107
108 include_once ABSPATH.'wp-admin/includes/admin.php';
109
110 @set_time_limit(0); // Make time for processing a larger userbase.
111 @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
112
113 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
114 do_action('ws_plugin__s2member_before_auto_eot_system', get_defined_vars());
115 unset($__refs, $__v); // Housekeeping.
116
117 if($GLOBALS['WS_PLUGIN__']['s2member']['o']['auto_eot_system_enabled'] /* Enabled? */)
118 {
119 $per_process = apply_filters('ws_plugin__s2member_auto_eot_system_per_process', $per_process, get_defined_vars());
120
121 //260414 Ignore zero/negative Auto-EOT values here. We had real PayPal Pro subscribers demoted
122 // because a stored `s2member_auto_eot_time` of `0` matched the old `<= now` query.
123 if(is_array($eots = $wpdb->get_results("SELECT `user_id` AS `ID` FROM `".$wpdb->usermeta."` WHERE `meta_key` = '".$wpdb->prefix."s2member_auto_eot_time' AND `meta_value` != '' AND `meta_value` > '0' AND `meta_value` <= '".esc_sql(strtotime("now"))."' LIMIT ".$per_process)))
124 {
125 foreach($eots as $eot) // Go through the array of EOTS. We need to (demote|delete) each of them.
126 {
127 if(($user_id = $eot->ID) && is_object($user = new WP_User ($user_id)) && $user->ID)
128 {
129 $auto_eot_time = (integer)get_user_option('s2member_auto_eot_time', $user_id);
130
131 $log_entry = array('user' => (array)$user); // Intialize.
132 $log_entry['auto_eot_time'] = $auto_eot_time; // Record EOT time.
133
134 //260414 Keep a minimal pre-demotion subscription snapshot in the log so we can tell later
135 // whether this member still had subscription metadata before anything was cleared.
136 $log_entry['subscr_gateway'] = get_user_option('s2member_subscr_gateway', $user_id);
137 $log_entry['subscr_id'] = get_user_option('s2member_subscr_id', $user_id);
138 $log_entry['has_ipn_signup_vars'] = is_array(get_user_option('s2member_ipn_signup_vars', $user_id)) ? 'yes' : 'no';
139
140 //260414 Defense in depth. A bad stored value of `0` caused false demotions in the wild.
141 // If one still reaches this loop for any reason, log it and skip instead of clearing fields.
142 if($auto_eot_time <= 0)
143 {
144 $log_entry['auto_eot_skip_reason'] = 'Skipped. Stored `s2member_auto_eot_time` was <= 0.';
145 c_ws_plugin__s2member_utils_logs::log_entry('auto-eot-system', $log_entry);
146 continue;
147 }
148
149 delete_user_option($user_id, 's2member_last_auto_eot_time');
150 delete_user_option($user_id, 's2member_auto_eot_time');
151
152 if(!$user->has_cap('administrator') /* Do NOT process Administrator accounts. */)
153 {
154 if($GLOBALS['WS_PLUGIN__']['s2member']['o']['membership_eot_behavior'] === 'demote')
155 {
156 $eot_del_type = 'auto-eot-cancellation-expiration-demotion'; // Set EOT/Del type.
157 $log_entry['eot_del_type'] = $eot_del_type; // Deleting user in this case.
158
159 $custom = get_user_option('s2member_custom', $user_id);
160 $subscr_gateway = get_user_option('s2member_subscr_gateway', $user_id);
161 $subscr_id = get_user_option('s2member_subscr_id', $user_id);
162 $subscr_baid = get_user_option('s2member_subscr_baid', $user_id);
163 $subscr_cid = get_user_option('s2member_subscr_cid', $user_id);
164 $fields = get_user_option('s2member_custom_fields', $user_id);
165 $user_reg_ip = get_user_option('s2member_registration_ip', $user_id);
166 $ipn_signup_vars = get_user_option('s2member_ipn_signup_vars', $user_id);
167
168 $demotion_role = c_ws_plugin__s2member_option_forces::force_demotion_role('subscriber');
169 $existing_role = c_ws_plugin__s2member_user_access::user_access_role($user);
170
171 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
172 do_action('ws_plugin__s2member_during_auto_eot_system_during_before_demote', get_defined_vars());
173 do_action('ws_plugin__s2member_during_collective_mods', $user_id, get_defined_vars(), $eot_del_type, 'modification', $demotion_role);
174 do_action('ws_plugin__s2member_during_collective_eots', $user_id, get_defined_vars(), $eot_del_type, 'modification');
175 unset($__refs, $__v); // Housekeeping.
176
177 if($existing_role !== $demotion_role /* Only if NOT the existing Role. */)
178 $user->set_role($demotion_role /* Give User the demotion Role. */);
179
180 if(apply_filters('ws_plugin__s2member_remove_ccaps_during_eot_events', (bool)$GLOBALS['WS_PLUGIN__']['s2member']['o']['eots_remove_ccaps'], get_defined_vars()))
181 foreach($user->allcaps as $cap => $cap_enabled)
182 if(preg_match('/^access_s2member_ccap_/', $cap))
183 $user->remove_cap($ccap = $cap);
184
185 delete_user_option($user_id, 's2member_subscr_gateway');
186 delete_user_option($user_id, 's2member_subscr_id');
187 delete_user_option($user_id, 's2member_subscr_baid');
188 delete_user_option($user_id, 's2member_subscr_cid');
189
190 delete_user_option($user_id, 's2member_ipn_signup_vars');
191 if(!apply_filters('ws_plugin__s2member_preserve_paid_registration_times', TRUE))
192 delete_user_option($user_id, 's2member_paid_registration_times');
193
194 delete_user_option($user_id, 's2member_last_status_scan');
195 delete_user_option($user_id, 's2member_first_payment_txn_id');
196 delete_user_option($user_id, 's2member_last_payment_time');
197 delete_user_option($user_id, 's2member_last_auto_eot_time');
198 delete_user_option($user_id, 's2member_auto_eot_time');
199
200 delete_user_option($user_id, 's2member_file_download_access_log');
201 delete_user_option($user_id, 's2member_authnet_payment_failures');
202
203 update_user_option($user_id, 's2member_last_auto_eot_time', $auto_eot_time);
204
205 c_ws_plugin__s2member_user_notes::append_user_notes($user_id, 'Demoted by s2Member: '.date('D M j, Y g:i a T'));
206 if($subscr_gateway && $subscr_id) // Also note the Paid Subscr. Gateway/ID so there is a reference left behind here.
207 c_ws_plugin__s2member_user_notes::append_user_notes($user_id, 'Paid Subscr. ID @ time of demotion: '.$subscr_gateway.''.$subscr_id);
208
209 if($GLOBALS['WS_PLUGIN__']['s2member']['o']['eot_del_notification_urls'])
210 {
211 foreach(preg_split('/['."\r\n\t".']+/', $GLOBALS['WS_PLUGIN__']['s2member']['o']['eot_del_notification_urls']) as $url) // Handle EOT Notifications.
212
213 if(($url = c_ws_plugin__s2member_utils_strings::fill_cvs($url, $custom, true)) && ($url = preg_replace('/%%eot_del_type%%/i', c_ws_plugin__s2member_utils_strings::esc_refs(urlencode('auto-eot-cancellation-expiration-demotion')), $url)) && ($url = preg_replace('/%%subscr_id%%/i', c_ws_plugin__s2member_utils_strings::esc_refs(urlencode($subscr_id)), $url)))
214 if(($url = preg_replace('/%%user_first_name%%/i', c_ws_plugin__s2member_utils_strings::esc_refs(urlencode($user->first_name)), $url)) && ($url = preg_replace('/%%user_last_name%%/i', c_ws_plugin__s2member_utils_strings::esc_refs(urlencode($user->last_name)), $url)))
215 if(($url = preg_replace('/%%user_full_name%%/i', c_ws_plugin__s2member_utils_strings::esc_refs(urlencode(trim($user->first_name.' '.$user->last_name))), $url)))
216 if(($url = preg_replace('/%%user_email%%/i', c_ws_plugin__s2member_utils_strings::esc_refs(urlencode($user->user_email)), $url)))
217 if(($url = preg_replace('/%%user_login%%/i', c_ws_plugin__s2member_utils_strings::esc_refs(urlencode($user->user_login)), $url)))
218 if(($url = preg_replace('/%%user_ip%%/i', c_ws_plugin__s2member_utils_strings::esc_refs(urlencode($user_reg_ip)), $url)))
219 if(($url = preg_replace('/%%user_id%%/i', c_ws_plugin__s2member_utils_strings::esc_refs(urlencode($user_id)), $url)))
220 {
221 if(is_array($fields) && !empty($fields))
222 foreach($fields as $var => $val /* Custom Registration/Profile Fields. */)
223 if(!($url = preg_replace('/%%'.preg_quote($var, '/').'%%/i', c_ws_plugin__s2member_utils_strings::esc_refs(urlencode(maybe_serialize($val))), $url)))
224 break;
225
226 if(($url = trim(preg_replace('/%%(.+?)%%/i', '', $url))))
227 c_ws_plugin__s2member_utils_urls::remote($url);
228 }
229 }
230 if($GLOBALS['WS_PLUGIN__']['s2member']['o']['eot_del_notification_recipients'])
231 {
232 $email_configs_were_on = c_ws_plugin__s2member_email_configs::email_config_status();
233 c_ws_plugin__s2member_email_configs::email_config_release();
234
235 $msg = $sbj = '(s2Member / API Notification Email) - EOT/Deletion';
236 $msg .= "\n\n"; // Spacing in the message body.
237
238 $msg .= 'eot_del_type: %%eot_del_type%%'."\n";
239 $msg .= 'subscr_id: %%subscr_id%%'."\n";
240 $msg .= 'subscr_baid: %%subscr_baid%%'."\n";
241 $msg .= 'subscr_cid: %%subscr_cid%%'."\n";
242 $msg .= 'user_first_name: %%user_first_name%%'."\n";
243 $msg .= 'user_last_name: %%user_last_name%%'."\n";
244 $msg .= 'user_full_name: %%user_full_name%%'."\n";
245 $msg .= 'user_email: %%user_email%%'."\n";
246 $msg .= 'user_login: %%user_login%%'."\n";
247 $msg .= 'user_ip: %%user_ip%%'."\n";
248 $msg .= 'user_id: %%user_id%%'."\n";
249
250 if(is_array($fields) && !empty($fields))
251 foreach($fields as $var => $val)
252 $msg .= $var.': %%'.$var.'%%'."\n";
253
254 $msg .= 'cv0: %%cv0%%'."\n";
255 $msg .= 'cv1: %%cv1%%'."\n";
256 $msg .= 'cv2: %%cv2%%'."\n";
257 $msg .= 'cv3: %%cv3%%'."\n";
258 $msg .= 'cv4: %%cv4%%'."\n";
259 $msg .= 'cv5: %%cv5%%'."\n";
260 $msg .= 'cv6: %%cv6%%'."\n";
261 $msg .= 'cv7: %%cv7%%'."\n";
262 $msg .= 'cv8: %%cv8%%'."\n";
263 $msg .= 'cv9: %%cv9%%';
264
265 if(($msg = c_ws_plugin__s2member_utils_strings::fill_cvs($msg, $custom)) && ($msg = preg_replace('/%%eot_del_type%%/i', c_ws_plugin__s2member_utils_strings::esc_refs('auto-eot-cancellation-expiration-demotion'), $msg)) && ($msg = preg_replace('/%%subscr_id%%/i', c_ws_plugin__s2member_utils_strings::esc_refs($subscr_id), $msg)))
266 if(($msg = preg_replace('/%%subscr_baid%%/i', c_ws_plugin__s2member_utils_strings::esc_refs($subscr_baid), $msg)) && ($msg = preg_replace('/%%subscr_cid%%/i', c_ws_plugin__s2member_utils_strings::esc_refs($subscr_cid), $msg)))
267 if(($msg = preg_replace('/%%user_first_name%%/i', c_ws_plugin__s2member_utils_strings::esc_refs($user->first_name), $msg)) && ($msg = preg_replace('/%%user_last_name%%/i', c_ws_plugin__s2member_utils_strings::esc_refs($user->last_name), $msg)))
268 if(($msg = preg_replace('/%%user_full_name%%/i', c_ws_plugin__s2member_utils_strings::esc_refs(trim($user->first_name.' '.$user->last_name)), $msg)))
269 if(($msg = preg_replace('/%%user_email%%/i', c_ws_plugin__s2member_utils_strings::esc_refs($user->user_email), $msg)))
270 if(($msg = preg_replace('/%%user_login%%/i', c_ws_plugin__s2member_utils_strings::esc_refs($user->user_login), $msg)))
271 if(($msg = preg_replace('/%%user_ip%%/i', c_ws_plugin__s2member_utils_strings::esc_refs($user_reg_ip), $msg)))
272 if(($msg = preg_replace('/%%user_id%%/i', c_ws_plugin__s2member_utils_strings::esc_refs($user_id), $msg)))
273 {
274 if(is_array($fields) && !empty($fields))
275 foreach($fields as $var => $val /* Custom Registration/Profile Fields. */)
276 if(!($msg = preg_replace('/%%'.preg_quote($var, '/').'%%/i', c_ws_plugin__s2member_utils_strings::esc_refs(maybe_serialize($val)), $msg)))
277 break;
278
279 if($sbj && ($msg = trim(preg_replace('/%%(.+?)%%/i', '', $msg))) /* Still have a ``$sbj`` and a ``$msg``? */)
280
281 foreach(c_ws_plugin__s2member_utils_strings::parse_emails($GLOBALS['WS_PLUGIN__']['s2member']['o']['eot_del_notification_recipients']) as $recipient)
282 wp_mail($recipient, apply_filters('ws_plugin__s2member_eot_del_notification_email_sbj', $sbj, get_defined_vars()), apply_filters('ws_plugin__s2member_eot_del_notification_email_msg', $msg, get_defined_vars()), 'Content-Type: text/plain; charset=UTF-8');
283 }
284 if($email_configs_were_on) c_ws_plugin__s2member_email_configs::email_config();
285 }
286 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
287 do_action('ws_plugin__s2member_during_auto_eot_system_during_demote', get_defined_vars());
288 unset($__refs, $__v); // Housekeeping.
289 }
290 else if($GLOBALS['WS_PLUGIN__']['s2member']['o']['membership_eot_behavior'] === 'delete')
291 {
292 $eot_del_type = $GLOBALS['ws_plugin__s2member_eot_del_type'] = 'auto-eot-cancellation-expiration-deletion';
293 $log_entry['eot_del_type'] = $eot_del_type; // Deleting user in this case.
294
295 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
296 do_action('ws_plugin__s2member_during_auto_eot_system_during_before_delete', get_defined_vars());
297 do_action('ws_plugin__s2member_during_collective_eots', $user_id, get_defined_vars(), $eot_del_type, 'removal-deletion');
298 unset($__refs, $__v); // Housekeeping.
299
300 if(is_multisite()/* Multisite does NOT actually delete; ONLY removes. */)
301 {
302 remove_user_from_blog($user_id, $current_blog->blog_id);
303 // This will automatically trigger `eot_del_notification_urls`.
304 c_ws_plugin__s2member_user_deletions::handle_ms_user_deletions($user_id, $current_blog->blog_id, 's2says');
305 }
306 else // Otherwise, we can actually delete them.
307 // This will automatically trigger `eot_del_notification_urls`
308 wp_delete_user($user_id /* `c_ws_plugin__s2member_user_deletions::handle_user_deletions()` */);
309
310 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
311 do_action('ws_plugin__s2member_during_auto_eot_system_during_delete', get_defined_vars());
312 unset($__refs, $__v); // Housekeeping.
313 }
314 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
315 do_action('ws_plugin__s2member_during_auto_eot_system', get_defined_vars());
316 unset($__refs, $__v); // Housekeeping.
317
318 c_ws_plugin__s2member_utils_logs::log_entry('auto-eot-system', $log_entry);
319 }
320 }
321 }
322 }
323 }
324 c_ws_plugin__s2member_utils_logs::cleanup_expired_s2m_transients();
325
326 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
327 do_action('ws_plugin__s2member_after_auto_eot_system', get_defined_vars());
328 unset($__refs, $__v); // Housekeeping.
329 }
330 }
331 }
332