s2Member Framework (Member Roles, Capabilities, Membership, PayPal Members) - Version 2.8.8

Version Description

  • Integration instructions for iDevAffiliate and ShareASale are now available under: s2Member -> API Tracking.
  • Fixed a bug in the new Email Confirmation template for Single-Page Access. The replacement code: %%access_url%% has been changed to %%sp_access_url%%. This was a typo. The variable remains the same as it was, but the typo in the default template was corrected.
  • Added a new replacement code to the Single-Page Email Confirmation template. See: s2Member -> PayPal Options -> Single-Page. The new replacement code is: %%sp_access_exp%%, indicating a human readable duration for link validity.
  • High priority bug fixed with s2Member Hook/Filter on Login Design. This bug was just introduced in v2.8.7. This bug was preventing a customized Login Design from being displayed properly. Corrected in v2.8.8.
  • Bug fix in PayPal Button Generator. The modify="" parameter was being set to a value of "1" in some rare cases, depending on button configuration. It should always default to a value of "0", and only be set to a value of "1" or "2" whenever a Subscription Modification Button is being generated. This bug was introduced in v2.8.6. Corrected in v2.8.8.
Download this release

Release Info

Developer PriMoThemes
Plugin Icon 128x128 s2Member Framework (Member Roles, Capabilities, Membership, PayPal Members)
Version 2.8.8
Comparing to
See all releases

Code changes from version 2.8.6 to 2.8.8

Files changed (50) hide show
  1. images/idev-logo.gif +0 -0
  2. images/sas-logo.png +0 -0
  3. includes/functions/activate-deactivate.inc.php +10 -0
  4. includes/functions/admin-lockout.inc.php +6 -1
  5. includes/functions/admin-notices.inc.php +17 -1
  6. includes/functions/catg-level-access.inc.php +9 -1
  7. includes/functions/constants.inc.php +10 -2
  8. includes/functions/email-configs.inc.php +10 -2
  9. includes/functions/file-download-access.inc.php +113 -4
  10. includes/functions/hide-some-systematics.inc.php +5 -3
  11. includes/functions/is-systematic.inc.php +13 -11
  12. includes/functions/js-globals.inc.php +11 -1
  13. includes/functions/login-customizations.inc.php +29 -19
  14. includes/functions/login-redirection.inc.php +8 -2
  15. includes/functions/max-download-period.inc.php +0 -44
  16. includes/functions/menu-pages.inc.php +81 -2
  17. includes/functions/min-level-4-downloads.inc.php +0 -41
  18. includes/functions/nocache.inc.php +16 -0
  19. includes/functions/page-level-access.inc.php +9 -1
  20. includes/functions/paypal-notify.inc.php +63 -11
  21. includes/functions/paypal-postvars.inc.php +4 -2
  22. includes/functions/paypal-return.inc.php +38 -3
  23. includes/functions/post-level-access.inc.php +9 -1
  24. includes/functions/profile-modifications.inc.php +10 -0
  25. includes/functions/ptag-level-access.inc.php +9 -1
  26. includes/functions/readme-parsing.inc.php +10 -4
  27. includes/functions/register-access.inc.php +48 -10
  28. includes/functions/ruri-level-access.inc.php +10 -2
  29. includes/functions/shortcodes.inc.php +18 -5
  30. includes/functions/sp-access.inc.php +18 -10
  31. includes/functions/translations.inc.php +3 -1
  32. includes/functions/user-access-level.inc.php +17 -9
  33. includes/functions/user-deletions.inc.php +4 -0
  34. includes/functions/user-downloads.inc.php +0 -58
  35. includes/functions/users-list.inc.php +30 -10
  36. includes/menu-pages/api-ops.inc.php +10 -9
  37. includes/menu-pages/button.html +1 -1
  38. includes/menu-pages/buttons.inc.php +10 -10
  39. includes/menu-pages/code-samples/idev-signup-tracking-code.php +6 -0
  40. includes/menu-pages/code-samples/sas-signup-tracking-code.php +6 -0
  41. includes/menu-pages/menu-pages.js +6 -3
  42. includes/menu-pages/paypal-ops.inc.php +7 -4
  43. includes/menu-pages/scripting.inc.php +10 -0
  44. includes/menu-pages/sp-button.html +1 -1
  45. includes/menu-pages/sp-shortcode.html +1 -1
  46. includes/menu-pages/start.inc.php +3 -3
  47. includes/menu-pages/trk-ops.inc.php +30 -2
  48. includes/syscon.inc.php +1 -1
  49. readme.txt +13 -2
  50. s2member.php +2 -2
images/idev-logo.gif ADDED
Binary file
images/sas-logo.png ADDED
Binary file
includes/functions/activate-deactivate.inc.php CHANGED
@@ -25,6 +25,8 @@ extra queries before they are set.
25
  */
26
  function ws_plugin__s2member_activate ()
27
  {
 
 
28
  add_role ("s2member_level1", "s2Member Level 1");
29
  add_role ("s2member_level2", "s2Member Level 2");
30
  add_role ("s2member_level3", "s2Member Level 3");
@@ -121,6 +123,8 @@ function ws_plugin__s2member_activate ()
121
  ws_plugin__s2member_enqueue_admin_notice ($notice, array ("plugins.php", "ws-plugin--s2member-options"));
122
  }
123
  /**/
 
 
124
  return;
125
  }
126
  /*
@@ -130,6 +134,8 @@ ws_plugin__$plugin_key_deactivate() is called by our themes.
130
  */
131
  function ws_plugin__s2member_deactivate ()
132
  {
 
 
133
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["run_deactivation_routines"])
134
  {
135
  remove_role ("s2member_level1");
@@ -191,8 +197,12 @@ function ws_plugin__s2member_deactivate ()
191
  delete_option ("ws_plugin__s2member_cache");
192
  delete_option ("ws_plugin__s2member_notices");
193
  delete_option ("ws_plugin__s2member_options");
 
 
194
  }
195
  /**/
 
 
196
  return;
197
  }
198
  ?>
25
  */
26
  function ws_plugin__s2member_activate ()
27
  {
28
+ do_action ("s2member_before_activation");
29
+ /**/
30
  add_role ("s2member_level1", "s2Member Level 1");
31
  add_role ("s2member_level2", "s2Member Level 2");
32
  add_role ("s2member_level3", "s2Member Level 3");
123
  ws_plugin__s2member_enqueue_admin_notice ($notice, array ("plugins.php", "ws-plugin--s2member-options"));
124
  }
125
  /**/
126
+ do_action ("s2member_after_activation");
127
+ /**/
128
  return;
129
  }
130
  /*
134
  */
135
  function ws_plugin__s2member_deactivate ()
136
  {
137
+ do_action ("s2member_before_deactivation");
138
+ /**/
139
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["run_deactivation_routines"])
140
  {
141
  remove_role ("s2member_level1");
197
  delete_option ("ws_plugin__s2member_cache");
198
  delete_option ("ws_plugin__s2member_notices");
199
  delete_option ("ws_plugin__s2member_options");
200
+ /**/
201
+ do_action ("s2member_during_deactivation");
202
  }
203
  /**/
204
+ do_action ("s2member_after_deactivation");
205
+ /**/
206
  return;
207
  }
208
  ?>
includes/functions/admin-lockout.inc.php CHANGED
@@ -19,11 +19,16 @@ Attach to: add_action("admin_init");
19
  */
20
  function ws_plugin__s2member_admin_lockout ()
21
  {
 
 
22
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["force_admin_lockouts"]/**/
23
  && !current_user_can ("edit_posts") /* In other words: Subscribers and Members. */
24
- && wp_redirect (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"])) !== "nill")
 
25
  exit;
26
  /**/
 
 
27
  return;
28
  }
29
  ?>
19
  */
20
  function ws_plugin__s2member_admin_lockout ()
21
  {
22
+ do_action ("s2member_before_admin_lockouts");
23
+ /**/
24
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["force_admin_lockouts"]/**/
25
  && !current_user_can ("edit_posts") /* In other words: Subscribers and Members. */
26
+ && apply_filters ("s2member_admin_lockout", true) && /* Give filters a chance here. */
27
+ wp_redirect (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"])) !== "nill")
28
  exit;
29
  /**/
30
+ do_action ("s2member_after_admin_lockouts");
31
+ /**/
32
  return;
33
  }
34
  ?>
includes/functions/admin-notices.inc.php CHANGED
@@ -18,6 +18,8 @@ Function displays an admin notice immediately.
18
  */
19
  function ws_plugin__s2member_display_admin_notice ($notice = FALSE, $error = FALSE)
20
  {
 
 
21
  if ($notice && $error) /* Special format for errors. */
22
  {
23
  echo '<div class="error fade"><p>' . $notice . '</p></div>';
@@ -27,6 +29,8 @@ function ws_plugin__s2member_display_admin_notice ($notice = FALSE, $error = FAL
27
  echo '<div class="updated fade"><p>' . $notice . '</p></div>';
28
  }
29
  /**/
 
 
30
  return;
31
  }
32
  /*
@@ -34,15 +38,21 @@ Function that enqueues admin notices.
34
  */
35
  function ws_plugin__s2member_enqueue_admin_notice ($notice = FALSE, $on_pages = FALSE, $error = FALSE, $time = FALSE)
36
  {
 
 
37
  if ($notice && is_string ($notice)) /* If we have a valid string. */
38
  {
39
  $notices = (array)get_option ("ws_plugin__s2member_notices");
40
  /**/
41
  array_push ($notices, array ("notice" => $notice, "on_pages" => $on_pages, "error" => $error, "time" => $time));
42
  /**/
 
 
43
  update_option ("ws_plugin__s2member_notices", ws_plugin__s2member_array_unique ($notices));
44
  }
45
  /**/
 
 
46
  return;
47
  }
48
  /*
@@ -53,6 +63,8 @@ function ws_plugin__s2member_admin_notices ()
53
  {
54
  global $pagenow; /* This holds the current page filename. */
55
  /**/
 
 
56
  if (is_array ($notices = get_option ("ws_plugin__s2member_notices")) && !empty ($notices))
57
  {
58
  foreach ($notices as $key => $notice) /* Check time on each notice. */
@@ -68,11 +80,15 @@ function ws_plugin__s2member_admin_notices ()
68
  }
69
  }
70
  /**/
71
- $notices = array_merge ($notices); /* Re-index array keys. */
 
 
72
  /**/
73
  update_option ("ws_plugin__s2member_notices", $notices);
74
  }
75
  /**/
 
 
76
  return;
77
  }
78
  ?>
18
  */
19
  function ws_plugin__s2member_display_admin_notice ($notice = FALSE, $error = FALSE)
20
  {
21
+ do_action ("s2member_before_display_admin_notice");
22
+ /**/
23
  if ($notice && $error) /* Special format for errors. */
24
  {
25
  echo '<div class="error fade"><p>' . $notice . '</p></div>';
29
  echo '<div class="updated fade"><p>' . $notice . '</p></div>';
30
  }
31
  /**/
32
+ do_action ("s2member_after_display_admin_notice");
33
+ /**/
34
  return;
35
  }
36
  /*
38
  */
39
  function ws_plugin__s2member_enqueue_admin_notice ($notice = FALSE, $on_pages = FALSE, $error = FALSE, $time = FALSE)
40
  {
41
+ do_action ("s2member_before_enqueue_admin_notice");
42
+ /**/
43
  if ($notice && is_string ($notice)) /* If we have a valid string. */
44
  {
45
  $notices = (array)get_option ("ws_plugin__s2member_notices");
46
  /**/
47
  array_push ($notices, array ("notice" => $notice, "on_pages" => $on_pages, "error" => $error, "time" => $time));
48
  /**/
49
+ do_action ("s2member_during_enqueue_admin_notice"); /* Give plugins a chance. */
50
+ /**/
51
  update_option ("ws_plugin__s2member_notices", ws_plugin__s2member_array_unique ($notices));
52
  }
53
  /**/
54
+ do_action ("s2member_after_enqueue_admin_notice");
55
+ /**/
56
  return;
57
  }
58
  /*
63
  {
64
  global $pagenow; /* This holds the current page filename. */
65
  /**/
66
+ do_action ("s2member_before_admin_notices");
67
+ /**/
68
  if (is_array ($notices = get_option ("ws_plugin__s2member_notices")) && !empty ($notices))
69
  {
70
  foreach ($notices as $key => $notice) /* Check time on each notice. */
80
  }
81
  }
82
  /**/
83
+ do_action ("s2member_during_admin_notices");
84
+ /**/
85
+ $notices = array_merge ($notices); /* Re-index. */
86
  /**/
87
  update_option ("ws_plugin__s2member_notices", $notices);
88
  }
89
  /**/
90
+ do_action ("s2member_after_admin_notices");
91
+ /**/
92
  return;
93
  }
94
  ?>
includes/functions/catg-level-access.inc.php CHANGED
@@ -21,7 +21,11 @@ function ws_plugin__s2member_check_catg_level_access ()
21
  {
22
  global $post; /* get_the_ID() not yet available here. */
23
  /**/
24
- if ((is_category () && ($cat_ID = get_query_var ("cat"))) || (is_single () && !is_page () && is_object ($post) && ($post_ID = $post->ID)))
 
 
 
 
25
  {
26
  if (!ws_plugin__s2member_is_systematic_use_page ()) /* Never restrict systematic use pages. */
27
  {
@@ -95,9 +99,13 @@ function ws_plugin__s2member_check_catg_level_access ()
95
  else if (($level4_catgs = preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_catgs"])) && (in_category ($level4_catgs, $post_ID) || ws_plugin__s2member_in_descendant_category ($level4_catgs, $post_ID)) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
96
  exit;
97
  }
 
 
98
  }
99
  }
100
  /**/
 
 
101
  return;
102
  }
103
  ?>
21
  {
22
  global $post; /* get_the_ID() not yet available here. */
23
  /**/
24
+ do_action ("s2member_before_check_catg_level_access");
25
+ /**/
26
+ $excluded = apply_filters ("s2member_check_catg_level_access_excluded", false);
27
+ /**/
28
+ if (!$excluded && ((is_category () && ($cat_ID = get_query_var ("cat"))) || (is_single () && !is_page () && is_object ($post) && ($post_ID = $post->ID))))
29
  {
30
  if (!ws_plugin__s2member_is_systematic_use_page ()) /* Never restrict systematic use pages. */
31
  {
99
  else if (($level4_catgs = preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_catgs"])) && (in_category ($level4_catgs, $post_ID) || ws_plugin__s2member_in_descendant_category ($level4_catgs, $post_ID)) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
100
  exit;
101
  }
102
+ /**/
103
+ do_action ("s2member_during_check_catg_level_access");
104
  }
105
  }
106
  /**/
107
+ do_action ("s2member_after_check_catg_level_access");
108
+ /**/
109
  return;
110
  }
111
  ?>
includes/functions/constants.inc.php CHANGED
@@ -20,6 +20,8 @@ Attach to: add_action("init");
20
  */
21
  function ws_plugin__s2member_constants ()
22
  {
 
 
23
  $links = ws_plugin__s2member_constant_links ();
24
  $metas = ws_plugin__s2member_constant_metas ();
25
  $level = ws_plugin__s2member_user_access_level ();
@@ -89,6 +91,8 @@ function ws_plugin__s2member_constants ()
89
  define ("S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0", ((S2MEMBER_CURRENT_USER_SUBSCR_ID) ? "Updating Subscr" : "")); /* Auto-fills the on0 value in PayPal buttons. */
90
  define ("S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0", ((S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0) ? S2MEMBER_CURRENT_USER_SUBSCR_ID : "")); /* For the os0 value. */
91
  /**/
 
 
92
  return;
93
  }
94
  /*
@@ -99,6 +103,8 @@ forced to execute get_page_link() all the time, which piles up DB queries.
99
  */
100
  function ws_plugin__s2member_constant_links ()
101
  {
 
 
102
  $cache_minutes = 15; /* Could be higher? */
103
  /**/
104
  $l["login_welcome_page"] = (string)"";
@@ -157,7 +163,7 @@ function ws_plugin__s2member_constant_links ()
157
  update_option ("ws_plugin__s2member_cache", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"]);
158
  }
159
  /**/
160
- return $l; /* Links. */
161
  }
162
  /*
163
  This function pulls all of the usermeta details needed for Constants.
@@ -167,6 +173,8 @@ function ws_plugin__s2member_constant_metas ()
167
  {
168
  global $wpdb; /* The global database object. */
169
  /**/
 
 
170
  $m["s2member_file_download_access_log"] = array ();
171
  $m["s2member_custom_fields"] = array ();
172
  $m["s2member_subscr_id"] = (string)"";
@@ -188,6 +196,6 @@ function ws_plugin__s2member_constant_metas ()
188
  }
189
  }
190
  /**/
191
- return $m; /* Metas. */
192
  }
193
  ?>
20
  */
21
  function ws_plugin__s2member_constants ()
22
  {
23
+ do_action ("s2member_before_constants");
24
+ /**/
25
  $links = ws_plugin__s2member_constant_links ();
26
  $metas = ws_plugin__s2member_constant_metas ();
27
  $level = ws_plugin__s2member_user_access_level ();
91
  define ("S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0", ((S2MEMBER_CURRENT_USER_SUBSCR_ID) ? "Updating Subscr" : "")); /* Auto-fills the on0 value in PayPal buttons. */
92
  define ("S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0", ((S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0) ? S2MEMBER_CURRENT_USER_SUBSCR_ID : "")); /* For the os0 value. */
93
  /**/
94
+ do_action ("s2member_after_constants");
95
+ /**/
96
  return;
97
  }
98
  /*
103
  */
104
  function ws_plugin__s2member_constant_links ()
105
  {
106
+ do_action ("s2member_before_constant_links");
107
+ /**/
108
  $cache_minutes = 15; /* Could be higher? */
109
  /**/
110
  $l["login_welcome_page"] = (string)"";
163
  update_option ("ws_plugin__s2member_cache", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"]);
164
  }
165
  /**/
166
+ return apply_filters ("s2member_constant_links", $l);
167
  }
168
  /*
169
  This function pulls all of the usermeta details needed for Constants.
173
  {
174
  global $wpdb; /* The global database object. */
175
  /**/
176
+ do_action ("s2member_before_constant_metas");
177
+ /**/
178
  $m["s2member_file_download_access_log"] = array ();
179
  $m["s2member_custom_fields"] = array ();
180
  $m["s2member_subscr_id"] = (string)"";
196
  }
197
  }
198
  /**/
199
+ return apply_filters ("s2member_constant_metas", $m);
200
  }
201
  ?>
includes/functions/email-configs.inc.php CHANGED
@@ -18,19 +18,27 @@ Functions that modify the email From: name/address.
18
  */
19
  function ws_plugin__s2member_email_config ()
20
  {
 
 
21
  add_filter ("wp_mail_from", "_ws_plugin__s2member_email_config_email");
22
  add_filter ("wp_mail_from_name", "_ws_plugin__s2member_email_config_name");
23
  /**/
 
 
24
  return;
25
  }
26
  /**/
27
  function _ws_plugin__s2member_email_config_email ($email = FALSE)
28
  {
29
- return $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"];
 
 
30
  }
31
  /**/
32
  function _ws_plugin__s2member_email_config_name ($name = FALSE)
33
  {
34
- return $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"];
 
 
35
  }
36
  ?>
18
  */
19
  function ws_plugin__s2member_email_config ()
20
  {
21
+ do_action ("s2member_before_email_config");
22
+ /**/
23
  add_filter ("wp_mail_from", "_ws_plugin__s2member_email_config_email");
24
  add_filter ("wp_mail_from_name", "_ws_plugin__s2member_email_config_name");
25
  /**/
26
+ do_action ("s2member_after_email_config");
27
+ /**/
28
  return;
29
  }
30
  /**/
31
  function _ws_plugin__s2member_email_config_email ($email = FALSE)
32
  {
33
+ do_action ("s2member_before_email_config_email");
34
+ /**/
35
+ return apply_filters ("s2member_email_config_email", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"]);
36
  }
37
  /**/
38
  function _ws_plugin__s2member_email_config_name ($name = FALSE)
39
  {
40
+ do_action ("s2member_before_email_config_name");
41
+ /**/
42
+ return apply_filters ("s2member_email_config_name", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]);
43
  }
44
  ?>
includes/functions/file-download-access.inc.php CHANGED
@@ -14,14 +14,119 @@ Direct access denial.
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
  exit;
16
  /*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  Function for handling download access permissions.
18
  Attach to: add_action("init");
19
  */
20
  function ws_plugin__s2member_check_file_download_access ()
21
  {
22
- if ($_GET["s2member_file_download"])
 
 
23
  {
24
- if (!$_GET["s2member_free_file_download_key"] || ws_plugin__s2member_xdecrypt ($_GET["s2member_free_file_download_key"]) !== $_GET["s2member_file_download"])
 
 
25
  {
26
  $_GET["s2member_file_download"] = trim ($_GET["s2member_file_download"], "/");
27
  /**/
@@ -49,13 +154,13 @@ function ws_plugin__s2member_check_file_download_access ()
49
  exit;
50
  /**/
51
  $previous_file_downloads = 0; /* Here we're going to count how many downloads they've performed. */
52
- $maximum_days_logged = ws_plugin__s2member_maximum_download_period (); /* The longest period in days. */
53
  $file_download_access_log = (array)get_usermeta ($current_user->ID, "s2member_file_download_access_log");
54
  $file_download_access_arc = (array)get_usermeta ($current_user->ID, "s2member_file_download_access_arc");
55
  /**/
56
  foreach ($file_download_access_log as $file_download_access_log_entry_key => $file_download_access_log_entry)
57
  {
58
- if (strtotime ($file_download_access_log_entry["date"]) < strtotime ("-" . $maximum_days_logged . " days"))
59
  {
60
  unset ($file_download_access_log[$file_download_access_log_entry_key]);
61
  $file_download_access_arc[] = $file_download_access_log_entry;
@@ -101,6 +206,8 @@ function ws_plugin__s2member_check_file_download_access ()
101
  $mimetype = ($mimetypes[$extension]) ? $mimetypes[$extension] : "application/octet-stream"; /* Lookup MIME type. */
102
  /**/
103
  $length = filesize ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $_GET["s2member_file_download"]);
 
 
104
  /*
105
  Now send the file to the browser. Be sure to turn off output compression.
106
  */
@@ -120,5 +227,7 @@ function ws_plugin__s2member_check_file_download_access ()
120
  /**/
121
  exit;
122
  }
 
 
123
  }
124
  ?>
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
  exit;
16
  /*
17
+ Function determines the max period in days for download access.
18
+ Returns number of days, where 0 means no access to files has been allowed.
19
+ */
20
+ function ws_plugin__s2member_max_download_period ()
21
+ {
22
+ do_action ("s2member_before_max_download_period");
23
+ /**/
24
+ if ($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed_days"])
25
+ {
26
+ $max = ($max < $days) ? $days : $max;
27
+ }
28
+ /**/
29
+ if ($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed_days"])
30
+ {
31
+ $max = ($max < $days) ? $days : $max;
32
+ }
33
+ /**/
34
+ if ($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed_days"])
35
+ {
36
+ $max = ($max < $days) ? $days : $max;
37
+ }
38
+ /**/
39
+ if ($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed_days"])
40
+ {
41
+ $max = ($max < $days) ? $days : $max;
42
+ }
43
+ /**/
44
+ return apply_filters ("s2member_max_download_period", (($max > 365) ? 365 : (int)$max));
45
+ }
46
+ /*
47
+ Function determines how many downloads allowed - etc, etc.
48
+ Returns an array with 3 elements: allowed, allowed_days, currently.
49
+ The 2nd parameter can be used to prevent another database connection.
50
+ */
51
+ function ws_plugin__s2member_user_downloads ($not_counting_this_particular_file = false, $log = null)
52
+ {
53
+ do_action ("s2member_before_user_downloads");
54
+ /**/
55
+ if (($current_user = (is_user_logged_in ()) ? wp_get_current_user () : false))
56
+ {
57
+ if (current_user_can ("access_s2member_level1") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed"])
58
+ {
59
+ $allowed = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed"];
60
+ $allowed_days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed_days"];
61
+ }
62
+ /**/
63
+ if (current_user_can ("access_s2member_level2") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed"])
64
+ {
65
+ $allowed = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed"];
66
+ $allowed_days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed_days"];
67
+ }
68
+ /**/
69
+ if (current_user_can ("access_s2member_level3") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed"])
70
+ {
71
+ $allowed = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed"];
72
+ $allowed_days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed_days"];
73
+ }
74
+ /**/
75
+ if (current_user_can ("access_s2member_level4") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed"])
76
+ {
77
+ $allowed = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed"];
78
+ $allowed_days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed_days"];
79
+ }
80
+ /**/
81
+ $file_download_access_log = (isset ($log)) ? (array)$log : (array)get_usermeta ($current_user->ID, "s2member_file_download_access_log");
82
+ foreach ($file_download_access_log as $file_download_access_log_entry_key => $file_download_access_log_entry)
83
+ if (strtotime ($file_download_access_log_entry["date"]) >= strtotime ("-" . (int)$allowed_days . " days"))
84
+ if ($file_download_access_log_entry["file"] !== $not_counting_this_particular_file)
85
+ $currently = ($currently) ? $currently + 1 : 1;
86
+ }
87
+ /**/
88
+ return apply_filters ("s2member_user_downloads", array ("allowed" => (int)$allowed, "allowed_days" => (int)$allowed_days, "currently" => (int)$currently));
89
+ }
90
+ /*
91
+ Function determines the minimum level required for file download access.
92
+ Returns 0-4, where 0 means no access to file downloads has been allowed.
93
+ */
94
+ function ws_plugin__s2member_min_level_4_downloads ()
95
+ {
96
+ do_action ("s2member_before_min_level_4_downloads");
97
+ /**/
98
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed_days"])
99
+ {
100
+ $file_download_access_is_allowed = $min_level_4_downloads = 1;
101
+ }
102
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed_days"])
103
+ {
104
+ $file_download_access_is_allowed = $min_level_4_downloads = 2;
105
+ }
106
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed_days"])
107
+ {
108
+ $file_download_access_is_allowed = $min_level_4_downloads = 3;
109
+ }
110
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed_days"])
111
+ {
112
+ $file_download_access_is_allowed = $min_level_4_downloads = 4;
113
+ }
114
+ /**/
115
+ return apply_filters ("s2member_min_level_4_downloads", (int)$min_level_4_downloads);
116
+ }
117
+ /*
118
  Function for handling download access permissions.
119
  Attach to: add_action("init");
120
  */
121
  function ws_plugin__s2member_check_file_download_access ()
122
  {
123
+ do_action ("s2member_before_file_download_access");
124
+ /**/
125
+ if ($_GET["s2member_file_download"]) /* Filter $excluded to force free downloads. */
126
  {
127
+ $excluded = apply_filters ("s2member_check_file_download_access_excluded", false); /* Or use $_GET["s2member_free_file_download_key"]. */
128
+ /**/
129
+ if (!$excluded && (!$_GET["s2member_free_file_download_key"] || ws_plugin__s2member_xdecrypt ($_GET["s2member_free_file_download_key"]) !== $_GET["s2member_file_download"]))
130
  {
131
  $_GET["s2member_file_download"] = trim ($_GET["s2member_file_download"], "/");
132
  /**/
154
  exit;
155
  /**/
156
  $previous_file_downloads = 0; /* Here we're going to count how many downloads they've performed. */
157
+ $max_days_logged = ws_plugin__s2member_max_download_period (); /* The longest period in days. */
158
  $file_download_access_log = (array)get_usermeta ($current_user->ID, "s2member_file_download_access_log");
159
  $file_download_access_arc = (array)get_usermeta ($current_user->ID, "s2member_file_download_access_arc");
160
  /**/
161
  foreach ($file_download_access_log as $file_download_access_log_entry_key => $file_download_access_log_entry)
162
  {
163
+ if (strtotime ($file_download_access_log_entry["date"]) < strtotime ("-" . $max_days_logged . " days"))
164
  {
165
  unset ($file_download_access_log[$file_download_access_log_entry_key]);
166
  $file_download_access_arc[] = $file_download_access_log_entry;
206
  $mimetype = ($mimetypes[$extension]) ? $mimetypes[$extension] : "application/octet-stream"; /* Lookup MIME type. */
207
  /**/
208
  $length = filesize ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $_GET["s2member_file_download"]);
209
+ /**/
210
+ do_action ("s2member_during_file_download_access"); /* Give plugins a chance. */
211
  /*
212
  Now send the file to the browser. Be sure to turn off output compression.
213
  */
227
  /**/
228
  exit;
229
  }
230
+ /**/
231
+ do_action ("s2member_after_file_download_access");
232
  }
233
  ?>
includes/functions/hide-some-systematics.inc.php CHANGED
@@ -11,7 +11,7 @@ If not, see: <http://www.gnu.org/licenses/>.
11
  /*
12
  Direct access denial.
13
  */
14
- if (realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
15
  exit;
16
  /*
17
  Function that hides some of the systematic use pages.
@@ -21,11 +21,13 @@ function ws_plugin__s2member_hide_some_systematics ($where = FALSE)
21
  {
22
  global $wpdb; /* Need this to get the table name. */
23
  /**/
24
- if (is_search()) /* Here we exclude a few systematic use pages from the search query. */
 
 
25
  {
26
  $where .= " AND " . $wpdb->posts . ".ID NOT IN ('" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"] . "', '" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"] . "', '" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"] . "')";
27
  }
28
  /**/
29
- return $where;
30
  }
31
  ?>
11
  /*
12
  Direct access denial.
13
  */
14
+ if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
  exit;
16
  /*
17
  Function that hides some of the systematic use pages.
21
  {
22
  global $wpdb; /* Need this to get the table name. */
23
  /**/
24
+ do_action ("s2member_before_hide_some_systematics");
25
+ /**/
26
+ if (is_search ()) /* Here we exclude a few systematic use pages from the search query. */
27
  {
28
  $where .= " AND " . $wpdb->posts . ".ID NOT IN ('" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"] . "', '" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"] . "', '" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"] . "')";
29
  }
30
  /**/
31
+ return apply_filters ("s2member_hide_some_systematics", $where);
32
  }
33
  ?>
includes/functions/is-systematic.inc.php CHANGED
@@ -20,45 +20,47 @@ function ws_plugin__s2member_is_systematic_use_page ()
20
  {
21
  static $is_systematic; /* For optimization. */
22
  /**/
23
- if (isset ($is_systematic)) /* Already cached? */
 
 
24
  {
25
- return $is_systematic; /* Saves time. */
26
  }
27
  else if (is_admin ()) /* In the admin area? */
28
  {
29
- return ($is_systematic = true);
30
  }
31
  else if (preg_match ("/^cli$/i", PHP_SAPI))
32
  {
33
- return ($is_systematic = true);
34
  }
35
  else if ($_SERVER["REMOTE_ADDR"] === $_SERVER["SERVER_ADDR"])
36
  {
37
- return ($is_systematic = true);
38
  }
39
  else if (preg_match ("/\/wp-login\.php/", $_SERVER["REQUEST_URI"]))
40
  {
41
- return ($is_systematic = true);
42
  }
43
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"] && is_page ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]))
44
  {
45
- return ($is_systematic = true);
46
  }
47
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"] && is_page ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"]))
48
  {
49
- return ($is_systematic = true);
50
  }
51
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"] && is_page ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"]))
52
  {
53
- return ($is_systematic = true);
54
  }
55
  else if (preg_match ("/^s2member/", $_SERVER["QUERY_STRING"]) && ($_SERVER["REQUEST_URI"] === "/" || strtolower (rtrim (get_bloginfo ("url"), "/")) === rtrim (strtolower ("http://" . $_SERVER["HTTP_HOST"]) . $_SERVER["REQUEST_URI"], "/")))
56
  {
57
- return ($is_systematic = true); /* Only true when the request starts with /?s2member from the root URL of the domain, or from the root URL of the WordPress® installation. */
58
  }
59
  else /* Otherwise, we return false. */
60
  {
61
- return ($is_systematic = false);
62
  }
63
  }
64
  ?>
20
  {
21
  static $is_systematic; /* For optimization. */
22
  /**/
23
+ do_action ("s2member_before_is_systematic_use_page");
24
+ /**/
25
+ if (isset ($is_systematic)) /* Already cached? This saves time. */
26
  {
27
+ return apply_filters ("s2member_is_systematic_use_page", $is_systematic);
28
  }
29
  else if (is_admin ()) /* In the admin area? */
30
  {
31
+ return ($is_systematic = apply_filters ("s2member_is_systematic_use_page", true));
32
  }
33
  else if (preg_match ("/^cli$/i", PHP_SAPI))
34
  {
35
+ return ($is_systematic = apply_filters ("s2member_is_systematic_use_page", true));
36
  }
37
  else if ($_SERVER["REMOTE_ADDR"] === $_SERVER["SERVER_ADDR"])
38
  {
39
+ return ($is_systematic = apply_filters ("s2member_is_systematic_use_page", true));
40
  }
41
  else if (preg_match ("/\/wp-login\.php/", $_SERVER["REQUEST_URI"]))
42
  {
43
+ return ($is_systematic = apply_filters ("s2member_is_systematic_use_page", true));
44
  }
45
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"] && is_page ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]))
46
  {
47
+ return ($is_systematic = apply_filters ("s2member_is_systematic_use_page", true));
48
  }
49
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"] && is_page ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"]))
50
  {
51
+ return ($is_systematic = apply_filters ("s2member_is_systematic_use_page", true));
52
  }
53
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"] && is_page ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"]))
54
  {
55
+ return ($is_systematic = apply_filters ("s2member_is_systematic_use_page", true));
56
  }
