$value) // Find all keys contained within ``$new_options`` matching `^ws_plugin__s2member_`. if(strpos($key, 'ws_plugin__s2member_') === 0) // A relevant ``$new_options`` key matching `^ws_plugin__s2member_`? if($key === 'ws_plugin__s2member_configured') // s2Member is now configured (according to these options)? ($GLOBALS['WS_PLUGIN__']['s2member']['c']['configured'] = $value).update_option('ws_plugin__s2member_configured', $value); else if(!is_array($value) || (is_array($value) && array_shift($value) === 'update-signal')) // Updating an array? $options[preg_replace('/^'.preg_quote('ws_plugin__s2member_', '/').'/', '', $key)] = $value; unset($key, $value); // Unset these utility variables now. This prevents bleeding vars into Hooks/Filters that are of no use. foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v; do_action('ws_plugin__s2member_during_update_all_options', get_defined_vars()); unset($__refs, $__v); // Housekeeping. //260812 Keep the old s2Get option synchronized for rollback compatibility, while accepting legacy updates during the transition. if(isset($new_options['ws_plugin__s2member_sc_s2get_userid_whitelist']) && !isset($new_options['ws_plugin__s2member_sc_user_fields_whitelist'])) $options['sc_user_fields_whitelist'] = $options['sc_s2get_userid_whitelist']; if(isset($options['sc_user_fields_whitelist'])) $options['sc_s2get_userid_whitelist'] = $options['sc_user_fields_whitelist']; $options = ws_plugin__s2member_configure_options_and_their_defaults(($options = array_merge($options, array('options_version' => (string)($options['options_version'] + 0.001))))); update_option('ws_plugin__s2member_options', $options).((is_multisite() && is_main_site()) ? update_site_option('ws_plugin__s2member_options', $options) : NULL).update_option('ws_plugin__s2member_cache', array()); if($update_other === TRUE || in_array('auto_eot_system', (array)$update_other)) // Handle the Auto-EOT System now (enable/disable). ($options['auto_eot_system_enabled'] == 1) ? c_ws_plugin__s2member_auto_eots::add_auto_eot_system() : c_ws_plugin__s2member_auto_eots::delete_auto_eot_system(); if(($display_notices === TRUE || in_array('success', (array)$display_notices)) && ($notice = 'Options saved.'.(($request_refresh) ? ' Please refresh.' : '').'')) ($enqueue_notices === TRUE || in_array('success', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*') : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice); if(empty($_GET['page']) || $_GET['page'] !== 'ws-plugin--s2member-mms-ops') // Do NOT display page-conflict-warnings on the Main Multisite Configuration panel. { if(!$options['membership_options_page'] && ($display_notices === TRUE || in_array('page-conflict-warnings', (array)$display_notices)) && ($notice = 'NOTE: s2Member security restrictions will NOT be enforced until you\'ve configured a Membership Options Page. See: s2Member → General Options → Membership Options Page.')) ($enqueue_notices === TRUE || in_array('page-conflict-warnings', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*', TRUE) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, TRUE); if($options['login_welcome_page'] && $options['login_welcome_page'] === $options['membership_options_page'] && ($display_notices === TRUE || in_array('page-conflict-warnings', (array)$display_notices)) && ($notice = 's2Member: Your Login Welcome Page is the same as your Membership Options Page. Please correct this. See: s2Member → General Options → Login Welcome Page.')) ($enqueue_notices === TRUE || in_array('page-conflict-warnings', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*', TRUE) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, TRUE); if($options['membership_options_page'] && (string)get_option('page_on_front') === $options['membership_options_page'] && ($display_notices === TRUE || in_array('page-conflict-warnings', (array)$display_notices)) && ($notice = 's2Member: Your Membership Options Page is currently configured as your Home Page (i.e., static page) for WordPress. This causes internal conflicts with s2Member. Your Membership Options Page MUST stand alone. Please correct this. See: WordPress → Reading Options. Or change: s2Member → General Options → Membership Options Page.')) ($enqueue_notices === TRUE || in_array('page-conflict-warnings', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*', TRUE) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, TRUE); if($options['login_welcome_page'] && (string)get_option('page_on_front') === $options['login_welcome_page'] && ($display_notices === TRUE || in_array('page-conflict-warnings', (array)$display_notices)) && ($notice = 's2Member: Your Login Welcome Page is currently configured as your Home Page (i.e., static page) for WordPress. This causes internal conflicts with s2Member. Your Login Welcome Page MUST stand alone. Please correct this. See: WordPress → Reading Options. Or change: s2Member → General Options → Login Welcome Page.')) ($enqueue_notices === TRUE || in_array('page-conflict-warnings', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*', TRUE) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, TRUE); if($options['membership_options_page'] && (string)get_option('page_for_posts') === $options['membership_options_page'] && ($display_notices === TRUE || in_array('page-conflict-warnings', (array)$display_notices)) && ($notice = 's2Member: Your Membership Options Page is currently configured as your Posts Page (i.e., static page) for WordPress. This causes internal conflicts with s2Member. Your Membership Options Page MUST stand alone. Please correct this. See: WordPress → Reading Options. Or change: s2Member → General Options → Membership Options Page.')) ($enqueue_notices === TRUE || in_array('page-conflict-warnings', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*', TRUE) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, TRUE); if($options['login_welcome_page'] && (string)get_option('page_for_posts') === $options['login_welcome_page'] && ($display_notices === TRUE || in_array('page-conflict-warnings', (array)$display_notices)) && ($notice = 's2Member: Your Login Welcome Page is currently configured as your Posts Page (i.e., static page) for WordPress. This causes internal conflicts with s2Member. Your Login Welcome Page MUST stand alone. Please correct this. See: WordPress → Reading Options. Or change: s2Member → General Options → Login Welcome Page.')) ($enqueue_notices === TRUE || in_array('page-conflict-warnings', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*', TRUE) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, TRUE); if($options['file_download_limit_exceeded_page'] && $options['file_download_limit_exceeded_page'] === $options['membership_options_page'] && ($display_notices === TRUE || in_array('page-conflict-warnings', (array)$display_notices)) && ($notice = 's2Member: Your Download Limit Exceeded Page is the same as your Membership Options Page. Please correct this. See: s2Member → Download Options.')) ($enqueue_notices === TRUE || in_array('page-conflict-warnings', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*', TRUE) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, TRUE); } $updated_all_options = TRUE; // Flag indicating this routine was processed successfully; and that all s2Member options have been updated successfully. } foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v; do_action('ws_plugin__s2member_after_update_all_options', get_defined_vars()); unset($__refs, $__v); // Housekeeping. return apply_filters('ws_plugin__s2member_update_all_options', (($updated_all_options) ? TRUE : FALSE), get_defined_vars()); } /** * Displays shared End-of-Term demotion-role settings on gateway option pages. * * @package s2Member\Menu_Pages * @since 260916.2004 * * @return null */ public static function eot_demotion_options() { $demotion_to_role = (string)$GLOBALS['WS_PLUGIN__']['s2member']['o']['eot_demotion_to_role']; $demotion_from = (string)$GLOBALS['WS_PLUGIN__']['s2member']['o']['eot_demotion_from']; $demotion_disabled = ($GLOBALS['WS_PLUGIN__']['s2member']['o']['membership_eot_behavior'] === 'delete'); //260917.0003 Keep Demote From/To visible but disabled when EOT behavior is Delete; JavaScript mirrors this immediately when the behavior selector changes. echo '
s2member_levelN role at EOT and preserve other WordPress roles; upgraded installations retain the legacy all-role replacement until you change this setting. Preserved roles also preserve their existing capabilities, so roles such as Editor/Author/Contributor or custom roles may continue to grant s2Member access.'."\n";
echo 'ws_plugin__s2member_force_demotion_role; see How do I specify the demotion role upon EOT?'."\n";
echo ''.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($logs_dir)).') does not exist. Please create this directory manually & make it writable (chmod 777).', TRUE);
else if(!is_writable($logs_dir)) // If the logs directory is not writable yet.
c_ws_plugin__s2member_admin_notices::display_admin_notice('Permissions error. The security-enabled logs directory ('.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($logs_dir)).') is not writable. Please make this directory writable (chmod 777).', TRUE);
if(!file_exists($htaccess)) // If the .htaccess file has not been created yet.
c_ws_plugin__s2member_admin_notices::display_admin_notice('The .htaccess protection file ('.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).') does not exist. Please create this file manually. Inside your .htaccess file, add this:'.esc_html($htaccess_contents).'', TRUE); else if(!preg_match('/deny from all/i', file_get_contents($htaccess))) // Else if the .htaccess file does not offer the required protection. c_ws_plugin__s2member_admin_notices::display_admin_notice('Unprotected. The .htaccess protection file (
'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).') does not contain deny from all. Inside your .htaccess file, add this:'.esc_html($htaccess_contents).'', TRUE); } include_once dirname(dirname(__FILE__)).'/menu-pages/paypal-ops.inc.php'; do_action('ws_plugin__s2member_after_paypal_ops_page', get_defined_vars()); } /** * Builds and handles the Download Options page. * * @package s2Member\Menu_Pages * @since 3.5 */ public static function down_ops_page() { do_action('ws_plugin__s2member_before_down_ops_page', get_defined_vars()); c_ws_plugin__s2member_menu_pages::update_all_options(); if(!empty($_REQUEST['ws_plugin__s2member_cf_options_reset']) && wp_verify_nonce($_REQUEST['ws_plugin__s2member_cf_options_reset'], 'ws-plugin--s2member-cf-options-reset') ) { c_ws_plugin__s2member_files_in::reset_aws_cf_config_values(); // A full CloudFront reset. c_ws_plugin__s2member_admin_notices::display_admin_notice('Amazon CloudFront configuration reset successfully.'); } $files_dir = $GLOBALS['WS_PLUGIN__']['s2member']['c']['files_dir']; $htaccess = $GLOBALS['WS_PLUGIN__']['s2member']['c']['files_dir'].'/.htaccess'; $htaccess_contents = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($GLOBALS['WS_PLUGIN__']['s2member']['c']['files_dir_htaccess']))); $no_gzip_htaccess = ABSPATH.'.htaccess'; // Always located in the absolute root path for WordPress. $no_gzip_htaccess_contents = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($GLOBALS['WS_PLUGIN__']['s2member']['c']['files_no_gzip_htaccess']))); if(!c_ws_plugin__s2member_files::no_gzip_rules_in_root_htaccess()) // If s2Member's GZIP exclusions do NOT yet exist in the root `.htaccess` file. c_ws_plugin__s2member_files::write_no_gzip_into_root_htaccess().clearstatcache(); // Handle the root `.htaccess` file now. if(!is_dir($files_dir) && is_writable(dirname(c_ws_plugin__s2member_utils_dirs::strip_dir_app_data($files_dir)))) mkdir($files_dir, 0777, TRUE).clearstatcache(); // Create this directory structure now. if(is_dir($files_dir) && is_writable($files_dir) && !file_exists($htaccess)) // This file does NOT exist yet? file_put_contents($htaccess, $htaccess_contents).clearstatcache(); // Create the `.htaccess` file now. if(!c_ws_plugin__s2member_files::no_gzip_rules_in_root_htaccess()) // If s2Member's GZIP exclusions do NOT yet exist in the root `.htaccess` file. c_ws_plugin__s2member_admin_notices::display_admin_notice('Possible GZIP conflict on server. Unable to write GZIP exclusions into root .htaccess file (
'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($no_gzip_htaccess)).'). Please read the panel below: Preventing GZIP Conflicts, and add this section yourself:'.esc_html($no_gzip_htaccess_contents).'', TRUE); if(!is_dir($files_dir)) // If the security-enabled files directory does not exist yet. c_ws_plugin__s2member_admin_notices::display_admin_notice('The security-enabled files directory (
'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($files_dir)).') does not exist. Please create this directory manually.', TRUE);
if(!file_exists($htaccess)) // If the `.htaccess` file has not been created yet.
c_ws_plugin__s2member_admin_notices::display_admin_notice('The .htaccess protection file ('.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).') does not exist. Please create this file manually. Inside your .htaccess file, add this:'.esc_html($htaccess_contents).'', TRUE); else if(!preg_match('/deny from all/i', file_get_contents($htaccess))) // Else if the `.htaccess` file does not offer the required protection. c_ws_plugin__s2member_admin_notices::display_admin_notice('Unprotected. The .htaccess protection file (
'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).') does not contain deny from all. Inside your .htaccess file, add this:'.esc_html($htaccess_contents).'', TRUE); if(!empty($_POST['ws_plugin__s2member_amazon_cf_files_auto_configure_distros']) && ($nonce = $_POST['ws_plugin__s2member_amazon_cf_files_auto_configure_distros']) && wp_verify_nonce($nonce, 'ws-plugin--s2member-amazon-cf-files-auto-configure-distros')) if(($amazon_cf_auto_configure_distros = c_ws_plugin__s2member_files_in::amazon_cf_auto_configure_distros()) && $amazon_cf_auto_configure_distros['success']) c_ws_plugin__s2member_admin_notices::display_admin_notice('Amazon CloudFront Distributions auto-configured successfully. Please allow 30 minutes for initial propagation. Tip: If you try to stream over the RTMP protocol using something like the
[s2Stream /] shortcode, and you keep getting an "ID Not Found" error while using JW Player; please note that it can sometimes take a full 24 hours for RTMP (i.e., streaming distributions) to begin working properly. This is because there are a few initialization routines that must complete on the AWS side when you first integrate with CloudFront. Please be patient.'.(($GLOBALS['WS_PLUGIN__']['s2member']['o']['amazon_cf_files_distro_downloads_cname']) ? ''.esc_html($GLOBALS['WS_PLUGIN__']['s2member']['o']['amazon_cf_files_distro_downloads_cname']).' —» '.esc_html($GLOBALS['WS_PLUGIN__']['s2member']['o']['amazon_cf_files_distro_downloads_dname']).'' : '').(($GLOBALS['WS_PLUGIN__']['s2member']['o']['amazon_cf_files_distro_streaming_cname']) ? ''.esc_html($GLOBALS['WS_PLUGIN__']['s2member']['o']['amazon_cf_files_distro_streaming_cname']).' —» '.esc_html($GLOBALS['WS_PLUGIN__']['s2member']['o']['amazon_cf_files_distro_streaming_dname']).'' : ''));
else // Else there was an error. We need to report this back to the site owner so they can understand what's going on.
(c_ws_plugin__s2member_menu_pages::$pre_display_errors['cf_files_auto_configure_distros'] = TRUE).c_ws_plugin__s2member_admin_notices::display_admin_notice('Unable to auto-configure Amazon CloudFront Distributions.'.esc_html($amazon_cf_auto_configure_distros['code']).'. Error Message: '.esc_html($amazon_cf_auto_configure_distros['message']).'', TRUE);
if(!empty($_POST['ws_plugin__s2member_amazon_s3_files_auto_configure_acls']) && ($nonce = $_POST['ws_plugin__s2member_amazon_s3_files_auto_configure_acls']) && wp_verify_nonce($nonce, 'ws-plugin--s2member-amazon-s3-files-auto-configure-acls'))
if(($amazon_s3_auto_configure_acls = c_ws_plugin__s2member_files_in::amazon_s3_auto_configure_acls()) && $amazon_s3_auto_configure_acls['success'])
c_ws_plugin__s2member_admin_notices::display_admin_notice('Amazon S3 ACLs auto-configured successfully.');
else // Else there was an error. We need to report this back to the site owner so they can understand what's going on.
(c_ws_plugin__s2member_menu_pages::$pre_display_errors['s3_files_auto_configure_acls'] = TRUE).c_ws_plugin__s2member_admin_notices::display_admin_notice('Unable to auto-configure Amazon S3 ACLs.'.esc_html($amazon_s3_auto_configure_acls['code']).'. Error Message: '.esc_html($amazon_s3_auto_configure_acls['message']).'', TRUE);
include_once dirname(dirname(__FILE__)).'/menu-pages/down-ops.inc.php';
do_action('ws_plugin__s2member_after_down_ops_page', get_defined_vars());
}
/**
* Builds and handles the API Tracking options page.
*
* @package s2Member\Menu_Pages
* @since 3.5
*/
public static function trk_ops_page()
{
do_action('ws_plugin__s2member_before_trk_ops_page', get_defined_vars());
c_ws_plugin__s2member_menu_pages::update_all_options();
include_once dirname(dirname(__FILE__)).'/menu-pages/trk-ops.inc.php';
do_action('ws_plugin__s2member_after_trk_ops_page', get_defined_vars());
}
/**
* Builds and handles the API List Server options page.
*
* @package s2Member\Menu_Pages
* @since 3.5
*/
public static function els_ops_page()
{
do_action('ws_plugin__s2member_before_els_ops_page', get_defined_vars());
c_ws_plugin__s2member_menu_pages::update_all_options();
include_once dirname(dirname(__FILE__)).'/menu-pages/els-ops.inc.php';
do_action('ws_plugin__s2member_after_els_ops_page', get_defined_vars());
}
/**
* Builds and handles the API Notifications page.
*
* @package s2Member\Menu_Pages
* @since 3.5
*/
public static function api_ops_page()
{
do_action('ws_plugin__s2member_before_api_ops_page', get_defined_vars());
c_ws_plugin__s2member_menu_pages::update_all_options();
include_once dirname(dirname(__FILE__)).'/menu-pages/api-ops.inc.php';
do_action('ws_plugin__s2member_after_api_ops_page', get_defined_vars());
}
/**
* Builds and handles the PayPal Button Generator page.
*
* @package s2Member\Menu_Pages
* @since 3.5
*/
public static function paypal_buttons_page()
{
do_action('ws_plugin__s2member_before_paypal_buttons_page', get_defined_vars());
if(!$GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_business'] || !$GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_merchant_id'] || !$GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_api_username'] || !$GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_api_password'] || !$GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_api_signature'])
c_ws_plugin__s2member_admin_notices::display_admin_notice('Please configure s2Member → PayPal Options first. Once all of your PayPal Options are configured; including your Email Address, Merchant ID, API Username, Password, and Signature; return to this page & generate your PayPal Button(s).', TRUE);
include_once dirname(dirname(__FILE__)).'/menu-pages/paypal-buttons.inc.php';
do_action('ws_plugin__s2member_after_paypal_buttons_page', get_defined_vars());
}
/**
* Builds and handles the API Scripting page.
*
* @package s2Member\Menu_Pages
* @since 3.5
*/
public static function scripting_page()
{
do_action('ws_plugin__s2member_before_scripting_page', get_defined_vars());
c_ws_plugin__s2member_menu_pages::update_all_options();
include_once dirname(dirname(__FILE__)).'/menu-pages/scripting.inc.php';
do_action('ws_plugin__s2member_after_scripting_page', get_defined_vars());
}
/**
* Builds and handles the Integrations page.
*
* @package s2Member\Menu_Pages
* @since 3.5
*/
public static function integrations_page()
{
do_action('ws_plugin__s2member_before_integrations_page', get_defined_vars());
include_once dirname(dirname(__FILE__)).'/menu-pages/integrations.inc.php';
do_action('ws_plugin__s2member_after_integrations_page', get_defined_vars());
}
/**
* Builds and handles the Logs page.
*
* @package s2Member\Menu_Pages
* @since 120310
*/
public static function logs_page()
{
do_action('ws_plugin__s2member_before_logs_page', get_defined_vars());
c_ws_plugin__s2member_menu_pages::update_all_options();
c_ws_plugin__s2member_menu_pages::archive_logs_start_fresh();
c_ws_plugin__s2member_menu_pages::delete_logs_start_fresh();
$logs_dir = $GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir'];
if(!is_dir($logs_dir) && is_writable(dirname(c_ws_plugin__s2member_utils_dirs::strip_dir_app_data($logs_dir))))
mkdir($logs_dir, 0777, TRUE).clearstatcache();
$htaccess = $GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir'].'/.htaccess';
$htaccess_contents = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir_htaccess'])));
if(is_dir($logs_dir) && is_writable($logs_dir) && !file_exists($htaccess))
file_put_contents($htaccess, $htaccess_contents).clearstatcache();
if(!is_dir($logs_dir)) // If the security-enabled logs directory does not exist yet.
c_ws_plugin__s2member_admin_notices::display_admin_notice('The security-enabled logs directory ('.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($logs_dir)).') does not exist. Please create this directory manually & make it writable (chmod 777).', TRUE);
else if(!is_writable($logs_dir)) // If the logs directory is not writable yet.
c_ws_plugin__s2member_admin_notices::display_admin_notice('Permissions error. The security-enabled logs directory ('.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($logs_dir)).') is not writable. Please make this directory writable (chmod 777).', TRUE);
if(!file_exists($htaccess)) // If the .htaccess file has not been created yet.
c_ws_plugin__s2member_admin_notices::display_admin_notice('The .htaccess protection file ('.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).') does not exist. Please create this file manually. Inside your .htaccess file, add this:'.esc_html($htaccess_contents).'', TRUE); else if(!preg_match('/deny from all/i', file_get_contents($htaccess))) // Else if the .htaccess file does not offer the required protection. c_ws_plugin__s2member_admin_notices::display_admin_notice('Unprotected. The .htaccess protection file (
'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).') does not contain deny from all. Inside your .htaccess file, add this:'.esc_html($htaccess_contents).'', TRUE); if(!$GLOBALS['WS_PLUGIN__']['s2member']['o']['gateway_debug_logs']) // Logging disabled? c_ws_plugin__s2member_admin_notices::display_admin_notice('Logging is currently disabled by your configuration.'); include_once dirname(dirname(__FILE__)).'/menu-pages/logs.inc.php'; do_action('ws_plugin__s2member_after_logs_page', get_defined_vars()); } /** * Registers the Get Help panel across admin pages. * * @package s2Member\Menu_Pages * @since 250824 * * @attaches-to ``add_action('admin_menu');`` */ public static function get_help_panel() { $hooks = array( // Framework 'ws_plugin__s2member_during_api_ops_page_before_left_sections_form', 'ws_plugin__s2member_during_down_ops_page_before_left_sections_form', 'ws_plugin__s2member_during_els_ops_page_before_left_sections_form', 'ws_plugin__s2member_during_gen_ops_page_before_left_sections_form', 'ws_plugin__s2member_during_help_page_before_left_sections', 'ws_plugin__s2member_during_integrations_page_before_left_sections', 'ws_plugin__s2member_during_logs_page_before_left_sections', 'ws_plugin__s2member_during_paypal_buttons_page_before_left_sections', 'ws_plugin__s2member_during_paypal_ops_page_before_left_sections_form', 'ws_plugin__s2member_during_res_ops_page_before_left_sections_form', 'ws_plugin__s2member_during_scripting_page_before_left_sections', 'ws_plugin__s2member_during_start_page_before_left_sections', 'ws_plugin__s2member_during_trk_ops_page_before_left_sections_form', // Pro 'ws_plugin__s2member_during_authnet_forms_page_before_left_sections', 'ws_plugin__s2member_during_authnet_ops_page_before_left_sections_form', 'ws_plugin__s2member_during_clickbank_buttons_page_before_left_sections', 'ws_plugin__s2member_during_clickbank_ops_page_before_left_sections_form', 'ws_plugin__s2member_during_coupon_codes_page_before_left_sections_form', 'ws_plugin__s2member_during_import_export_page_before_left_sections', 'ws_plugin__s2member_during_mms_ops_page_before_left_sections_form', 'ws_plugin__s2member_during_other_gateways_page_before_left_sections_form', 'ws_plugin__s2member_during_paypal_forms_page_before_left_sections', 'ws_plugin__s2member_during_stripe_forms_page_before_left_sections', 'ws_plugin__s2member_during_stripe_ops_page_before_left_sections_form', ); foreach ($hooks as $hook) { add_action($hook, 'c_ws_plugin__s2member_menu_pages::get_help_panel_load', 1, 1); } } /** * Renders the Get Help panel (computes $notice/$draft and includes template). * * @package s2Member\Menu_Pages * @since 250824 * * @param array $vars Optional vars passed by the hook (unused). */ public static function get_help_panel_load($vars = array()) { if (!current_user_can('manage_options')) return; // Build notice (if POST). $notice = array('type' => '', 'text' => ''); if (!empty($_POST['s2m_help_nonce']) && isset($_POST['s2m_help_submit']) && wp_verify_nonce($_POST['s2m_help_nonce'], 's2member_get_help')) { $result = c_ws_plugin__s2member_menu_pages::get_help_mail(); if (!empty($result['ok'])) { $notice = array('type' => 'success', 'text' => __('Thanks — your message was sent. You’ll receive a copy by email.', 's2member')); $_POST = array(); // clear fields after success so defaults repopulate } else { $msg = isset($result['msg']) ? $result['msg'] : __('Sorry, your message could not be sent. Please try again.', 's2member'); $notice = array('type' => 'error', 'text' => $msg); } } // Build draft (preserve POST on error; else defaults from current user). $current = wp_get_current_user(); $draft = array( 'name' => is_object($current) ? trim($current->display_name) : '', 'email' => is_object($current) ? trim($current->user_email) : '', 'subject' => '', 'details' => '', 'meta' => home_url()."\n" .'PHP v'.PHP_VERSION .', WordPress v'.(isset($GLOBALS['wp_version']) ? $GLOBALS['wp_version'] : '') .', s2Member v'.(defined('WS_PLUGIN__S2MEMBER_VERSION') ? WS_PLUGIN__S2MEMBER_VERSION : '') .(defined('WS_PLUGIN__S2MEMBER_PRO_VERSION') ? ', Pro v'.WS_PLUGIN__S2MEMBER_PRO_VERSION : ''), ); if (isset($_POST['name'])) $draft['name'] = wp_strip_all_tags(trim(wp_unslash($_POST['name']))); if (isset($_POST['email'])) $draft['email'] = sanitize_email(trim(wp_unslash($_POST['email']))); if (isset($_POST['subject'])) $draft['subject'] = sanitize_text_field(trim(wp_unslash($_POST['subject']))); if (isset($_POST['details'])) $draft['details'] = trim(wp_unslash($_POST['details'])); if (isset($_POST['meta'])) $draft['meta'] = trim(wp_unslash($_POST['meta'])); // Include template (variables $draft and $notice are in scope for the include). include_once dirname(dirname(__FILE__)).'/menu-pages/get-help-panel.inc.php'; } /** * Sends the Get Help email (simple contact form, Bcc user). * * @package s2Member\Menu_Pages * @since 250824 * * @return array Array like ['ok' => bool, 'msg' => string]. */ public static function get_help_mail() { if (!current_user_can('manage_options')) { return array('ok' => false, 'msg' => __('You do not have permission to send support requests from this page.', 's2member')); } $name = isset($_POST['name']) ? wp_strip_all_tags(trim(wp_unslash($_POST['name']))) : ''; $email = isset($_POST['email']) ? sanitize_email(trim(wp_unslash($_POST['email']))) : ''; $subject_in = isset($_POST['subject']) ? sanitize_text_field(trim(wp_unslash($_POST['subject']))) : ''; $details = isset($_POST['details']) ? trim(wp_unslash($_POST['details'])) : ''; $meta = isset($_POST['meta']) ? trim(wp_unslash($_POST['meta'])) : ''; $email = str_replace(array("\r", "\n"), '', $email); // header-injection safety if (empty($email) || !is_email($email)) { return array('ok' => false, 'msg' => __('Please provide a valid email address.', 's2member')); } if ($details === '') { return array('ok' => false, 'msg' => __('Please describe how I can help.', 's2member')); } // Cap length and normalize body fields $max_len = 100000; if (strlen($details) > $max_len) $details = substr($details, 0, $max_len); if (strlen($meta) > $max_len) $meta = substr($meta, 0, $max_len); $details = str_replace(array("\r\n", "\r"), "\n", $details); $meta = str_replace(array("\r\n", "\r"), "\n", $meta); $message = $details."\n\n".$meta; // Subject with fallback/prefix $subject = (string) apply_filters('ws_plugin__s2member_get_help_subject', $subject_in); $subject = str_replace(array("\r\n", "\r", "\n"), ' ', trim($subject)); $subject = ($subject === '') ? __('s2Member help request', 's2member') : 's2Member help: '.$subject; // Sanitize display names $name_hdr = str_replace(array("\r\n", "\r", "\n"), ' ', (string) $name); $name_hdr = str_replace('"', "'", $name_hdr); $sitename = c_ws_plugin__s2member_utils_urls::parse_url(home_url(), PHP_URL_HOST); $sitename = is_string($sitename) ? strtolower($sitename) : ''; if (strpos($sitename, 'www.') === 0) $sitename = substr($sitename, 4); $default_from_email = 'wordpress@'.$sitename; $default_from_name = ($name_hdr !== '' ? $name_hdr : get_bloginfo('name')); // Honor WP and s2 filters, then cleanup $from_email = (string) apply_filters('wp_mail_from', $default_from_email); $from_name = (string) apply_filters('wp_mail_from_name', $default_from_name); $from_email = (string) apply_filters('ws_plugin__s2member_get_help_from_email', $from_email); $from_name = (string) apply_filters('ws_plugin__s2member_get_help_from_name', $from_name); $from_email = str_replace(array("\r", "\n"), '', $from_email); $from_name = str_replace(array("\r\n", "\r", "\n"), ' ', $from_name); $from_name = str_replace('"', "'", $from_name); // Build headers $from_line = '"'.$from_name.'" <'.$from_email.'>'; $user_line = ($name_hdr !== '' ? '"'.$name_hdr.'" ' : '').'<'.$email.'>'; $headers = array('Content-Type: text/plain; charset=UTF-8'); $headers[] = 'From: '.$from_line; $headers[] = 'Reply-To: '.$user_line; $headers[] = 'Bcc: '.$user_line; $headers[] = 'X-s2Member-Help: 1'; $headers = apply_filters('ws_plugin__s2member_get_help_headers', $headers, compact('name','email','subject','details','meta')); // Recipient $to = (string) apply_filters('ws_plugin__s2member_get_help_mailbox', 'support@wpsharks.com'); if (empty($to) || !is_email($to)) { return array('ok' => false, 'msg' => __('Support mailbox is not configured correctly.', 's2member')); } $sent = wp_mail($to, $subject, $message, $headers); if (!$sent) { if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { error_log('s2Member Get Help: wp_mail() returned false. To='.$to.' | Subject='.$subject); } return array('ok' => false, 'msg' => __('Email could not be sent (mail server issue). Please try again or contact us directly.', 's2member')); } return array('ok' => true, 'msg' => __('Thanks — your message was sent. You’ll receive a copy by email.', 's2member')); } } }