57
  else if (preg_match ("/^s2member/", $_SERVER["QUERY_STRING"]) && ($_SERVER["REQUEST_URI"] === "/" || strtolower (rtrim (get_bloginfo ("url"), "/")) === rtrim (strtolower ("http://" . $_SERVER["HTTP_HOST"]) . $_SERVER["REQUEST_URI"], "/")))
58
  {
59
+ return ($is_systematic = apply_filters ("s2member_is_systematic_use_page", true)); /* Only true when the request starts with /?s2member from the root URL of the domain, or from the root URL of the WordPress® installation. */
60
  }
61
  else /* Otherwise, we return false. */
62
  {
63
+ return ($is_systematic = apply_filters ("s2member_is_systematic_use_page", false));
64
  }
65
  }
66
  ?>
includes/functions/js-globals.inc.php CHANGED
@@ -21,6 +21,8 @@ Attach to: add_action("wp_print_scripts");
21
  */
22
  function ws_plugin__s2member_add_js_w_globals ()
23
  {
 
 
24
  if (!is_admin ()) /* Not in the admin. */
25
  {
26
  if (is_user_logged_in ())
@@ -42,8 +44,12 @@ function ws_plugin__s2member_add_js_w_globals ()
42
  { /* This essentially creates 2 versions of the script. One while logged in & another when not. */
43
  wp_enqueue_script ("ws-plugin--s2member", get_bloginfo ("url") . "/?ws_plugin__s2member_js_w_globals=1&qcABC=1", array ("jquery"), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["options_version"] . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["filemtime"]);
44
  }
 
 
45
  }
46
  /**/
 
 
47
  return;
48
  }
49
  /*
@@ -52,6 +58,8 @@ Attach to: add_action("init");
52
  */
53
  function ws_plugin__s2member_js_w_globals ()
54
  {
 
 
55
  if ($_GET["ws_plugin__s2member_js_w_globals"])
56
  {
57
  header ("Content-Type: text/javascript; charset=utf-8");
@@ -123,9 +131,11 @@ function ws_plugin__s2member_js_w_globals ()
123
  $j = file_get_contents (dirname (dirname (__FILE__)) . "/s2member-min.js");
124
  $j = preg_replace ("/('|\")%%globals%%('|\");/", $g, $j);
125
  /**/
126
- echo $j;
127
  /**/
128
  exit;
129
  }
 
 
130
  }
131
  ?>
21
  */
22
  function ws_plugin__s2member_add_js_w_globals ()
23
  {
24
+ do_action ("s2member_before_add_js_w_globals");
25
+ /**/
26
  if (!is_admin ()) /* Not in the admin. */
27
  {
28
  if (is_user_logged_in ())
44
  { /* This essentially creates 2 versions of the script. One while logged in & another when not. */
45
  wp_enqueue_script ("ws-plugin--s2member", get_bloginfo ("url") . "/?ws_plugin__s2member_js_w_globals=1&qcABC=1", array ("jquery"), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["options_version"] . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["filemtime"]);
46
  }
47
+ /**/
48
+ do_action ("s2member_during_add_js_w_globals");
49
  }
50
  /**/
51
+ do_action ("s2member_after_add_js_w_globals");
52
+ /**/
53
  return;
54
  }
55
  /*
58
  */
59
  function ws_plugin__s2member_js_w_globals ()
60
  {
61
+ do_action ("s2member_before_js_w_globals");
62
+ /**/
63
  if ($_GET["ws_plugin__s2member_js_w_globals"])
64
  {
65
  header ("Content-Type: text/javascript; charset=utf-8");
131
  $j = file_get_contents (dirname (dirname (__FILE__)) . "/s2member-min.js");
132
  $j = preg_replace ("/('|\")%%globals%%('|\");/", $g, $j);
133
  /**/
134
+ echo apply_filters ("s2member_js_w_globals", $j);
135
  /**/
136
  exit;
137
  }
138
+ /**/
139
+ do_action ("s2member_after_js_w_globals");
140
  }
141
  ?>
includes/functions/login-customizations.inc.php CHANGED
@@ -19,9 +19,11 @@ Attach to: add_filter("login_headerurl");
19
  */
20
  function ws_plugin__s2member_login_header_url ($url = FALSE)
21
  {
 
 
22
  $url = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_url"];
23
  /**/
24
- return $url;
25
  }
26
  /*
27
  Function for filtering the login logo title.
@@ -29,9 +31,11 @@ Attach to: add_filter("login_headertitle");
29
  */
30
  function ws_plugin__s2member_login_header_title ($title = FALSE)
31
  {
 
 
32
  $title = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_title"];
33
  /**/
34
- return $title;
35
  }
36
  /*
37
  Function for creating the styles for the login panel.
@@ -39,31 +43,37 @@ Attach to: add_action("login_head");
39
  */
40
  function ws_plugin__s2member_login_header_styles ()
41
  {
42
- echo "\n" . '<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>' . "\n";
43
- echo '<script type="text/javascript" src="' . get_bloginfo ("url") . '/?ws_plugin__s2member_js_w_globals=1&amp;no-cache=' . urlencode (md5 (mt_rand ())) . '"></script>' . "\n";
 
 
44
  /**/
45
- echo "\n" . '<style type="text/css">' . "\n";
46
  /**/
47
- echo 'html, body { border: 0 !important; background: none !important; }' . "\n"; /* Clear borders & existing background. */
48
- echo 'html { background-color: #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_color"] . ' !important; }' . "\n";
49
- echo 'html { background-image: url(' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_image"] . ') !important; }' . "\n";
50
  /**/
51
- echo 'p#backtoblog a, p#backtoblog a:hover, p#backtoblog a:active, p#backtoblog a:focus { color: #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_color"] . ' !important; text-shadow: 1px 1px 3px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_shadow_color"] . ' !important; top: 15px !important; left: 15px !important; padding: 10px !important; border:1px solid #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ' !important; background-color: #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_color"] . ' !important; -moz-border-radius:3px !important; -webkit-border-radius:3px !important; border-radius:3px !important; }' . "\n";
52
  /**/
53
- echo 'div#login { width: ' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_width"] . 'px !important; }' . "\n";
54
- echo 'div#login h1 a { background: url(' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src"] . ') no-repeat top center !important; }' . "\n";
55
- echo 'div#login h1 a { display: block !important; width: 100% !important; height: ' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_height"] . 'px !important; }' . "\n";
56
- echo 'div#login p#nav, div#login p#nav a, div#login p#nav a:hover, div#login p#nav a:active, div#login p#nav a:focus { color: #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_color"] . ' !important; text-shadow: 1px 1px 3px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_shadow_color"] . ' !important; }' . "\n";
57
- echo 'div#login form { -moz-box-shadow: 1px 1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ', -1px -1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ' !important; -webkit-box-shadow: 1px 1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ', -1px -1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ' !important; -khtml-box-shadow: 1px 1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ', -1px -1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ' !important; box-shadow: 1px 1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ', -1px -1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ' !important; }' . "\n";
58
- echo 'div#login form input[type="submit"], div#login form input[type="submit"]:hover, div#login form input[type="submit"]:active, div#login form input[type="submit"]:focus { color: #333333 !important; border: 1px solid #666666 !important; background: #CCCCCC !important; padding: 5px !important; -moz-border-radius: 3px !important; -webkit-border-radius: 3px !important; -khtml-border-radius: 3px !important; border-radius: 3px !important; }' . "\n";
59
- echo 'div#login form input[type="submit"]:hover, div#login form input[type="submit"]:active, div#login form input[type="submit"]:focus { color: #000000 !important; border: 1px solid #000000 !important; }' . "\n";
60
  /**/
61
- echo 'div#login form input.ws-plugin--s2member-custom-reg-field { background:none repeat scroll 0 0 #FBFBFB; border:1px solid #E5E5E5; font-size:24px; margin-bottom:16px; margin-right:6px; margin-top:2px; padding:3px; width:97%; }' . "\n";
62
  /**/
63
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"])
64
- echo 'p#reg_passmail { display: none; }' . "\n";
 
 
 
 
65
  /**/
66
- echo '</style>' . "\n\n";
67
  /**/
68
  return;
69
  }
19
  */
20
  function ws_plugin__s2member_login_header_url ($url = FALSE)
21
  {
22
+ do_action ("s2member_before_login_header_url");
23
+ /**/
24
  $url = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_url"];
25
  /**/
26
+ return apply_filters ("s2member_login_header_url", $url);
27
  }
28
  /*
29
  Function for filtering the login logo title.
31
  */
32
  function ws_plugin__s2member_login_header_title ($title = FALSE)
33
  {
34
+ do_action ("s2member_before_login_header_title");
35
+ /**/
36
  $title = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_title"];
37
  /**/
38
+ return apply_filters ("s2member_login_header_title", $title);
39
  }
40
  /*
41
  Function for creating the styles for the login panel.
43
  */
44
  function ws_plugin__s2member_login_header_styles ()
45
  {
46
+ do_action ("s2member_before_login_header_styles");
47
+ /**/
48
+ $s = "\n" . '<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>' . "\n";
49
+ $s .= '<script type="text/javascript" src="' . get_bloginfo ("url") . '/?ws_plugin__s2member_js_w_globals=1&amp;no-cache=' . urlencode (md5 (mt_rand ())) . '"></script>' . "\n";
50
  /**/
51
+ $s .= "\n" . '<style type="text/css">' . "\n";
52
  /**/
53
+ $s .= 'html, body { border: 0 !important; background: none !important; }' . "\n"; /* Clear borders & existing background. */
54
+ $s .= 'html { background-color: #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_color"] . ' !important; }' . "\n";
55
+ $s .= 'html { background-image: url(' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_image"] . ') !important; }' . "\n";
56
  /**/
57
+ $s .= 'p#backtoblog a, p#backtoblog a:hover, p#backtoblog a:active, p#backtoblog a:focus { color: #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_color"] . ' !important; text-shadow: 1px 1px 3px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_shadow_color"] . ' !important; top: 15px !important; left: 15px !important; padding: 10px !important; border:1px solid #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ' !important; background-color: #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_color"] . ' !important; -moz-border-radius:3px !important; -webkit-border-radius:3px !important; border-radius:3px !important; }' . "\n";
58
  /**/
59
+ $s .= 'div#login { width: ' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_width"] . 'px !important; }' . "\n";
60
+ $s .= 'div#login h1 a { background: url(' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src"] . ') no-repeat top center !important; }' . "\n";
61
+ $s .= 'div#login h1 a { display: block !important; width: 100% !important; height: ' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_height"] . 'px !important; }' . "\n";
62
+ $s .= 'div#login p#nav, div#login p#nav a, div#login p#nav a:hover, div#login p#nav a:active, div#login p#nav a:focus { color: #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_color"] . ' !important; text-shadow: 1px 1px 3px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_shadow_color"] . ' !important; }' . "\n";
63
+ $s .= 'div#login form { -moz-box-shadow: 1px 1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ', -1px -1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ' !important; -webkit-box-shadow: 1px 1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ', -1px -1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ' !important; -khtml-box-shadow: 1px 1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ', -1px -1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ' !important; box-shadow: 1px 1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ', -1px -1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ' !important; }' . "\n";
64
+ $s .= 'div#login form input[type="submit"], div#login form input[type="submit"]:hover, div#login form input[type="submit"]:active, div#login form input[type="submit"]:focus { color: #333333 !important; border: 1px solid #666666 !important; background: #CCCCCC !important; padding: 5px !important; -moz-border-radius: 3px !important; -webkit-border-radius: 3px !important; -khtml-border-radius: 3px !important; border-radius: 3px !important; }' . "\n";
65
+ $s .= 'div#login form input[type="submit"]:hover, div#login form input[type="submit"]:active, div#login form input[type="submit"]:focus { color: #000000 !important; border: 1px solid #000000 !important; }' . "\n";
66
  /**/
67
+ $s .= 'div#login form input.ws-plugin--s2member-custom-reg-field { background:none repeat scroll 0 0 #FBFBFB; border:1px solid #E5E5E5; font-size:24px; margin-bottom:16px; margin-right:6px; margin-top:2px; padding:3px; width:97%; }' . "\n";
68
  /**/
69
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"])
70
+ $s .= 'p#reg_passmail { display: none; }' . "\n";
71
+ /**/
72
+ $s .= '</style>' . "\n\n";
73
+ /**/
74
+ echo apply_filters ("s2member_login_header_styles", $s);
75
  /**/
76
+ do_action ("s2member_after_login_header_styles");
77
  /**/
78
  return;
79
  }
includes/functions/login-redirection.inc.php CHANGED
@@ -22,10 +22,14 @@ function ws_plugin__s2member_login_redirect ()
22
  /* Note that current_user_can() will not work here because the cookie was just set. */
23
  global $user; /* Available during the login routine just before wp_login is hooked in. */
24
  /**/
25
- $uzer = new WP_User ($user->ID); /* Now lets get a user object to check capabilities. */
26
  /**/
27
- if (!$uzer->has_cap ("edit_posts")) /* In other words, all subscribers & members. */
 
 
28
  {
 
 
29
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"])
30
  wp_redirect ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"]);
31
  /**/
@@ -35,6 +39,8 @@ function ws_plugin__s2member_login_redirect ()
35
  exit;
36
  }
37
  /**/
 
 
38
  return;
39
  }
40
  ?>
22
  /* Note that current_user_can() will not work here because the cookie was just set. */
23
  global $user; /* Available during the login routine just before wp_login is hooked in. */
24
  /**/
25
+ do_action ("s2member_before_login_redirect");
26
  /**/
27
+ $uzer = new WP_User ($user->ID); /* Now lets get a user object to check Capabilities. */
28
+ /**/
29
+ if (!$uzer->has_cap ("edit_posts")) /* In other words, all Subscribers & Members. */
30
  {
31
+ do_action ("s2member_during_login_redirect");
32
+ /**/
33
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"])
34
  wp_redirect ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"]);
35
  /**/
39
  exit;
40
  }
41
  /**/
42
+ do_action ("s2member_after_login_redirect");
43
+ /**/
44
  return;
45
  }
46
  ?>
includes/functions/max-download-period.inc.php DELETED
@@ -1,44 +0,0 @@
1
- <?php
2
- /*
3
- Copyright: © 2009 WebSharks, Inc. ( coded in the USA )
4
- <mailto:support@websharks-inc.com> <http://www.websharks-inc.com/>
5
-
6
- Released under the terms of the GNU General Public License.
7
- You should have received a copy of the GNU General Public License,
8
- along with this software. In the main directory, see: /licensing/
9
- If not, see: <http://www.gnu.org/licenses/>.
10
- */
11
- /*
12
- Direct access denial.
13
- */
14
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
- exit;
16
- /*
17
- Function determines the maximum period in days for download access.
18
- Returns number of days, where 0 means no access to files has been allowed.
19
- */
20
- function ws_plugin__s2member_maximum_download_period ()
21
- {
22
- if ($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed_days"])
23
- {
24
- $maximum = ($maximum < $days) ? $days : $maximum;
25
- }
26
- /**/
27
- if ($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed_days"])
28
- {
29
- $maximum = ($maximum < $days) ? $days : $maximum;
30
- }
31
- /**/
32
- if ($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed_days"])
33
- {
34
- $maximum = ($maximum < $days) ? $days : $maximum;
35
- }
36
- /**/
37
- if ($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed_days"])
38
- {
39
- $maximum = ($maximum < $days) ? $days : $maximum;
40
- }
41
- /**/
42
- return ($maximum > 365) ? 365 : (int)$maximum;
43
- }
44
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/functions/menu-pages.inc.php CHANGED
@@ -18,6 +18,8 @@ Function for saving all options from any page.
18
  */
19
  function ws_plugin__s2member_update_all_options ()
20
  {
 
 
21
  if (($nonce = $_POST["ws_plugin__s2member_options_save"]) && wp_verify_nonce ($nonce, "ws-plugin--s2member-options-save"))
22
  {
23
  $options = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]; /* Get current options. */
@@ -46,9 +48,14 @@ function ws_plugin__s2member_update_all_options ()
46
  /**/
47
  update_option ("ws_plugin__s2member_options", $options) . update_option ("ws_plugin__s2member_cache", array ());
48
  /**/
 
 
 
49
  ws_plugin__s2member_display_admin_notice ('<strong>Options saved.</strong>'); /* Display admin notice. */
50
  }
51
  /**/
 
 
52
  return;
53
  }
54
  /*
@@ -57,6 +64,8 @@ Attach to: add_action("admin_menu");
57
  */
58
  function ws_plugin__s2member_add_admin_options ()
59
  {
 
 
60
  add_filter ("plugin_action_links", "_ws_plugin__s2member_add_settings_link", 10, 2);
61
  /**/
62
  add_menu_page ("s2Member Options", "s2Member", "edit_plugins", "ws-plugin--s2member-start", "ws_plugin__s2member_start_page");
@@ -71,6 +80,8 @@ function ws_plugin__s2member_add_admin_options ()
71
  add_submenu_page ("ws-plugin--s2member-start", "s2Member API / Scripting", "API / Scripting", "edit_plugins", "ws-plugin--s2member-scripting", "ws_plugin__s2member_scripting_page");
72
  add_submenu_page ("ws-plugin--s2member-start", "s2Member Information", "s2Member Info", "edit_plugins", "ws-plugin--s2member-info", "ws_plugin__s2member_info_page");
73
  /**/
 
 
74
  return;
75
  }
76
  /*
@@ -78,13 +89,17 @@ A sort of callback function to add the settings link.
78
  */
79
  function _ws_plugin__s2member_add_settings_link ($links = array (), $file = "")
80
  {
 
 
81
  if (preg_match ("/" . preg_quote ($file, "/") . "$/", $GLOBALS["WS_PLUGIN__"]["s2member"]["l"]) && is_array ($links))
82
  {
83
  $settings = '<a href="admin.php?page=ws-plugin--s2member-options">Settings</a>';
84
- array_unshift ($links, $settings);
 
 
85
  }
86
  /**/
87
- return $links;
88
  }
89
  /*
90
  Add scripts to admin panels.
@@ -92,14 +107,20 @@ Attach to: add_action("admin_print_scripts");
92
  */
93
  function ws_plugin__s2member_add_admin_scripts ()
94
  {
 
 
95
  if ($_GET["page"] && preg_match ("/ws-plugin--s2member-/", $_GET["page"]))
96
  {
97
  wp_enqueue_script ("jquery");
98
  wp_enqueue_script ("thickbox");
99
  wp_enqueue_script ("media-upload");
100
  wp_enqueue_script ("ws-plugin--s2member-menu-pages", get_bloginfo ("url") . "/?ws_plugin__s2member_menu_pages_js=1", array ("jquery", "thickbox", "media-upload"), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["options_version"] . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["filemtime"]);
 
 
101
  }
102
  /**/
 
 
103
  return;
104
  }
105
  /*
@@ -108,12 +129,18 @@ Attach to: add_action("admin_print_styles");
108
  */
109
  function ws_plugin__s2member_add_admin_styles ()
110
  {
 
 
111
  if ($_GET["page"] && preg_match ("/ws-plugin--s2member-/", $_GET["page"]))
112
  {
113
  wp_enqueue_style ("thickbox");
114
  wp_enqueue_style ("ws-plugin--s2member-menu-pages", get_bloginfo ("url") . "/?ws_plugin__s2member_menu_pages_css=1", array ("thickbox"), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["options_version"] . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["filemtime"], "all");
 
 
115
  }
116
  /**/
 
 
117
  return;
118
  }
119
  /*
@@ -122,6 +149,8 @@ Attach to: add_action("init");
122
  */
123
  function ws_plugin__s2member_menu_pages_js ()
124
  {
 
 
125
  if ($_GET["ws_plugin__s2member_menu_pages_js"] && is_user_logged_in () && current_user_can ("edit_plugins"))
126
  {
127
  header ("Content-Type: text/javascript; charset=utf-8");
@@ -135,8 +164,12 @@ function ws_plugin__s2member_menu_pages_js ()
135
  /**/
136
  include_once dirname (dirname (__FILE__)) . "/menu-pages/menu-pages.js";
137
  /**/
 
 
138
  exit;
139
  }
 
 
140
  }
141
  /*
142
  Function that outputs the CSS for menu pages.
@@ -144,6 +177,8 @@ Attach to: add_action("init");
144
  */
145
  function ws_plugin__s2member_menu_pages_css ()
146
  {
 
 
147
  if ($_GET["ws_plugin__s2member_menu_pages_css"] && is_user_logged_in () && current_user_can ("edit_plugins"))
148
  {
149
  header ("Content-Type: text/css; charset=utf-8");
@@ -157,16 +192,24 @@ function ws_plugin__s2member_menu_pages_css ()
157
  /**/
158
  include_once dirname (dirname (__FILE__)) . "/menu-pages/menu-pages.css";
159
  /**/
 
 
160
  exit;
161
  }
 
 
162
  }
163
  /*
164
  Function for building and handling the Quick Start page.
165
  */
166
  function ws_plugin__s2member_start_page ()
167
  {
 
 
168
  include_once dirname (dirname (__FILE__)) . "/menu-pages/start.inc.php";
169
  /**/
 
 
170
  return;
171
  }
172
  /*
@@ -174,10 +217,14 @@ Function for building and handling the General Options page.
174
  */
175
  function ws_plugin__s2member_options_page ()
176
  {
 
 
177
  ws_plugin__s2member_update_all_options ();
178
  /**/
179
  include_once dirname (dirname (__FILE__)) . "/menu-pages/options.inc.php";
180
  /**/
 
 
181
  return;
182
  }
183
  /*
@@ -185,6 +232,8 @@ Function for building and handling the Paypal Options page.
185
  */
186
  function ws_plugin__s2member_paypal_ops_page ()
187
  {
 
 
188
  ws_plugin__s2member_update_all_options ();
189
  /**/
190
  $logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"];
@@ -214,6 +263,8 @@ function ws_plugin__s2member_paypal_ops_page ()
214
  /**/
215
  include_once dirname (dirname (__FILE__)) . "/menu-pages/paypal-ops.inc.php";
216
  /**/
 
 
217
  return;
218
  }
219
  /*
@@ -221,6 +272,8 @@ Function for building and handling the Download Options page.
221
  */
222
  function ws_plugin__s2member_down_ops_page ()
223
  {
 
 
224
  ws_plugin__s2member_update_all_options ();
225
  /**/
226
  $files_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"];
@@ -244,6 +297,8 @@ function ws_plugin__s2member_down_ops_page ()
244
  /**/
245
  include_once dirname (dirname (__FILE__)) . "/menu-pages/down-ops.inc.php";
246
  /**/
 
 
247
  return;
248
  }
249
  /*
@@ -251,10 +306,14 @@ Function for building and handling the API Tracking options page.
251
  */
252
  function ws_plugin__s2member_trk_ops_page ()
253
  {
 
 
254
  ws_plugin__s2member_update_all_options ();
255
  /**/
256
  include_once dirname (dirname (__FILE__)) . "/menu-pages/trk-ops.inc.php";
257
  /**/
 
 
258
  return;
259
  }
260
  /*
@@ -262,10 +321,14 @@ Function for building and handling the API List Server options page.
262
  */
263
  function ws_plugin__s2member_els_ops_page ()
264
  {
 
 
265
  ws_plugin__s2member_update_all_options ();
266
  /**/
267
  include_once dirname (dirname (__FILE__)) . "/menu-pages/els-ops.inc.php";
268
  /**/
 
 
269
  return;
270
  }
271
  /*
@@ -273,10 +336,14 @@ Function for building and handling the API Notifications page.
273
  */
274
  function ws_plugin__s2member_api_ops_page ()
275
  {
 
 
276
  ws_plugin__s2member_update_all_options ();
277
  /**/
278
  include_once dirname (dirname (__FILE__)) . "/menu-pages/api-ops.inc.php";
279
  /**/
 
 
280
  return;
281
  }
282
  /*
@@ -284,8 +351,12 @@ Function for building the PayPal Button Generator page.
284
  */
285
  function ws_plugin__s2member_buttons_page ()
286
  {
 
 
287
  include_once dirname (dirname (__FILE__)) . "/menu-pages/buttons.inc.php";
288
  /**/
 
 
289
  return;
290
  }
291
  /*
@@ -293,8 +364,12 @@ Function for building the API Scripting page.
293
  */
294
  function ws_plugin__s2member_scripting_page ()
295
  {
 
 
296
  include_once dirname (dirname (__FILE__)) . "/menu-pages/scripting.inc.php";
297
  /**/
 
 
298
  return;
299
  }
300
  /*
@@ -302,8 +377,12 @@ Function for building the s2Member Info page.
302
  */
303
  function ws_plugin__s2member_info_page ()
304
  {
 
 
305
  include_once dirname (dirname (__FILE__)) . "/menu-pages/info.inc.php";
306
  /**/
 
 
307
  return;
308
  }
309
  ?>
18
  */
19
  function ws_plugin__s2member_update_all_options ()
20
  {
21
+ do_action ("s2member_before_update_all_options");
22
+ /**/
23
  if (($nonce = $_POST["ws_plugin__s2member_options_save"]) && wp_verify_nonce ($nonce, "ws-plugin--s2member-options-save"))
24
  {
25
  $options = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]; /* Get current options. */
48
  /**/
49
  update_option ("ws_plugin__s2member_options", $options) . update_option ("ws_plugin__s2member_cache", array ());
50
  /**/
51
+ do_action ("s2member_during_update_all_options"); /* Purposely after the update. */
52
+ /* If you need to save custom options, please save them into a separate option key of your own. */
53
+ /**/
54
  ws_plugin__s2member_display_admin_notice ('<strong>Options saved.</strong>'); /* Display admin notice. */
55
  }
56
  /**/
57
+ do_action ("s2member_after_update_all_options");
58
+ /**/
59
  return;
60
  }
61
  /*
64
  */
65
  function ws_plugin__s2member_add_admin_options ()
66
  {
67
+ do_action ("s2member_before_add_admin_options");
68
+ /**/
69
  add_filter ("plugin_action_links", "_ws_plugin__s2member_add_settings_link", 10, 2);
70
  /**/
71
  add_menu_page ("s2Member Options", "s2Member", "edit_plugins", "ws-plugin--s2member-start", "ws_plugin__s2member_start_page");
80
  add_submenu_page ("ws-plugin--s2member-start", "s2Member API / Scripting", "API / Scripting", "edit_plugins", "ws-plugin--s2member-scripting", "ws_plugin__s2member_scripting_page");
81
  add_submenu_page ("ws-plugin--s2member-start", "s2Member Information", "s2Member Info", "edit_plugins", "ws-plugin--s2member-info", "ws_plugin__s2member_info_page");
82
  /**/
83
+ do_action ("s2member_after_add_admin_options");
84
+ /**/
85
  return;
86
  }
87
  /*
89
  */
90
  function _ws_plugin__s2member_add_settings_link ($links = array (), $file = "")
91
  {
92
+ do_action ("s2member_before_add_settings_link");
93
+ /**/
94
  if (preg_match ("/" . preg_quote ($file, "/") . "$/", $GLOBALS["WS_PLUGIN__"]["s2member"]["l"]) && is_array ($links))
95
  {
96
  $settings = '<a href="admin.php?page=ws-plugin--s2member-options">Settings</a>';
97
+ array_unshift ($links, apply_filters ("s2member_add_settings_link", $settings));
98
+ /**/
99
+ do_action ("s2member_during_add_settings_link");
100
  }
101
  /**/
102
+ return apply_filters ("s2member_add_settings_link", $links);
103
  }
104
  /*
105
  Add scripts to admin panels.
107
  */
108
  function ws_plugin__s2member_add_admin_scripts ()
109
  {
110
+ do_action ("s2member_before_add_admin_scripts");
111
+ /**/
112
  if ($_GET["page"] && preg_match ("/ws-plugin--s2member-/", $_GET["page"]))
113
  {
114
  wp_enqueue_script ("jquery");
115
  wp_enqueue_script ("thickbox");
116
  wp_enqueue_script ("media-upload");
117
  wp_enqueue_script ("ws-plugin--s2member-menu-pages", get_bloginfo ("url") . "/?ws_plugin__s2member_menu_pages_js=1", array ("jquery", "thickbox", "media-upload"), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["options_version"] . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["filemtime"]);
118
+ /**/
119
+ do_action ("s2member_during_add_admin_scripts");
120
  }
121
  /**/
122
+ do_action ("s2member_after_add_admin_scripts");
123
+ /**/
124
  return;
125
  }
126
  /*
129
  */
130
  function ws_plugin__s2member_add_admin_styles ()
131
  {
132
+ do_action ("s2member_before_add_admin_styles");
133
+ /**/
134
  if ($_GET["page"] && preg_match ("/ws-plugin--s2member-/", $_GET["page"]))
135
  {
136
  wp_enqueue_style ("thickbox");
137
  wp_enqueue_style ("ws-plugin--s2member-menu-pages", get_bloginfo ("url") . "/?ws_plugin__s2member_menu_pages_css=1", array ("thickbox"), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["options_version"] . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["filemtime"], "all");
138
+ /**/
139
+ do_action ("s2member_during_add_admin_styles");
140
  }
141
  /**/
142
+ do_action ("s2member_after_add_admin_styles");
143
+ /**/
144
  return;
145
  }
146
  /*
149
  */
150
  function ws_plugin__s2member_menu_pages_js ()
151
  {
152
+ do_action ("s2member_before_menu_pages_js");
153
+ /**/
154
  if ($_GET["ws_plugin__s2member_menu_pages_js"] && is_user_logged_in () && current_user_can ("edit_plugins"))
155
  {
156
  header ("Content-Type: text/javascript; charset=utf-8");
164
  /**/
165
  include_once dirname (dirname (__FILE__)) . "/menu-pages/menu-pages.js";
166
  /**/
167
+ do_action ("s2member_during_menu_pages_js");
168
+ /**/
169
  exit;
170
  }
171
+ /**/
172
+ do_action ("s2member_after_menu_pages_js");
173
  }
174
  /*
175
  Function that outputs the CSS for menu pages.
177
  */
178
  function ws_plugin__s2member_menu_pages_css ()
179
  {
180
+ do_action ("s2member_before_menu_pages_css");
181
+ /**/
182
  if ($_GET["ws_plugin__s2member_menu_pages_css"] && is_user_logged_in () && current_user_can ("edit_plugins"))
183
  {
184
  header ("Content-Type: text/css; charset=utf-8");
192
  /**/
193
  include_once dirname (dirname (__FILE__)) . "/menu-pages/menu-pages.css";
194
  /**/
195
+ do_action ("s2member_during_menu_pages_css");
196
+ /**/
197
  exit;
198
  }
199
+ /**/
200
+ do_action ("s2member_after_menu_pages_css");
201
  }
202
  /*
203
  Function for building and handling the Quick Start page.
204
  */
205
  function ws_plugin__s2member_start_page ()
206
  {
207
+ do_action ("s2member_before_start_page");
208
+ /**/
209
  include_once dirname (dirname (__FILE__)) . "/menu-pages/start.inc.php";
210
  /**/
211
+ do_action ("s2member_after_start_page");
212
+ /**/
213
  return;
214
  }
215
  /*
217
  */
218
  function ws_plugin__s2member_options_page ()
219
  {
220
+ do_action ("s2member_before_options_page");
221
+ /**/
222
  ws_plugin__s2member_update_all_options ();
223
  /**/
224
  include_once dirname (dirname (__FILE__)) . "/menu-pages/options.inc.php";
225
  /**/
226
+ do_action ("s2member_after_options_page");
227
+ /**/
228
  return;
229
  }
230
  /*
232
  */
233
  function ws_plugin__s2member_paypal_ops_page ()
234
  {
235
+ do_action ("s2member_before_paypal_ops_page");
236
+ /**/
237
  ws_plugin__s2member_update_all_options ();
238
  /**/
239
  $logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"];
263
  /**/
264
  include_once dirname (dirname (__FILE__)) . "/menu-pages/paypal-ops.inc.php";
265
  /**/
266
+ do_action ("s2member_after_paypal_ops_page");
267
+ /**/
268
  return;
269
  }
270
  /*
272
  */
273
  function ws_plugin__s2member_down_ops_page ()
274
  {
275
+ do_action ("s2member_before_down_ops_page");
276
+ /**/
277
  ws_plugin__s2member_update_all_options ();
278
  /**/
279
  $files_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"];
297
  /**/
298
  include_once dirname (dirname (__FILE__)) . "/menu-pages/down-ops.inc.php";
299
  /**/
300
+ do_action ("s2member_after_down_ops_page");
301
+ /**/
302
  return;
303
  }
304
  /*
306
  */
307
  function ws_plugin__s2member_trk_ops_page ()
308
  {
309
+ do_action ("s2member_before_trk_ops_page");
310
+ /**/
311
  ws_plugin__s2member_update_all_options ();
312
  /**/
313
  include_once dirname (dirname (__FILE__)) . "/menu-pages/trk-ops.inc.php";
314
  /**/
315
+ do_action ("s2member_after_trk_ops_page");
316
+ /**/
317
  return;
318
  }
319
  /*
321
  */
322
  function ws_plugin__s2member_els_ops_page ()
323
  {
324
+ do_action ("s2member_before_els_ops_page");
325
+ /**/
326
  ws_plugin__s2member_update_all_options ();
327
  /**/
328
  include_once dirname (dirname (__FILE__)) . "/menu-pages/els-ops.inc.php";
329
  /**/
330
+ do_action ("s2member_after_els_ops_page");
331
+ /**/
332
  return;
333
  }
334
  /*
336
  */
337
  function ws_plugin__s2member_api_ops_page ()
338
  {
339
+ do_action ("s2member_before_api_ops_page");
340
+ /**/
341
  ws_plugin__s2member_update_all_options ();
342
  /**/
343
  include_once dirname (dirname (__FILE__)) . "/menu-pages/api-ops.inc.php";
344
  /**/
345
+ do_action ("s2member_after_api_ops_page");
346
+ /**/
347
  return;
348
  }
349
  /*
351
  */
352
  function ws_plugin__s2member_buttons_page ()
353
  {
354
+ do_action ("s2member_before_buttons_page");
355
+ /**/
356
  include_once dirname (dirname (__FILE__)) . "/menu-pages/buttons.inc.php";
357
  /**/
358
+ do_action ("s2member_after_buttons_page");
359
+ /**/
360
  return;
361
  }
362
  /*
364
  */
365
  function ws_plugin__s2member_scripting_page ()
366
  {
367
+ do_action ("s2member_before_scripting_page");
368
+ /**/
369
  include_once dirname (dirname (__FILE__)) . "/menu-pages/scripting.inc.php";
370
  /**/
371
+ do_action ("s2member_after_scripting_page");
372
+ /**/
373
  return;
374
  }
375
  /*
377
  */
378
  function ws_plugin__s2member_info_page ()
379
  {
380
+ do_action ("s2member_before_info_page");
381
+ /**/
382
  include_once dirname (dirname (__FILE__)) . "/menu-pages/info.inc.php";
383
  /**/
384
+ do_action ("s2member_after_info_page");
385
+ /**/
386
  return;
387
  }
388
  ?>
includes/functions/min-level-4-downloads.inc.php DELETED
@@ -1,41 +0,0 @@
1
- <?php
2
- /*
3
- Copyright: © 2009 WebSharks, Inc. ( coded in the USA )
4
- <mailto:support@websharks-inc.com> <http://www.websharks-inc.com/>
5
-
6
- Released under the terms of the GNU General Public License.
7
- You should have received a copy of the GNU General Public License,
8
- along with this software. In the main directory, see: /licensing/
9
- If not, see: <http://www.gnu.org/licenses/>.
10
- */
11
- /*
12
- Direct access denial.
13
- */
14
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
- exit;
16
- /*
17
- Function determines the minimum level required for file download access.
18
- Returns 0-4, where 0 means no access to file downloads has been allowed.
19
- */
20
- function ws_plugin__s2member_min_level_4_downloads ()
21
- {
22
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed_days"])
23
- {
24
- $file_download_access_is_allowed = $minimum_level_required_to_download_files = 1;
25
- }
26
- else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed_days"])
27
- {
28
- $file_download_access_is_allowed = $minimum_level_required_to_download_files = 2;
29
- }
30
- else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed_days"])
31
- {
32
- $file_download_access_is_allowed = $minimum_level_required_to_download_files = 3;
33
- }
34
- else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed_days"])
35
- {
36
- $file_download_access_is_allowed = $minimum_level_required_to_download_files = 4;
37
- }
38
- /**/
39
- return (int)$minimum_level_required_to_download_files;
40
- }
41
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/functions/nocache.inc.php CHANGED
@@ -20,8 +20,12 @@ Attach to: add_action("init");
20
  */
21
  function ws_plugin__s2member_nocache ()
22
  {
 
 
23
  ws_plugin__s2member_nocache_constants () . ws_plugin__s2member_nocache_headers ();
24
  /**/
 
 
25
  return;
26
  }
27
  /*
@@ -49,11 +53,17 @@ These additional supplemental routines, include:
49
  */
50
  function ws_plugin__s2member_nocache_constants ($nocache = FALSE) /* Always obey the Quick Cache plugin. */
51
  {
 
 
52
  if (!$_GET["qcAC"] && ($nocache || is_user_logged_in () || (preg_match ("/^s2member/", $_SERVER["QUERY_STRING"]) && ($_SERVER["REQUEST_URI"] === "/" || strtolower (rtrim (get_bloginfo ("url"), "/")) === rtrim (strtolower ("http://" . $_SERVER["HTTP_HOST"]) . $_SERVER["REQUEST_URI"], "/")))))
53
  {
54
  define ("QUICK_CACHE_ALLOWED", false) . define ("DONOTCACHEPAGE", true);
 
 
55
  }
56
  /**/
 
 
57
  return;
58
  }
59
  /*
@@ -64,6 +74,8 @@ This is compatible with the Quick Cache parameter ?qcABC=1 as well.
64
  */
65
  function ws_plugin__s2member_nocache_headers () /* Cache-Control header. */
66
  {
 
 
67
  if (!$_GET["qcABC"]) /* Always obey the Quick Cache plugin. */
68
  {
69
  if (is_array ($headers = headers_list ()))
@@ -73,8 +85,12 @@ function ws_plugin__s2member_nocache_headers () /* Cache-Control header. */
73
  /**/
74
  if (!$no_cache_already_sent)
75
  nocache_headers ();
 
 
76
  }
77
  /**/
 
 
78
  return;
79
  }
80
  ?>
20
  */
21
  function ws_plugin__s2member_nocache ()
22
  {
23
+ do_action ("s2member_before_nocache");
24
+ /**/
25
  ws_plugin__s2member_nocache_constants () . ws_plugin__s2member_nocache_headers ();
26
  /**/
27
+ do_action ("s2member_after_nocache");
28
+ /**/
29
  return;
30
  }
31
  /*
53
  */
54
  function ws_plugin__s2member_nocache_constants ($nocache = FALSE) /* Always obey the Quick Cache plugin. */
55
  {
56
+ do_action ("s2member_before_nocache_constants");
57
+ /**/
58
  if (!$_GET["qcAC"] && ($nocache || is_user_logged_in () || (preg_match ("/^s2member/", $_SERVER["QUERY_STRING"]) && ($_SERVER["REQUEST_URI"] === "/" || strtolower (rtrim (get_bloginfo ("url"), "/")) === rtrim (strtolower ("http://" . $_SERVER["HTTP_HOST"]) . $_SERVER["REQUEST_URI"], "/")))))
59
  {
60
  define ("QUICK_CACHE_ALLOWED", false) . define ("DONOTCACHEPAGE", true);
61
+ /**/
62
+ do_action ("s2member_during_nocache_constants");
63
  }
64
  /**/
65
+ do_action ("s2member_after_nocache_constants");
66
+ /**/
67
  return;
68
  }
69
  /*
74
  */
75
  function ws_plugin__s2member_nocache_headers () /* Cache-Control header. */
76
  {
77
+ do_action ("s2member_before_nocache_headers");
78
+ /**/
79
  if (!$_GET["qcABC"]) /* Always obey the Quick Cache plugin. */
80
  {
81
  if (is_array ($headers = headers_list ()))
85
  /**/
86
  if (!$no_cache_already_sent)
87
  nocache_headers ();
88
+ /**/
89
+ do_action ("s2member_during_nocache_headers");
90
  }
91
  /**/
92
+ do_action ("s2member_after_nocache_headers");
93
+ /**/
94
  return;
95
  }
96
  ?>
includes/functions/page-level-access.inc.php CHANGED
@@ -21,7 +21,11 @@ function ws_plugin__s2member_check_page_level_access ()
21
  {
22
  global $post; /* get_the_ID() not yet available here. */
23
  /**/
24
- if (is_page () && is_object ($post) && ($page_ID = $post->ID))
 
 
 
 
25
  {
26
  $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false;
27
  /**/
@@ -57,8 +61,12 @@ function ws_plugin__s2member_check_page_level_access ()
57
  /**/
58
  else if (in_array ($page_ID, preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["single_pages"])) && ws_plugin__s2member_nocache_constants () !== "nill" && !ws_plugin__s2member_sp_access ($page_ID) && !ws_plugin__s2member_is_systematic_use_page () && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_sp_req=" . urlencode ($page_ID))) !== "nill")
59
  exit;
 
 
60
  }
61
  /**/
 
 
62
  return;
63
  }
64
  ?>
21
  {
22
  global $post; /* get_the_ID() not yet available here. */
23
  /**/
24
+ do_action ("s2member_before_check_page_level_access");
25
+ /**/
26
+ $excluded = apply_filters ("s2member_check_page_level_access_excluded", false);
27
+ /**/
28
+ if (!$excluded && is_page () && is_object ($post) && ($page_ID = $post->ID))
29
  {
30
  $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false;
31
  /**/
61
  /**/
62
  else if (in_array ($page_ID, preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["single_pages"])) && ws_plugin__s2member_nocache_constants () !== "nill" && !ws_plugin__s2member_sp_access ($page_ID) && !ws_plugin__s2member_is_systematic_use_page () && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_sp_req=" . urlencode ($page_ID))) !== "nill")
63
  exit;
64
+ /**/
65
+ do_action ("s2member_during_check_page_level_access");
66
  }
67
  /**/
68
+ do_action ("s2member_after_check_page_level_access");
69
+ /**/
70
  return;
71
  }
72
  ?>
includes/functions/paypal-notify.inc.php CHANGED
@@ -19,6 +19,8 @@ Attach to: add_action("init");
19
  */
20
  function ws_plugin__s2member_paypal_notify ()
21
  {
 
 
22
  if ($_GET["s2member_paypal_notify"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])
23
  {
24
  global $wpdb; /* Need this global variable as a reference to the database object. */
@@ -34,16 +36,21 @@ function ws_plugin__s2member_paypal_notify ()
34
  /*
35
  Single-Page Access.
36
  */
37
- if (preg_match ("/^web_accept$/i", $paypal["txn_type"]) && $paypal["payer_email"] && $paypal["txn_id"] && preg_match ("/^sp\:[0-9]+$/", $paypal["item_number"]))
38
  {
 
 
39
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept) for Single-Page access.";
40
  /**/
41
- list (, $paypal["page"]) = preg_split ("/\:/", $paypal["item_number"], 2);
42
  /**/
43
- if (($sp_access_url = ws_plugin__s2member_sp_access_link_gen ($paypal["page"])) && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
44
  {
45
  $sbj = preg_replace ("/%%sp_access_url%%/i", $sp_access_url, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["single_page_email_subject"]);
 
 
46
  $msg = preg_replace ("/%%sp_access_url%%/i", $sp_access_url, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["single_page_email_message"]);
 
47
  /**/
48
  if (($sbj = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $sbj)) && ($sbj = preg_replace ("/%%txn_id%%/i", $paypal["txn_id"], $sbj)))
49
  if (($sbj = preg_replace ("/%%amount%%/i", $paypal["mc_gross"], $sbj))) /* Full amount of the payment, before fee is subtracted. */
@@ -71,24 +78,31 @@ function ws_plugin__s2member_paypal_notify ()
71
  foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_notification_urls"]) as $url)
72
  /**/
73
  if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%sp_access_url%%/i", rawurlencode ($sp_access_url), $url)))
74
- if (($url = preg_replace ("/%%amount%%/i", urlencode ($paypal["mc_gross"]), $url)) && ($url = preg_replace ("/%%txn_id%%/i", urlencode ($paypal["txn_id"]), $url)))
75
- if (($url = preg_replace ("/%%item_number%%/i", urlencode ($paypal["item_number"]), $url)) && ($url = preg_replace ("/%%item_name%%/i", urlencode ($paypal["item_name"]), $url)))
76
- if (($url = preg_replace ("/%%first_name%%/i", urlencode ($paypal["first_name"]), $url)) && ($url = preg_replace ("/%%last_name%%/i", urlencode ($paypal["last_name"]), $url)))
77
- if (($url = preg_replace ("/%%full_name%%/i", urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $url)))
78
- if (($url = preg_replace ("/%%payer_email%%/i", urlencode ($paypal["payer_email"]), $url)))
79
- /**/
80
- if (($url = trim ($url))) /* Make sure it is not empty. */
81
- ws_plugin__s2member_curlpsr ($url, "s2member=1");
 
82
  /**/
83
  $paypal["s2member_log"][] = "Payment Notification URLs have been processed.";
84
  }
 
 
85
  }
 
 
86
  }
87
  /*
88
  New subscriptions. Possibly containing advanced updated vars ( option_name1, option_selection1 ); which allow account modifications.
89
  */
90
  else if (preg_match ("/^(web_accept|subscr_signup)$/i", $paypal["txn_type"]) && $paypal["payer_email"] && ($paypal["subscr_id"] || ($paypal["subscr_id"] = $paypal["txn_id"])) && preg_match ("/^[1-4](\:|$)/", $paypal["item_number"]))
91
  {
 
 
92
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup).";
93
  /**/
94
  list ($paypal["level"], $paypal["ccaps"]) = preg_split ("/\:/", $paypal["item_number"], 2);
@@ -99,6 +113,8 @@ function ws_plugin__s2member_paypal_notify ()
99
  /* This advanced method is required whenever a subscription that is already completed, or was never setup to recur in the first place needs to be modified. PayPal will not allow the
100
  modify=1|2 parameter to be used in those scenarios, because technically there is nothing to update. The only thing that actually needs to be updated is their existing account. */
101
  {
 
 
102
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup) w/ update vars.";
103
  /**/
104
  /* Here we need to check for both the old & new s2member_subscr_id's, just in case the Return routine has already changed it. */
@@ -124,6 +140,8 @@ function ws_plugin__s2member_paypal_notify ()
124
  delete_usermeta ($user_id, "s2member_file_download_access_log");
125
  /**/
126
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated w/ advanced update routines.";
 
 
127
  }
128
  else
129
  {
@@ -134,12 +152,16 @@ function ws_plugin__s2member_paypal_notify ()
134
  {
135
  $paypal["s2member_log"][] = "Unable to modify subscription. Could not find existing subscription in the DB. Please check the on0 and os0 variables in your Button Code.";
136
  }
 
 
137
  }
138
  /*
139
  New subscription. Normal subscription signup, we are not updating anything for a past subscription.
140
  */
141
  else /* Else this is a normal subscription signup, we are not updating anything for a past subscription. */
142
  {
 
 
143
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup) w/o update vars.";
144
  /**/
145
  if ($registration_url = ws_plugin__s2member_register_link_gen ($paypal["subscr_id"], $paypal["custom"], $paypal["item_number"]) && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
@@ -181,7 +203,11 @@ function ws_plugin__s2member_paypal_notify ()
181
  /**/
182
  $paypal["s2member_log"][] = "Email sent after signup, with a URL to assist Customer w/ registration.";
183
  }
 
 
184
  }
 
 
185
  }
186
  /**/
187
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
@@ -213,12 +239,16 @@ function ws_plugin__s2member_paypal_notify ()
213
  /**/
214
  $paypal["s2member_log"][] = "Signup Notification URLs have been processed.";
215
  }
 
 
216
  }
217
  /*
218
  Subscription modifications.
219
  */
220
  else if (preg_match ("/^subscr_modify$/i", $paypal["txn_type"]) && $paypal["subscr_id"] && preg_match ("/^[1-4](\:|$)/", $paypal["item_number"]))
221
  {
 
 
222
  $paypal["s2member_log"][] = "s2Member txn_type identified as subscr_modify.";
223
  /**/
224
  list ($paypal["level"], $paypal["ccaps"]) = preg_split ("/\:/", $paypal["item_number"], 2);
@@ -244,6 +274,8 @@ function ws_plugin__s2member_paypal_notify ()
244
  delete_usermeta ($user_id, "s2member_file_download_access_log");
245
  /**/
246
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated on subscription modification.";
 
 
247
  }
248
  else
249
  {
@@ -254,12 +286,16 @@ function ws_plugin__s2member_paypal_notify ()
254
  {
255
  $paypal["s2member_log"][] = "Unable to modify subscription. Could not find existing subscription in the DB.";
256
  }
 
 
257
  }
258
  /*
259
  Subscription payments.
260
  */
261
  else if (preg_match ("/^subscr_payment$/i", $paypal["txn_type"]) && $paypal["payer_email"] && $paypal["subscr_id"] && preg_match ("/^[1-4](\:|$)/", $paypal["item_number"]) && $paypal["txn_id"] && $paypal["mc_gross"])
262
  {
 
 
263
  $paypal["s2member_log"][] = "s2Member txn_type identified as subscr_payment.";
264
  /**/
265
  list ($paypal["level"], $paypal["ccaps"]) = preg_split ("/\:/", $paypal["item_number"], 2);
@@ -280,12 +316,16 @@ function ws_plugin__s2member_paypal_notify ()
280
  /**/
281
  $paypal["s2member_log"][] = "Payment Notification URLs have been processed.";
282
  }
 
 
283
  }
284
  /*
285
  Subscription terminations.
286
  */
287
  else if ((preg_match ("/^subscr_eot$/i", $paypal["txn_type"]) || preg_match ("/^(refunded|reversed)$/i", $paypal["payment_status"])) && ($paypal["subscr_id"] || ($paypal["subscr_id"] = $paypal["parent_txn_id"])) && preg_match ("/^[1-4](\:|$)/", $paypal["item_number"]))
288
  {
 
 
289
  $paypal["s2member_log"][] = "s2Member txn_type identified as subscr_eot - or - payment_status (refunded|reversed).";
290
  /**/
291
  list ($paypal["level"], $paypal["ccaps"]) = preg_split ("/\:/", $paypal["item_number"], 2);
@@ -324,6 +364,8 @@ function ws_plugin__s2member_paypal_notify ()
324
  /**/
325
  $paypal["s2member_log"][] = "EOT/Deletion Notification URLs have been processed.";
326
  }
 
 
327
  }
328
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_eot_behavior"] === "delete")
329
  {
@@ -333,7 +375,11 @@ function ws_plugin__s2member_paypal_notify ()
333
  $paypal["s2member_log"][] = "The Member's account has been deleted completely.";
334
  /**/
335
  $paypal["s2member_log"][] = "EOT/Deletion Notification URLs have been processed.";
 
 
336
  }
 
 
337
  }
338
  else
339
  {
@@ -364,6 +410,8 @@ function ws_plugin__s2member_paypal_notify ()
364
  {
365
  $paypal["s2member_log"][] = "Unable to (demote|delete) Member. Could not find existing subscription in the DB. It's possible that it was already removed manually by a site administrator.";
366
  }
 
 
367
  }
368
  else
369
  {
@@ -388,7 +436,11 @@ function ws_plugin__s2member_paypal_notify ()
388
  if (is_writable ($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
389
  file_put_contents ($logs_dir . "/paypal-ipn.log", var_export ($paypal, true) . "\n\n", FILE_APPEND);
390
  /**/
 
 
391
  exit;
392
  }
 
 
393
  }
394
  ?>
19
  */
20
  function ws_plugin__s2member_paypal_notify ()
21
  {
22
+ do_action ("s2member_before_paypal_notify");
23
+ /**/
24
  if ($_GET["s2member_paypal_notify"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])
25
  {
26
  global $wpdb; /* Need this global variable as a reference to the database object. */
36
  /*
37
  Single-Page Access.
38
  */
39
+ if (preg_match ("/^web_accept$/i", $paypal["txn_type"]) && $paypal["payer_email"] && $paypal["txn_id"] && preg_match ("/^sp\:[0-9]+\:[0-9]+$/", $paypal["item_number"]))
40
  {
41
+ do_action ("s2member_during_paypal_notify_before_sp_access");
42
+ /**/
43
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept) for Single-Page access.";
44
  /**/
45
+ list (, $paypal["page"], $paypal["hours"]) = preg_split ("/\:/", $paypal["item_number"], 3);
46
  /**/
47
+ if (($sp_access_url = ws_plugin__s2member_sp_access_link_gen ($paypal["page"], $paypal["hours"])) && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
48
  {
49
  $sbj = preg_replace ("/%%sp_access_url%%/i", $sp_access_url, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["single_page_email_subject"]);
50
+ $sbj = preg_replace ("/%%sp_access_exp%%/i", human_time_diff (strtotime ("now"), strtotime ("+" . $paypal["hours"] . " hours")), $sbj);
51
+ /**/
52
  $msg = preg_replace ("/%%sp_access_url%%/i", $sp_access_url, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["single_page_email_message"]);
53
+ $msg = preg_replace ("/%%sp_access_exp%%/i", human_time_diff (strtotime ("now"), strtotime ("+" . $paypal["hours"] . " hours")), $msg);
54
  /**/
55
  if (($sbj = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $sbj)) && ($sbj = preg_replace ("/%%txn_id%%/i", $paypal["txn_id"], $sbj)))
56
  if (($sbj = preg_replace ("/%%amount%%/i", $paypal["mc_gross"], $sbj))) /* Full amount of the payment, before fee is subtracted. */
78
  foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_notification_urls"]) as $url)
79
  /**/
80
  if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%sp_access_url%%/i", rawurlencode ($sp_access_url), $url)))
81
+ if (($url = preg_replace ("/%%sp_access_exp%%/i", urlencode (human_time_diff (strtotime ("now"), strtotime ("+" . $paypal["hours"] . " hours"))), $url)))
82
+ if (($url = preg_replace ("/%%amount%%/i", urlencode ($paypal["mc_gross"]), $url)) && ($url = preg_replace ("/%%txn_id%%/i", urlencode ($paypal["txn_id"]), $url)))
83
+ if (($url = preg_replace ("/%%item_number%%/i", urlencode ($paypal["item_number"]), $url)) && ($url = preg_replace ("/%%item_name%%/i", urlencode ($paypal["item_name"]), $url)))
84
+ if (($url = preg_replace ("/%%first_name%%/i", urlencode ($paypal["first_name"]), $url)) && ($url = preg_replace ("/%%last_name%%/i", urlencode ($paypal["last_name"]), $url)))
85
+ if (($url = preg_replace ("/%%full_name%%/i", urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $url)))
86
+ if (($url = preg_replace ("/%%payer_email%%/i", urlencode ($paypal["payer_email"]), $url)))
87
+ /**/
88
+ if (($url = trim ($url))) /* Make sure it is not empty. */
89
+ ws_plugin__s2member_curlpsr ($url, "s2member=1");
90
  /**/
91
  $paypal["s2member_log"][] = "Payment Notification URLs have been processed.";
92
  }
93
+ /**/
94
+ do_action ("s2member_during_paypal_notify_during_sp_access");
95
  }
96
+ /**/
97
+ do_action ("s2member_during_paypal_notify_after_sp_access");
98
  }
99
  /*
100
  New subscriptions. Possibly containing advanced updated vars ( option_name1, option_selection1 ); which allow account modifications.
101
  */
102
  else if (preg_match ("/^(web_accept|subscr_signup)$/i", $paypal["txn_type"]) && $paypal["payer_email"] && ($paypal["subscr_id"] || ($paypal["subscr_id"] = $paypal["txn_id"])) && preg_match ("/^[1-4](\:|$)/", $paypal["item_number"]))
103
  {
104
+ do_action ("s2member_during_paypal_notify_before_subscr_signup");
105
+ /**/
106
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup).";
107
  /**/
108
  list ($paypal["level"], $paypal["ccaps"]) = preg_split ("/\:/", $paypal["item_number"], 2);
113
  /* This advanced method is required whenever a subscription that is already completed, or was never setup to recur in the first place needs to be modified. PayPal will not allow the
114
  modify=1|2 parameter to be used in those scenarios, because technically there is nothing to update. The only thing that actually needs to be updated is their existing account. */
115
  {
116
+ do_action ("s2member_during_paypal_notify_before_subscr_signup_w_update_vars");
117
+ /**/
118
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup) w/ update vars.";
119
  /**/
120
  /* Here we need to check for both the old & new s2member_subscr_id's, just in case the Return routine has already changed it. */
140
  delete_usermeta ($user_id, "s2member_file_download_access_log");
141
  /**/
142
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated w/ advanced update routines.";
143
+ /**/
144
+ do_action ("s2member_during_paypal_notify_during_subscr_signup_w_update_vars");
145
  }
146
  else
147
  {
152
  {
153
  $paypal["s2member_log"][] = "Unable to modify subscription. Could not find existing subscription in the DB. Please check the on0 and os0 variables in your Button Code.";
154
  }
155
+ /**/
156
+ do_action ("s2member_during_paypal_notify_after_subscr_signup_w_update_vars");
157
  }
158
  /*
159
  New subscription. Normal subscription signup, we are not updating anything for a past subscription.
160
  */
161
  else /* Else this is a normal subscription signup, we are not updating anything for a past subscription. */
162
  {
163
+ do_action ("s2member_during_paypal_notify_before_subscr_signup_wo_update_vars");
164
+ /**/
165
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup) w/o update vars.";
166
  /**/
167
  if ($registration_url = ws_plugin__s2member_register_link_gen ($paypal["subscr_id"], $paypal["custom"], $paypal["item_number"]) && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
203
  /**/
204
  $paypal["s2member_log"][] = "Email sent after signup, with a URL to assist Customer w/ registration.";
205
  }
206
+ /**/
207
+ do_action ("s2member_during_paypal_notify_during_subscr_signup_wo_update_vars");
208
  }
209
+ /**/
210
+ do_action ("s2member_during_paypal_notify_after_subscr_signup_wo_update_vars");
211
  }
212
  /**/
213
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
239
  /**/
240
  $paypal["s2member_log"][] = "Signup Notification URLs have been processed.";
241
  }
242
+ /**/
243
+ do_action ("s2member_during_paypal_notify_after_subscr_signup");
244
  }
245
  /*
246
  Subscription modifications.
247
  */
248
  else if (preg_match ("/^subscr_modify$/i", $paypal["txn_type"]) && $paypal["subscr_id"] && preg_match ("/^[1-4](\:|$)/", $paypal["item_number"]))
249
  {
250
+ do_action ("s2member_during_paypal_notify_before_subscr_modify");
251
+ /**/
252
  $paypal["s2member_log"][] = "s2Member txn_type identified as subscr_modify.";
253
  /**/
254
  list ($paypal["level"], $paypal["ccaps"]) = preg_split ("/\:/", $paypal["item_number"], 2);
274
  delete_usermeta ($user_id, "s2member_file_download_access_log");
275
  /**/
276
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated on subscription modification.";
277
+ /**/
278
+ do_action ("s2member_during_paypal_notify_during_subscr_modify");
279
  }
280
  else
281
  {
286
  {
287
  $paypal["s2member_log"][] = "Unable to modify subscription. Could not find existing subscription in the DB.";
288
  }
289
+ /**/
290
+ do_action ("s2member_during_paypal_notify_after_subscr_modify");
291
  }
292
  /*
293
  Subscription payments.
294
  */
295
  else if (preg_match ("/^subscr_payment$/i", $paypal["txn_type"]) && $paypal["payer_email"] && $paypal["subscr_id"] && preg_match ("/^[1-4](\:|$)/", $paypal["item_number"]) && $paypal["txn_id"] && $paypal["mc_gross"])
296
  {
297
+ do_action ("s2member_during_paypal_notify_before_subscr_payment");
298
+ /**/
299
  $paypal["s2member_log"][] = "s2Member txn_type identified as subscr_payment.";
300
  /**/
301
  list ($paypal["level"], $paypal["ccaps"]) = preg_split ("/\:/", $paypal["item_number"], 2);
316
  /**/
317
  $paypal["s2member_log"][] = "Payment Notification URLs have been processed.";
318
  }
319
+ /**/
320
+ do_action ("s2member_during_paypal_notify_after_subscr_payment");
321
  }
322
  /*
323
  Subscription terminations.
324
  */
325
  else if ((preg_match ("/^subscr_eot$/i", $paypal["txn_type"]) || preg_match ("/^(refunded|reversed)$/i", $paypal["payment_status"])) && ($paypal["subscr_id"] || ($paypal["subscr_id"] = $paypal["parent_txn_id"])) && preg_match ("/^[1-4](\:|$)/", $paypal["item_number"]))
326
  {
327
+ do_action ("s2member_during_paypal_notify_before_subscr_eot");
328
+ /**/
329
  $paypal["s2member_log"][] = "s2Member txn_type identified as subscr_eot - or - payment_status (refunded|reversed).";
330
  /**/
331
  list ($paypal["level"], $paypal["ccaps"]) = preg_split ("/\:/", $paypal["item_number"], 2);
364
  /**/
365
  $paypal["s2member_log"][] = "EOT/Deletion Notification URLs have been processed.";
366
  }
367
+ /**/
368
+ do_action ("s2member_during_paypal_notify_during_subscr_eot_demote");
369
  }
370
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_eot_behavior"] === "delete")
371
  {
375
  $paypal["s2member_log"][] = "The Member's account has been deleted completely.";
376
  /**/
377
  $paypal["s2member_log"][] = "EOT/Deletion Notification URLs have been processed.";
378
+ /**/
379
+ do_action ("s2member_during_paypal_notify_during_subscr_eot_delete");
380
  }
381
+ /**/
382
+ do_action ("s2member_during_paypal_notify_during_subscr_eot");
383
  }
384
  else
385
  {
410
  {
411
  $paypal["s2member_log"][] = "Unable to (demote|delete) Member. Could not find existing subscription in the DB. It's possible that it was already removed manually by a site administrator.";
412
  }
413
+ /**/
414
+ do_action ("s2member_during_paypal_notify_after_subscr_eot");
415
  }
416
  else
417
  {
436
  if (is_writable ($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
437
  file_put_contents ($logs_dir . "/paypal-ipn.log", var_export ($paypal, true) . "\n\n", FILE_APPEND);
438
  /**/
439
+ do_action ("s2member_during_paypal_notify");
440
+ /**/
441
  exit;
442
  }
443
+ /**/
444
+ do_action ("s2member_after_paypal_notify");
445
  }
446
  ?>
includes/functions/paypal-postvars.inc.php CHANGED
@@ -18,6 +18,8 @@ Get post vars from paypal, verify and return array.
18
  */
19
  function ws_plugin__s2member_paypal_postvars ()
20
  {
 
 
21
  if ($_GET["tx"]) /* PDT with Auto-Return. */
22
  {
23
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_identity_token"])
@@ -38,7 +40,7 @@ function ws_plugin__s2member_paypal_postvars ()
38
  $postvars[$key] = trim (stripslashes (urldecode ($value)));
39
  }
40
  /**/
41
- return $postvars;
42
  }
43
  }
44
  /**/
@@ -58,7 +60,7 @@ function ws_plugin__s2member_paypal_postvars ()
58
  /**/
59
  if (strtolower (trim (ws_plugin__s2member_curlpsr ("https://" . $endpoint . "/cgi-bin/webscr", $postback))) === "verified")
60
  {
61
- return $postvars;
62
  }
63
  /**/
64
  return false;
18
  */
19
  function ws_plugin__s2member_paypal_postvars ()
20
  {
21
+ do_action ("s2member_before_paypal_postvars");
22
+ /**/
23
  if ($_GET["tx"]) /* PDT with Auto-Return. */
24
  {
25
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_identity_token"])
40
  $postvars[$key] = trim (stripslashes (urldecode ($value)));
41
  }
42
  /**/
43
+ return apply_filters ("s2member_paypal_postvars", $postvars);
44
  }
45
  }
46
  /**/
60
  /**/
61
  if (strtolower (trim (ws_plugin__s2member_curlpsr ("https://" . $endpoint . "/cgi-bin/webscr", $postback))) === "verified")
62
  {
63
+ return apply_filters ("s2member_paypal_postvars", $postvars);
64
  }
65
  /**/
66
  return false;
includes/functions/paypal-return.inc.php CHANGED
@@ -19,6 +19,8 @@ Attach to: add_action("init");
19
  */
20
  function ws_plugin__s2member_paypal_return ()
21
  {
 
 
22
  /* Note: Auto-Return with PDT does not send anything when subscriptions are modified.
23
  Therefore, we need to be sure that we always send a thank you message here by default,
24
  and then we'll just leave the rest of the modification up to the IPN handler instead. */
@@ -37,14 +39,18 @@ function ws_plugin__s2member_paypal_return ()
37
  /*
38
  Single-Page Access.
39
  */
40
- if (preg_match ("/^web_accept$/i", $paypal["txn_type"]) && $paypal["txn_id"] && preg_match ("/^sp\:[0-9]+$/", $paypal["item_number"]))
41
  {
 
 
42
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept) for Single-Page access.";
43
  /**/
44
- list (, $paypal["page"]) = preg_split ("/\:/", $paypal["item_number"], 2);
45
  /**/
46
- if (($sp_access_url = ws_plugin__s2member_sp_access_link_gen ($paypal["page"], false)))
47
  {
 
 
48
  header ("Location: " . $sp_access_url);
49
  }
50
  else /* Otherwise, the page ID must have been invalid. Or it's possible that the Page was deleted. */
@@ -58,6 +64,8 @@ function ws_plugin__s2member_paypal_return ()
58
  /**/
59
  $paypal["s2member_log"][] = "Redirecting Customer to the Home Page, due to an error that occurred.";
60
  }
 
 
61
  }
62
  /*
63
  New subscriptions. Possibly containing advanced updated vars ( option_name1, option_selection1 ); which allow account modifications.
@@ -65,6 +73,9 @@ function ws_plugin__s2member_paypal_return ()
65
  else if (preg_match ("/^(web_accept|subscr_signup|subscr_payment)$/i", $paypal["txn_type"]) && ($paypal["subscr_id"] || ($paypal["subscr_id"] = $paypal["txn_id"])) && preg_match ("/^[1-4](\:|$)/", $paypal["item_number"]))
66
  { /* With Auto-Return/PDT, PayPal will send subscr_payment instead of subscr_signup to the return URL.
67
  So we need to look for (web_accept|subscr_signup|subscr_payment), and treat them as the same. */
 
 
 
68
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup|subscr_payment).";
69
  /**/
70
  list ($paypal["level"], $paypal["ccaps"]) = preg_split ("/\:/", $paypal["item_number"], 2);
@@ -75,6 +86,8 @@ function ws_plugin__s2member_paypal_return ()
75
  /* This advanced method is required whenever a subscription that is already completed, or was never setup to recur in the first place needs to be modified. PayPal® will not allow the
76
  modify=2 parameter to be used in those scenarios, because technically there is nothing to update. The only thing to be updated is the existing account. */
77
  {
 
 
78
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup|subscr_payment) w/ update vars.";
79
  /**/
80
  /* Here we need to check for both the old & new s2member_subscr_id's, just in case the IPN routine has already changed it. */
@@ -101,6 +114,8 @@ function ws_plugin__s2member_paypal_return ()
101
  /**/
102
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated w/ advanced update routines.";
103
  /**/
 
 
104
  echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
105
  echo '<html xmlns="http://www.w3.org/1999/xhtml" ', language_attributes (), '>' . "\n";
106
  echo '<head profile="http://gmpg.org/xfn/11">' . "\n";
@@ -175,12 +190,16 @@ function ws_plugin__s2member_paypal_return ()
175
  /**/
176
  $paypal["s2member_log"][] = "Redirecting Customer to the Login Page, due to an error that occurred.";
177
  }
 
 
178
  }
179
  /*
180
  New subscription. Normal subscription signup, we are not updating anything for a past subscription.
181
  */
182
  else /* Else this is a normal subscription signup, we are not updating anything for a past subscription. */
183
  {
 
 
184
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup|subscr_payment) w/o update vars.";
185
  /**/
186
  setcookie ("s2member_subscr_id", $paypal["subscr_id"], time () + 31556926, "/");
@@ -189,6 +208,8 @@ function ws_plugin__s2member_paypal_return ()
189
  /**/
190
  $paypal["s2member_log"][] = "s2Member cookies set on (web_accept|subscr_signup|subscr_payment) w/o update vars.";
191
  /**/
 
 
192
  echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
193
  echo '<html xmlns="http://www.w3.org/1999/xhtml" ', language_attributes (), '>' . "\n";
194
  echo '<head profile="http://gmpg.org/xfn/11">' . "\n";
@@ -239,13 +260,19 @@ function ws_plugin__s2member_paypal_return ()
239
  /**/
240
  echo '</body>' . "\n";
241
  echo '</html>';
 
 
242
  }
 
 
243
  }
244
  /*
245
  Subscription modifications.
246
  */
247
  else if (preg_match ("/^subscr_modify$/i", $paypal["txn_type"]) && $paypal["subscr_id"] && preg_match ("/^[1-4](\:|$)/", $paypal["item_number"]))
248
  {
 
 
249
  $paypal["s2member_log"][] = "s2Member txn_type identified as subscr_modify.";
250
  /**/
251
  list ($paypal["level"], $paypal["ccaps"]) = preg_split ("/\:/", $paypal["item_number"], 2);
@@ -272,6 +299,8 @@ function ws_plugin__s2member_paypal_return ()
272
  /**/
273
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated on subscription modification.";
274
  /**/
 
 
275
  echo '<script type="text/javascript">' . "\n";
276
  echo "alert('Thank You! Your membership has been updated to:\\n\\n" . esc_js ($paypal["item_name"]) . "\\n\\nYou\\'ll need to log back in now.');" . "\n";
277
  echo "window.location = '" . esc_js (wp_login_url ()) . "';";
@@ -302,6 +331,8 @@ function ws_plugin__s2member_paypal_return ()
302
  /**/
303
  $paypal["s2member_log"][] = "Redirecting Customer to the Login Page, due to an error that occurred.";
304
  }
 
 
305
  }
306
  else
307
  {
@@ -347,7 +378,11 @@ function ws_plugin__s2member_paypal_return ()
347
  if (is_writable ($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
348
  file_put_contents ($logs_dir . "/paypal-rtn.log", var_export ($paypal, true) . "\n\n", FILE_APPEND);
349
  /**/
 
 
350
  exit;
351
  }
 
 
352
  }
353
  ?>
19
  */
20
  function ws_plugin__s2member_paypal_return ()
21
  {
22
+ do_action ("s2member_before_paypal_return");
23
+ /**/
24
  /* Note: Auto-Return with PDT does not send anything when subscriptions are modified.
25
  Therefore, we need to be sure that we always send a thank you message here by default,
26
  and then we'll just leave the rest of the modification up to the IPN handler instead. */
39
  /*
40
  Single-Page Access.
41
  */
42
+ if (preg_match ("/^web_accept$/i", $paypal["txn_type"]) && $paypal["txn_id"] && preg_match ("/^sp\:[0-9]+\:[0-9]+$/", $paypal["item_number"]))
43
  {
44
+ do_action ("s2member_during_paypal_return_before_sp_access");
45
+ /**/
46
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept) for Single-Page access.";
47
  /**/
48
+ list (, $paypal["page"], $paypal["hours"]) = preg_split ("/\:/", $paypal["item_number"], 3);
49
  /**/
50
+ if (($sp_access_url = ws_plugin__s2member_sp_access_link_gen ($paypal["page"], $paypal["hours"], false)))
51
  {
52
+ do_action ("s2member_during_paypal_return_during_sp_access");
53
+ /**/
54
  header ("Location: " . $sp_access_url);
55
  }
56
  else /* Otherwise, the page ID must have been invalid. Or it's possible that the Page was deleted. */
64
  /**/
65
  $paypal["s2member_log"][] = "Redirecting Customer to the Home Page, due to an error that occurred.";
66
  }
67
+ /**/
68
+ do_action ("s2member_during_paypal_return_after_sp_access");
69
  }
70
  /*
71
  New subscriptions. Possibly containing advanced updated vars ( option_name1, option_selection1 ); which allow account modifications.
73
  else if (preg_match ("/^(web_accept|subscr_signup|subscr_payment)$/i", $paypal["txn_type"]) && ($paypal["subscr_id"] || ($paypal["subscr_id"] = $paypal["txn_id"])) && preg_match ("/^[1-4](\:|$)/", $paypal["item_number"]))
74
  { /* With Auto-Return/PDT, PayPal will send subscr_payment instead of subscr_signup to the return URL.
75
  So we need to look for (web_accept|subscr_signup|subscr_payment), and treat them as the same. */
76
+ /**/
77
+ do_action ("s2member_during_paypal_return_before_subscr_signup");
78
+ /**/
79
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup|subscr_payment).";
80
  /**/
81
  list ($paypal["level"], $paypal["ccaps"]) = preg_split ("/\:/", $paypal["item_number"], 2);
86
  /* This advanced method is required whenever a subscription that is already completed, or was never setup to recur in the first place needs to be modified. PayPal® will not allow the
87
  modify=2 parameter to be used in those scenarios, because technically there is nothing to update. The only thing to be updated is the existing account. */
88
  {
89
+ do_action ("s2member_during_paypal_return_before_subscr_signup_w_update_vars");
90
+ /**/
91
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup|subscr_payment) w/ update vars.";
92
  /**/
93
  /* Here we need to check for both the old & new s2member_subscr_id's, just in case the IPN routine has already changed it. */
114
  /**/
115
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated w/ advanced update routines.";
116
  /**/
117
+ do_action ("s2member_during_paypal_return_during_subscr_signup_w_update_vars");
118
+ /**/
119
  echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
120
  echo '<html xmlns="http://www.w3.org/1999/xhtml" ', language_attributes (), '>' . "\n";
121
  echo '<head profile="http://gmpg.org/xfn/11">' . "\n";
190
  /**/
191
  $paypal["s2member_log"][] = "Redirecting Customer to the Login Page, due to an error that occurred.";
192
  }
193
+ /**/
194
+ do_action ("s2member_during_paypal_return_after_subscr_signup_w_update_vars");
195
  }
196
  /*
197
  New subscription. Normal subscription signup, we are not updating anything for a past subscription.
198
  */
199
  else /* Else this is a normal subscription signup, we are not updating anything for a past subscription. */
200
  {
201
+ do_action ("s2member_during_paypal_return_before_subscr_signup_wo_update_vars");
202
+ /**/
203
  $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup|subscr_payment) w/o update vars.";
204
  /**/
205
  setcookie ("s2member_subscr_id", $paypal["subscr_id"], time () + 31556926, "/");
208
  /**/
209
  $paypal["s2member_log"][] = "s2Member cookies set on (web_accept|subscr_signup|subscr_payment) w/o update vars.";
210
  /**/
211
+ do_action ("s2member_during_paypal_return_during_subscr_signup_wo_update_vars");
212
+ /**/
213
  echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
214
  echo '<html xmlns="http://www.w3.org/1999/xhtml" ', language_attributes (), '>' . "\n";
215
  echo '<head profile="http://gmpg.org/xfn/11">' . "\n";
260
  /**/
261
  echo '</body>' . "\n";
262
  echo '</html>';
263
+ /**/
264
+ do_action ("s2member_during_paypal_return_after_subscr_signup_wo_update_vars");
265
  }
266
+ /**/
267
+ do_action ("s2member_during_paypal_return_after_subscr_signup");
268
  }
269
  /*
270
  Subscription modifications.
271
  */
272
  else if (preg_match ("/^subscr_modify$/i", $paypal["txn_type"]) && $paypal["subscr_id"] && preg_match ("/^[1-4](\:|$)/", $paypal["item_number"]))
273
  {
274
+ do_action ("s2member_during_paypal_return_before_subscr_modify");
275
+ /**/
276
  $paypal["s2member_log"][] = "s2Member txn_type identified as subscr_modify.";
277
  /**/
278
  list ($paypal["level"], $paypal["ccaps"]) = preg_split ("/\:/", $paypal["item_number"], 2);
299
  /**/
300
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated on subscription modification.";
301
  /**/
302
+ do_action ("s2member_during_paypal_return_during_subscr_modify");
303
+ /**/
304
  echo '<script type="text/javascript">' . "\n";
305
  echo "alert('Thank You! Your membership has been updated to:\\n\\n" . esc_js ($paypal["item_name"]) . "\\n\\nYou\\'ll need to log back in now.');" . "\n";
306
  echo "window.location = '" . esc_js (wp_login_url ()) . "';";
331
  /**/
332
  $paypal["s2member_log"][] = "Redirecting Customer to the Login Page, due to an error that occurred.";
333
  }
334
+ /**/
335
+ do_action ("s2member_during_paypal_return_after_subscr_modify");
336
  }
337
  else
338
  {
378
  if (is_writable ($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
379
  file_put_contents ($logs_dir . "/paypal-rtn.log", var_export ($paypal, true) . "\n\n", FILE_APPEND);
380
  /**/
381
+ do_action ("s2member_during_paypal_return");
382
+ /**/
383
  exit;
384
  }
385
+ /**/
386
+ do_action ("s2member_after_paypal_return");
387
  }
388
  ?>
includes/functions/post-level-access.inc.php CHANGED
@@ -21,7 +21,11 @@ function ws_plugin__s2member_check_post_level_access ()
21
  {
22
  global $post; /* get_the_ID() not yet available here. */
23
  /**/
24
- if (is_single () && !is_page () && is_object ($post) && ($post_ID = $post->ID))
 
 
 
 
25
  {
26
  if (!ws_plugin__s2member_is_systematic_use_page ()) /* Never restrict systematic use pages. */
27
  {
@@ -50,9 +54,13 @@ function ws_plugin__s2member_check_post_level_access ()
50
  /**/
51
  else if (in_array ($post_ID, preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_posts"])) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
52
  exit;
 
 
53
  }
54
  }
55
  /**/
 
 
56
  return;
57
  }
58
  ?>
21
  {
22
  global $post; /* get_the_ID() not yet available here. */
23
  /**/
24
+ do_action ("s2member_before_check_post_level_access");
25
+ /**/
26
+ $excluded = apply_filters ("s2member_check_post_level_access_excluded", false);
27
+ /**/
28
+ if (!$excluded && is_single () && !is_page () && is_object ($post) && ($post_ID = $post->ID))
29
  {
30
  if (!ws_plugin__s2member_is_systematic_use_page ()) /* Never restrict systematic use pages. */
31
  {
54
  /**/
55
  else if (in_array ($post_ID, preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_posts"])) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
56
  exit;
57
+ /**/
58
+ do_action ("s2member_during_check_post_level_access");
59
  }
60
  }
61
  /**/
62
+ do_action ("s2member_after_check_post_level_access");
63
+ /**/
64
  return;
65
  }
66
  ?>
includes/functions/profile-modifications.inc.php CHANGED
@@ -19,6 +19,8 @@ Attach to: add_action("init");
19
  */
20
  function ws_plugin__s2member_handle_profile_modifications ()
21
  {
 
 
22
  if ($_GET["s2member_profile"] && ($current_user = (is_user_logged_in ()) ? wp_get_current_user () : false))
23
  {
24
  if (($nonce = $_POST["ws_plugin__s2member_profile_save"]) && wp_verify_nonce ($nonce, "ws-plugin--s2member-profile-save"))
@@ -54,6 +56,8 @@ function ws_plugin__s2member_handle_profile_modifications ()
54
  /**/
55
  update_usermeta ($user_id, "s2member_custom_fields", $fields);
56
  /**/
 
 
57
  echo '<script type="text/javascript">' . "\n";
58
  echo "if(window.parent && window.parent != window) { try{ window.parent.Shadowbox.close(); } catch(e){} try{ window.parent.tb_remove(); } catch(e){} window.parent.alert('Profile updated successfully!'); window.parent.location = '" . esc_js (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"])) . "'; }";
59
  echo "else if(window.opener) { window.close(); window.opener.alert('Profile updated successfully!'); window.opener.location = '" . esc_js (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"])) . "'; }";
@@ -63,11 +67,17 @@ function ws_plugin__s2member_handle_profile_modifications ()
63
  exit;
64
  }
65
  /**/
 
 
66
  include_once dirname (dirname (__FILE__)) . "/profile.inc.php";
67
  /**/
 
 
68
  exit;
69
  }
70
  /**/
 
 
71
  return;
72
  }
73
  ?>
19
  */
20
  function ws_plugin__s2member_handle_profile_modifications ()
21
  {
22
+ do_action ("s2member_before_handle_profile_modifications");
23
+ /**/
24
  if ($_GET["s2member_profile"] && ($current_user = (is_user_logged_in ()) ? wp_get_current_user () : false))
25
  {
26
  if (($nonce = $_POST["ws_plugin__s2member_profile_save"]) && wp_verify_nonce ($nonce, "ws-plugin--s2member-profile-save"))
56
  /**/
57
  update_usermeta ($user_id, "s2member_custom_fields", $fields);
58
  /**/
59
+ do_action ("s2member_during_handle_profile_modifications");
60
+ /**/
61
  echo '<script type="text/javascript">' . "\n";
62
  echo "if(window.parent && window.parent != window) { try{ window.parent.Shadowbox.close(); } catch(e){} try{ window.parent.tb_remove(); } catch(e){} window.parent.alert('Profile updated successfully!'); window.parent.location = '" . esc_js (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"])) . "'; }";
63
  echo "else if(window.opener) { window.close(); window.opener.alert('Profile updated successfully!'); window.opener.location = '" . esc_js (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"])) . "'; }";
67
  exit;
68
  }
69
  /**/
70
+ do_action ("s2member_before_profile");
71
+ /**/
72
  include_once dirname (dirname (__FILE__)) . "/profile.inc.php";
73
  /**/
74
+ do_action ("s2member_after_profile");
75
+ /**/
76
  exit;
77
  }
78
  /**/
79
+ do_action ("s2member_after_handle_profile_modifications");
80
+ /**/
81
  return;
82
  }
83
  ?>
includes/functions/ptag-level-access.inc.php CHANGED
@@ -21,7 +21,11 @@ function ws_plugin__s2member_check_ptag_level_access ()
21
  {
22
  global $post; /* get_the_ID() not yet available here. */
23
  /**/
24
- if ((is_tag () && ($tag_ID = get_query_var ("tag"))) || (is_single () && has_tag () && is_object ($post) && ($post_ID = $post->ID)))
 
 
 
 
25
  {
26
  if (!ws_plugin__s2member_is_systematic_use_page ()) /* Never restrict systematic use pages. */
27
  {
@@ -79,9 +83,13 @@ function ws_plugin__s2member_check_ptag_level_access ()
79
  else if (($level4_ptags = preg_split ("/,/", preg_replace ("/( +)/", "-", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_ptags"]))) && has_tag ($level4_ptags) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
80
  exit;
81
  }
 
 
82
  }
83
  }
84
  /**/
 
 
85
  return;
86
  }
87
  ?>
21
  {
22
  global $post; /* get_the_ID() not yet available here. */
23
  /**/
24
+ do_action ("s2member_before_check_ptag_level_access");
25
+ /**/
26
+ $excluded = apply_filters ("s2member_check_ptag_level_access_excluded", false);
27
+ /**/
28
+ if (!$excluded && ((is_tag () && ($tag_ID = get_query_var ("tag"))) || (is_single () && has_tag () && is_object ($post) && ($post_ID = $post->ID))))
29
  {
30
  if (!ws_plugin__s2member_is_systematic_use_page ()) /* Never restrict systematic use pages. */
31
  {
83
  else if (($level4_ptags = preg_split ("/,/", preg_replace ("/( +)/", "-", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_ptags"]))) && has_tag ($level4_ptags) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
84
  exit;
85
  }
86
+ /**/
87
+ do_action ("s2member_during_check_ptag_level_access");
88
  }
89
  }
90
  /**/
91
+ do_action ("s2member_after_check_ptag_level_access");
92
+ /**/
93
  return;
94
  }
95
  ?>
includes/functions/readme-parsing.inc.php CHANGED
@@ -18,6 +18,8 @@ Function that handles readme.txt parsing.
18
  */
19
  function ws_plugin__s2member_parse_readme ()
20
  {
 
 
21
  if (file_exists (dirname (dirname (dirname (__FILE__))) . "/readme.txt"))
22
  {
23
  if (!function_exists ("NC_Markdown"))
@@ -46,9 +48,9 @@ function ws_plugin__s2member_parse_readme ()
46
  $readme .= $rm . "\n"; /* Content. */
47
  $readme .= '</div>' . "\n";
48
  /**/
49
- return $readme;
50
  }
51
- else /* In case readme.txt is deleted. */
52
  {
53
  return "Unable to parse /readme.txt.";
54
  }
@@ -58,11 +60,13 @@ Callback function that helps readme file parsing with specs.
58
  */
59
  function _ws_plugin__s2member_parse_readme_specs ($str = FALSE)
60
  {
 
 
61
  $str = preg_replace ("/(\<p\>|^)(.+?)(\:)( )(.+?)($|\<\/p\>)/mi", "$1" . '<li><strong>' . "$2" . '</strong>' . "$3" . '&nbsp;&nbsp;&nbsp;&nbsp;<code>' . "$5" . '</code></li>' . "$6", $str);
62
  $str = preg_replace ("/\<p\>\<li\>/i", '<ul><li>', $str); /* Open the list items. */
63
  $str = preg_replace ("/\<\/li\>\<\/p\>/i", '</li></ul><br />', $str);
64
  /**/
65
- return $str;
66
  }
67
  /*
68
  Function for parsing readme.txt files and returning a key value.
@@ -71,6 +75,8 @@ function ws_plugin__s2member_parse_readme_value ($key = FALSE)
71
  {
72
  static $readme; /* For repeated lookups. */
73
  /**/
 
 
74
  $path = dirname (dirname (dirname (__FILE__))) . "/readme.txt";
75
  /**/
76
  if (isset ($readme) || file_exists ($path))
@@ -84,7 +90,7 @@ function ws_plugin__s2member_parse_readme_value ($key = FALSE)
84
  /**/
85
  preg_match ("/(^)(" . preg_quote ($key, "/") . ")(\:)( )(.+?)($)/m", $readme, $m);
86
  /**/
87
- return strlen ($m[5] = trim ($m[5])) ? $m[5] : false;
88
  }
89
  else /* Nope. */
90
  return false;
18
  */
19
  function ws_plugin__s2member_parse_readme ()
20
  {
21
+ do_action ("s2member_before_parse_readme");
22
+ /**/
23
  if (file_exists (dirname (dirname (dirname (__FILE__))) . "/readme.txt"))
24
  {
25
  if (!function_exists ("NC_Markdown"))
48
  $readme .= $rm . "\n"; /* Content. */
49
  $readme .= '</div>' . "\n";
50
  /**/
51
+ return apply_filters ("s2member_parse_readme", $readme);
52
  }
53
+ else /* Just in case readme.txt was deleted by the site owner. */
54
  {
55
  return "Unable to parse /readme.txt.";
56
  }
60
  */
61
  function _ws_plugin__s2member_parse_readme_specs ($str = FALSE)
62
  {
63
+ do_action ("s2member_before_parse_readme_specs");
64
+ /**/
65
  $str = preg_replace ("/(\<p\>|^)(.+?)(\:)( )(.+?)($|\<\/p\>)/mi", "$1" . '<li><strong>' . "$2" . '</strong>' . "$3" . '&nbsp;&nbsp;&nbsp;&nbsp;<code>' . "$5" . '</code></li>' . "$6", $str);
66
  $str = preg_replace ("/\<p\>\<li\>/i", '<ul><li>', $str); /* Open the list items. */
67
  $str = preg_replace ("/\<\/li\>\<\/p\>/i", '</li></ul><br />', $str);
68
  /**/
69
+ return apply_filters ("s2member_parse_readme_specs", $str);
70
  }
71
  /*
72
  Function for parsing readme.txt files and returning a key value.
75
  {
76
  static $readme; /* For repeated lookups. */
77
  /**/
78
+ do_action ("s2member_before_parse_readme_value");
79
+ /**/
80
  $path = dirname (dirname (dirname (__FILE__))) . "/readme.txt";
81
  /**/
82
  if (isset ($readme) || file_exists ($path))
90
  /**/
91
  preg_match ("/(^)(" . preg_quote ($key, "/") . ")(\:)( )(.+?)($)/m", $readme, $m);
92
  /**/
93
+ return strlen ($m[5] = trim ($m[5])) ? apply_filters ("s2member_parse_readme_value", $m[5]) : false;
94
  }
95
  else /* Nope. */
96
  return false;
includes/functions/register-access.inc.php CHANGED
@@ -19,7 +19,9 @@ Attach to: add_filter("pre_option_default_role");
19
  */
20
  function ws_plugin__s2member_force_default_role ($default_role = FALSE)
21
  {
22
- return ($default_role = "subscriber");
 
 
23
  }
24
  /*
25
  Function for allowing access to the register form.
@@ -29,9 +31,11 @@ function ws_plugin__s2member_check_register_access ($users_can_register = FALSE)
29
  {
30
  global $pagenow; /* Check if we are on the General Options page. */
31
  /**/
 
 
32
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"])
33
  {
34
- return ($users_can_register = "1");
35
  }
36
  else if ($pagenow !== "options-general.php" && $_COOKIE["s2member_subscr_id"] && $_COOKIE["s2member_custom"] && preg_match ("/^[1-4](\:|$)/", $_COOKIE["s2member_level"]))
37
  {
@@ -39,11 +43,11 @@ function ws_plugin__s2member_check_register_access ($users_can_register = FALSE)
39
  /**/
40
  if (!$usermeta = $wpdb->get_row ("SELECT `user_id` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = 's2member_subscr_id' AND `meta_value` = '" . $wpdb->escape ($_COOKIE["s2member_subscr_id"]) . "' LIMIT 1"))
41
  {
42
- return ($users_can_register = "1");
43
  }
44
  }
45
  /**/
46
- return ($users_can_register = "0");
47
  }
48
  /*
49
  Function that describes the General Option overrides for clarity.
@@ -53,12 +57,20 @@ function ws_plugin__s2member_general_ops_notice ()
53
  {
54
  global $pagenow; /* Need this. */
55
  /**/
 
 
56
  if ($pagenow === "options-general.php" && !isset ($_GET["page"]))
57
  {
58
  $notice = "<em>* Note: The s2Member plugin has control over two options on this page. <code>Anyone Can Register = " . esc_html (get_option ("users_can_register")) . "</code>, and <code>Default Role = " . esc_html (get_option ("default_role")) . "</code>.";
59
  /**/
 
 
60
  ws_plugin__s2member_enqueue_admin_notice ($notice, $pagenow);
61
  }
 
 
 
 
62
  }
63
  /*
64
  This adds custom fields to the registration form.
@@ -66,6 +78,8 @@ Attach to: add_action("register_form");
66
  */
67
  function ws_plugin__s2member_custom_registration_fields ()
68
  {
 
 
69
  if (!defined ("BP_VERSION")) /* Not compatible with BuddyPress. */
70
  {
71
  echo '<input type="hidden" name="ws_plugin__s2member_registration" value="' . esc_attr (wp_create_nonce ("ws-plugin--s2member-registration")) . '" />' . "\n";
@@ -112,8 +126,12 @@ function ws_plugin__s2member_custom_registration_fields ()
112
  echo '</p>';
113
  }
114
  }
 
 
115
  }
116
  /**/
 
 
117
  return;
118
  }
119
  /*
@@ -121,15 +139,17 @@ Generates registration links.
121
  */
122
  function ws_plugin__s2member_register_link_gen ($subscr_id = FALSE, $custom = FALSE, $item_number = FALSE, $shrink = TRUE)
123
  {
 
 
124
  if ($subscr_id && $custom && $item_number) /* Must have all of these. */
125
  {
126
  $register = ws_plugin__s2member_xencrypt ("subscr_id_custom_item_number:.:|:.:" . $subscr_id . ":.:|:.:" . $custom . ":.:|:.:" . $item_number);
127
  $register_link = ws_plugin__s2member_append_query_var (get_bloginfo ("url") . "/", "s2member_register=" . urlencode ($register));
128
  /**/
129
  if ($shrink && ($tinyurl = @file_get_contents ("http://tinyurl.com/api-create.php?url=" . rawurlencode ($register_link))))
130
- return $tinyurl; /* tinyURL is easier to work with, but fails if allow_url_fopen = no. */
131
- else /* Else use the long one. */
132
- return $register_link;
133
  }
134
  /**/
135
  return false;
@@ -141,6 +161,8 @@ $_GET["s2member_paypal_register"] deprecated in v2.8.6.
141
  */
142
  function ws_plugin__s2member_register ()
143
  {
 
 
144
  if ($_GET["s2member_register"] || ($_GET["s2member_register"] = $_GET["s2member_paypal_register"]))
145
  {
146
  if (is_array ($register = preg_split ("/\:\.\:\|\:\.\:/", ws_plugin__s2member_xdecrypt ($_GET["s2member_register"]))))
@@ -151,6 +173,8 @@ function ws_plugin__s2member_register ()
151
  setcookie ("s2member_custom", $register[2], time () + 31556926, "/");
152
  setcookie ("s2member_level", $register[3], time () + 31556926, "/");
153
  /**/
 
 
154
  echo '<script type="text/javascript">' . "\n";
155
  echo "window.location = '" . esc_js (add_query_arg ("action", "register", wp_login_url ())) . "';";
156
  echo '</script>' . "\n";
@@ -158,6 +182,8 @@ function ws_plugin__s2member_register ()
158
  }
159
  exit;
160
  }
 
 
161
  }
162
  /*
163
  Function for configuring new users.
@@ -169,6 +195,8 @@ function ws_plugin__s2member_configure_user_registration ($user_id = FALSE)
169
  global $wpdb; /* Global database object may be required for this routine. */
170
  static $processed; /* Prevents duplicate processing when attached to multiple hooks in support of plugins like BuddyPress. */
171
  /**/
 
 
172
  if (!$processed && $user_id && is_array ($_POST = stripslashes_deep ($_POST)) && is_object ($user = new WP_User ($user_id)) && ($processed = true))
173
  {
174
  ws_plugin__s2member_email_config (); /* Configures From: header that will be used in new user notifications. */
@@ -242,9 +270,11 @@ function ws_plugin__s2member_configure_user_registration ($user_id = FALSE)
242
  if (($url = preg_replace ("/%%user_email%%/i", urlencode ($email), $url)))
243
  if (($url = preg_replace ("/%%user_login%%/i", urlencode ($login), $url)))
244
  if (($url = preg_replace ("/%%user_pass%%/i", urlencode ($pass), $url)))
245
- if (($url = trim ($url))) /* Make sure it is not empty now. */
246
  ws_plugin__s2member_curlpsr ($url, "s2member=1");
247
  }
 
 
248
  }
249
  /**/
250
  setcookie ("s2member_subscr_id", "", time () + 31556926, "/");
@@ -334,9 +364,11 @@ function ws_plugin__s2member_configure_user_registration ($user_id = FALSE)
334
  if (($url = preg_replace ("/%%user_email%%/i", urlencode ($email), $url)))
335
  if (($url = preg_replace ("/%%user_login%%/i", urlencode ($login), $url)))
336
  if (($url = preg_replace ("/%%user_pass%%/i", urlencode ($pass), $url)))
337
- if (($url = trim ($url))) /* Make sure it is not empty now. */
338
  ws_plugin__s2member_curlpsr ($url, "s2member=1");
339
  }
 
 
340
  }
341
  /**/
342
  if (!is_admin () && !defined ("BP_VERSION")) /* This processes Custom Fields. */
@@ -360,8 +392,12 @@ function ws_plugin__s2member_configure_user_registration ($user_id = FALSE)
360
  /**/
361
  update_usermeta ($user_id, "s2member_custom_fields", $fields);
362
  }
 
 
363
  }
364
  /**/
 
 
365
  return;
366
  }
367
  /*
@@ -377,6 +413,8 @@ if (!function_exists ("wp_generate_password"))
377
  /**/
378
  function ws_plugin__s2member_generate_password ($length = 12, $special_chars = TRUE)
379
  {
 
 
380
  $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
381
  $chars .= ($special_chars) ? "!@#$%^&*()" : "";
382
  /**/
@@ -388,7 +426,7 @@ if (!function_exists ("wp_generate_password"))
388
  if ($custom = trim (stripslashes ($_POST["ws_plugin__s2member_custom_reg_field_user_pass"])))
389
  $password = $custom;
390
  /**/
391
- return $password;
392
  }
393
  }
394
  ?>
19
  */
20
  function ws_plugin__s2member_force_default_role ($default_role = FALSE)
21
  {
22
+ do_action ("s2member_before_force_default_role");
23
+ /**/
24
+ return apply_filters ("s2member_force_default_role", ($default_role = "subscriber"));
25
  }
26
  /*
27
  Function for allowing access to the register form.
31
  {
32
  global $pagenow; /* Check if we are on the General Options page. */
33
  /**/
34
+ do_action ("s2member_before_check_register_access");
35
+ /**/
36
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"])
37
  {
38
+ return apply_filters ("s2member_check_register_access", ($users_can_register = "1"));
39
  }
40
  else if ($pagenow !== "options-general.php" && $_COOKIE["s2member_subscr_id"] && $_COOKIE["s2member_custom"] && preg_match ("/^[1-4](\:|$)/", $_COOKIE["s2member_level"]))
41
  {
43
  /**/
44
  if (!$usermeta = $wpdb->get_row ("SELECT `user_id` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = 's2member_subscr_id' AND `meta_value` = '" . $wpdb->escape ($_COOKIE["s2member_subscr_id"]) . "' LIMIT 1"))
45
  {
46
+ return apply_filters ("s2member_check_register_access", ($users_can_register = "1"));
47
  }
48
  }
49
  /**/
50
+ return apply_filters ("s2member_check_register_access", ($users_can_register = "0"));
51
  }
52
  /*
53
  Function that describes the General Option overrides for clarity.
57
  {
58
  global $pagenow; /* Need this. */
59
  /**/
60
+ do_action ("s2member_before_general_ops_notice");
61
+ /**/
62
  if ($pagenow === "options-general.php" && !isset ($_GET["page"]))
63
  {
64
  $notice = "<em>* Note: The s2Member plugin has control over two options on this page. <code>Anyone Can Register = " . esc_html (get_option ("users_can_register")) . "</code>, and <code>Default Role = " . esc_html (get_option ("default_role")) . "</code>.";
65
  /**/
66
+ do_action ("s2member_during_general_ops_notice");
67
+ /**/
68
  ws_plugin__s2member_enqueue_admin_notice ($notice, $pagenow);
69
  }
70
+ /**/
71
+ do_action ("s2member_after_general_ops_notice");
72
+ /**/
73
+ return;
74
  }
75
  /*
76
  This adds custom fields to the registration form.
78
  */
79
  function ws_plugin__s2member_custom_registration_fields ()
80
  {
81
+ do_action ("s2member_before_custom_registration_fields");
82
+ /**/
83
  if (!defined ("BP_VERSION")) /* Not compatible with BuddyPress. */
84
  {
85
  echo '<input type="hidden" name="ws_plugin__s2member_registration" value="' . esc_attr (wp_create_nonce ("ws-plugin--s2member-registration")) . '" />' . "\n";
126
  echo '</p>';
127
  }
128
  }
129
+ /**/
130
+ do_action ("s2member_during_custom_registration_fields");
131
  }
132
  /**/
133
+ do_action ("s2member_after_custom_registration_fields");
134
+ /**/
135
  return;
136
  }
137
  /*
139
  */
140
  function ws_plugin__s2member_register_link_gen ($subscr_id = FALSE, $custom = FALSE, $item_number = FALSE, $shrink = TRUE)
141
  {
142
+ do_action ("s2member_before_register_link_gen");
143
+ /**/
144
  if ($subscr_id && $custom && $item_number) /* Must have all of these. */
145
  {
146
  $register = ws_plugin__s2member_xencrypt ("subscr_id_custom_item_number:.:|:.:" . $subscr_id . ":.:|:.:" . $custom . ":.:|:.:" . $item_number);
147
  $register_link = ws_plugin__s2member_append_query_var (get_bloginfo ("url") . "/", "s2member_register=" . urlencode ($register));
148
  /**/
149
  if ($shrink && ($tinyurl = @file_get_contents ("http://tinyurl.com/api-create.php?url=" . rawurlencode ($register_link))))
150
+ return apply_filters ("s2member_register_link_gen", $tinyurl); /* tinyURL is easier to work with. */
151
+ else /* Else use the long one; tinyURL fails if allow_url_fopen = no. */
152
+ return apply_filters ("s2member_register_link_gen", $register_link);
153
  }
154
  /**/
155
  return false;
161
  */
162
  function ws_plugin__s2member_register ()
163
  {
164
+ do_action ("s2member_before_register");
165
+ /**/
166
  if ($_GET["s2member_register"] || ($_GET["s2member_register"] = $_GET["s2member_paypal_register"]))
167
  {
168
  if (is_array ($register = preg_split ("/\:\.\:\|\:\.\:/", ws_plugin__s2member_xdecrypt ($_GET["s2member_register"]))))
173
  setcookie ("s2member_custom", $register[2], time () + 31556926, "/");
174
  setcookie ("s2member_level", $register[3], time () + 31556926, "/");
175
  /**/
176
+ do_action ("s2member_during_register");
177
+ /**/
178
  echo '<script type="text/javascript">' . "\n";
179
  echo "window.location = '" . esc_js (add_query_arg ("action", "register", wp_login_url ())) . "';";
180
  echo '</script>' . "\n";
182
  }
183
  exit;
184
  }
185
+ /**/
186
+ do_action ("s2member_after_register");
187
  }
188
  /*
189
  Function for configuring new users.
195
  global $wpdb; /* Global database object may be required for this routine. */
196
  static $processed; /* Prevents duplicate processing when attached to multiple hooks in support of plugins like BuddyPress. */
197
  /**/
198
+ do_action ("s2member_before_configure_user_registration");
199
+ /**/
200
  if (!$processed && $user_id && is_array ($_POST = stripslashes_deep ($_POST)) && is_object ($user = new WP_User ($user_id)) && ($processed = true))
201
  {
202
  ws_plugin__s2member_email_config (); /* Configures From: header that will be used in new user notifications. */
270
  if (($url = preg_replace ("/%%user_email%%/i", urlencode ($email), $url)))
271
  if (($url = preg_replace ("/%%user_login%%/i", urlencode ($login), $url)))
272
  if (($url = preg_replace ("/%%user_pass%%/i", urlencode ($pass), $url)))
273
+ if (($url = trim ($url))) /* Make sure it is not empty. */
274
  ws_plugin__s2member_curlpsr ($url, "s2member=1");
275
  }
276
+ /**/
277
+ do_action ("s2member_during_configure_user_registration_front_side");
278
  }
279
  /**/
280
  setcookie ("s2member_subscr_id", "", time () + 31556926, "/");
364
  if (($url = preg_replace ("/%%user_email%%/i", urlencode ($email), $url)))
365
  if (($url = preg_replace ("/%%user_login%%/i", urlencode ($login), $url)))
366
  if (($url = preg_replace ("/%%user_pass%%/i", urlencode ($pass), $url)))
367
+ if (($url = trim ($url))) /* Make sure it is not empty. */
368
  ws_plugin__s2member_curlpsr ($url, "s2member=1");
369
  }
370
+ /**/
371
+ do_action ("s2member_during_configure_user_registration_admin_side");
372
  }
373
  /**/
374
  if (!is_admin () && !defined ("BP_VERSION")) /* This processes Custom Fields. */
392
  /**/
393
  update_usermeta ($user_id, "s2member_custom_fields", $fields);
394
  }
395
+ /**/
396
+ do_action ("s2member_during_configure_user_registration");
397
  }
398
  /**/
399
+ do_action ("s2member_after_configure_user_registration");
400
+ /**/
401
  return;
402
  }
403
  /*
413
  /**/
414
  function ws_plugin__s2member_generate_password ($length = 12, $special_chars = TRUE)
415
  {
416
+ do_action ("s2member_before_s2member_generate_password");
417
+ /**/
418
  $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
419
  $chars .= ($special_chars) ? "!@#$%^&*()" : "";
420
  /**/
426
  if ($custom = trim (stripslashes ($_POST["ws_plugin__s2member_custom_reg_field_user_pass"])))
427
  $password = $custom;
428
  /**/
429
+ return $password; /* No filter here for security purposes. */
430
  }
431
  }
432
  ?>
includes/functions/ruri-level-access.inc.php CHANGED
@@ -19,9 +19,13 @@ Attach to: add_action("template_redirect");
19
  */
20
  function ws_plugin__s2member_check_ruri_level_access ()
21
  {
22
- if (!ws_plugin__s2member_is_systematic_use_page ()) /* Never restrict systematic use pages. */
 
 
 
 
23
  {
24
- $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false;
25
  /**/
26
  foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_ruris"]) as $str)
27
  if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
@@ -38,8 +42,12 @@ function ws_plugin__s2member_check_ruri_level_access ()
38
  foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_ruris"]) as $str)
39
  if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
40
  exit;
 
 
41
  }
42
  /**/
 
 
43
  return;
44
  }
45
  ?>
19
  */
20
  function ws_plugin__s2member_check_ruri_level_access ()
21
  {
22
+ do_action ("s2member_before_check_ruri_level_access");
23
+ /**/
24
+ $excluded = apply_filters ("s2member_check_ruri_level_access_excluded", false);
25
+ /**/
26
+ if (!$excluded && !ws_plugin__s2member_is_systematic_use_page ()) /* Never restrict systematic use pages. */
27
  {
28
+ $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false; /* Is a user logged in? */
29
  /**/
30
  foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_ruris"]) as $str)
31
  if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
42
  foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_ruris"]) as $str)
43
  if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
44
  exit;
45
+ /**/
46
+ do_action ("s2member_during_check_ruri_level_access");
47
  }
48
  /**/
49
+ do_action ("s2member_after_check_ruri_level_access");
50
+ /**/
51
  return;
52
  }
53
  ?>
includes/functions/shortcodes.inc.php CHANGED
@@ -17,7 +17,7 @@ if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
17
  Function that handles the Shortcode for [s2Member-PayPal-Button /].
18
 
19
  [s2Member-PayPal-Button level="1" ccaps="" desc="" ps="paypal" cc="USD" custom="www.domain.com" tp="0" tt="D" ra="0.01" rp="1" rt="M" rr="1" /]
20
- [s2Member-PayPal-Button page="0" desc="Single-Page Access" ps="paypal" cc="USD" custom="www.domain.com" ra="0.01" sp="1" /]
21
 
22
  The desc attribute is only required for Single-Page buttons, optional for others.
23
  The page attribute is only used for Single-Page buttons.
@@ -30,13 +30,19 @@ Attach to: add_shortcode("s2Member-PayPal-Button");
30
  */
31
  function ws_plugin__s2member_paypal_button ($attr = FALSE, $content = FALSE, $shortcode = FALSE)
32
  {
33
- $sc = shortcode_atts (array ("page" => "0", "level" => "1", "ccaps" => "", "desc" => "", "ps" => "paypal", "cc" => "USD", "custom" => $_SERVER["HTTP_HOST"], "tp" => "0", "tt" => "D", "ra" => "0.01", "rp" => "1", "rt" => "M", "rr" => "1", "mb" => "0", "cb" => "0", "sp" => "0"), $attr);
 
 
 
 
34
  /**/
35
  if ($sc["cb"]) /* This is a special routine for Cancellation Buttons. Cancellation Buttons use a different template. */
36
  {
37
  $code = trim (file_get_contents (dirname (dirname (__FILE__)) . "/menu-pages/c-button.html"));
38
  $code = preg_replace ("/%%endpoint%%/", (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com"), $code);
39
  $code = preg_replace ("/%%paypal_business%%/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"], $code);
 
 
40
  }
41
  /**/
42
  else if ($sc["sp"]) /* This is a special routine for Single-Page Buttons. Single-Page Buttons use a different template. */
@@ -50,11 +56,13 @@ function ws_plugin__s2member_paypal_button ($attr = FALSE, $content = FALSE, $sh
50
  $code = preg_replace ("/%%domain%%/", strtolower ($_SERVER["HTTP_HOST"]), $code);
51
  /**/
52
  $code = preg_replace ('/ name\="item_name" value\="(.*?)"/', ' name="item_name" value="' . $sc["desc"] . '"', $code);
53
- $code = preg_replace ('/ name\="item_number" value\="(.*?)"/', ' name="item_number" value="sp:' . $sc["page"] . '"', $code);
54
  $code = preg_replace ('/ name\="page_style" value\="(.*?)"/', ' name="page_style" value="' . $sc["ps"] . '"', $code);
55
  $code = preg_replace ('/ name\="currency_code" value\="(.*?)"/', ' name="currency_code" value="' . $sc["cc"] . '"', $code);
56
  $code = preg_replace ('/ name\="custom" value\="(.*?)"/', ' name="custom" value="' . $sc["custom"] . '"', $code);
57
  $code = preg_replace ('/ name\="amount" value\="(.*?)"/', ' name="amount" value="' . $sc["ra"] . '"', $code);
 
 
58
  }
59
  else /* Otherwise, we'll process this Button normally, using the Membership routines. Also handles Modification Buttons. */
60
  {
@@ -85,7 +93,7 @@ function ws_plugin__s2member_paypal_button ($attr = FALSE, $content = FALSE, $sh
85
  $code = preg_replace ('/ name\="custom" value\="(.*?)"/', ' name="custom" value="' . $sc["custom"] . '"', $code);
86
  $code = preg_replace ('/ name\="on0" value\="(.*?)"/', ' name="on0" value="' . S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0 . '"', $code);
87
  $code = preg_replace ('/ name\="os0" value\="(.*?)"/', ' name="os0" value="' . S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0 . '"', $code);
88
- $code = preg_replace ('/ name\="modify" value\="(.*?)"/', ' name="modify" value="1"', $code);
89
  $code = preg_replace ('/ name\="amount" value\="(.*?)"/', ' name="amount" value="' . $sc["ra"] . '"', $code);
90
  $code = preg_replace ('/ name\="src" value\="(.*?)"/', ' name="src" value="' . $sc["rr"] . '"', $code);
91
  $code = preg_replace ('/ name\="p1" value\="(.*?)"/', ' name="p1" value="' . $sc["tp"] . '"', $code);
@@ -93,8 +101,13 @@ function ws_plugin__s2member_paypal_button ($attr = FALSE, $content = FALSE, $sh
93
  $code = preg_replace ('/ name\="a3" value\="(.*?)"/', ' name="a3" value="' . $sc["ra"] . '"', $code);
94
  $code = preg_replace ('/ name\="p3" value\="(.*?)"/', ' name="p3" value="' . $sc["rp"] . '"', $code);
95
  $code = preg_replace ('/ name\="t3" value\="(.*?)"/', ' name="t3" value="' . $sc["rt"] . '"', $code);
 
 
 
 
 
96
  }
97
  /**/
98
- return $code; /* The finished PayPal® Button. */
99
  }
100
  ?>
17
  Function that handles the Shortcode for [s2Member-PayPal-Button /].
18
 
19
  [s2Member-PayPal-Button level="1" ccaps="" desc="" ps="paypal" cc="USD" custom="www.domain.com" tp="0" tt="D" ra="0.01" rp="1" rt="M" rr="1" /]
20
+ [s2Member-PayPal-Button page="0" exp="72" desc="Single-Page Access" ps="paypal" cc="USD" custom="www.domain.com" ra="0.01" sp="1" /]
21
 
22
  The desc attribute is only required for Single-Page buttons, optional for others.
23
  The page attribute is only used for Single-Page buttons.
30
  */
31
  function ws_plugin__s2member_paypal_button ($attr = FALSE, $content = FALSE, $shortcode = FALSE)
32
  {
33
+ do_action ("s2member_before_paypal_button");
34
+ /**/
35
+ $sc = shortcode_atts (array ("page" => "0", "exp" => "72", "level" => "1", "ccaps" => "", "desc" => "", "ps" => "paypal", "cc" => "USD", "custom" => $_SERVER["HTTP_HOST"], "tp" => "0", "tt" => "D", "ra" => "0.01", "rp" => "1", "rt" => "M", "rr" => "1", "mb" => "0", "cb" => "0", "sp" => "0"), $attr);
36
+ /**/
37
+ do_action ("s2member_before_paypal_button_after_shortcode_atts");
38
  /**/
39
  if ($sc["cb"]) /* This is a special routine for Cancellation Buttons. Cancellation Buttons use a different template. */
40
  {
41
  $code = trim (file_get_contents (dirname (dirname (__FILE__)) . "/menu-pages/c-button.html"));
42
  $code = preg_replace ("/%%endpoint%%/", (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com"), $code);
43
  $code = preg_replace ("/%%paypal_business%%/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"], $code);
44
+ /**/
45
+ do_action ("s2member_during_paypal_button_cb");
46
  }
47
  /**/
48
  else if ($sc["sp"]) /* This is a special routine for Single-Page Buttons. Single-Page Buttons use a different template. */
56
  $code = preg_replace ("/%%domain%%/", strtolower ($_SERVER["HTTP_HOST"]), $code);
57
  /**/
58
  $code = preg_replace ('/ name\="item_name" value\="(.*?)"/', ' name="item_name" value="' . $sc["desc"] . '"', $code);
59
+ $code = preg_replace ('/ name\="item_number" value\="(.*?)"/', ' name="item_number" value="sp:' . $sc["page"] . ':' . $sc["exp"] . '"', $code);
60
  $code = preg_replace ('/ name\="page_style" value\="(.*?)"/', ' name="page_style" value="' . $sc["ps"] . '"', $code);
61
  $code = preg_replace ('/ name\="currency_code" value\="(.*?)"/', ' name="currency_code" value="' . $sc["cc"] . '"', $code);
62
  $code = preg_replace ('/ name\="custom" value\="(.*?)"/', ' name="custom" value="' . $sc["custom"] . '"', $code);
63
  $code = preg_replace ('/ name\="amount" value\="(.*?)"/', ' name="amount" value="' . $sc["ra"] . '"', $code);
64
+ /**/
65
+ do_action ("s2member_during_paypal_button_sp");
66
  }
67
  else /* Otherwise, we'll process this Button normally, using the Membership routines. Also handles Modification Buttons. */
68
  {
93
  $code = preg_replace ('/ name\="custom" value\="(.*?)"/', ' name="custom" value="' . $sc["custom"] . '"', $code);
94
  $code = preg_replace ('/ name\="on0" value\="(.*?)"/', ' name="on0" value="' . S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0 . '"', $code);
95
  $code = preg_replace ('/ name\="os0" value\="(.*?)"/', ' name="os0" value="' . S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0 . '"', $code);
96
+ $code = preg_replace ('/ name\="modify" value\="(.*?)"/', ' name="modify" value="' . (($sc["mb"]) ? '1' : '0') . '"', $code);
97
  $code = preg_replace ('/ name\="amount" value\="(.*?)"/', ' name="amount" value="' . $sc["ra"] . '"', $code);
98
  $code = preg_replace ('/ name\="src" value\="(.*?)"/', ' name="src" value="' . $sc["rr"] . '"', $code);
99
  $code = preg_replace ('/ name\="p1" value\="(.*?)"/', ' name="p1" value="' . $sc["tp"] . '"', $code);
101
  $code = preg_replace ('/ name\="a3" value\="(.*?)"/', ' name="a3" value="' . $sc["ra"] . '"', $code);
102
  $code = preg_replace ('/ name\="p3" value\="(.*?)"/', ' name="p3" value="' . $sc["rp"] . '"', $code);
103
  $code = preg_replace ('/ name\="t3" value\="(.*?)"/', ' name="t3" value="' . $sc["rt"] . '"', $code);
104
+ /**/
105
+ if ($sc["mb"])
106
+ do_action ("s2member_during_paypal_button_mb");
107
+ else
108
+ do_action ("s2member_during_paypal_button");
109
  }
110
  /**/
111
+ return apply_filters ("s2member_paypal_button", $code); /* The finished PayPal® Button. */
112
  }
113
  ?>
includes/functions/sp-access.inc.php CHANGED
@@ -16,17 +16,19 @@ if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
16
  /*
17
  Generates Single-Page Access links.
18
  */
19
- function ws_plugin__s2member_sp_access_link_gen ($page_ID = FALSE, $shrink = TRUE)
20
  {
21
- if ($page_ID) /* Must have a page ID in order to create an access link. */
 
 
22
  {
23
- $sp_access = ws_plugin__s2member_xencrypt ("sp:.:|:.:" . $page_ID . ":.:|:.:" . strtotime ("now"));
24
  $sp_access_link = ws_plugin__s2member_append_query_var (get_page_link ($page_ID), "s2member_sp_access=" . urlencode ($sp_access));
25
  /**/
26
  if ($shrink && ($tinyurl = @file_get_contents ("http://tinyurl.com/api-create.php?url=" . rawurlencode ($sp_access_link))))
27
- return $tinyurl; /* tinyURL is easier to work with, but fails if allow_url_fopen = no. */
28
- else /* Else use the long one. */
29
- return $sp_access_link;
30
  }
31
  /**/
32
  return false;
@@ -37,9 +39,11 @@ Attach to: add_action("wp_ajax_s2member_sp_access_link");
37
  */
38
  function ws_plugin__s2member_sp_access_link ()
39
  {
 
 
40
  if (current_user_can ("edit_plugins")) /* Check priveledges as well. */
41
  if (($nonce = $_POST["s2member_sp_access_link"]) && wp_verify_nonce ($nonce, "ws-plugin--s2member-sp-access-link"))
42
- echo ws_plugin__s2member_sp_access_link_gen ($_POST["s2member_sp_access_link_page"]);
43
  /**/
44
  exit;
45
  }
@@ -48,16 +52,20 @@ Handles Single-Page Access authentication.
48
  */
49
  function ws_plugin__s2member_sp_access ($page_ID = FALSE)
50
  {
51
- if (current_user_can ("edit_posts"))
 
 
 
 
52
  return true; /* Edit access. */
53
  /**/
54
  else if ($_GET["s2member_sp_access"] && $page_ID)
55
  {
56
  if (is_array ($sp_access = preg_split ("/\:\.\:\|\:\.\:/", ws_plugin__s2member_xdecrypt ($_GET["s2member_sp_access"]))))
57
  {
58
- if (count ($sp_access) === 3 && $sp_access[0] === "sp" && $sp_access[1] == $page_ID && $sp_access[2] >= strtotime ("-72 hours"))
59
  {
60
- if ($sp_access[2] <= strtotime ("now")) /* Prevent arbitrarily long times from hacking in. */
61
  return true; /* Looks good! Single-Page Access granted. */
62
  }
63
  }
16
  /*
17
  Generates Single-Page Access links.
18
  */
19
+ function ws_plugin__s2member_sp_access_link_gen ($page_ID = FALSE, $hours = 72, $shrink = TRUE)
20
  {
21
+ do_action ("s2member_before_sp_access_link_gen");
22
+ /**/
23
+ if ($page_ID && $hours) /* Must have page_ID/hours in order to create an access link. */
24
  {
25
+ $sp_access = ws_plugin__s2member_xencrypt ("sp:.:|:.:" . $page_ID . ":.:|:.:" . strtotime ("now") . ":.:|:.:" . $hours);
26
  $sp_access_link = ws_plugin__s2member_append_query_var (get_page_link ($page_ID), "s2member_sp_access=" . urlencode ($sp_access));
27
  /**/
28
  if ($shrink && ($tinyurl = @file_get_contents ("http://tinyurl.com/api-create.php?url=" . rawurlencode ($sp_access_link))))
29
+ return apply_filters ("s2member_sp_access_link_gen", $tinyurl); /* tinyURL is easier to work with. */
30
+ else /* Else use the long one; tinyURL fails if allow_url_fopen = no. */
31
+ return apply_filters ("s2member_sp_access_link_gen", $sp_access_link);
32
  }
33
  /**/
34
  return false;
39
  */
40
  function ws_plugin__s2member_sp_access_link ()
41
  {
42
+ do_action ("s2member_before_sp_access_link");
43
+ /**/
44
  if (current_user_can ("edit_plugins")) /* Check priveledges as well. */
45
  if (($nonce = $_POST["s2member_sp_access_link"]) && wp_verify_nonce ($nonce, "ws-plugin--s2member-sp-access-link"))
46
+ echo apply_filters ("s2member_sp_access_link", ws_plugin__s2member_sp_access_link_gen ($_POST["s2member_sp_access_link_page"], $_POST["s2member_sp_access_link_hours"]));
47
  /**/
48
  exit;
49
  }
52
  */
53
  function ws_plugin__s2member_sp_access ($page_ID = FALSE)
54
  {
55
+ do_action ("s2member_before_sp_access");
56
+ /**/
57
+ $excluded = apply_filters ("s2member_sp_access_excluded", false);
58
+ /**/
59
+ if ($excluded || current_user_can ("edit_posts"))
60
  return true; /* Edit access. */
61
  /**/
62
  else if ($_GET["s2member_sp_access"] && $page_ID)
63
  {
64
  if (is_array ($sp_access = preg_split ("/\:\.\:\|\:\.\:/", ws_plugin__s2member_xdecrypt ($_GET["s2member_sp_access"]))))
65
  {
66
+ if (count ($sp_access) === 4 && $sp_access[0] === "sp_time_hours" && $sp_access[1] == $page_ID && $sp_access[2] >= strtotime ("-" . $sp_access[3] . " hours"))
67
  {
68
+ if ($sp_access[2] <= strtotime ("now")) /* Additional sanity check. */
69
  return true; /* Looks good! Single-Page Access granted. */
70
  }
71
  }
includes/functions/translations.inc.php CHANGED
@@ -21,6 +21,8 @@ function ws_plugin__s2member_translation_mangler ($translated = FALSE, $original
21
  {
22
  static $is_admin_media_upload, $is_wp_login; /* Optimizes this routine. */
23
  /**/
 
 
24
  if (!isset ($is_admin_media_upload) || $is_admin_media_upload)
25
  {
26
  if ($is_admin_media_upload || (is_admin () && preg_match ("/\/(async-upload|media-upload)\.php/", $_SERVER["REQUEST_URI"])))
@@ -59,6 +61,6 @@ function ws_plugin__s2member_translation_mangler ($translated = FALSE, $original
59
  }
60
  }
61
  /**/
62
- return $translated;
63
  }
64
  ?>
21
  {
22
  static $is_admin_media_upload, $is_wp_login; /* Optimizes this routine. */
23
  /**/
24
+ do_action ("s2member_before_translation_mangler");
25
+ /**/
26
  if (!isset ($is_admin_media_upload) || $is_admin_media_upload)
27
  {
28
  if ($is_admin_media_upload || (is_admin () && preg_match ("/\/(async-upload|media-upload)\.php/", $_SERVER["REQUEST_URI"])))
61
  }
62
  }
63
  /**/
64
+ return apply_filters ("s2member_translation_mangler", $translated);
65
  }
66
  ?>
includes/functions/user-access-level.inc.php CHANGED
@@ -14,34 +14,42 @@ Direct access denial.
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
  exit;
16
  /*
17
- Function for determing the access level of a user.
18
- Returns 0-4 according to the current user's access level.
19
  */
20
  function ws_plugin__s2member_user_access_level ()
21
  {
 
 
22
  if (!($current_user = (is_user_logged_in ()) ? wp_get_current_user () : false))
23
  {
24
- return -1; /* Return of -1, means not logged in. */
 
25
  }
26
  else if (current_user_can ("access_s2member_level4"))
27
  {
28
- return 4; /* User logged in with level 4 access. */
 
29
  }
30
  else if (current_user_can ("access_s2member_level3"))
31
  {
32
- return 3; /* User logged in with level 3 access. */
 
33
  }
34
  else if (current_user_can ("access_s2member_level2"))
35
  {
36
- return 2; /* User logged in with level 2 access. */
 
37
  }
38
  else if (current_user_can ("access_s2member_level1"))
39
  {
40
- return 1; /* User logged in with level 1 access. */
 
41
  }
42
- else /* If a user is logged in but has no access. */
43
  {
44
- return 0; /* User is logged in without access. */
 
45
  }
46
  }
47
  ?>
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
  exit;
16
  /*
17
+ Function for determing the Access Level of a User/Member.
18
+ Returns 0-4 according to the current User/Member's Access Level.
19
  */
20
  function ws_plugin__s2member_user_access_level ()
21
  {
22
+ do_action ("s2member_before_user_access_level");
23
+ /**/
24
  if (!($current_user = (is_user_logged_in ()) ? wp_get_current_user () : false))
25
  {
26
+ return apply_filters ("s2member_user_access_level", -1);
27
+ /* Return of -1, means a User is not logged in. */
28
  }
29
  else if (current_user_can ("access_s2member_level4"))
30
  {
31
+ return apply_filters ("s2member_user_access_level", 4);
32
+ /* Member logged in with Level 4 Access. */
33
  }
34
  else if (current_user_can ("access_s2member_level3"))
35
  {
36
+ return apply_filters ("s2member_user_access_level", 3);
37
+ /* Member logged in with Level 3 Access. */
38
  }
39
  else if (current_user_can ("access_s2member_level2"))
40
  {
41
+ return apply_filters ("s2member_user_access_level", 2);
42
+ /* Member logged in with Level 2 Access. */
43
  }
44
  else if (current_user_can ("access_s2member_level1"))
45
  {
46
+ return apply_filters ("s2member_user_access_level", 1);
47
+ /* Member logged in with Level 1 Access. */
48
  }
49
+ else /* Else if a User ( Free Subscriber ) is logged in. */
50
  {
51
+ return apply_filters ("s2member_user_access_level", 0);
52
+ /* User is logged in without Access. A Free Subscriber. */
53
  }
54
  }
55
  ?>
includes/functions/user-deletions.inc.php CHANGED
@@ -19,6 +19,8 @@ Attach to: add_action("delete_user");
19
  */
20
  function ws_plugin__s2member_handle_user_deletions ($user_id = FALSE)
21
  {
 
 
22
  $user = new WP_User ($user_id);
23
  $paypal["custom"] = get_usermeta ($user_id, "s2member_custom");
24
  $paypal["subscr_id"] = get_usermeta ($user_id, "s2member_subscr_id");
@@ -35,6 +37,8 @@ function ws_plugin__s2member_handle_user_deletions ($user_id = FALSE)
35
  ws_plugin__s2member_curlpsr ($url, "s2member=1");
36
  }
37
  /**/
 
 
38
  return;
39
  }
40
  ?>
19
  */
20
  function ws_plugin__s2member_handle_user_deletions ($user_id = FALSE)
21
  {
22
+ do_action ("s2member_before_handle_user_deletions");
23
+ /**/
24
  $user = new WP_User ($user_id);
25
  $paypal["custom"] = get_usermeta ($user_id, "s2member_custom");
26
  $paypal["subscr_id"] = get_usermeta ($user_id, "s2member_subscr_id");
37
  ws_plugin__s2member_curlpsr ($url, "s2member=1");
38
  }
39
  /**/
40
+ do_action ("s2member_after_handle_user_deletions");
41
+ /**/
42
  return;
43
  }
44
  ?>
includes/functions/user-downloads.inc.php DELETED
@@ -1,58 +0,0 @@
1
- <?php
2
- /*
3
- Copyright: © 2009 WebSharks, Inc. ( coded in the USA )
4
- <mailto:support@websharks-inc.com> <http://www.websharks-inc.com/>
5
-
6
- Released under the terms of the GNU General Public License.
7
- You should have received a copy of the GNU General Public License,
8
- along with this software. In the main directory, see: /licensing/
9
- If not, see: <http://www.gnu.org/licenses/>.
10
- */
11
- /*
12
- Direct access denial.
13
- */
14
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
- exit;
16
- /*
17
- Function determines how many downloads allowed - etc, etc.
18
- Returns an array with 3 elements: allowed, allowed_days, currently.
19
- The 2nd parameter can be used to prevent another database connection.
20
- */
21
- function ws_plugin__s2member_user_downloads ($not_counting_this_particular_file = false, $log = null)
22
- {
23
- if (($current_user = (is_user_logged_in ()) ? wp_get_current_user () : false))
24
- {
25
- if (current_user_can ("access_s2member_level1") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed"])
26
- {
27
- $allowed = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed"];
28
- $allowed_days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed_days"];
29
- }
30
- /**/
31
- if (current_user_can ("access_s2member_level2") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed"])
32
- {
33
- $allowed = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed"];
34
- $allowed_days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed_days"];
35
- }
36
- /**/
37
- if (current_user_can ("access_s2member_level3") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed"])
38
- {
39
- $allowed = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed"];
40
- $allowed_days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed_days"];
41
- }
42
- /**/
43
- if (current_user_can ("access_s2member_level4") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed"])
44
- {
45
- $allowed = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed"];
46
- $allowed_days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed_days"];
47
- }
48
- /**/
49
- $file_download_access_log = (isset ($log)) ? (array)$log : (array)get_usermeta ($current_user->ID, "s2member_file_download_access_log");
50
- foreach ($file_download_access_log as $file_download_access_log_entry_key => $file_download_access_log_entry)
51
- if (strtotime ($file_download_access_log_entry["date"]) >= strtotime ("-" . (int)$allowed_days . " days"))
52
- if ($file_download_access_log_entry["file"] !== $not_counting_this_particular_file)
53
- $currently = ($currently) ? $currently + 1 : 1;
54
- }
55
- /**/
56
- return array ("allowed" => (int)$allowed, "allowed_days" => (int)$allowed_days, "currently" => (int)$currently);
57
- }
58
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/functions/users-list.inc.php CHANGED
@@ -19,6 +19,8 @@ Attach to: add_filter ("manage_users_columns");
19
  */
20
  function ws_plugin__s2member_users_list_cols ($cols = FALSE)
21
  {
 
 
22
  $cols["s2member_registration_time"] = "Registered On"; /* Date they signed up. */
23
  $cols["s2member_subscr_id"] = "PayPal® Subscr. ID"; /* Special field that is always applied. */
24
  $cols["s2member_ccaps"] = "Custom Capabilities"; /* Special field that is always applied. */
@@ -34,7 +36,7 @@ function ws_plugin__s2member_users_list_cols ($cols = FALSE)
34
  }
35
  }
36
  /**/
37
- return $cols;
38
  }
39
  /*
40
  Function that displays column data in the row of details.
@@ -43,18 +45,19 @@ Attach to: add_filter ("manage_users_custom_column");
43
  function ws_plugin__s2member_users_list_display_cols ($_ = FALSE, $col = FALSE, $user_id = FALSE)
44
  {
45
  global $user_object; /* The user_row() function already has this. */
46
- $user = $user_object; /* Shorter reference to the user_object var. */
47
- static $fields, $fields_4_user_id; /* Used to conserve resources. */
 
 
48
  /**/
49
  if ((!isset ($fields) || $fields_4_user_id !== $user_id) && ($fields_4_user_id = $user_id))
50
  $fields = get_usermeta ($user_id, "s2member_custom_fields");
51
  /**/
52
  if ($col === "s2member_registration_time")
53
- return ($r = $user->user_registered) ? /* Displays date & time ( 2 lines ). */
54
- date ("D M j, Y", strtotime ($r)) . '<br />@exactly ' . date ("g:i a", strtotime ($r)) : "—";
55
  /**/
56
  else if ($col === "s2member_subscr_id")
57
- return ($r = get_usermeta ($user_id, "s2member_subscr_id")) ? esc_html ($r) : "—";
58
  /**/
59
  else if ($col === "s2member_ccaps") /* Custom Capabilities. */
60
  {
@@ -62,13 +65,16 @@ function ws_plugin__s2member_users_list_display_cols ($_ = FALSE, $col = FALSE,
62
  if (preg_match ("/^access_s2member_ccap_/", $cap))
63
  $ccaps[] = preg_replace ("/^access_s2member_ccap_/", "", $cap);
64
  /**/
65
- return (!empty ($ccaps)) ? implode ("<br />", $ccaps) : "—";
66
  }
67
  /**/
68
- if ($fields[$col] && preg_match ("/^http(s?)\:/i", $fields[$col]))
69
- return '<a href="' . esc_attr ($fields[$col]) . '" target="_blank">' . esc_html (substr ($fields[$col], strpos ($fields[$col], ":") + 3, 25) . "...") . '</a>';
 
 
 
70
  /**/
71
- return ($fields[$col]) ? esc_html ($fields[$col]) : "—";
72
  }
73
  /*
74
  Function that adds custom fields to the admin profile editing page.
@@ -77,6 +83,8 @@ Attach to: add_action("show_user_profile");
77
  */
78
  function ws_plugin__s2member_users_list_edit_cols ($user = FALSE)
79
  {
 
 
80
  if (current_user_can ("edit_users")) /* Security check. */
81
  {
82
  echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
@@ -116,10 +124,16 @@ function ws_plugin__s2member_users_list_edit_cols ($user = FALSE)
116
  }
117
  }
118
  /**/
 
 
119
  echo '</table>' . "\n";
120
  /**/
121
  echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
122
  }
 
 
 
 
123
  }
124
  /*
125
  Function that saves custom fields after an admin updates profile.
@@ -128,6 +142,8 @@ Attach to: add_action("personal_options_update");
128
  */
129
  function ws_plugin__s2member_users_list_update_cols ($user_id = FALSE)
130
  {
 
 
131
  if (current_user_can ("edit_users")) /* Quick security check here. */
132
  {
133
  if (is_array ($_POST = stripslashes_deep ($_POST)) && !empty ($_POST))
@@ -156,7 +172,11 @@ function ws_plugin__s2member_users_list_update_cols ($user_id = FALSE)
156
  /**/
157
  update_usermeta ($user_id, "s2member_custom_fields", $fields);
158
  }
 
 
159
  }
160
  }
 
 
161
  }
162
  ?>
19
  */
20
  function ws_plugin__s2member_users_list_cols ($cols = FALSE)
21
  {
22
+ do_action ("s2member_before_users_list_cols");
23
+ /**/
24
  $cols["s2member_registration_time"] = "Registered On"; /* Date they signed up. */
25
  $cols["s2member_subscr_id"] = "PayPal® Subscr. ID"; /* Special field that is always applied. */
26
  $cols["s2member_ccaps"] = "Custom Capabilities"; /* Special field that is always applied. */
36
  }
37
  }
38
  /**/
39
+ return apply_filters ("s2member_users_list_cols", $cols);
40
  }
41
  /*
42
  Function that displays column data in the row of details.
45
  function ws_plugin__s2member_users_list_display_cols ($_ = FALSE, $col = FALSE, $user_id = FALSE)
46
  {
47
  global $user_object; /* The user_row() function already has this. */
48
+ $user = $user_object; /* Shorter reference to the $user_object var. */
49
+ static $fields, $fields_4_user_id; /* Used for optimization. */
50
+ /**/
51
+ do_action ("s2member_before_users_list_display_cols");
52
  /**/
53
  if ((!isset ($fields) || $fields_4_user_id !== $user_id) && ($fields_4_user_id = $user_id))
54
  $fields = get_usermeta ($user_id, "s2member_custom_fields");
55
  /**/
56
  if ($col === "s2member_registration_time")
57
+ $val = ($r = $user->user_registered) ? date ("D M j, Y", strtotime ($r)) . '<br />@exactly ' . date ("g:i a", strtotime ($r)) : "—";
 
58
  /**/
59
  else if ($col === "s2member_subscr_id")
60
+ $val = ($r = get_usermeta ($user_id, "s2member_subscr_id")) ? esc_html ($r) : "—";
61
  /**/
62
  else if ($col === "s2member_ccaps") /* Custom Capabilities. */
63
  {
65
  if (preg_match ("/^access_s2member_ccap_/", $cap))
66
  $ccaps[] = preg_replace ("/^access_s2member_ccap_/", "", $cap);
67
  /**/
68
+ $val = (!empty ($ccaps)) ? implode ("<br />", $ccaps) : "—";
69
  }
70
  /**/
71
+ else if ($fields[$col] && preg_match ("/^http(s?)\:/i", $fields[$col]))
72
+ $val = '<a href="' . esc_attr ($fields[$col]) . '" target="_blank">' . esc_html (substr ($fields[$col], strpos ($fields[$col], ":") + 3, 25) . "...") . '</a>';
73
+ /**/
74
+ else if ($fields[$col])
75
+ $val = esc_html ($fields[$col]);
76
  /**/
77
+ return apply_filters ("s2member_users_list_display_cols", (($val) ? $val : "—"));
78
  }
79
  /*
80
  Function that adds custom fields to the admin profile editing page.
83
  */
84
  function ws_plugin__s2member_users_list_edit_cols ($user = FALSE)
85
  {
86
+ do_action ("s2member_before_users_list_edit_cols");
87
+ /**/
88
  if (current_user_can ("edit_users")) /* Security check. */
89
  {
90
  echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
124
  }
125
  }
126
  /**/
127
+ do_action ("s2member_during_users_list_edit_cols");
128
+ /**/
129
  echo '</table>' . "\n";
130
  /**/
131
  echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
132
  }
133
+ /**/
134
+ do_action ("s2member_after_users_list_edit_cols");
135
+ /**/
136
+ return;
137
  }
138
  /*
139
  Function that saves custom fields after an admin updates profile.
142
  */
143
  function ws_plugin__s2member_users_list_update_cols ($user_id = FALSE)
144
  {
145
+ do_action ("s2member_before_users_list_update_cols");
146
+ /**/
147
  if (current_user_can ("edit_users")) /* Quick security check here. */
148
  {
149
  if (is_array ($_POST = stripslashes_deep ($_POST)) && !empty ($_POST))
172
  /**/
173
  update_usermeta ($user_id, "s2member_custom_fields", $fields);
174
  }
175
+ /**/
176
+ do_action ("s2member_during_users_list_update_cols");
177
  }
178
  }
179
+ /**/
180
+ do_action ("s2member_after_users_list_update_cols");
181
  }
182
  ?>
includes/menu-pages/api-ops.inc.php CHANGED
@@ -54,11 +54,11 @@ echo '<tr>' . "\n";
54
  echo '<td>' . "\n";
55
  echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
56
  echo '<textarea name="ws_plugin__s2member_signup_notification_urls" id="ws-plugin--s2member-signup-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_urls"]) . '</textarea><br />' . "\n";
57
- echo 'Signup Notifications take place silently behind-the-scenes, using a cURL connection. Each URL will be notified every time a new user signs up successfully through PayPal.<br /><br />' . "\n";
58
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
59
  echo '<ul>' . "\n";
60
  echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
61
- echo '<li><code>%%initial%% = The Initial Fee charged during signup. If you offered a free trial, this will be 0.</code> [ <a href="#" onclick="alert(\'If no initial period was offered or required, this initial amount will be equal to the %%regular%% rate. In other words, this will always represent the amount of money the Customer spent whenever they signed up, no matter what.\\n\\nIf a user signs up under the terms of a free trial period, this will be 0. So be careful using this value with 3rd party affiliate integrations because a $0 sale amount could cause havoc. If you have a lot of trouble, try using the %%regular%% amount, or use the `Payment` Notifications instead of the `Signup` Notifications.\'); return false;">?</a> ]</li>' . "\n";
62
  echo '<li><code>%%regular%% = The Regular Amount of the subscription. This value is always > 0, no matter what.</code> [ <a href="#" onclick="alert(\'This is how much the subscription costs after an initial period expires. The %%regular%% rate is always > 0. If you did not offer an initial period, %%initial%% and %%regular%% will be equal to the same thing.\'); return false;">?</a> ]</li>' . "\n";
63
  echo '<li><code>%%recurring%% = This is the amount that will be charged on a Recurring basis, or 0 if non-Recurring.</code> [ <a href="#" onclick="alert(\'If recurring payments have not been required, this will be equal to 0. That being said, %%regular%% &amp; %%recurring%% are usually the same value. This variable can be used in two different ways. You can use it to determine what the regular recurring rate is, or to determine whether the subscription will recur or not. If it is going to recur, %%recurring%% will be > 0.\\n\\nThe only time this is NOT equal to the %%regular%% rate, is when recurring payments are not required; and only a one-time regular rate applies. If you have trouble, try using the %%regular%% amount, or use the `Payment` Notifications instead of the `Signup` Notifications.\'); return false;">?</a> ]</li>' . "\n";
64
  echo '<li><code>%%first_name%% = The First Name of the Customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
@@ -109,7 +109,7 @@ echo '<tr>' . "\n";
109
  echo '<td>' . "\n";
110
  echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
111
  echo '<textarea name="ws_plugin__s2member_registration_notification_urls" id="ws-plugin--s2member-registration-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["registration_notification_urls"]) . '</textarea><br />' . "\n";
112
- echo 'Registration Notifications take place silently behind-the-scenes, using a cURL connection. Each URL will be notified every time a new user registers a Username.<br /><br />' . "\n";
113
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
114
  echo '<ul>' . "\n";
115
  echo '<li><code>%%level%% = The level number ( 0, 1, 2, 3, 4 ) 0 = Free Subscriber.</code></li>' . "\n";
@@ -160,7 +160,7 @@ echo '<tr>' . "\n";
160
  echo '<td>' . "\n";
161
  echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
162
  echo '<textarea name="ws_plugin__s2member_payment_notification_urls" id="ws-plugin--s2member-payment-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_urls"]) . '</textarea><br />' . "\n";
163
- echo 'Payment Notifications take place silently behind-the-scenes, using a cURL connection. Each URL will be notified every time an initial and/or recurring payment occurs.<br /><br />' . "\n";
164
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
165
  echo '<ul>' . "\n";
166
  echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the Transaction ID for the payment.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
@@ -214,7 +214,7 @@ echo '<tr>' . "\n";
214
  echo '<td>' . "\n";
215
  echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
216
  echo '<textarea name="ws_plugin__s2member_eot_del_notification_urls" id="ws-plugin--s2member-eot-del-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_urls"]) . '</textarea><br />' . "\n";
217
- echo 'EOT/Deletion Notifications take place silently behind-the-scenes, using a cURL connection. Each URL will be notified every time a subscription reaches the end of its term or is deleted.<br /><br />' . "\n";
218
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
219
  echo '<ul>' . "\n";
220
  echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remained constant throughout the lifetime of the membership.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the original Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime subscriptions are NOT recurring ( i.e. there was only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
@@ -263,7 +263,7 @@ echo '<tr>' . "\n";
263
  echo '<td>' . "\n";
264
  echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
265
  echo '<textarea name="ws_plugin__s2member_ref_rev_notification_urls" id="ws-plugin--s2member-ref-rev-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_urls"]) . '</textarea><br />' . "\n";
266
- echo 'Refund/Reversal Notifications take place silently behind-the-scenes, using a cURL connection. Each URL will be notified every time a payment is refunded through PayPal® or a chargeback occurs.<br /><br />' . "\n";
267
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
268
  echo '<ul>' . "\n";
269
  echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remained constant throughout the lifetime of the membership.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the original Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime subscriptions are NOT recurring ( i.e. there was only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
@@ -315,17 +315,18 @@ echo '<tr>' . "\n";
315
  echo '<td>' . "\n";
316
  echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
317
  echo '<textarea name="ws_plugin__s2member_sp_notification_urls" id="ws-plugin--s2member-sp-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_notification_urls"]) . '</textarea><br />' . "\n";
318
- echo 'Single-Page Notifications take place silently behind-the-scenes, using a cURL connection. Each URL will be notified every time a sale occurs.<br /><br />' . "\n";
319
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
320
  echo '<ul>' . "\n";
321
- echo '<li><code>%%sp_access_url%% = The full URL ( generated by s2Member ) where the Customer can gain access. Valid for 72 hours.</code></li>' . "\n";
 
322
  echo '<li><code>%%txn_id%% = The PayPal® Transaction ID. PayPal® assigns a unique identifier for every purchase.</code></li>' . "\n";
323
  echo '<li><code>%%amount%% = The full Amount of the sale. Most affiliate programs calculate commissions from this.</code></li>' . "\n";
324
  echo '<li><code>%%first_name%% = The First Name of the Customer who purchased Single-Page Access through PayPal®.</code></li>' . "\n";
325
  echo '<li><code>%%last_name%% = The Last Name of the Customer who purchased Single-Page Access through PayPal®.</code></li>' . "\n";
326
  echo '<li><code>%%full_name%% = The Full Name ( First & Last ) of the Customer who purchased Single-Page Access.</code></li>' . "\n";
327
  echo '<li><code>%%payer_email%% = The Email Address of the Customer who purchased Single-Page Access through PayPal®.</code></li>' . "\n";
328
- echo '<li><code>%%item_number%% = The Item Number. Ex: <em>sp:13</em> ( the numerical portion is a Single-Page ID ).</code></li>' . "\n";
329
  echo '<li><code>%%item_name%% = The Item Name. In other words, a brief description, detailing what this purchase was for.</code></li>' . "\n";
330
  echo '</ul>' . "\n";
331
  echo '<strong>Custom replacement codes can also be inserted using these instructions:</strong>' . "\n";
54
  echo '<td>' . "\n";
55
  echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
56
  echo '<textarea name="ws_plugin__s2member_signup_notification_urls" id="ws-plugin--s2member-signup-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_urls"]) . '</textarea><br />' . "\n";
57
+ echo 'Signup Notifications take place silently behind-the-scene, using a cURL connection. Each URL will be notified every time a new user signs up successfully through PayPal.<br /><br />' . "\n";
58
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
59
  echo '<ul>' . "\n";
60
  echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
61
+ echo '<li><code>%%initial%% = The Initial Fee charged during signup. If you offered a free trial, this will be 0.</code> [ <a href="#" onclick="alert(\'This will always represent the amount of money the Customer spent, whenever they initially signed up, no matter what. Even if that amount is 0.\\n\\nIf a Customer signs up, under the terms of a free trial period, this will be 0. So be careful using %%initial%% when you offer a free trial period, because a $0.00 sale amount could cause havoc with affiliate programs. If you\\\'re offering a free trial period, and you need to track sales through affiliate programs, you can either hard-code an amount; or use `Payment Notifications` instead.\'); return false;">?</a> ]</li>' . "\n";
62
  echo '<li><code>%%regular%% = The Regular Amount of the subscription. This value is always > 0, no matter what.</code> [ <a href="#" onclick="alert(\'This is how much the subscription costs after an initial period expires. The %%regular%% rate is always > 0. If you did not offer an initial period, %%initial%% and %%regular%% will be equal to the same thing.\'); return false;">?</a> ]</li>' . "\n";
63
  echo '<li><code>%%recurring%% = This is the amount that will be charged on a Recurring basis, or 0 if non-Recurring.</code> [ <a href="#" onclick="alert(\'If recurring payments have not been required, this will be equal to 0. That being said, %%regular%% &amp; %%recurring%% are usually the same value. This variable can be used in two different ways. You can use it to determine what the regular recurring rate is, or to determine whether the subscription will recur or not. If it is going to recur, %%recurring%% will be > 0.\\n\\nThe only time this is NOT equal to the %%regular%% rate, is when recurring payments are not required; and only a one-time regular rate applies. If you have trouble, try using the %%regular%% amount, or use the `Payment` Notifications instead of the `Signup` Notifications.\'); return false;">?</a> ]</li>' . "\n";
64
  echo '<li><code>%%first_name%% = The First Name of the Customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
109
  echo '<td>' . "\n";
110
  echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
111
  echo '<textarea name="ws_plugin__s2member_registration_notification_urls" id="ws-plugin--s2member-registration-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["registration_notification_urls"]) . '</textarea><br />' . "\n";
112
+ echo 'Registration Notifications take place silently behind-the-scene, using a cURL connection. Each URL will be notified every time a new user registers a Username.<br /><br />' . "\n";
113
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
114
  echo '<ul>' . "\n";
115
  echo '<li><code>%%level%% = The level number ( 0, 1, 2, 3, 4 ) 0 = Free Subscriber.</code></li>' . "\n";
160
  echo '<td>' . "\n";
161
  echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
162
  echo '<textarea name="ws_plugin__s2member_payment_notification_urls" id="ws-plugin--s2member-payment-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_urls"]) . '</textarea><br />' . "\n";
163
+ echo 'Payment Notifications take place silently behind-the-scene, using a cURL connection. Each URL will be notified every time an initial and/or recurring payment occurs.<br /><br />' . "\n";
164
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
165
  echo '<ul>' . "\n";
166
  echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the Transaction ID for the payment.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
214
  echo '<td>' . "\n";
215
  echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
216
  echo '<textarea name="ws_plugin__s2member_eot_del_notification_urls" id="ws-plugin--s2member-eot-del-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_urls"]) . '</textarea><br />' . "\n";
217
+ echo 'EOT/Deletion Notifications take place silently behind-the-scene, using a cURL connection. Each URL will be notified every time a subscription reaches the end of its term or is deleted.<br /><br />' . "\n";
218
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
219
  echo '<ul>' . "\n";
220
  echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remained constant throughout the lifetime of the membership.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the original Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime subscriptions are NOT recurring ( i.e. there was only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
263
  echo '<td>' . "\n";
264
  echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
265
  echo '<textarea name="ws_plugin__s2member_ref_rev_notification_urls" id="ws-plugin--s2member-ref-rev-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_urls"]) . '</textarea><br />' . "\n";
266
+ echo 'Refund/Reversal Notifications take place silently behind-the-scene, using a cURL connection. Each URL will be notified every time a payment is refunded through PayPal® or a chargeback occurs.<br /><br />' . "\n";
267
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
268
  echo '<ul>' . "\n";
269
  echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remained constant throughout the lifetime of the membership.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the original Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime subscriptions are NOT recurring ( i.e. there was only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
315
  echo '<td>' . "\n";
316
  echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
317
  echo '<textarea name="ws_plugin__s2member_sp_notification_urls" id="ws-plugin--s2member-sp-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_notification_urls"]) . '</textarea><br />' . "\n";
318
+ echo 'Single-Page Notifications take place silently behind-the-scene, using a cURL connection. Each URL will be notified every time a sale occurs.<br /><br />' . "\n";
319
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
320
  echo '<ul>' . "\n";
321
+ echo '<li><code>%%sp_access_url%% = The full URL ( generated by s2Member ) where the Customer can gain access.</code></li>' . "\n";
322
+ echo '<li><code>%%sp_access_exp%% = Human readable expiration for %%sp_access_url%%. Ex: <em>( link expires in %%sp_access_exp%% )</em>.</code></li>' . "\n";
323
  echo '<li><code>%%txn_id%% = The PayPal® Transaction ID. PayPal® assigns a unique identifier for every purchase.</code></li>' . "\n";
324
  echo '<li><code>%%amount%% = The full Amount of the sale. Most affiliate programs calculate commissions from this.</code></li>' . "\n";
325
  echo '<li><code>%%first_name%% = The First Name of the Customer who purchased Single-Page Access through PayPal®.</code></li>' . "\n";
326
  echo '<li><code>%%last_name%% = The Last Name of the Customer who purchased Single-Page Access through PayPal®.</code></li>' . "\n";
327
  echo '<li><code>%%full_name%% = The Full Name ( First & Last ) of the Customer who purchased Single-Page Access.</code></li>' . "\n";
328
  echo '<li><code>%%payer_email%% = The Email Address of the Customer who purchased Single-Page Access through PayPal®.</code></li>' . "\n";
329
+ echo '<li><code>%%item_number%% = The Item Number. Ex: <em>sp:13:72</em> ( sp:page_ID:expiration_hours ).</code></li>' . "\n";
330
  echo '<li><code>%%item_name%% = The Item Name. In other words, a brief description, detailing what this purchase was for.</code></li>' . "\n";
331
  echo '</ul>' . "\n";
332
  echo '<strong>Custom replacement codes can also be inserted using these instructions:</strong>' . "\n";
includes/menu-pages/button.html CHANGED
@@ -17,7 +17,7 @@
17
  <!-- Identifies/Updates An Existing Member After Checkout -->
18
  <input type="hidden" name="on0" value="<?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0; ?>" />
19
  <input type="hidden" name="os0" value="<?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0; ?>" />
20
- <input type="hidden" name="modify" value="1" />
21
  <!-- Customizes Prices, Payments & Billing Cycle -->
22
  <!--<input type="hidden" name="amount" value="0.01" />-->
23
  <input type="hidden" name="src" value="1" />
17
  <!-- Identifies/Updates An Existing Member After Checkout -->
18
  <input type="hidden" name="on0" value="<?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0; ?>" />
19
  <input type="hidden" name="os0" value="<?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0; ?>" />
20
+ <input type="hidden" name="modify" value="0" />
21
  <!-- Customizes Prices, Payments & Billing Cycle -->
22
  <!--<input type="hidden" name="amount" value="0.01" />-->
23
  <input type="hidden" name="src" value="1" />
includes/menu-pages/buttons.inc.php CHANGED
@@ -36,7 +36,7 @@ if (get_option ("ws_plugin__s2member_configured") && $GLOBALS["WS_PLUGIN__"]["s2
36
  /**/
37
  echo '<div class="ws-menu-page-section ws-plugin--s2member-button-code-1-section">' . "\n";
38
  echo '<h3>Button Code Generator For Level #1 Access</h3>' . "\n";
39
- echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These special PayPal® Buttons are customized to work with s2Member seamlessly. Member accounts will be activated instantly, in an automated fashion. When you, or a Member, cancels their membership, or fails to make payments on time, s2Member will automatically terminate their membership privileges. s2Member makes extensive use of the PayPal® IPN service. s2Member receives updates from PayPal® behind-the-scenes.</p>' . "\n";
40
  echo '<p><em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one. If you\'re in Sandbox Test-Mode, and you\'re NOT using the Shortcode Format, please remember to come back and re-generate your Buttons before you go live.</em></p>' . "\n";
41
  /**/
42
  echo '<table class="form-table">' . "\n";
@@ -94,7 +94,7 @@ if (get_option ("ws_plugin__s2member_configured") && $GLOBALS["WS_PLUGIN__"]["s2
94
  /**/
95
  echo '<div class="ws-menu-page-section ws-plugin--s2member-button-code-2-section">' . "\n";
96
  echo '<h3>Button Code Generator For Level #2 Access</h3>' . "\n";
97
- echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These special PayPal® Buttons are customized to work with s2Member seamlessly. Member accounts will be activated instantly, in an automated fashion. When you, or a Member, cancels their membership, or fails to make payments on time, s2Member will automatically terminate their membership privileges. s2Member makes extensive use of the PayPal® IPN service. s2Member receives updates from PayPal® behind-the-scenes.</p>' . "\n";
98
  echo '<p><em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one. If you\'re in Sandbox Test-Mode, and you\'re NOT using the Shortcode Format, please remember to come back and re-generate your Buttons before you go live.</em></p>' . "\n";
99
  /**/
100
  echo '<table class="form-table">' . "\n";
@@ -152,7 +152,7 @@ if (get_option ("ws_plugin__s2member_configured") && $GLOBALS["WS_PLUGIN__"]["s2
152
  /**/
153
  echo '<div class="ws-menu-page-section ws-plugin--s2member-button-code-3-section">' . "\n";
154
  echo '<h3>Button Code Generator For Level #3 Access</h3>' . "\n";
155
- echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These special PayPal® Buttons are customized to work with s2Member seamlessly. Member accounts will be activated instantly, in an automated fashion. When you, or a Member, cancels their membership, or fails to make payments on time, s2Member will automatically terminate their membership privileges. s2Member makes extensive use of the PayPal® IPN service. s2Member receives updates from PayPal® behind-the-scenes.</p>' . "\n";
156
  echo '<p><em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one. If you\'re in Sandbox Test-Mode, and you\'re NOT using the Shortcode Format, please remember to come back and re-generate your Buttons before you go live.</em></p>' . "\n";
157
  /**/
158
  echo '<table class="form-table">' . "\n";
@@ -210,7 +210,7 @@ if (get_option ("ws_plugin__s2member_configured") && $GLOBALS["WS_PLUGIN__"]["s2
210
  /**/
211
  echo '<div class="ws-menu-page-section ws-plugin--s2member-button-code-4-section">' . "\n";
212
  echo '<h3>Button Code Generator For Level #4 Access</h3>' . "\n";
213
- echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These special PayPal® Buttons are customized to work with s2Member seamlessly. Member accounts will be activated instantly, in an automated fashion. When you, or a Member, cancels their membership, or fails to make payments on time, s2Member will automatically terminate their membership privileges. s2Member makes extensive use of the PayPal® IPN service. s2Member receives updates from PayPal® behind-the-scenes.</p>' . "\n";
214
  echo '<p><em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one. If you\'re in Sandbox Test-Mode, and you\'re NOT using the Shortcode Format, please remember to come back and re-generate your Buttons before you go live.</em></p>' . "\n";
215
  /**/
216
  echo '<table class="form-table">' . "\n";
@@ -332,7 +332,7 @@ if (get_option ("ws_plugin__s2member_configured") && $GLOBALS["WS_PLUGIN__"]["s2
332
  echo '<div class="ws-menu-page-section ws-plugin--s2member-cancellation-section">' . "\n";
333
  echo '<h3>One Button Does It All For Cancellations ( copy/paste )</h3>' . "\n";
334
  echo '<p>Since every paid Membership is associated with a PayPal® Subscription; and every PayPal® Subscription is associated with a PayPal® Account; your Members will always have a PayPal® Account of their own, which is tied to their Membership with you. So... a Member can simply log into their own PayPal® account and cancel their subscription(s) with you at anytime, all on their own. However, some Customers do not realize this. So, if you would like to make it clearer ( easier ) for Members to cancel their own subscription(s), you can provide this Cancellation Button for them on your Login Welcome Page, or somewhere in the support section of your website. Note... you don\'t have to use this Cancellation Button at all, if you don\'t want to. It\'s completely optional.</p>' . "\n";
335
- echo '<p><em><strong>*Cancellation Process*</strong> Very simple. A Member clicks the Cancellation Button. PayPal® asks them to log into their PayPal® account. Once they\'re logged in, PayPal® will display a list of all active subscriptions they have with you. They choose which ones they want to cancel, and s2Member is notified silently behind the scenes, through the PayPal® IPN service.</em></p>' . "\n";
336
  /**/
337
  echo '<table class="form-table">' . "\n";
338
  echo '<tbody>' . "\n";
@@ -382,7 +382,7 @@ if (get_option ("ws_plugin__s2member_configured") && $GLOBALS["WS_PLUGIN__"]["s2
382
  /**/
383
  echo '<div class="ws-menu-page-section ws-plugin--s2member-sp-section">' . "\n";
384
  echo '<h3>Button Code Generator For Single-Page Buy Now Buttons</h3>' . "\n";
385
- echo '<p>s2Member now supports an additional layer of functionality ( very powerful ), which allows you to sell access to specific Pages that you\'ve created in WordPress®. Single-Page Access works independently from Member Level Access. That is, you can sell an unlimited number of Pages using "Buy Now" Buttons, and your Customers will NOT be required to have a Membership Account with your site in order to receive access. If they are already a Member, that\'s fine, but they won\'t need to be. In other words, Customers will NOT need to login, just to receive access to the Single-Page they purchased access to. s2Member will immediately redirect the Customer to the Single-Page after checkout is completed successfully. An email is also sent to the Customer with a link ( see: <code>s2Member -> PayPal® Options -> Single-Page Email</code> ). Authentication is handled automatically through self-expiring links, good for 72 hours.</p>' . "\n";
386
  echo '<p>Single-Page Access, is sort of like selling a product. Only, instead of shipping anything to the Customer, you just give them access to a specific Page on your site; one that you created in WordPress®. A Single-Page that is protected by s2Member, might contain a download link for your eBook, access to file &amp; music downloads, access to additional support services, and the list goes on and on. The possibilities with this are endless; as long as your digital product can be delivered through access to a WordPress® Page that you\'ve created. To protect Single-Pages, please see: <code>s2Member -> General Options -> Single-Page Access Restrictions</code>. Once you\'ve configured your Single-Page Restrictions, those Pages will be available in the drop-down menu below.</p>' . "\n";
387
  echo '<p>Very simple. All you do is customize the form fields provided, for each Page that you plan to sell. Then press (Generate Button Code). These special PayPal® Buttons are customized to work with s2Member seamlessly.</p>' . "\n";
388
  echo '<p><em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your WordPress® Editor, wherever you feel it would be most appropriate. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one. If you\'re in Sandbox Test-Mode, and you\'re NOT using the Shortcode Format, please remember to come back and re-generate your Buttons before you go live.</em></p>' . "\n";
@@ -417,7 +417,7 @@ if (get_option ("ws_plugin__s2member_configured") && $GLOBALS["WS_PLUGIN__"]["s2
417
  /**/
418
  echo '</select></p>' . "\n";
419
  echo '<p>Description: <input type="text" id="ws-plugin--s2member-sp-desc" value="" size="68" /></p>' . "\n";
420
- echo '<p>I want to charge: $<input type="text" id="ws-plugin--s2member-sp-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-sp-term"><option value="72-H">Buy Now ( Single-Page Link, valid for 72 hours )</option></select></p>' . "\n";
421
  echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal® account. PayPal® allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\'); return false;">[?]</a>: <input type="text" id="ws-plugin--s2member-sp-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-sp-currency"><optgroup label="Currency"><option value="USD" title="U.S. Dollar">USD</option><option value="AUD" title="Australian Dollar">AUD</option><option value="BRL" title="Brazilian Real">BRL</option><option value="CAD" title="Canadian Dollar">CAD</option><option value="CZK" title="Czech Koruna">CZK</option><option value="DKK" title="Danish Krone">DKK</option><option value="EUR" title="Euro">EUR</option><option value="HKD" title="Hong Kong Dollar">HKD</option><option value="HUF" title="Hungarian Forint">HUF</option><option value="ILS" title="Israeli New Sheqel">ILS</option><option value="JPY" title="Japanese Yen">JPY</option><option value="MYR" title="Malaysian Ringgit">MYR</option><option value="MXN" title="Mexican Peso">MXN</option><option value="NOK" title="Norwegian Krone">NOK</option><option value="NZD" title="New Zealand Dollar">NZD</option><option value="PHP" title="Philippine Peso">PHP</option><option value="PLN" title="Polish Zloty">PLN</option><option value="GBP" title="Pound Sterling">GBP</option><option value="SGD" title="Singapore Dollar">SGD</option><option value="SEK" title="Swedish Krona">SEK</option><option value="CHF" title="Swiss Franc">CHF</option><option value="TWD" title="Taiwan New Dollar">TWD</option><option value="THB" title="Thai Baht">THB</option><option value="USD" title="U.S. Dollar">USD</option></optgroup></select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalSpButtonGenerate();" class="button-primary" /></p>' . "\n";
422
  echo '</td>' . "\n";
423
  /**/
@@ -449,8 +449,8 @@ if (get_option ("ws_plugin__s2member_configured") && $GLOBALS["WS_PLUGIN__"]["s2
449
  /**/
450
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
451
  /**/
452
- echo '<h3>Single-Page Link Generator ( good for 72 hours )</h3>' . "\n";
453
- echo '<p>s2Member automatically generates Single-Page Links for your Customers after checkout, and also sends them a link in a Confirmation Email. However, if you ever need to deal with a Customer Service issue that requires a new Single-Page Link to be created, you can use this tool for that. Single-Page Links are valid for 72 hours.</p>' . "\n";
454
  /**/
455
  echo '<table class="form-table">' . "\n";
456
  echo '<tbody>' . "\n";
@@ -470,7 +470,7 @@ if (get_option ("ws_plugin__s2member_configured") && $GLOBALS["WS_PLUGIN__"]["s2
470
  if (!in_array ($ws_plugin__s2member_temp_o->ID, preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_pages"])))
471
  echo '<option value="' . esc_attr ($ws_plugin__s2member_temp_o->ID) . '">' . esc_html ($ws_plugin__s2member_temp_o->post_title) . '</option>' . "\n";
472
  /**/
473
- echo '</select> <input type="button" value="Generate Link" onclick="ws_plugin__s2member_paypalSpLinkGenerate();" class="button-primary" /> <img id="ws-plugin--s2member-sp-link-loading" src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/ajax-loader.gif" alt="" style="display:none;" /></p>' . "\n";
474
  /**/
475
  echo '<p id="ws-plugin--s2member-sp-link" style="font-family:Consolas, monospace; display:none;"></p>' . "\n";
476
  echo '</td>' . "\n";
36
  /**/
37
  echo '<div class="ws-menu-page-section ws-plugin--s2member-button-code-1-section">' . "\n";
38
  echo '<h3>Button Code Generator For Level #1 Access</h3>' . "\n";
39
+ echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These special PayPal® Buttons are customized to work with s2Member seamlessly. Member accounts will be activated instantly, in an automated fashion. When you, or a Member, cancels their membership, or fails to make payments on time, s2Member will automatically terminate their membership privileges. s2Member makes extensive use of the PayPal® IPN service. s2Member receives updates from PayPal® behind-the-scene.</p>' . "\n";
40
  echo '<p><em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one. If you\'re in Sandbox Test-Mode, and you\'re NOT using the Shortcode Format, please remember to come back and re-generate your Buttons before you go live.</em></p>' . "\n";
41
  /**/
42
  echo '<table class="form-table">' . "\n";
94
  /**/
95
  echo '<div class="ws-menu-page-section ws-plugin--s2member-button-code-2-section">' . "\n";
96
  echo '<h3>Button Code Generator For Level #2 Access</h3>' . "\n";
97
+ echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These special PayPal® Buttons are customized to work with s2Member seamlessly. Member accounts will be activated instantly, in an automated fashion. When you, or a Member, cancels their membership, or fails to make payments on time, s2Member will automatically terminate their membership privileges. s2Member makes extensive use of the PayPal® IPN service. s2Member receives updates from PayPal® behind-the-scene.</p>' . "\n";
98
  echo '<p><em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one. If you\'re in Sandbox Test-Mode, and you\'re NOT using the Shortcode Format, please remember to come back and re-generate your Buttons before you go live.</em></p>' . "\n";
99
  /**/
100
  echo '<table class="form-table">' . "\n";
152
  /**/
153
  echo '<div class="ws-menu-page-section ws-plugin--s2member-button-code-3-section">' . "\n";
154
  echo '<h3>Button Code Generator For Level #3 Access</h3>' . "\n";
155
+ echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These special PayPal® Buttons are customized to work with s2Member seamlessly. Member accounts will be activated instantly, in an automated fashion. When you, or a Member, cancels their membership, or fails to make payments on time, s2Member will automatically terminate their membership privileges. s2Member makes extensive use of the PayPal® IPN service. s2Member receives updates from PayPal® behind-the-scene.</p>' . "\n";
156
  echo '<p><em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one. If you\'re in Sandbox Test-Mode, and you\'re NOT using the Shortcode Format, please remember to come back and re-generate your Buttons before you go live.</em></p>' . "\n";
157
  /**/
158
  echo '<table class="form-table">' . "\n";
210
  /**/
211
  echo '<div class="ws-menu-page-section ws-plugin--s2member-button-code-4-section">' . "\n";
212
  echo '<h3>Button Code Generator For Level #4 Access</h3>' . "\n";
213
+ echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These special PayPal® Buttons are customized to work with s2Member seamlessly. Member accounts will be activated instantly, in an automated fashion. When you, or a Member, cancels their membership, or fails to make payments on time, s2Member will automatically terminate their membership privileges. s2Member makes extensive use of the PayPal® IPN service. s2Member receives updates from PayPal® behind-the-scene.</p>' . "\n";
214
  echo '<p><em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one. If you\'re in Sandbox Test-Mode, and you\'re NOT using the Shortcode Format, please remember to come back and re-generate your Buttons before you go live.</em></p>' . "\n";
215
  /**/
216
  echo '<table class="form-table">' . "\n";
332
  echo '<div class="ws-menu-page-section ws-plugin--s2member-cancellation-section">' . "\n";
333
  echo '<h3>One Button Does It All For Cancellations ( copy/paste )</h3>' . "\n";
334
  echo '<p>Since every paid Membership is associated with a PayPal® Subscription; and every PayPal® Subscription is associated with a PayPal® Account; your Members will always have a PayPal® Account of their own, which is tied to their Membership with you. So... a Member can simply log into their own PayPal® account and cancel their subscription(s) with you at anytime, all on their own. However, some Customers do not realize this. So, if you would like to make it clearer ( easier ) for Members to cancel their own subscription(s), you can provide this Cancellation Button for them on your Login Welcome Page, or somewhere in the support section of your website. Note... you don\'t have to use this Cancellation Button at all, if you don\'t want to. It\'s completely optional.</p>' . "\n";
335
+ echo '<p><em><strong>*Cancellation Process*</strong> Very simple. A Member clicks the Cancellation Button. PayPal® asks them to log into their PayPal® account. Once they\'re logged in, PayPal® will display a list of all active subscriptions they have with you. They choose which ones they want to cancel, and s2Member is notified silently behind-the-scene, through the PayPal® IPN service.</em></p>' . "\n";
336
  /**/
337
  echo '<table class="form-table">' . "\n";
338
  echo '<tbody>' . "\n";
382
  /**/
383
  echo '<div class="ws-menu-page-section ws-plugin--s2member-sp-section">' . "\n";
384
  echo '<h3>Button Code Generator For Single-Page Buy Now Buttons</h3>' . "\n";
385
+ echo '<p>s2Member now supports an additional layer of functionality ( very powerful ), which allows you to sell access to specific Pages that you\'ve created in WordPress®. Single-Page Access works independently from Member Level Access. That is, you can sell an unlimited number of Pages using "Buy Now" Buttons, and your Customers will NOT be required to have a Membership Account with your site in order to receive access. If they are already a Member, that\'s fine, but they won\'t need to be. In other words, Customers will NOT need to login, just to receive access to the Single-Page they purchased access to. s2Member will immediately redirect the Customer to the Single-Page after checkout is completed successfully. An email is also sent to the Customer with a link ( see: <code>s2Member -> PayPal® Options -> Single-Page Email</code> ). Authentication is handled automatically through self-expiring links, good for 72 hours by default.</p>' . "\n";
386
  echo '<p>Single-Page Access, is sort of like selling a product. Only, instead of shipping anything to the Customer, you just give them access to a specific Page on your site; one that you created in WordPress®. A Single-Page that is protected by s2Member, might contain a download link for your eBook, access to file &amp; music downloads, access to additional support services, and the list goes on and on. The possibilities with this are endless; as long as your digital product can be delivered through access to a WordPress® Page that you\'ve created. To protect Single-Pages, please see: <code>s2Member -> General Options -> Single-Page Access Restrictions</code>. Once you\'ve configured your Single-Page Restrictions, those Pages will be available in the drop-down menu below.</p>' . "\n";
387
  echo '<p>Very simple. All you do is customize the form fields provided, for each Page that you plan to sell. Then press (Generate Button Code). These special PayPal® Buttons are customized to work with s2Member seamlessly.</p>' . "\n";
388
  echo '<p><em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your WordPress® Editor, wherever you feel it would be most appropriate. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one. If you\'re in Sandbox Test-Mode, and you\'re NOT using the Shortcode Format, please remember to come back and re-generate your Buttons before you go live.</em></p>' . "\n";
417
  /**/
418
  echo '</select></p>' . "\n";
419
  echo '<p>Description: <input type="text" id="ws-plugin--s2member-sp-desc" value="" size="68" /></p>' . "\n";
420
+ echo '<p>I want to charge: $<input type="text" id="ws-plugin--s2member-sp-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-sp-hours"><optgroup label="Expires In Hours"><option value="2">Buy Now ( Single-Page Link, valid for 2 hours )</option><option value="4">Buy Now ( Single-Page Link, valid for 4 hours )</option><option value="6">Buy Now ( Single-Page Link, valid for 6 hours )</option><option value="8">Buy Now ( Single-Page Link, valid for 8 hours )</option><option value="10">Buy Now ( Single-Page Link, valid for 10 hours )</option><option value="12">Buy Now ( Single-Page Link, valid for 12 hours )</option></optgroup><optgroup label="Expires In Days"><option value="24">Buy Now ( Single-Page Link, valid for 1 day )</option><option value="48">Buy Now ( Single-Page Link, valid for 2 days )</option><option value="72" selected="selected">Buy Now ( Single-Page Link, valid for 3 days )</option><option value="96">Buy Now ( Single-Page Link, valid for 4 days )</option><option value="120">Buy Now ( Single-Page Link, valid for 5 days )</option><option value="144">Buy Now ( Single-Page Link, valid for 6 days )</option></optgroup><optgroup label="Expires In Weeks"><option value="168">Buy Now ( Single-Page Link, valid for 1 week )</option><option value="336">Buy Now ( Single-Page Link, valid for 2 weeks )</option><option value="504">Buy Now ( Single-Page Link, valid for 3 weeks )</option></optgroup><optgroup label="Expires In Months"><option value="720">Buy Now ( Single-Page Link, valid for 1 month )</option><option value="1440">Buy Now ( Single-Page Link, valid for 2 months )</option><option value="2190">Buy Now ( Single-Page Link, valid for 3 months )</option><option value="4380">Buy Now ( Single-Page Link, valid for 6 months )</option></optgroup><optgroup label="Expires In Years"><option value="8760">Buy Now ( Single-Page Link, valid for 1 year )</option><option value="17520">Buy Now ( Single-Page Link, valid for 2 years )</option><option value="26280">Buy Now ( Single-Page Link, valid for 3 years )</option><option value="35040">Buy Now ( Single-Page Link, valid for 4 years )</option><option value="43800">Buy Now ( Single-Page Link, valid for 5 years )</option></optgroup></select></p>' . "\n";
421
  echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal® account. PayPal® allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\'); return false;">[?]</a>: <input type="text" id="ws-plugin--s2member-sp-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-sp-currency"><optgroup label="Currency"><option value="USD" title="U.S. Dollar">USD</option><option value="AUD" title="Australian Dollar">AUD</option><option value="BRL" title="Brazilian Real">BRL</option><option value="CAD" title="Canadian Dollar">CAD</option><option value="CZK" title="Czech Koruna">CZK</option><option value="DKK" title="Danish Krone">DKK</option><option value="EUR" title="Euro">EUR</option><option value="HKD" title="Hong Kong Dollar">HKD</option><option value="HUF" title="Hungarian Forint">HUF</option><option value="ILS" title="Israeli New Sheqel">ILS</option><option value="JPY" title="Japanese Yen">JPY</option><option value="MYR" title="Malaysian Ringgit">MYR</option><option value="MXN" title="Mexican Peso">MXN</option><option value="NOK" title="Norwegian Krone">NOK</option><option value="NZD" title="New Zealand Dollar">NZD</option><option value="PHP" title="Philippine Peso">PHP</option><option value="PLN" title="Polish Zloty">PLN</option><option value="GBP" title="Pound Sterling">GBP</option><option value="SGD" title="Singapore Dollar">SGD</option><option value="SEK" title="Swedish Krona">SEK</option><option value="CHF" title="Swiss Franc">CHF</option><option value="TWD" title="Taiwan New Dollar">TWD</option><option value="THB" title="Thai Baht">THB</option><option value="USD" title="U.S. Dollar">USD</option></optgroup></select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalSpButtonGenerate();" class="button-primary" /></p>' . "\n";
422
  echo '</td>' . "\n";
423
  /**/
449
  /**/
450
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
451
  /**/
452
+ echo '<h3>Single-Page Link Generator ( for Customer Service )</h3>' . "\n";
453
+ echo '<p>s2Member automatically generates Single-Page Links for your Customers after checkout, and also sends them a link in a Confirmation Email. However, if you ever need to deal with a Customer Service issue that requires a new Single-Page Link to be created, you can use this tool for that.</p>' . "\n";
454
  /**/
455
  echo '<table class="form-table">' . "\n";
456
  echo '<tbody>' . "\n";
470
  if (!in_array ($ws_plugin__s2member_temp_o->ID, preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_pages"])))
471
  echo '<option value="' . esc_attr ($ws_plugin__s2member_temp_o->ID) . '">' . esc_html ($ws_plugin__s2member_temp_o->post_title) . '</option>' . "\n";
472
  /**/
473
+ echo '</select> <select id="ws-plugin--s2member-sp-link-hours"><optgroup label="Hours"><option value="2">valid for 2 hours</option><option value="4">valid for 4 hours</option><option value="6">valid for 6 hours</option><option value="8">valid for 8 hours</option><option value="10">valid for 10 hours</option><option value="12">valid for 12 hours</option></optgroup><optgroup label="Days"><option value="24">valid for 1 day</option><option value="48">valid for 2 days</option><option value="72" selected="selected">valid for 3 days</option><option value="96">valid for 4 days</option><option value="120">valid for 5 days</option><option value="144">valid for 6 days</option></optgroup><optgroup label="Weeks"><option value="168">valid for 1 week</option><option value="336">valid for 2 weeks</option><option value="504">valid for 3 weeks</option></optgroup><optgroup label="Months"><option value="720">valid for 1 month</option><option value="1440">valid for 2 months</option><option value="2190">valid for 3 months</option><option value="4380">valid for 6 months</option></optgroup><optgroup label="Years"><option value="8760">valid for 1 year</option><option value="17520">valid for 2 years</option><option value="26280">valid for 3 years</option><option value="35040">valid for 4 years</option><option value="43800">valid for 5 years</option></optgroup></select> <input type="button" value="Generate Link" onclick="ws_plugin__s2member_paypalSpLinkGenerate();" class="button-primary" /> <img id="ws-plugin--s2member-sp-link-loading" src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/ajax-loader.gif" alt="" style="display:none;" /></p>' . "\n";
474
  /**/
475
  echo '<p id="ws-plugin--s2member-sp-link" style="font-family:Consolas, monospace; display:none;"></p>' . "\n";
476
  echo '</td>' . "\n";
includes/menu-pages/code-samples/idev-signup-tracking-code.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ idev_saleamt=%%initial%%
2
+ idev_ordernum=%%subscr_id%%
3
+
4
+ <img src="http://www.example.com/idevaffiliate/sale.php
5
+ ?profile=123&idev_saleamt=%%initial%%&idev_ordernum=%%subscr_id%%"
6
+ width="1" height="1" border="0" />
includes/menu-pages/code-samples/sas-signup-tracking-code.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ amount=%%initial%%
2
+ tracking=%%subscr_id%%
3
+
4
+ <img src="https://shareasale.com/sale.cfm
5
+ ?amount=%%initial%%&tracking=%%subscr_id%%&transtype=SALE&merchantID=123"
6
+ width="1" height="1" border="0" />
includes/menu-pages/menu-pages.js CHANGED
@@ -196,6 +196,7 @@ jQuery(document).ready (function($)
196
  code.val (code.val ().replace (/ name\="page_style" value\="(.*?)"/, ' name="page_style" value="' + pageStyle + '"'));
197
  code.val (code.val ().replace (/ name\="currency_code" value\="(.*?)"/, ' name="currency_code" value="' + currencyCode + '"'));
198
  code.val (code.val ().replace (/ name\="custom" value\="(.*?)"/, ' name="custom" value="<?php echo $_SERVER["HTTP_HOST"]; ?>"'));
 
199
  code.val (code.val ().replace (/ name\="amount" value\="(.*?)"/, ' name="amount" value="' + regAmount + '"'));
200
  code.val (code.val ().replace (/ name\="src" value\="(.*?)"/, ' name="src" value="' + regRecur + '"'));
201
  code.val (code.val ().replace (/ name\="p1" value\="(.*?)"/, ' name="p1" value="' + trialPeriod + '"'));
@@ -227,6 +228,7 @@ jQuery(document).ready (function($)
227
  var code = $('textarea#ws-plugin--s2member-sp-button');
228
  /**/
229
  var page = $('select#ws-plugin--s2member-sp-page').val ().replace (/[^0-9]/g, '');
 
230
  var desc = $.trim ($('input#ws-plugin--s2member-sp-desc').val ().replace (/"/g, ''));
231
  /**/
232
  if (!page) /* Must have a Page ID to work with. Otherwise, the purchase would fail. */
@@ -244,12 +246,12 @@ jQuery(document).ready (function($)
244
  var pageStyle = $.trim ($('input#ws-plugin--s2member-sp-page-style').val ().replace (/"/g, ''));
245
  var currencyCode = $('select#ws-plugin--s2member-sp-currency').val ().replace (/[^A-Z]/g, '');
246
  /**/
247
- shortCodeTemplateAttrs += 'page="' + page + '" desc="' + desc + '" ps="' + pageStyle + '" cc="' + currencyCode + '"';
248
  shortCodeTemplateAttrs += ' custom="<?php echo $_SERVER["HTTP_HOST"]; ?>" ra="' + regAmount + '" sp="1"';
249
  shortCode.val (shortCodeTemplate.replace (/%%attrs%%/, shortCodeTemplateAttrs));
250
  /**/
251
  code.val (code.val ().replace (/ name\="item_name" value\="(.*?)"/, ' name="item_name" value="' + desc + '"'));
252
- code.val (code.val ().replace (/ name\="item_number" value\="(.*?)"/, ' name="item_number" value="sp:' + page + '"'));
253
  code.val (code.val ().replace (/ name\="page_style" value\="(.*?)"/, ' name="page_style" value="' + pageStyle + '"'));
254
  code.val (code.val ().replace (/ name\="currency_code" value\="(.*?)"/, ' name="currency_code" value="' + currencyCode + '"'));
255
  code.val (code.val ().replace (/ name\="custom" value\="(.*?)"/, ' name="custom" value="<?php echo $_SERVER["HTTP_HOST"]; ?>"'));
@@ -270,6 +272,7 @@ jQuery(document).ready (function($)
270
  ws_plugin__s2member_paypalSpLinkGenerate = function() /* Handles PayPal® Link Generation for Single-Page access. */
271
  {
272
  var page = $('select#ws-plugin--s2member-sp-link-page').val ().replace (/[^0-9]/g, '');
 
273
  var $link = $('p#ws-plugin--s2member-sp-link'), $loading = $('img#ws-plugin--s2member-sp-link-loading');
274
  /**/
275
  if (!page) /* Must have a Page ID to work with. Otherwise, link generation would fail. */
@@ -278,7 +281,7 @@ jQuery(document).ready (function($)
278
  return false;
279
  }
280
  /**/
281
- $link.hide (), $loading.show (), $.post (ajaxurl, {action: 's2member_sp_access_link', s2member_sp_access_link: '<?php echo ws_plugin__s2member_esc_sq (wp_create_nonce ("ws-plugin--s2member-sp-access-link")); ?>', s2member_sp_access_link_page: page}, function(response)
282
  {
283
  $link.show ().html ('<a href="' + response + '" target="_blank" rel="xlink">' + response + '</a>'), $loading.hide ();
284
  });
196
  code.val (code.val ().replace (/ name\="page_style" value\="(.*?)"/, ' name="page_style" value="' + pageStyle + '"'));
197
  code.val (code.val ().replace (/ name\="currency_code" value\="(.*?)"/, ' name="currency_code" value="' + currencyCode + '"'));
198
  code.val (code.val ().replace (/ name\="custom" value\="(.*?)"/, ' name="custom" value="<?php echo $_SERVER["HTTP_HOST"]; ?>"'));
199
+ code.val (code.val ().replace (/ name\="modify" value\="(.*?)"/, ' name="modify" value="' + ((button === 'modification') ? '1' : '0') + '"'));
200
  code.val (code.val ().replace (/ name\="amount" value\="(.*?)"/, ' name="amount" value="' + regAmount + '"'));
201
  code.val (code.val ().replace (/ name\="src" value\="(.*?)"/, ' name="src" value="' + regRecur + '"'));
202
  code.val (code.val ().replace (/ name\="p1" value\="(.*?)"/, ' name="p1" value="' + trialPeriod + '"'));
228
  var code = $('textarea#ws-plugin--s2member-sp-button');
229
  /**/
230
  var page = $('select#ws-plugin--s2member-sp-page').val ().replace (/[^0-9]/g, '');
231
+ var hours = $('select#ws-plugin--s2member-sp-hours').val ().replace (/[^0-9]/g, '');
232
  var desc = $.trim ($('input#ws-plugin--s2member-sp-desc').val ().replace (/"/g, ''));
233
  /**/
234
  if (!page) /* Must have a Page ID to work with. Otherwise, the purchase would fail. */
246
  var pageStyle = $.trim ($('input#ws-plugin--s2member-sp-page-style').val ().replace (/"/g, ''));
247
  var currencyCode = $('select#ws-plugin--s2member-sp-currency').val ().replace (/[^A-Z]/g, '');
248
  /**/
249
+ shortCodeTemplateAttrs += 'page="' + page + '" exp="' + hours + '" desc="' + desc + '" ps="' + pageStyle + '" cc="' + currencyCode + '"';
250
  shortCodeTemplateAttrs += ' custom="<?php echo $_SERVER["HTTP_HOST"]; ?>" ra="' + regAmount + '" sp="1"';
251
  shortCode.val (shortCodeTemplate.replace (/%%attrs%%/, shortCodeTemplateAttrs));
252
  /**/
253
  code.val (code.val ().replace (/ name\="item_name" value\="(.*?)"/, ' name="item_name" value="' + desc + '"'));
254
+ code.val (code.val ().replace (/ name\="item_number" value\="(.*?)"/, ' name="item_number" value="sp:' + page + ':' + hours + '"'));
255
  code.val (code.val ().replace (/ name\="page_style" value\="(.*?)"/, ' name="page_style" value="' + pageStyle + '"'));
256
  code.val (code.val ().replace (/ name\="currency_code" value\="(.*?)"/, ' name="currency_code" value="' + currencyCode + '"'));
257
  code.val (code.val ().replace (/ name\="custom" value\="(.*?)"/, ' name="custom" value="<?php echo $_SERVER["HTTP_HOST"]; ?>"'));
272
  ws_plugin__s2member_paypalSpLinkGenerate = function() /* Handles PayPal® Link Generation for Single-Page access. */
273
  {
274
  var page = $('select#ws-plugin--s2member-sp-link-page').val ().replace (/[^0-9]/g, '');
275
+ var hours = $('select#ws-plugin--s2member-sp-link-hours').val ().replace (/[^0-9]/g, '');
276
  var $link = $('p#ws-plugin--s2member-sp-link'), $loading = $('img#ws-plugin--s2member-sp-link-loading');
277
  /**/
278
  if (!page) /* Must have a Page ID to work with. Otherwise, link generation would fail. */
281
  return false;
282
  }
283
  /**/
284
+ $link.hide (), $loading.show (), $.post (ajaxurl, {action: 's2member_sp_access_link', s2member_sp_access_link: '<?php echo ws_plugin__s2member_esc_sq (wp_create_nonce ("ws-plugin--s2member-sp-access-link")); ?>', s2member_sp_access_link_page: page, s2member_sp_access_link_hours: hours}, function(response)
285
  {
286
  $link.show ().html ('<a href="' + response + '" target="_blank" rel="xlink">' + response + '</a>'), $loading.hide ();
287
  });
includes/menu-pages/paypal-ops.inc.php CHANGED
@@ -93,6 +93,8 @@ echo '</td>' . "\n";
93
  echo '</tr>' . "\n";
94
  echo '</tbody>' . "\n";
95
  echo '</table>' . "\n";
 
 
96
  echo '</div>' . "\n";
97
  /**/
98
  echo '</div>' . "\n";
@@ -105,7 +107,7 @@ echo '<p>Log into your PayPal® account and navigate to this section:<br /><code
105
  echo '<p>Edit your IPN settings &amp; turn IPN Notifications: <strong><code>On</code></strong></p>' . "\n";
106
  echo '<p>You\'ll need your IPN URL, which is:<br /><code>' . get_bloginfo ("url") . '/?s2member_paypal_notify=1</code></p>' . "\n";
107
  echo '<p><strong>Quick tip:</strong> In addition to the default IPN Settings inside your PayPal® account, the IPN URL is also set on a per-transaction basis by the special PayPal® Button Code that s2Member provides you with. In other words, if you have multiple sites operating on one PayPal® account, that\'s OK. s2Member dynamically sets the IPN URL for each transaction. The result is that the IPN URL configured from within your PayPal® account, becomes the default, which is then overwritten on a per transaction basis. In fact, PayPal® recently updated their system to support IPN URL preservation. One PayPal® account can handle multiple sites, all using different IPN URLs.' . "\n";
108
- echo '<p><strong>More information:</strong> You\'ll be happy to know that s2Member handles cancellations, expirations, failed payments ( more than 2 in a row ), terminations ( e.g. refunds &amp; chargebacks ) for you automatically. If you log into your PayPal® account and cancel a Member\'s subscription, or, if the Member logs into their PayPal® account and cancels their own subscription, s2Member will be notified of these important changes and react accordingly through the PayPal® IPN service that runs silently behind the scenes. The PayPal® IPN service will notify s2Member whenever a Member\'s payments have been failing ( more than 2 times in a row ), and/or whenever a Member\'s subscription has expired for any reason. Even refunds &amp; chargeback reversals are supported through the IPN service. If you issue a refund to an unhappy Customer through PayPal®, s2Member will be notified, and the account for that Customer will either be demote to a Free Subscriber, or deleted automatically ( based on your configuration ). The communication from PayPal® -> s2Member is seamless.</p>' . "\n";
109
  echo '</div>' . "\n";
110
  /**/
111
  echo '</div>' . "\n";
@@ -188,7 +190,7 @@ echo '<strong>You can also use these special replacement codes if you need them:
188
  echo '<ul>' . "\n";
189
  echo '<li><code>%%registration_url%% = The full URL ( generated by s2Member ) where the Customer can get registered.</code></li>' . "\n";
190
  echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
191
- echo '<li><code>%%initial%% = The Initial Fee charged during signup. If you offered a free trial, this will be 0.</code> [ <a href="#" onclick="alert(\'If no initial period was offered or required, this initial amount will be equal to the %%regular%% rate. In other words, this will always represent the amount of money the Customer spent whenever they signed up, no matter what.\\n\\nIf a user signs up under the terms of a free trial period, this will be 0.\'); return false;">?</a> ]</li>' . "\n";
192
  echo '<li><code>%%regular%% = The Regular Amount of the subscription. This value is always > 0, no matter what.</code> [ <a href="#" onclick="alert(\'This is how much the subscription costs after an initial period expires. The %%regular%% rate is always > 0. If you did not offer an initial period, %%initial%% and %%regular%% will be equal to the same thing.\'); return false;">?</a> ]</li>' . "\n";
193
  echo '<li><code>%%recurring%% = This is the amount that will be charged on a Recurring basis, or 0 if non-Recurring.</code> [ <a href="#" onclick="alert(\'If recurring payments have not been required, this will be equal to 0. That being said, %%regular%% &amp; %%recurring%% are usually the same value. This variable can be used in two different ways. You can use it to determine what the regular recurring rate is, or to determine whether the subscription will recur or not. If it is going to recur, %%recurring%% will be > 0.\\n\\nThe only time this is NOT equal to the %%regular%% rate, is when recurring payments are not required; and only a one-time regular rate applies.\'); return false;">?</a> ]</li>' . "\n";
194
  echo '<li><code>%%first_name%% = The First Name of the Customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
@@ -258,14 +260,15 @@ echo '<textarea name="ws_plugin__s2member_single_page_email_message" id="ws-plug
258
  echo 'Message Body used in the email sent to a Customer after a successful purchase has occurred through PayPal® for Single-Page Access.<br /><br />' . "\n";
259
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
260
  echo '<ul>' . "\n";
261
- echo '<li><code>%%sp_access_url%% = The full URL ( generated by s2Member ) where the Customer can gain access. Valid for 72 hours.</code></li>' . "\n";
 
262
  echo '<li><code>%%txn_id%% = The PayPal® Transaction ID. PayPal® assigns a unique identifier for every purchase.</code></li>' . "\n";
263
  echo '<li><code>%%amount%% = The full Amount that you charged for Single-Page Access. This value will always be > 0.</code></li>' . "\n";
264
  echo '<li><code>%%first_name%% = The First Name of the Customer who purchased Single-Page Access through PayPal®.</code></li>' . "\n";
265
  echo '<li><code>%%last_name%% = The Last Name of the Customer who purchased Single-Page Access through PayPal®.</code></li>' . "\n";
266
  echo '<li><code>%%full_name%% = The Full Name ( First & Last ) of the Customer who purchased Single-Page Access.</code></li>' . "\n";
267
  echo '<li><code>%%payer_email%% = The Email Address of the Customer who purchased Single-Page Access through PayPal®.</code></li>' . "\n";
268
- echo '<li><code>%%item_number%% = The Item Number. Ex: <em>sp:13</em> ( the numerical portion is a Single-Page ID ).</code></li>' . "\n";
269
  echo '<li><code>%%item_name%% = The Item Name. In other words, a brief description, detailing what this purchase was for.</code></li>' . "\n";
270
  echo '</ul>' . "\n";
271
  echo '<strong>Custom replacement codes can also be inserted using these instructions:</strong>' . "\n";
93
  echo '</tr>' . "\n";
94
  echo '</tbody>' . "\n";
95
  echo '</table>' . "\n";
96
+ /**/
97
+ echo '<p><em><strong>*Sandbox Tip*</strong> If you\'re testing your site through a PayPal® Sandbox account, please remember that Email Confirmations from s2Member will NOT be received after a test purchase. s2Member sends its Confirmation Emails to the PayPal® Email Address of the Customer. Since PayPal® Sandbox addresses are usually bogus ( for testing ), you will have to run live transactions before Email Confirmations from s2Member are received. That being said, all other s2Member functionality CAN be tested through a PayPal® Sandbox account. Email Confirmations are the only hang-up.</em></p>' . "\n";
98
  echo '</div>' . "\n";
99
  /**/
100
  echo '</div>' . "\n";
107
  echo '<p>Edit your IPN settings &amp; turn IPN Notifications: <strong><code>On</code></strong></p>' . "\n";
108
  echo '<p>You\'ll need your IPN URL, which is:<br /><code>' . get_bloginfo ("url") . '/?s2member_paypal_notify=1</code></p>' . "\n";
109
  echo '<p><strong>Quick tip:</strong> In addition to the default IPN Settings inside your PayPal® account, the IPN URL is also set on a per-transaction basis by the special PayPal® Button Code that s2Member provides you with. In other words, if you have multiple sites operating on one PayPal® account, that\'s OK. s2Member dynamically sets the IPN URL for each transaction. The result is that the IPN URL configured from within your PayPal® account, becomes the default, which is then overwritten on a per transaction basis. In fact, PayPal® recently updated their system to support IPN URL preservation. One PayPal® account can handle multiple sites, all using different IPN URLs.' . "\n";
110
+ echo '<p><strong>More information:</strong> You\'ll be happy to know that s2Member handles cancellations, expirations, failed payments ( more than 2 in a row ), terminations ( e.g. refunds &amp; chargebacks ) for you automatically. If you log into your PayPal® account and cancel a Member\'s subscription, or, if the Member logs into their PayPal® account and cancels their own subscription, s2Member will be notified of these important changes and react accordingly through the PayPal® IPN service that runs silently behind-the-scene. The PayPal® IPN service will notify s2Member whenever a Member\'s payments have been failing ( more than 2 times in a row ), and/or whenever a Member\'s subscription has expired for any reason. Even refunds &amp; chargeback reversals are supported through the IPN service. If you issue a refund to an unhappy Customer through PayPal®, s2Member will be notified, and the account for that Customer will either be demote to a Free Subscriber, or deleted automatically ( based on your configuration ). The communication from PayPal® -> s2Member is seamless.</p>' . "\n";
111
  echo '</div>' . "\n";
112
  /**/
113
  echo '</div>' . "\n";
190
  echo '<ul>' . "\n";
191
  echo '<li><code>%%registration_url%% = The full URL ( generated by s2Member ) where the Customer can get registered.</code></li>' . "\n";
192
  echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
193
+ echo '<li><code>%%initial%% = The Initial Fee charged during signup. If you offered a free trial, this will be 0.</code> [ <a href="#" onclick="alert(\'This will always represent the amount of money the Customer spent, whenever they initially signed up, no matter what. If a Customer signs up, under the terms of a free trial period, this will be 0.\'); return false;">?</a> ]</li>' . "\n";
194
  echo '<li><code>%%regular%% = The Regular Amount of the subscription. This value is always > 0, no matter what.</code> [ <a href="#" onclick="alert(\'This is how much the subscription costs after an initial period expires. The %%regular%% rate is always > 0. If you did not offer an initial period, %%initial%% and %%regular%% will be equal to the same thing.\'); return false;">?</a> ]</li>' . "\n";
195
  echo '<li><code>%%recurring%% = This is the amount that will be charged on a Recurring basis, or 0 if non-Recurring.</code> [ <a href="#" onclick="alert(\'If recurring payments have not been required, this will be equal to 0. That being said, %%regular%% &amp; %%recurring%% are usually the same value. This variable can be used in two different ways. You can use it to determine what the regular recurring rate is, or to determine whether the subscription will recur or not. If it is going to recur, %%recurring%% will be > 0.\\n\\nThe only time this is NOT equal to the %%regular%% rate, is when recurring payments are not required; and only a one-time regular rate applies.\'); return false;">?</a> ]</li>' . "\n";
196
  echo '<li><code>%%first_name%% = The First Name of the Customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
260
  echo 'Message Body used in the email sent to a Customer after a successful purchase has occurred through PayPal® for Single-Page Access.<br /><br />' . "\n";
261
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
262
  echo '<ul>' . "\n";
263
+ echo '<li><code>%%sp_access_url%% = The full URL ( generated by s2Member ) where the Customer can gain access.</code></li>' . "\n";
264
+ echo '<li><code>%%sp_access_exp%% = Human readable expiration for %%sp_access_url%%. Ex: <em>( link expires in %%sp_access_exp%% )</em>.</code></li>' . "\n";
265
  echo '<li><code>%%txn_id%% = The PayPal® Transaction ID. PayPal® assigns a unique identifier for every purchase.</code></li>' . "\n";
266
  echo '<li><code>%%amount%% = The full Amount that you charged for Single-Page Access. This value will always be > 0.</code></li>' . "\n";
267
  echo '<li><code>%%first_name%% = The First Name of the Customer who purchased Single-Page Access through PayPal®.</code></li>' . "\n";
268
  echo '<li><code>%%last_name%% = The Last Name of the Customer who purchased Single-Page Access through PayPal®.</code></li>' . "\n";
269
  echo '<li><code>%%full_name%% = The Full Name ( First & Last ) of the Customer who purchased Single-Page Access.</code></li>' . "\n";
270
  echo '<li><code>%%payer_email%% = The Email Address of the Customer who purchased Single-Page Access through PayPal®.</code></li>' . "\n";
271
+ echo '<li><code>%%item_number%% = The Item Number. Ex: <em>sp:13:72</em> ( sp:page_ID:expiration_hours ).</code></li>' . "\n";
272
  echo '<li><code>%%item_name%% = The Item Name. In other words, a brief description, detailing what this purchase was for.</code></li>' . "\n";
273
  echo '</ul>' . "\n";
274
  echo '<strong>Custom replacement codes can also be inserted using these instructions:</strong>' . "\n";
includes/menu-pages/scripting.inc.php CHANGED
@@ -393,6 +393,16 @@ echo '</div>' . "\n";
393
  /**/
394
  echo '</div>' . "\n";
395
  /**/
 
 
 
 
 
 
 
 
 
 
396
  echo '</td>' . "\n";
397
  /**/
398
  echo '<td class="ws-menu-page-table-r">' . "\n";
393
  /**/
394
  echo '</div>' . "\n";
395
  /**/
396
+ echo '<div class="ws-menu-page-group" title="s2Member API / WP® Hooks &amp; Filters">' . "\n";
397
+ /**/
398
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-api-hooks-section">' . "\n";
399
+ echo '<h3>WP® Hooks For Theme/Plugin Developers ( scripting required )</h3>' . "\n";
400
+ echo '<p>In addition to its API Constants, s2Member also makes several Hooks/Filters available throughout its framework. This makes it possible to build onto ( or even modify ) s2Member in lots of different ways. If you need to add custom processing routines, modify the behavior of existing processing routines, or tinker with things otherwise; you should use API Hooks/Filters. API Hooks &amp; Filters, give you the ability to "hook into", and/or "filter" processing routines, with files/functions of your own; instead of editing the s2Member plugin files directly. If you don\'t use a Hook/Filter, and instead, you edit the plugin files for s2Member, you\'ll have to merge all of your changes every time a new version of s2Member is released.</p>' . "\n";
401
+ echo '<p>Un-documented. There are simply too many Hooks/Filters spread throughout s2Member\'s framework. Rather than documenting each Hook/Filter, it is easier to browse through the files inside: <code>/s2member/includes/functions/</code>. Inspecting Hooks/Filters in this way, also leads you to a better understanding of how they work. One way to save time, is to run a search for <code>do_action</code> and/or <code>apply_filters</code>.</p>' . "\n";
402
+ echo '</div>' . "\n";
403
+ /**/
404
+ echo '</div>' . "\n";
405
+ /**/
406
  echo '</td>' . "\n";
407
  /**/
408
  echo '<td class="ws-menu-page-table-r">' . "\n";
includes/menu-pages/sp-button.html CHANGED
@@ -13,7 +13,7 @@
13
  <input type="hidden" name="currency_code" value="USD" />
14
  <input type="hidden" name="page_style" value="paypal" />
15
  <input type="hidden" name="item_name" value="Single-Page Access" />
16
- <input type="hidden" name="item_number" value="sp:0" />
17
  <input type="hidden" name="amount" value="0.01" />
18
  <!-- Displays The PayPal® Image Button -->
19
  <input type="image" alt="PayPal®" style="border:0;" src="https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif" />
13
  <input type="hidden" name="currency_code" value="USD" />
14
  <input type="hidden" name="page_style" value="paypal" />
15
  <input type="hidden" name="item_name" value="Single-Page Access" />
16
+ <input type="hidden" name="item_number" value="sp:0:72" />
17
  <input type="hidden" name="amount" value="0.01" />
18
  <!-- Displays The PayPal® Image Button -->
19
  <input type="image" alt="PayPal®" style="border:0;" src="https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif" />
includes/menu-pages/sp-shortcode.html CHANGED
@@ -1 +1 @@
1
- [s2Member-PayPal-Button page="0" desc="Single-Page Access" ps="paypal" cc="USD" custom="%%domain%%" ra="0.01" sp="1" /]
1
+ [s2Member-PayPal-Button page="0" exp="72" desc="Single-Page Access" ps="paypal" cc="USD" custom="%%domain%%" ra="0.01" sp="1" /]
includes/menu-pages/start.inc.php CHANGED
@@ -34,7 +34,7 @@ echo '<div class="ws-menu-page-section ws-plugin--s2member-registration-process-
34
  echo '<h3>The Subscription Signup/Registration Process</h3>' . "\n";
35
  echo '<p>1. Internet Users will go to your Membership Options Page ( which you\'ll need to configure on the s2Member General Options panel ). On this Membership Options Page, that YOU will create in WordPress®, you\'ll insert the PayPal® Subscription Buttons that were generated for you by s2Member.</p>' . "\n";
36
  echo '<p>2. An Internet User will click on a PayPal® Subscription Button from your Membership Options Page. They will be transferred over to PayPal® in order to agree to your membership terms and pricing. You can customize the Checkout Page Style, Pricing, Payment Periods, and more whenever you generate your PayPal® Buttons through s2Member.</p>' . "\n";
37
- echo '<p>3. Once a User has completed the Subscription Signup Process at PayPal®, they\'ll be returned to your site, where they\'ll be activated by s2Member instantly, and given the opportunity to register a Username &amp; Password for their membership. ( Note: they\'ll be allowed to register a Username &amp; Password, even if you\'ve set \'Anyone Can Register\' to `Off` in your General WordPress® options; because s2Member identifies the User as having paid for membership access through PayPal® ). s2Member will also send the User an email with instructions on how to register their Username &amp; Password, just in case they missed the instructions after checkout. That email will be sent to their PayPal® email address; and it will be sent even if they never returned to your site after checkout for some reason. Much of this is handled through the PayPal® IPN service behind the scenes, where PayPal® and s2Member communicate with each other.</p>' . "\n";
38
  echo '<p>4. Once a User has completed checkout and registered a Username &amp; Password, they\'ll be able to login. The first page they\'ll see after logging in, will be your Login Welcome Page ( which you\'ll need to configure on the s2Member General Options panel ). Your Login Welcome Page can contain whatever you like. You\'ll need to design this Page in WordPress®, and be creative!</p>' . "\n";
39
  echo '</div>' . "\n";
40
  /**/
@@ -83,7 +83,7 @@ echo '<div class="ws-menu-page-group" title="Subscription Cancellations">' . "\n
83
  /**/
84
  echo '<div class="ws-menu-page-section ws-plugin--s2member-automation-process-section">' . "\n";
85
  echo '<h3>Subscription Cancellations / Expirations / Terminations</h3>' . "\n";
86
- echo '<p>You\'ll be happy to know that s2Member handles cancellations, expirations, failed payments ( more than 2 in a row ), terminations ( e.g. refunds &amp; chargebacks ) for you automatically. If you log into your PayPal® account and cancel a Member\'s subscription, or, if the Member logs into their PayPal® account and cancels their own subscription, s2Member will be notified of these important changes and react accordingly through the PayPal® IPN service that runs silently behind the scenes.</p>' . "\n";
87
  echo '<p>The PayPal® IPN service will notify s2Member whenever a Member\'s payments have been failing ( more than 2 times in a row ), and/or whenever a Member\'s subscription has expired for any reason. Even refunds &amp; chargeback reversals are supported through the IPN service. If you issue a refund to an unhappy Customer through PayPal®, s2Member will be notified, and the account for that Customer will either be demoted to a Free Subscriber, or deleted automatically ( based on your configuration ). The communication from PayPal® -> s2Member is seamless.</p>' . "\n";
88
  echo '<p>You may also want to check the s2Member API Notifications panel. You\'ll find additional layers of automation available through the use of the `Signup`, `Registration`, `Payment`, `EOT/Deletion`, `Refund/Reversal`, and `Single-Page` notifications that are available to you through the s2Member API. These make it possible to integrate with 3rd party applications; like affiliate programs, list servers, and other back-office routines.</p>' . "\n";
89
  echo '</div>' . "\n";
@@ -102,7 +102,7 @@ echo '<div class="ws-menu-page-group" title="Upgrading/Downgrading Accounts">' .
102
  echo '<div class="ws-menu-page-section ws-plugin--s2member-upgrading-downgrading-section">' . "\n";
103
  echo '<h3>Upgrading And/Or Downgrading User Accounts</h3>' . "\n";
104
  echo '<p>s2Member builds upon existing functionality offered through WordPress® Roles and Capabilities. From your WordPress® Dashboard, go to: <code>Users -> Authors &amp; Users</code>. You can use the bulk actions to modify Member Access Levels all at once, or click on an individual Member account to modify only their specific Access Level. If you want to temporarily demote a Member so they cannot access membership privileges, set their Role to Subscriber. When you\'re ready to give them their membership privileges back, change their Role back to one of the s2Member Levels.</p>' . "\n";
105
- echo '<p>All financial details, such as pricing, trial periods, subscription lengths, refunds, and other Customer service issues; should be handled by YOU, through your PayPal® account, and NOT through WordPress®. Feel free to modify your Members\' Subscriptions via PayPal® as often as you like. s2Member will be notified through the PayPal® IPN service behind the scenes automatically. For example... If you log into PayPal® and cancel a Members\'s paid Subscription, s2Member will be notified by PayPal® behind the scenes, and s2Member will remove their membership privileges at the correct point in time.</p>' . "\n";
106
  echo '<p>That being said, if you log into your WordPress® Dashboard and delete a Member\'s account, you will still need to log into PayPal® and cancel billing for the account you deleted. In other words, s2Member can be notified automatically about actions you take inside PayPal\'s interface, but PayPal® CANNOT be notified of actions you take inside your WordPress® Dashboard. At least, not in an automated fashion, as that would create a security issue for PayPal®. So... automation works seamlessly from PayPal® -> to s2Member, but NOT the other way around.</p>' . "\n";
107
  echo '</div>' . "\n";
108
  /**/
34
  echo '<h3>The Subscription Signup/Registration Process</h3>' . "\n";
35
  echo '<p>1. Internet Users will go to your Membership Options Page ( which you\'ll need to configure on the s2Member General Options panel ). On this Membership Options Page, that YOU will create in WordPress®, you\'ll insert the PayPal® Subscription Buttons that were generated for you by s2Member.</p>' . "\n";
36
  echo '<p>2. An Internet User will click on a PayPal® Subscription Button from your Membership Options Page. They will be transferred over to PayPal® in order to agree to your membership terms and pricing. You can customize the Checkout Page Style, Pricing, Payment Periods, and more whenever you generate your PayPal® Buttons through s2Member.</p>' . "\n";
37
+ echo '<p>3. Once a User has completed the Subscription Signup Process at PayPal®, they\'ll be returned to your site, where they\'ll be activated by s2Member instantly, and given the opportunity to register a Username &amp; Password for their membership. ( Note: they\'ll be allowed to register a Username &amp; Password, even if you\'ve set \'Anyone Can Register\' to `Off` in your General WordPress® options; because s2Member identifies the User as having paid for membership access through PayPal® ). s2Member will also send the User an email with instructions on how to register their Username &amp; Password, just in case they missed the instructions after checkout. That email will be sent to their PayPal® email address; and it will be sent even if they never returned to your site after checkout for some reason. Much of this is handled through the PayPal® IPN service behind-the-scene, where PayPal® and s2Member communicate with each other.</p>' . "\n";
38
  echo '<p>4. Once a User has completed checkout and registered a Username &amp; Password, they\'ll be able to login. The first page they\'ll see after logging in, will be your Login Welcome Page ( which you\'ll need to configure on the s2Member General Options panel ). Your Login Welcome Page can contain whatever you like. You\'ll need to design this Page in WordPress®, and be creative!</p>' . "\n";
39
  echo '</div>' . "\n";
40
  /**/
83
  /**/
84
  echo '<div class="ws-menu-page-section ws-plugin--s2member-automation-process-section">' . "\n";
85
  echo '<h3>Subscription Cancellations / Expirations / Terminations</h3>' . "\n";
86
+ echo '<p>You\'ll be happy to know that s2Member handles cancellations, expirations, failed payments ( more than 2 in a row ), terminations ( e.g. refunds &amp; chargebacks ) for you automatically. If you log into your PayPal® account and cancel a Member\'s subscription, or, if the Member logs into their PayPal® account and cancels their own subscription, s2Member will be notified of these important changes and react accordingly through the PayPal® IPN service that runs silently behind-the-scene.</p>' . "\n";
87
  echo '<p>The PayPal® IPN service will notify s2Member whenever a Member\'s payments have been failing ( more than 2 times in a row ), and/or whenever a Member\'s subscription has expired for any reason. Even refunds &amp; chargeback reversals are supported through the IPN service. If you issue a refund to an unhappy Customer through PayPal®, s2Member will be notified, and the account for that Customer will either be demoted to a Free Subscriber, or deleted automatically ( based on your configuration ). The communication from PayPal® -> s2Member is seamless.</p>' . "\n";
88
  echo '<p>You may also want to check the s2Member API Notifications panel. You\'ll find additional layers of automation available through the use of the `Signup`, `Registration`, `Payment`, `EOT/Deletion`, `Refund/Reversal`, and `Single-Page` notifications that are available to you through the s2Member API. These make it possible to integrate with 3rd party applications; like affiliate programs, list servers, and other back-office routines.</p>' . "\n";
89
  echo '</div>' . "\n";
102
  echo '<div class="ws-menu-page-section ws-plugin--s2member-upgrading-downgrading-section">' . "\n";
103
  echo '<h3>Upgrading And/Or Downgrading User Accounts</h3>' . "\n";
104
  echo '<p>s2Member builds upon existing functionality offered through WordPress® Roles and Capabilities. From your WordPress® Dashboard, go to: <code>Users -> Authors &amp; Users</code>. You can use the bulk actions to modify Member Access Levels all at once, or click on an individual Member account to modify only their specific Access Level. If you want to temporarily demote a Member so they cannot access membership privileges, set their Role to Subscriber. When you\'re ready to give them their membership privileges back, change their Role back to one of the s2Member Levels.</p>' . "\n";
105
+ echo '<p>All financial details, such as pricing, trial periods, subscription lengths, refunds, and other Customer service issues; should be handled by YOU, through your PayPal® account, and NOT through WordPress®. Feel free to modify your Members\' Subscriptions via PayPal® as often as you like. s2Member will be notified through the PayPal® IPN service behind-the-scene automatically. For example... If you log into PayPal® and cancel a Members\'s paid Subscription, s2Member will be notified by PayPal® behind-the-scene, and s2Member will remove their membership privileges at the correct point in time.</p>' . "\n";
106
  echo '<p>That being said, if you log into your WordPress® Dashboard and delete a Member\'s account, you will still need to log into PayPal® and cancel billing for the account you deleted. In other words, s2Member can be notified automatically about actions you take inside PayPal\'s interface, but PayPal® CANNOT be notified of actions you take inside your WordPress® Dashboard. At least, not in an automated fashion, as that would create a security issue for PayPal®. So... automation works seamlessly from PayPal® -> to s2Member, but NOT the other way around.</p>' . "\n";
107
  echo '</div>' . "\n";
108
  /**/
includes/menu-pages/trk-ops.inc.php CHANGED
@@ -58,7 +58,7 @@ echo 'Any valid XHTML / JavaScript' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["c"
58
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
59
  echo '<ul>' . "\n";
60
  echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
61
- echo '<li><code>%%initial%% = The Initial Fee charged during signup. If you offered a free trial, this will be 0.</code> [ <a href="#" onclick="alert(\'If no initial period was offered or required, this initial amount will be equal to the regular subscription rate. In other words, this will always represent the amount of money the Customer spent whenever they signed up, no matter what.\\n\\nIf a user signs up under the terms of a free trial period, this will be 0. So be careful using this value with 3rd party affiliate integrations because a $0 sale amount could cause havoc. If you have a lot of trouble, try using the more advanced `Payment` notifications available in the API Notifications panel for s2Member.\'); return false;">?</a> ]</li>' . "\n";
62
  echo '<li><code>%%first_name%% = The First Name of the Customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
63
  echo '<li><code>%%last_name%% = The Last Name of the Customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
64
  echo '<li><code>%%full_name%% = The Full Name ( First & Last ) of the Customer who purchased the membership subscription.</code></li>' . "\n";
@@ -83,6 +83,34 @@ echo '</div>' . "\n";
83
  /**/
84
  echo '</div>' . "\n";
85
  /**/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  echo '<div class="ws-menu-page-group" title="Tracking Single-Page Access">' . "\n";
87
  /**/
88
  echo '<div class="ws-menu-page-section ws-plugin--s2member-sp-access-section">' . "\n";
@@ -96,7 +124,7 @@ echo '<div class="ws-menu-page-group" title="Other Tracking Methods Available">'
96
  /**/
97
  echo '<div class="ws-menu-page-section ws-plugin--s2member-other-methods-section">' . "\n";
98
  echo '<h3>Other Tracking Methods Are Available ( there\'s always a way )</h3>' . "\n";
99
- echo '<p>Check the s2Member API Notifications panel. You\'ll find additional layers of automation available through the use of the `Signup`, `Registration`, `Payment`, `EOT/Deletion`, `Refund/Reversal`, and `Single-Page` notifications that are available to you through the s2Member API. The s2Member API Notifications make it possible to integrate with 3rd party applications; like list servers, affiliate programs, and other back-office routines; in more advanced ways. Since the s2Member API Notifications operate silently on the back-end, in conjunction with the PayPal® IPN system, they tend to be more reliable and also more versatile. That being said, nothing replaces the simplicity of Tracking Codes. The more advanced API Notifications are NOT always the best tool for the job. For instance, API Notifications will NOT work with Google® Analytics, or 1 pixel &lt;img&gt; tags. They operate silently behind-the-scenes, using cURL connections, as opposed to being loaded in a browser.</p>' . "\n";
100
  echo '</div>' . "\n";
101
  /**/
102
  echo '</div>' . "\n";
58
  echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
59
  echo '<ul>' . "\n";
60
  echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
61
+ echo '<li><code>%%initial%% = The Initial Fee charged during signup. If you offered a free trial, this will be 0.</code> [ <a href="#" onclick="alert(\'This will always represent the amount of money the Customer spent, whenever they initially signed up, no matter what. Even if that amount is 0.\\n\\nIf a Customer signs up, under the terms of a free trial period, this will be 0. So be careful using %%initial%% when you offer a free trial period, because a $0.00 sale amount could cause havoc with affiliate programs. If you\\\'re offering a free trial period, and you need to track sales through affiliate programs, you can either hard-code an amount into your Tracking Code; or use the more advanced `Payment Notifications`. See: `s2Member -> API Notifications`.\'); return false;">?</a> ]</li>' . "\n";
62
  echo '<li><code>%%first_name%% = The First Name of the Customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
63
  echo '<li><code>%%last_name%% = The Last Name of the Customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
64
  echo '<li><code>%%full_name%% = The Full Name ( First & Last ) of the Customer who purchased the membership subscription.</code></li>' . "\n";
83
  /**/
84
  echo '</div>' . "\n";
85
  /**/
86
+ echo '<div class="ws-menu-page-group" title="Integrating iDevAffiliate® Software">' . "\n";
87
+ /**/
88
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-idev-section">' . "\n";
89
+ echo '<h3>Integrating iDevAffiliate® ( affiliate program management )</h3>' . "\n";
90
+ echo '<a href="http://www.idevdirect.com/14200.html" target="_blank"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/idev-logo.gif" class="ws-menu-page-right" style="width:125px; height:125px; border:0;" alt="." /></a>' . "\n";
91
+ echo '<p>Adding affiliate tracking software to your site is one of the most effective ways to achieve more sales, more traffic, and more search engine ranking. <a href="http://www.idevdirect.com/14200.html" target="_blank" rel="xlink">iDevAffiliate®</a> ( an affiliate management portal ), installs in just minutes, and can be integrated seamlessly with s2Member. We recommend <a href="http://www.idevdirect.com/14200.html" target="_blank" rel="xlink">iDevAffiliate® Standard</a> ( $99 ) because of its proven track record, and its ability to integrate with s2Member using a variety of techniques. The most popular being a Hidden Image Tag.</p>' . "\n";
92
+ echo '<p>If you choose to <a href="http://www.idevdirect.com/14200.html" target="_blank" rel="xlink">install iDevAffiliate®</a>, you will need to configure your <code>iDevAffiliate® -> Shopping Cart Integration</code>. Please choose <code>Generic Tracking Pixel</code>. Then, grab your Hidden Image Tag, and pop the code provided by iDevAffiliate® into the Custom Tracking field at the top of this page. You MUST also add replacement codes to your Hidden Image Tag. To save you some trouble, we\'ve provided an example below. These are the two variables that iDevAffiliate® needs.</p>' . "\n";
93
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/code-samples/idev-signup-tracking-code.php"), true) . '</p>' . "\n";
94
+ echo '<p>Your <code>profile</code> ID will be assigned by iDevAffiliate®. Be sure to replace <code>profile=123</code> with your own profile ID.</p>' . "\n";
95
+ echo '<p><em><strong>*Tip*</strong> iDevAffiliate® also provides an alternative method, using a 3rd-party call. The alternative 3rd-party call, could be used with <code>s2Member -> API Notifications.</code> A 3rd-party call, is essentially an HTTP connection that runs silently behind-the-scene, as opposed to being loaded in a browser. It\'s a bit more powerful, but also more advanced.</em></p>' . "\n";
96
+ echo '</div>' . "\n";
97
+ /**/
98
+ echo '</div>' . "\n";
99
+ /**/
100
+ echo '<div class="ws-menu-page-group" title="Integrating ShareASale® Tracking">' . "\n";
101
+ /**/
102
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-shareasale-section">' . "\n";
103
+ echo '<h3>Integrating ShareASale® ( affiliate program management )</h3>' . "\n";
104
+ echo '<a href="http://www.shareasale.com/merchantsignup.cfm" target="_blank"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/sas-logo.png" class="ws-menu-page-right" style="width:125px; height:125px; border:0;" alt="." /></a>' . "\n";
105
+ echo '<p>Established in 2000, <a href="http://www.shareasale.com/merchantsignup.cfm" target="_blank" rel="xlink">ShareASale®</a> provides award winning technology and service; which will enable you to connect with a network of established affiliates, as well as recruit new ones. Joining ShareASale®, maximizes your ability to reach the greatest number of affiliates, with the least amount of work. At ShareASale®, you\'ll have access to an existing affiliate-base. You place your site on the market, and let their existing affiliates promote your products/services.</p>' . "\n";
106
+ echo '<p>If you <a href="http://www.shareasale.com/merchantsignup.cfm" target="_blank" rel="xlink">become a Merchant at ShareASale®</a>, you will need to configure your <code>ShareASale® -> Sale Tracking</code>. Grab your Hidden Image Tag, and pop the code provided by ShareASale® into the Custom Tracking field at the top of this page. You MUST also add replacement codes to your Hidden Image Tag. To save you some trouble, we\'ve provided an example below. These are the two variables that ShareASale® needs.</p>' . "\n";
107
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/code-samples/sas-signup-tracking-code.php"), true) . '</p>' . "\n";
108
+ echo '<p>Your <code>merchantID</code> will be assigned by ShareASale®. Be sure to replace <code>merchantID=123</code> with the one they assign you.</p>' . "\n";
109
+ echo '<p><em><strong>*Tip*</strong> ShareASale® also provides an alternative method, using a 3rd-party call. The alternative 3rd-party call, could be used with <code>s2Member -> API Notifications.</code> A 3rd-party call, is essentially an HTTP connection that runs silently behind-the-scene, as opposed to being loaded in a browser. It\'s a bit more powerful, but also more advanced.</em></p>' . "\n";
110
+ echo '</div>' . "\n";
111
+ /**/
112
+ echo '</div>' . "\n";
113
+ /**/
114
  echo '<div class="ws-menu-page-group" title="Tracking Single-Page Access">' . "\n";
115
  /**/
116
  echo '<div class="ws-menu-page-section ws-plugin--s2member-sp-access-section">' . "\n";
124
  /**/
125
  echo '<div class="ws-menu-page-section ws-plugin--s2member-other-methods-section">' . "\n";
126
  echo '<h3>Other Tracking Methods Are Available ( there\'s always a way )</h3>' . "\n";
127
+ echo '<p>Check the s2Member API Notifications panel. You\'ll find additional layers of automation available through the use of the `Signup`, `Registration`, `Payment`, `EOT/Deletion`, `Refund/Reversal`, and `Single-Page` notifications that are available to you through the s2Member API. The s2Member API Notifications make it possible to integrate with 3rd party applications; like list servers, affiliate programs, and other back-office routines; in more advanced ways. Since the s2Member API Notifications operate silently on the back-end, in conjunction with the PayPal® IPN system, they tend to be more reliable and also more versatile. That being said, nothing replaces the simplicity of Tracking Codes. The more advanced API Notifications are NOT always the best tool for the job. For instance, API Notifications will NOT work with Google® Analytics, or 1 pixel &lt;img&gt; tags. They operate silently behind-the-scene, using cURL connections, as opposed to being loaded in a browser.</p>' . "\n";
128
  echo '</div>' . "\n";
129
  /**/
130
  echo '</div>' . "\n";
includes/syscon.inc.php CHANGED
@@ -104,7 +104,7 @@ function ws_plugin__s2member_configure_options_and_their_defaults ($options = FA
104
  "signup_email_message" => "Thanks %%first_name%%! Your membership has been approved.\n\nIf you haven't already done so, the next step is to Register a Username.\n\nComplete your registration here:\n%%registration_url%%\n\nIf you have any trouble, please feel free to contact us.\n\nBest Regards,\n" . get_bloginfo ("name"),/**/
105
  /**/
106
  "single_page_email_subject" => "Thank You! ( instructions for access )",/**/
107
- "single_page_email_message" => "Thanks %%first_name%%!\n\n%%item_name%%\n\nYour order can be retrieved here:\n%%access_url%%\n( link expires after 72 hours )\n\nIf you have any trouble, please feel free to contact us.\n\nBest Regards,\n" . get_bloginfo ("name"),/**/
108
  /**/
109
  "mailchimp_api_key" => "", /* MailChimp® API Key for MailChimp® integration. */
110
  "level0_mailchimp_list_ids" => "", /* Comma delimited list of MailChimp® List IDs. */
104
  "signup_email_message" => "Thanks %%first_name%%! Your membership has been approved.\n\nIf you haven't already done so, the next step is to Register a Username.\n\nComplete your registration here:\n%%registration_url%%\n\nIf you have any trouble, please feel free to contact us.\n\nBest Regards,\n" . get_bloginfo ("name"),/**/
105
  /**/
106
  "single_page_email_subject" => "Thank You! ( instructions for access )",/**/
107
+ "single_page_email_message" => "Thanks %%first_name%%!\n\n%%item_name%%\n\nYour order can be retrieved here:\n%%sp_access_url%%\n( link expires in %%sp_access_exp%% )\n\nIf you have any trouble, please feel free to contact us.\n\nBest Regards,\n" . get_bloginfo ("name"),/**/
108
  /**/
109
  "mailchimp_api_key" => "", /* MailChimp® API Key for MailChimp® integration. */
110
  "level0_mailchimp_list_ids" => "", /* Comma delimited list of MailChimp® List IDs. */
readme.txt CHANGED
@@ -1,7 +1,7 @@
1
  === s2Member ( Membership w/ PayPal® Integration ) also works w/ BuddyPress ===
2
 
3
- Version: 2.8.6
4
- Stable tag: 2.8.6
5
  Framework: WS-P-2.1
6
 
7
  WordPress Compatible: yes
@@ -104,6 +104,17 @@ Yes. In the form of comments on [this page](http://www.primothemes.com/post/s2me
104
 
105
  == Changelog ==
106
 
 
 
 
 
 
 
 
 
 
 
 
107
  = 2.8.6 =
108
  * Powerful new feature! - s2Member now supports unlimited Custom Capabilities. This allows you to create an unlimited number of Membership Packages, all with different Capabilities ( customized specifically for what your site offers ). Custom Capabilities can also be configured on a per-User basis through your WordPress® Dashboard, under `Users`. For further details, see: `s2Member -> API Scripting -> Custom Capability Packages`.
109
  * Powerful new feature! - Now you can sell Single-Page Access too, using "Buy Now" buttons. Single-Page Access works independently from Member Level Access. That is, you can sell an unlimited number of Pages using "Buy Now" Buttons, and your Customers will NOT be required to have a Membership Account with your site in order to receive access. If they are already a Member, that's fine, but they won't need to be. Further details are provided under `s2Member -> PayPal® Buttons`.
1
  === s2Member ( Membership w/ PayPal® Integration ) also works w/ BuddyPress ===
2
 
3
+ Version: 2.8.8
4
+ Stable tag: 2.8.8
5
  Framework: WS-P-2.1
6
 
7
  WordPress Compatible: yes
104
 
105
  == Changelog ==
106
 
107
+ = 2.8.8 =
108
+ * Integration instructions for iDevAffiliate® and ShareASale® are now available under: `s2Member -> API Tracking`.
109
+ * Fixed a bug in the new Email Confirmation template for Single-Page Access. The replacement code: %%access_url%% has been changed to %%sp_access_url%%. This was a typo. The variable remains the same as it was, but the typo in the default template was corrected.
110
+ * Added a new replacement code to the Single-Page Email Confirmation template. See: `s2Member -> PayPal® Options -> Single-Page`. The new replacement code is: %%sp_access_exp%%, indicating a human readable duration for link validity.
111
+ * High priority bug fixed with s2Member Hook/Filter on Login Design. This bug was just introduced in v2.8.7. This bug was preventing a customized Login Design from being displayed properly. Corrected in v2.8.8.
112
+ * Bug fix in PayPal® Button Generator. The modify="" parameter was being set to a value of "1" in some rare cases, depending on button configuration. It should always default to a value of "0", and only be set to a value of "1" or "2" whenever a Subscription Modification Button is being generated. This bug was introduced in v2.8.6. Corrected in v2.8.8.
113
+
114
+ = 2.8.7 =
115
+ * Over 100 WordPress® Hooks and Filters have been added to the s2Member framework. In addition to its API Constants, s2Member now makes several Hooks/Filters available throughout its framework. This makes it possible to build onto ( or even modify ) s2Member in lots of different ways. If you need to add custom processing routines, modify the behavior of existing processing routines, or tinker with things otherwise; you should use API Hooks/Filters. API Hooks &amp; Filters, give you the ability to "hook into", and/or "filter" processing routines, with files/functions of your own; instead of editing the s2Member plugin files directly. If you don't use a Hook/Filter, and instead, you edit the plugin files for s2Member, you'll have to merge all of your changes every time a new version of s2Member is released.
116
+ * You can now set a custom expiration time for Single-Page Access links. Instead of the default 72 hours, you may now choose an option that works best for your site. Anywhere from 2 hours, up to 5 years.
117
+
118
  = 2.8.6 =
119
  * Powerful new feature! - s2Member now supports unlimited Custom Capabilities. This allows you to create an unlimited number of Membership Packages, all with different Capabilities ( customized specifically for what your site offers ). Custom Capabilities can also be configured on a per-User basis through your WordPress® Dashboard, under `Users`. For further details, see: `s2Member -> API Scripting -> Custom Capability Packages`.
120
  * Powerful new feature! - Now you can sell Single-Page Access too, using "Buy Now" buttons. Single-Page Access works independently from Member Level Access. That is, you can sell an unlimited number of Pages using "Buy Now" Buttons, and your Customers will NOT be required to have a Membership Account with your site in order to receive access. If they are already a Member, that's fine, but they won't need to be. Further details are provided under `s2Member -> PayPal® Buttons`.
s2member.php CHANGED
@@ -9,8 +9,8 @@ along with this software. In the main directory, see: /licensing/
9
  If not, see: <http://www.gnu.org/licenses/>.
10
  */
11
  /*
12
- Version: 2.8.6
13
- Stable tag: 2.8.6
14
  Framework: WS-P-2.1
15
 
16
  WordPress Compatible: yes
9
  If not, see: <http://www.gnu.org/licenses/>.
10
  */
11
  /*
12
+ Version: 2.8.8
13
+ Stable tag: 2.8.8
14
  Framework: WS-P-2.1
15
 
16
  WordPress Compatible: yes