From: Chuck Scott Date: Mon, 18 May 2015 18:22:24 +0000 (-0400) Subject: initial commit X-Git-Url: http://cvs2.gaslightmedia.com/gitweb/?a=commitdiff_plain;h=869dd53bf8f31b4c54d907e5c3e40fe67d681add;p=WP-Plugins%2Fsimple-membership.git initial commit --- 869dd53bf8f31b4c54d907e5c3e40fe67d681add diff --git a/classes/class.bAccessControl.php b/classes/class.bAccessControl.php new file mode 100644 index 0000000..92c3c8f --- /dev/null +++ b/classes/class.bAccessControl.php @@ -0,0 +1,109 @@ +lastError = ''; + $this->moretags = array(); + } + public static function get_instance(){ + self::$_this = empty(self::$_this)? new BAccessControl():self::$_this; + return self::$_this; + } + + public function can_i_read_post($id){ + $this->lastError = ''; + global $post; + $auth = BAuth::get_instance(); + $protect_everything = BSettings::get_instance()->get_value('protect-everything'); + if(!empty($protect_everything)){ + $error_msg = BUtils::_( 'You need to login to view this content. ' ) . BSettings::get_instance()->get_login_link(); + $this->lastError = apply_filters('swpm_not_logged_in_post_msg', $error_msg); + return false; + } + $protected = BProtection::get_instance(); + if (!$protected->is_protected($id)){ return true;} + if(!$auth->is_logged_in()){ + $error_msg = BUtils::_( 'You need to login to view this content. ' ) . BSettings::get_instance()->get_login_link(); + $this->lastError = apply_filters('swpm_not_logged_in_post_msg', $error_msg); + return false; + } + + if ($auth->is_expired_account()){ + $error_msg = '
'.BUtils::_('Your account has expired. Please renew your account to gain access to this content.').'
'; + $this->lastError = apply_filters('swpm_account_expired_msg', $error_msg); + return false; + } + $protect_older_posts = apply_filters('swpm_should_protect_older_post', false, $id); + if ($protect_older_posts){ + $this->lastError = apply_filters ('swpm_restricted_post_msg_older_post', + BUtils::_('This content can only be viewed by members who joined on or before ' . date(get_option( 'date_format' ), strtotime($post->post_date)))) ; + return false; + } + $perms = BPermission::get_instance($auth->get('membership_level')); + if($perms->is_permitted($id)) {return true;} + $this->lastError = apply_filters ('swpm_restricted_post_msg', '
'.BUtils::_('This content is not permitted for your membership level.').'
') ; + return false; + } + public function can_i_read_comment($id){ + $this->lastError = ''; + $protected = BProtection::get_instance(); + if (!$protected->is_protected_comment($id)){ return true;} + $auth = BAuth::get_instance(); + if(!$auth->is_logged_in()){ + $this->lastError = apply_filters('swpm_not_logged_in_comment_msg', BUtils::_("You need to login to view this content. ") + . BSettings::get_instance()->get_login_link()); + return false; + } + if ($auth->is_expired_account()){ + $error_msg = '
'.BUtils::_('Your account has expired. Please renew your account to gain access to this content.').'
'; + $this->lastError = apply_filters('swpm_account_expired_msg', $error_msg); + return false; + } + $perms = BPermission::get_instance($auth->get('membership_level')); + if($perms->is_permitted_comment($id)) {return true; } + $this->lastError = apply_filters ('swpm_restricted_comment_msg', '
'.BUtils::_("This content is not permitted for your membership level.").'
' ); + return false; + } + public function why(){ + return $this->lastError; + } + public function filter_post($id,$content){ + if(in_array($id, $this->moretags)) {return $content; } + if($this->can_i_read_post($id)) {return $content; } + $moretag = BSettings::get_instance()->get_value('enable-moretag'); + if (empty($moretag)){ + return $this->lastError; + } + $post = get_post($id); + $post_segments = explode( '', $post->post_content); + + if (count($post_segments) >= 2){ + if (BAuth::get_instance()->is_logged_in()){ + $error_msg = '
' . BUtils::_(" The rest of the content is not permitted for your membership level.") . '
'; + $this->lastError = apply_filters ('swpm_restricted_more_tag_msg', $error_msg); + } + else { + $error_msg = '
' . BUtils::_("You need to login to view the rest of the content. ") . BSettings::get_instance()->get_login_link() . '
'; + $this->lastError = apply_filters('swpm_not_logged_in_more_tag_msg', $error_msg); + } + + return do_shortcode($post_segments[0]) . $this->lastError; + } + + return $this->lastError; + } + public function filter_comment($id,$content){ + if($this->can_i_read_comment($id)) { return $content; } + return $this->lastError; + } + public function filter_post_with_moretag($id, $more_link, $more_link_text){ + $this->moretags[] = $id; + if($this->can_i_read_post($id)) { + return $more_link; + } + $msg = BUtils::_("You need to login to view the rest of the content. ") . BSettings::get_instance()->get_login_link(); + return apply_filters('swpm_not_logged_in_more_tag_msg', $msg); + } +} diff --git a/classes/class.bAdminRegistration.php b/classes/class.bAdminRegistration.php new file mode 100644 index 0000000..84f5881 --- /dev/null +++ b/classes/class.bAdminRegistration.php @@ -0,0 +1,92 @@ +is_valid()) { + $member_info = $form->get_sanitized(); + $account_status = BSettings::get_instance()->get_value('default-account-status', 'active'); + $member_info['account_state'] = $account_status; + $plain_password = $member_info['plain_password']; + unset($member_info['plain_password']); + $wpdb->insert($wpdb->prefix . "swpm_members_tbl", $member_info); + /* * ******************** register to wordpress ********** */ + $query = $wpdb->prepare("SELECT role FROM " . $wpdb->prefix . "swpm_membership_tbl WHERE id = %d", $member_info['membership_level']) ; + $wp_user_info = array(); + $wp_user_info['user_nicename'] = implode('-', explode(' ', $member_info['user_name'])); + $wp_user_info['display_name'] = $member_info['user_name']; + $wp_user_info['user_email'] = $member_info['email']; + $wp_user_info['nickname'] = $member_info['user_name']; + if (isset($member_info['first_name'])){$wp_user_info['first_name'] = $member_info['first_name']; } + if (isset($member_info['last_name'])){$wp_user_info['last_name'] = $member_info['last_name'];} + $wp_user_info['user_login'] = $member_info['user_name']; + $wp_user_info['password'] = $plain_password; + $wp_user_info['role'] = $wpdb->get_var($query); + $wp_user_info['user_registered'] = date('Y-m-d H:i:s'); + BUtils::create_wp_user($wp_user_info); + /* * ******************** register to wordpress ********** */ + $send_notification = BSettings::get_instance()->get_value('enable-notification-after-manual-user-add'); + $member_info['plain_password'] = $plain_password; + $this->member_info = $member_info; + if (!empty($send_notification)){ + $this->send_reg_email(); + } + $message = array('succeeded' => true, 'message' => BUtils::_('Registration Successful.')); + BTransfer::get_instance()->set('status', $message); + wp_redirect('admin.php?page=simple_wp_membership'); + return; + } + $message = array('succeeded' => false, 'message' => BUtils::_('Please correct the following:'), 'extra' => $form->get_errors()); + BTransfer::get_instance()->set('status', $message); + } + public function edit($id){ + global $wpdb; + $query = $wpdb->prepare("SELECT * FROM " . $wpdb->prefix . "swpm_members_tbl WHERE member_id = %d", $id); + $member = $wpdb->get_row($query, ARRAY_A); + $email_address = $member['email']; + $user_name = $member['user_name']; + unset($member['member_id']); + unset($member['user_name']); + $form = new BForm($member); + if ($form->is_valid()) { + $member = $form->get_sanitized(); + BUtils::update_wp_user($user_name, $member); + unset($member['plain_password']); + $wpdb->update($wpdb->prefix . "swpm_members_tbl", $member, array('member_id' => $id)); + $message = array('succeeded' => true, 'message' => 'Updated Successfully.'); + do_action('swpm_admin_edit_custom_fields', $member + array('member_id'=>$id)); + BTransfer::get_instance()->set('status', $message); + $send_notification = filter_input(INPUT_POST, 'account_status_change'); + if (!empty($send_notification)){ + $settings = BSettings::get_instance(); + $from_address = $settings->get_value('email-from'); + $headers = 'From: ' . $from_address . "\r\n"; + $subject = filter_input(INPUT_POST,'notificationmailhead'); + $body = filter_input(INPUT_POST, 'notificationmailbody'); + $settings->set_value('account-change-email-body', $body)->set_value('account-change-email-subject', $subject)->save(); + $member['login_link'] = $settings->get_value('login-page-url'); + $values = array_values($member); + $keys = array_map('swpm_enclose_var', array_keys($member)); + $body = str_replace($keys, $values, $body); + wp_mail($email_address, $subject, $body, $headers); + } + wp_redirect('admin.php?page=simple_wp_membership'); + } + $message = array('succeeded' => false, 'message' => BUtils::_('Please correct the following:'), 'extra' => $form->get_errors()); + BTransfer::get_instance()->set('status', $message); + } +} diff --git a/classes/class.bAjax.php b/classes/class.bAjax.php new file mode 100644 index 0000000..7a48d9e --- /dev/null +++ b/classes/class.bAjax.php @@ -0,0 +1,36 @@ +prefix . "swpm_members_tbl"; + $query = $wpdb->prepare("SELECT member_id FROM $table WHERE email = %s", $field_value); + $db_id = $wpdb->get_var($query) ; + $exists = ($db_id > 0) && $db_id != $member_id; + echo '[ "' . $field_id . (($exists) ? '",false, "χ '.BUtils::_('Aready taken').'"]' : '",true, "√ Available"]'); + exit; + } + + public static function validate_user_name_ajax() { + global $wpdb; + $field_value = filter_input(INPUT_GET, 'fieldValue'); + $field_id = filter_input(INPUT_GET, 'fieldId'); + $table = $wpdb->prefix . "swpm_members_tbl"; + $query = $wpdb->prepare("SELECT COUNT(*) FROM $table WHERE user_name = %s", $field_value); + $exists = $wpdb->get_var($query) > 0; + echo '[ "' . $field_id . (($exists) ? '",false,"χ '. BUtils::_('Aready taken'). '"]' : + '",true,"√ '.BUtils::_('Available'). '"]'); + exit; + } +} diff --git a/classes/class.bAuth.php b/classes/class.bAuth.php new file mode 100644 index 0000000..1b4eaf0 --- /dev/null +++ b/classes/class.bAuth.php @@ -0,0 +1,291 @@ +isLoggedIn = false; + $this->userData = null; + $this->protected = BProtection::get_instance(); + } + private function init(){ + $valid = $this->validate(); + //Blog::log_simple_debug("init:". ($valid? "valid": "invalid"), true); + if (!$valid){ + $this->authenticate(); + } + } + public static function get_instance() { + if (empty(self::$_this)){ + self::$_this = new BAuth(); + self::$_this->init(); + } + return self::$_this; + } + + private function authenticate($user = null, $pass = null) { + global $wpdb; + $swpm_password = empty($pass)?filter_input(INPUT_POST, 'swpm_password') : $pass; + $swpm_user_name = empty($user)? apply_filters('swpm_user_name', filter_input(INPUT_POST, 'swpm_user_name')) : $user; + //Blog::log_simple_debug("Authenticate:" . $swpm_user_name, true); + if (!empty($swpm_user_name) && !empty($swpm_password)) { + $user = sanitize_user($swpm_user_name); + $pass = trim($swpm_password); + $query = "SELECT * FROM " . $wpdb->prefix . "swpm_members_tbl WHERE user_name = %s"; + $userData = $wpdb->get_row($wpdb->prepare($query, $user)); + $this->userData = $userData; + if (!$userData) { + $this->isLoggedIn = false; + $this->userData = null; + $this->lastStatusMsg = BUtils::_("User Not Found."); + return false; + } + $check = $this->check_password($pass, $userData->password); + if (!$check) { + $this->isLoggedIn = false; + $this->userData = null; + $this->lastStatusMsg = BUtils::_("Password Empty or Invalid."); + return false; + } + if ($this->check_constraints()) { + $rememberme = filter_input(INPUT_POST, 'rememberme'); + $remember = empty($rememberme) ? false : true; + $this->set_cookie($remember); + $this->isLoggedIn = true; + $this->lastStatusMsg = "Logged In."; + Blog::log_simple_debug("swpm_login action.", true); + do_action('swpm_login', $user, $pass, $remember); + return true; + } + } + return false; + } + + private function check_constraints() { + if (empty($this->userData)){ + return false; + } + $enable_expired_login = BSettings::get_instance()->get_value('enable-expired-account-login', ''); + + $can_login = true; + if( $this->userData->account_state == 'inactive'){ + $this->lastStatusMsg = BUtils::_('Account is inactive.'); + $can_login = false; + } + else if( $this->userData->account_state == 'pending'){ + $this->lastStatusMsg = BUtils::_('Account is pending.'); + $can_login = false; + } + else if( ($this->userData->account_state == 'expired') && empty($enable_expired_login) ){ + $this->lastStatusMsg = BUtils::_('Account has expired.'); + $can_login = false; + } + + if(!$can_login){ + $this->isLoggedIn = false; + $this->userData = null; + return false; + } + + if (BUtils::is_subscription_expired($this->userData)){ + if ($this->userData->account_state == 'active'){ + global $wpdb; + $wpdb->update( + $wpdb->prefix . 'swpm_members_tbl', + array( 'account_state' => 'expired'), + array( 'member_id' => $this->userData->member_id ), + array( '%s'), + array( '%d' ) + ); + } + if (empty($enable_expired_login)){ + $this->lastStatusMsg = BUtils::_('Account has expired.'); + $this->isLoggedIn = false; + $this->userData = null; + return false; + } + } + + $this->permitted = BPermission::get_instance($this->userData->membership_level); + $this->lastStatusMsg = BUtils::_("You are logged in as:") . $this->userData->user_name; + $this->isLoggedIn = true; + return true; + } + + private function check_password($password, $hash) { + global $wp_hasher; + if (empty($password)){ + return false; + } + if (empty($wp_hasher)) { + require_once( ABSPATH . 'wp-includes/class-phpass.php'); + $wp_hasher = new PasswordHash(8, TRUE); + } + return $wp_hasher->CheckPassword($password, $hash); + } + public function match_password($password){ + if (!$this->is_logged_in()) {return false;} + return $this->check_password($password, $this->get('password')); + } + public function login($user, $pass, $remember = '', $secure = '') { + Blog::log_simple_debug("login",true); + if ($this->isLoggedIn){ + return; + } + if ($this->authenticate($user, $pass) && $this->validate()) { + $this->set_cookie($remember, $secure); + } else { + $this->isLoggedIn = false; + $this->userData = null; + } + return $this->lastStatusMsg; + } + + public function logout() { + if (!$this->isLoggedIn){ + return; + } + setcookie(SIMPLE_WP_MEMBERSHIP_AUTH, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN); + setcookie(SIMPLE_WP_MEMBERSHIP_SEC_AUTH, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN); + $this->userData = null; + $this->isLoggedIn = false; + $this->lastStatusMsg = BUtils::_("Logged Out Successfully."); + do_action('swpm_logout'); + } + + private function set_cookie($remember = '', $secure = '') { + if ($remember){ + $expiration = time() + 1209600; // 14 days + $expire = $expiration + 43200; // 12 hours grace period + } + else{ + $expiration = time() + 172800; // 2 days. + $expire = $expiration;//The minimum cookie expiration should be at least couple of days. + } + + $expiration_timestamp = BUtils::get_expiration_timestamp($this->userData); + $enable_expired_login = BSettings::get_instance()->get_value('enable-expired-account-login', ''); + // make sure cookie doesn't live beyond account expiration date. + // but if expired account login is enabled then ignore if account is expired + $expiration = empty($enable_expired_login)? min ($expiration,$expiration_timestamp) : $expiration; + $pass_frag = substr($this->userData->password, 8, 4); + $scheme = 'auth'; + if (!$secure){ + $secure = is_ssl(); + } + $key = BAuth::b_hash($this->userData->user_name . $pass_frag . '|' . $expiration, $scheme); + $hash = hash_hmac('md5', $this->userData->user_name . '|' . $expiration, $key); + $auth_cookie = $this->userData->user_name . '|' . $expiration . '|' . $hash; + $auth_cookie_name = $secure ? SIMPLE_WP_MEMBERSHIP_SEC_AUTH : SIMPLE_WP_MEMBERSHIP_AUTH; + //setcookie($auth_cookie_name, $auth_cookie, $expire, PLUGINS_COOKIE_PATH, COOKIE_DOMAIN, $secure, true); + setcookie($auth_cookie_name, $auth_cookie, $expire, COOKIEPATH, COOKIE_DOMAIN, $secure, true); + } + + private function validate() { + $auth_cookie_name = is_ssl() ? SIMPLE_WP_MEMBERSHIP_SEC_AUTH : SIMPLE_WP_MEMBERSHIP_AUTH; + if (!isset($_COOKIE[$auth_cookie_name]) || empty($_COOKIE[$auth_cookie_name])){ + return false; + } + $cookie_elements = explode('|', $_COOKIE[$auth_cookie_name]); + if (count($cookie_elements) != 3){ + return false; + } + Blog::log_simple_debug("validate:" . $_COOKIE[$auth_cookie_name],true); + list($username, $expiration, $hmac) = $cookie_elements; + $expired = $expiration; + // Allow a grace period for POST and AJAX requests + if (defined('DOING_AJAX') || 'POST' == $_SERVER['REQUEST_METHOD']){ + $expired += HOUR_IN_SECONDS; + } + // Quick check to see if an honest cookie has expired + if ($expired < time()) { + $this->lastStatusMsg = BUtils::_("Session Expired."); //do_action('auth_cookie_expired', $cookie_elements); + return false; + } + Blog::log_simple_debug("validate:Session Expired",true); + global $wpdb; + $query = " SELECT * FROM " . $wpdb->prefix . "swpm_members_tbl WHERE user_name = %s"; + $user = $wpdb->get_row($wpdb->prepare($query, $username)); + if (empty($user)) { + $this->lastStatusMsg = BUtils::_("Invalid User Name"); + return false; + } + Blog::log_simple_debug("validate:Invalid User Name:" . serialize($user),true); + $pass_frag = substr($user->password, 8, 4); + $key = BAuth::b_hash($username . $pass_frag . '|' . $expiration); + $hash = hash_hmac('md5', $username . '|' . $expiration, $key); + if ($hmac != $hash) { + $this->lastStatusMsg = BUtils::_("Sorry! Something went wrong"); + return false; + } + Blog::log_simple_debug("validate:bad hash",true); + if ($expiration < time()){ + $GLOBALS['login_grace_period'] = 1; + } + $this->userData = $user; + return $this->check_constraints(); + } + + public static function b_hash($data, $scheme = 'auth') { + $salt = wp_salt($scheme) . 'j4H!B3TA,J4nIn4.'; + return hash_hmac('md5', $data, $salt); + } + + public function is_logged_in() { + return $this->isLoggedIn; + } + + public function get($key, $default = "") { + if (isset($this->userData->$key)){ + return $this->userData->$key; + } + if (isset($this->permitted->$key)){ + return $this->permitted->$key; + } + if (!empty($this->permitted)){ + return $this->permitted->get($key, $default); + } + return $default; + } + + public function get_message() { + return $this->lastStatusMsg; + } + public function get_expire_date(){ + if ($this->isLoggedIn){ + return BUtils::get_expire_date( + $this->get('subscription_starts'), + $this->get('subscription_period'), + $this->get('subscription_duration_type')); + } + return ""; + } + public function delete(){ + if (!$this->is_logged_in()) {return ;} + $user_name = $this->get('user_name'); + $user_id = $this->get('member_id'); + wp_clear_auth_cookie(); + $this->logout(); + BMembers::delete_swpm_user_by_id($user_id); + BMembers::delete_wp_user($user_name); + } + + public function reload_user_data(){ + if (!$this->is_logged_in()) {return ;} + global $wpdb; + $query = "SELECT * FROM " . $wpdb->prefix . "swpm_members_tbl WHERE member_id = %d"; + $this->userData = $wpdb->get_row($wpdb->prepare($query, $this->userData->member_id)); + + } + public function is_expired_account(){ + // should be called after logging in. + if (!$this->is_logged_in()) {return null;} + return $this->get('account_state') === 'expired'; + } +} diff --git a/classes/class.bAuthPermissionCollection.php b/classes/class.bAuthPermissionCollection.php new file mode 100644 index 0000000..803c1a4 --- /dev/null +++ b/classes/class.bAuthPermissionCollection.php @@ -0,0 +1,9 @@ + BUtils::_('Membership Level'), + 'plural' => BUtils::_('Membership Levels'), + 'ajax' => false + )); + $this->category = array(); + $selected = filter_input(INPUT_POST, 'membership_level_id'); + $this->selected_level_id = empty($selected) ? 1 : $selected; + $this->category = ($this->selected_level_id == 1) ? + BProtection::get_instance() : + BPermission::get_instance($this->selected_level_id); + } + + function get_columns() { + return array( + 'cb' => '' + , 'term_id' => BUtils::_('ID') + , 'name' => BUtils::_('Name') + , 'description' => BUtils::_('Description') + , 'count' => BUtils::_('Count') + ); + } + + function get_sortable_columns() { + return array( + 'name' => array('name', true) + ); + } + + function column_default($item, $column_name) { + return stripslashes($item->$column_name); + } + + function column_term_id($item) { + return $item->term_id; + } + + function column_cb($item) { + return sprintf( + '', $this->category->in_categories($item->term_id) ? "checked" : "", $item->term_id + ); + } + + function prepare_items() { + $submitted = filter_input(INPUT_POST, 'update_category_list'); + if (!empty($submitted)) { + $args = array('ids' => array( + 'filter' => FILTER_VALIDATE_INT, + 'flags' => FILTER_REQUIRE_ARRAY, + )); + $filtered = filter_input_array(INPUT_POST, $args); + $ids = $filtered['ids']; + $this->category->apply($ids, 'category')->save(); + $message = array('succeeded' => true, 'message' => BUtils::_('Updated! ')); + BTransfer::get_instance()->set('status', $message); + } + $all_categories = array(); + $all_cat_ids = get_categories(array('hide_empty' => '0')); + $totalitems = count($all_cat_ids); + $perpage = 100; + $paged = !empty($_GET["paged"]) ? mysql_real_escape_string($_GET["paged"]) : ''; + if (empty($paged) || !is_numeric($paged) || $paged <= 0) { + $paged = 1; + } + $totalpages = ceil($totalitems / $perpage); + $offset = 0; + if (!empty($paged) && !empty($perpage)) { + $offset = ($paged - 1) * $perpage; + } + for ($i = $offset; $i < ((int) $offset + (int) $perpage) && !empty($all_cat_ids[$i]); $i++) { + $all_categories[] = $all_cat_ids[$i]; + } + $this->set_pagination_args(array( + "total_items" => $totalitems, + "total_pages" => $totalpages, + "per_page" => $perpage, + )); + + $columns = $this->get_columns(); + $hidden = array(); + $sortable = $this->get_sortable_columns(); + + $this->_column_headers = array($columns, $hidden, $sortable); + $this->items = $all_categories; + } + + function no_items() { + BUtils::e('No category found.'); + } + +} diff --git a/classes/class.bCronJob.php b/classes/class.bCronJob.php new file mode 100644 index 0000000..7495996 --- /dev/null +++ b/classes/class.bCronJob.php @@ -0,0 +1,60 @@ +prepare("SELECT member_id, membership_level, subscription_starts, account_state + FROM {$wpdb->prefix}swpm_members_tbl LIMIT %d, 100", $counter); + $results = $wpdb->get_results($query); + if (empty($results)) {break;} + $expired = array(); + foreach($results as $result){ + $timestamp = BUtils::get_expiration_timestamp($result); + if ($timestamp < time() && $result->account_state == 'active'){ + $expired[] = $result->member_id; + } + } + if (count($expired)>0){ + $query = "UPDATE {$wpdb->prefix}swpm_members_tbl + SET account_state='expired' WHERE member_id IN (" . implode(',', $expired) . ")"; + $wpdb->query($query); + } + } + } + + public function delete_pending_account(){ + global $wpdb; + $interval = BSettings::get_instance()->get_value('delete-pending-account'); + if (empty($interval)) {return;} + for($counter = 0;; $counter += 100){ + $query = $wpdb->prepare("SELECT member_id + FROM + {$wpdb->prefix}swpm_members_tbl + WHERE account_state='pending' + AND subscription_starts < DATE_SUB(NOW(), INTERVAL %d MONTH) LIMIT %d, 100", + $interval, $counter); + $results = $wpdb->get_results($query); + if (empty($results)) {break;} + $to_delete = array(); + foreach($results as $result){ + $to_delete[] = $result->member_id; + } + if (count($to_delete)>0){ + Blog::log_simple_debug("Auto deleting pending account.", true); + $query = "DELETE FROM {$wpdb->prefix}swpm_members_tbl + WHERE member_id IN (" . implode(',', $to_delete) . ")"; + $wpdb->query($query); + } + } + } +} diff --git a/classes/class.bForm.php b/classes/class.bForm.php new file mode 100644 index 0000000..031eeec --- /dev/null +++ b/classes/class.bForm.php @@ -0,0 +1,308 @@ +fields = $fields; + $this->sanitized = array(); + $this->validate_wp_user_email(); + if ($this->is_valid()){ + foreach ($fields as $key => $value){ + $this->$key(); + } + } + } + protected function validate_wp_user_email(){ + $user_name = filter_input(INPUT_POST, 'user_name',FILTER_SANITIZE_STRING); + $email = filter_input(INPUT_POST, 'email', FILTER_UNSAFE_RAW); + if (empty($user_name)) {return;} + $user = get_user_by('login', $user_name); + if ($user && ($user->email != $email)){ + $this->errors['wp_email'] = BUtils::_('Wordpress account exists with given user name. But given email doesn\'t match.'); + return; + } + $user = get_user_by('email', $email); + if($user && ($user_name != $user->login)){ + $this->errors['wp_user'] = BUtils::_('Wordpress account exists with given email. But given user name doesn\'t match.'); + + } + } + protected function user_name() { + global $wpdb; + if (!empty($this->fields['user_name'])){return;} + $user_name = filter_input(INPUT_POST, 'user_name',FILTER_SANITIZE_STRING); + if (empty($user_name)) { + $this->errors['user_name'] = BUtils::_('User name is required'); + return; + } + if (preg_match("/^[a-zA-Z0-9!@#$%&*+\/=?^_`{|}~\.-]+$/", $user_name) === 0) { + $this->errors['user_name'] = BUtils::_('User name contains invalid character'); + return; + } + $saned = sanitize_text_field($user_name); + $query = "SELECT count(member_id) FROM {$wpdb->prefix}swpm_members_tbl WHERE user_name= %s"; + $result = $wpdb->get_var($wpdb->prepare($query, strip_tags($saned))); + if ($result > 0) { + if ($saned != $this->fields['user_name']) { + $this->errors['user_name'] = BUtils::_('User name already exists.'); + return; + } + } + $this->sanitized['user_name'] = $saned; + } + + protected function first_name() { + $first_name = filter_input(INPUT_POST, 'first_name', FILTER_SANITIZE_STRING); + if (empty($first_name)) {return;} + $this->sanitized['first_name'] = sanitize_text_field($first_name); + } + + protected function last_name() { + $last_name = filter_input(INPUT_POST, 'last_name', FILTER_SANITIZE_STRING); + if (empty($last_name)) {return;} + $this->sanitized['last_name'] = sanitize_text_field($last_name); + } + + protected function password() { + $password = filter_input(INPUT_POST, 'password',FILTER_UNSAFE_RAW); + $password_re = filter_input(INPUT_POST, 'password_re',FILTER_UNSAFE_RAW); + if (empty($this->fields['password']) && empty($password)) { + $this->errors['password'] = BUtils::_('Password is required'); + return; + } + if (!empty($password)) { + $saned = sanitize_text_field($password); + $saned_re = sanitize_text_field($password_re); + if ($saned != $saned_re){ + $this->errors['password'] = BUtils::_('Password mismatch'); + } + $this->sanitized['plain_password'] = $password; + $this->sanitized['password'] = BUtils::encrypt_password(trim($password)); //should use $saned??; + } + } + + protected function email() { + global $wpdb; + $email = filter_input(INPUT_POST, 'email', FILTER_UNSAFE_RAW); + if (empty($email)) { + $this->errors['email'] = BUtils::_('Email is required'); + return; + } + if (!is_email($email)) { + $this->errors['email'] = BUtils::_('Email is invalid'); + return; + } + $saned = sanitize_email($email); + $query = "SELECT count(member_id) FROM {$wpdb->prefix}swpm_members_tbl WHERE email= %s"; + $member_id = filter_input(INPUT_GET, 'member_id', FILTER_SANITIZE_NUMBER_INT); + if (!empty($member_id)) { + $query .= ' AND member_id !=%d'; + $result = $wpdb->get_var($wpdb->prepare($query, strip_tags($saned), $member_id)); + } + else{ + $result = $wpdb->get_var($wpdb->prepare($query, strip_tags($saned))); + } + + if ($result > 0) { + if ($saned != $this->fields['email']) { + $this->errors['email'] = BUtils::_('Email is already used.'); + return; + } + } + $this->sanitized['email'] = $saned; + } + + protected function phone() { + $phone = filter_input(INPUT_POST, 'phone', FILTER_UNSAFE_RAW); + if (empty($phone)) {return;} + $saned = wp_kses($phone, array()); + $this->sanitized['phone'] = $saned; + return; + //Not doing phone number validation + +// $saned = wp_kses($phone, array()); +// $this->sanitized['phone'] = $saned; +// if (strlen($saned) > 9 && preg_match('/^((\+)?[1-9]{1,2})?([-\s\.])?((\(\d{1,4}\))|\d{1,4})(([-\s\.])?[0-9]{1,12}){1,2}$/', $saned)){ +// $this->sanitized['phone'] = $saned; +// } +// else{ +// $this->errors['phone'] = BUtils::_('Phone number is invalid'); +// } + } + + protected function address_street() { + $address_street = filter_input(INPUT_POST, 'address_street', FILTER_SANITIZE_STRING); + if (empty($address_street)) { return;} + $this->sanitized['address_street'] = wp_kses($address_street, array()); + } + + protected function address_city() { + $address_city = filter_input(INPUT_POST, 'address_city', FILTER_SANITIZE_STRING); + if (empty($address_city)){ return; } + $this->sanitized['address_city'] = wp_kses($address_city, array()); + } + + protected function address_state() { + $address_state = filter_input(INPUT_POST, 'address_state', FILTER_SANITIZE_STRING); + if (empty($address_state)) {return;} + $this->sanitized['address_state'] = wp_kses($address_state, array()); + } + + protected function address_zipcode() { + $address_zipcode = filter_input(INPUT_POST, 'address_zipcode', FILTER_UNSAFE_RAW); + if (empty($address_zipcode)){ return;} + $this->sanitized['address_zipcode'] = wp_kses($address_zipcode, array()); + } + + protected function country() { + $country = filter_input(INPUT_POST, 'country', FILTER_SANITIZE_STRING); + if (empty($country)){ return;} + $this->sanitized['country'] = wp_kses($country, array()); + } + + protected function company_name() { + $company_name = filter_input(INPUT_POST, 'company_name', FILTER_SANITIZE_STRING); + $this->sanitized['company_name'] = $company_name; + } + + protected function member_since() { + $member_since = filter_input(INPUT_POST, 'member_since', FILTER_UNSAFE_RAW); + if (empty($member_since)) {return;} + if (preg_match('/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/', $member_since)){ + $this->sanitized['member_since'] = sanitize_text_field($member_since); + return; + } + $this->errors['member_since'] = BUtils::_('Member since field is invalid'); + + } + + protected function subscription_starts() { + $subscription_starts = filter_input(INPUT_POST, 'subscription_starts', FILTER_SANITIZE_STRING); + if(empty($subscription_starts)) {return ;} + if (preg_match('/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/', $subscription_starts)){ + $this->sanitized['subscription_starts'] = sanitize_text_field($subscription_starts); + return; + } + $this->errors['subscription_starts'] = BUtils::_('Access starts field is invalid'); + } + + protected function gender() { + $gender = filter_input(INPUT_POST, 'gender', FILTER_SANITIZE_STRING); + if(empty($gender)) {return;} + if (in_array($gender, array('male', 'female', 'not specified'))){ + $this->sanitized['gender'] = $gender; + } + else{ + $this->errors['gender'] = BUtils::_('Gender field is invalid'); + } + } + + protected function account_state() { + $account_state = filter_input(INPUT_POST, 'account_state', FILTER_SANITIZE_STRING); + if(empty($account_state)) {return;} + if (in_array($account_state, array('active', 'pending', 'inactive', 'expired'))){ + $this->sanitized['account_state'] = $account_state; + } + else{ + $this->errors['account_state'] = BUtils::_('Account state field is invalid'); + } + } + + protected function membership_level() { + $membership_level = filter_input(INPUT_POST, 'membership_level', FILTER_SANITIZE_NUMBER_INT); + if ($membership_level == 1){ + $this->errors['membership_level'] = BUtils::_('Invalid membership level'); + return; + } + + if (empty($membership_level)) {return;} + $this->sanitized['membership_level'] = $membership_level; + } + + protected function password_re() { + + } + + protected function last_accessed() { + + } + + protected function last_accessed_from_ip() { + + } + + protected function referrer() { + + } + + protected function extra_info() { + + } + + protected function reg_code() { + + } + + protected function txn_id() { + + } + + protected function subscr_id() { + $subscr_id = filter_input(INPUT_POST, 'subscr_id', FILTER_SANITIZE_STRING); + $this->sanitized['subscr_id'] = $subscr_id; + } + + protected function flags() { + + } + + protected function more_membership_levels() { + + } + + protected function initial_membership_level() { + + } + + protected function home_page() { + + } + + protected function notes() { + + } + + protected function profile_image() { + + } + + protected function expiry_1st() { + + } + + protected function expiry_2nd() { + + } + + protected function member_id() { + + } + + public function is_valid() { + return count($this->errors) < 1; + } + + public function get_sanitized() { + return $this->sanitized; + } + + public function get_errors() { + return $this->errors; + } + +} diff --git a/classes/class.bFrontForm.php b/classes/class.bFrontForm.php new file mode 100644 index 0000000..92adc82 --- /dev/null +++ b/classes/class.bFrontForm.php @@ -0,0 +1,7 @@ +get_value('join-us-page-url'); + $membership_level = ''; + $member_id = filter_input(INPUT_GET, 'member_id', FILTER_SANITIZE_NUMBER_INT); + $code = filter_input(INPUT_GET, 'code', FILTER_SANITIZE_STRING); + + global $wpdb; + if (BUtils::is_paid_registration()){ + $member = $member = BUtils::get_paid_member_info(); + if (empty($member)){ + BUtils::e('Error! Invalid Request. Could not find a match for the given security code and the user ID.'); + } + $membership_level = $member->membership_level; + } + else if (!empty($level)) { + $member = BTransfer::$default_fields; + $membership_level = absint($level); + } + if (empty($membership_level)) { + $joinuspage_link = 'Join us'; + BUtils::e('Free membership is disabled on this site. Please make a payment from the ' . $joinuspage_link . ' page to pay for a premium membership.'); + return; + } + $form = apply_filters('swpm_registration_form_override', '', $membership_level); + if (!empty($form)) {return $form;} + + $mebership_info = BPermission::get_instance($membership_level); + $membership_level = $mebership_info->get('id'); + if (empty($membership_level)) { + return "Membership Level Not Found."; + } + $level_identifier = md5($membership_level); + $membership_level_alias = $mebership_info->get('alias'); + $swpm_registration_submit = filter_input(INPUT_POST, 'swpm_registration_submit'); + if (!empty($swpm_registration_submit)){ + $member = $_POST; + } + ob_start(); + extract((array)$member, EXTR_SKIP); + include(SIMPLE_WP_MEMBERSHIP_PATH . 'views/add.php'); + return ob_get_clean(); + } + public function register() { + if($this->create_swpm_user()&&$this->create_wp_user()&&$this->send_reg_email()){ + do_action('swpm_front_end_registration_complete'); + + $login_page_url = BSettings::get_instance()->get_value('login-page-url'); + $after_rego_msg = '

'. BUtils::_('Registration Successful. '). BUtils::_('Please').' '.BUtils::_('Login').'

'; + $message = array('succeeded' => true, 'message' => $after_rego_msg); + BTransfer::get_instance()->set('status', $message); + return; + } + } + private function create_swpm_user(){ + global $wpdb; + $member = BTransfer::$default_fields; + $form = new BFrontForm($member); + if (!$form->is_valid()) { + $message = array('succeeded' => false, 'message' => BUtils::_('Please correct the following'), + 'extra' => $form->get_errors()); + BTransfer::get_instance()->set('status', $message); + return false; + } + + + $member_info = $form->get_sanitized(); + $free_level = BUtils::get_free_level(); + $account_status = BSettings::get_instance()->get_value('default-account-status', 'active'); + $member_info['last_accessed_from_ip'] = BTransfer::get_real_ip_addr(); + $member_info['member_since'] = date("Y-m-d"); + $member_info['subscription_starts'] = date("Y-m-d"); + $member_info['account_state'] = $account_status; + $plain_password = $member_info['plain_password']; + unset($member_info['plain_password']); + + if (BUtils::is_paid_registration()){ + $member_info['reg_code'] = ''; + $member_id = filter_input(INPUT_GET, 'member_id', FILTER_SANITIZE_NUMBER_INT); + $code = filter_input(INPUT_GET, 'code', FILTER_SANITIZE_STRING); + $wpdb->update($wpdb->prefix . "swpm_members_tbl", $member_info, + array('member_id' => $member_id,'reg_code'=>$code)); + + $query = $wpdb->prepare('SELECT membership_level FROM ' . $wpdb->prefix . 'swpm_members_tbl WHERE member_id=%d', $member_id); + $member_info['membership_level'] = $wpdb->get_var( $query ); + $last_insert_id = $member_id; + } + else if (!empty($free_level)){ + $member_info['membership_level'] = $free_level; + $wpdb->insert($wpdb->prefix . "swpm_members_tbl", $member_info); + $last_insert_id = $wpdb->insert_id; + } + else{ + $message = array('succeeded' => false, 'message' => BUtils::_('Membership Level Couldn\'t be found.')); + BTransfer::get_instance()->set('status', $message); + return false; + } + $member_info['plain_password'] = $plain_password; + $this->member_info = $member_info; + return true; + } + private function create_wp_user(){ + global $wpdb; + $member_info = $this->member_info; + $query = $wpdb->prepare("SELECT role FROM " . $wpdb->prefix . "swpm_membership_tbl WHERE id = %d", $member_info['membership_level']) ; + $wp_user_info = array(); + $wp_user_info['user_nicename'] = implode('-', explode(' ', $member_info['user_name'])); + $wp_user_info['display_name'] = $member_info['user_name']; + $wp_user_info['user_email'] = $member_info['email']; + $wp_user_info['nickname'] = $member_info['user_name']; + $wp_user_info['first_name'] = $member_info['first_name']; + $wp_user_info['last_name'] = $member_info['last_name']; + $wp_user_info['user_login'] = $member_info['user_name']; + $wp_user_info['password'] = $member_info['plain_password']; + $wp_user_info['role'] = $wpdb->get_var($query); + $wp_user_info['user_registered'] = date('Y-m-d H:i:s'); + BUtils::create_wp_user($wp_user_info); + return true; + } + public function edit() { + global $wpdb; + $auth = BAuth::get_instance(); + if (!$auth->is_logged_in()) { + return; + } + $user_data = (array) $auth->userData; + unset($user_data['permitted']); + $form = new BForm($user_data); + if ($form->is_valid()) { + global $wpdb; + $member_info = $form->get_sanitized(); + // update corresponding wp user. + BUtils::update_wp_user($auth->get('user_name'),$member_info); + if (isset($member_info['plain_password'])) { + unset($member_info['plain_password']); + } + + $wpdb->update( + $wpdb->prefix . "swpm_members_tbl", $member_info, array('member_id' => $auth->get('member_id'))); + $auth->reload_user_data(); + $message = array('succeeded' => true, 'message' => 'Profile Updated.'); + BTransfer::get_instance()->set('status', $message); + } else { + $message = array('succeeded' => false, 'message' => BUtils::_('Please correct the following'), + 'extra' => $form->get_errors()); + BTransfer::get_instance()->set('status', $message); + return; + } + } + + public function reset_password($email) { + $email = sanitize_email($email); + if (!is_email($email)) { + $message = '
' . BUtils::_("Email address not valid.") . '
'; + $message = array('succeeded' => false, 'message' => $message); + BTransfer::get_instance()->set('status', $message); + return; + } + global $wpdb; + $query = 'SELECT member_id,user_name,first_name, last_name FROM ' . + $wpdb->prefix . 'swpm_members_tbl ' . + ' WHERE email = %s'; + $user = $wpdb->get_row($wpdb->prepare($query, $email)); + if (empty($user)) { + $message = '
' . BUtils::_("No user not found with that email address.") .'
'; + $message .= '
' . BUtils::_("Email Address: ") . $email .'
'; + $message = array('succeeded' => false, 'message' => $message); + BTransfer::get_instance()->set('status', $message); + return; + } + $settings = BSettings::get_instance(); + $password = wp_generate_password(); + + $password_hash = BUtils::encrypt_password(trim($password)); //should use $saned??; + $wpdb->update($wpdb->prefix . "swpm_members_tbl", array('password' => $password_hash), array('member_id' => $user->member_id)); + + // update wp user pass. + BUtils::update_wp_user($user->user_name, array('plain_password'=>$password)); + + $body = $settings->get_value('reset-mail-body'); + $subject = $settings->get_value('reset-mail-subject'); + $search = array('{user_name}', '{first_name}', '{last_name}', '{password}'); + $replace = array($user->user_name, $user->first_name, $user->last_name, $password); + $body = str_replace($search, $replace, $body); + $from = $settings->get_value('email-from'); + $headers = "From: " . $from . "\r\n"; + wp_mail($email, $subject, $body, $headers); + $message = '
' . BUtils::_("New password has been sent to your email address.") .'
'; + $message .= '
' . BUtils::_("Email Address: ") . $email .'
'; + + $message = array('succeeded' => false, 'message' => $message); + BTransfer::get_instance()->set('status', $message); + } +} diff --git a/classes/class.bInstallation.php b/classes/class.bInstallation.php new file mode 100644 index 0000000..8adb4d7 --- /dev/null +++ b/classes/class.bInstallation.php @@ -0,0 +1,243 @@ +blogid; + // Get all blog ids + $blogids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs"); + foreach ($blogids as $blog_id) { + switch_to_blog($blog_id); + BInstallation::installer(); + BInstallation::initdb(); + } + switch_to_blog($old_blog); + return; + } + } + + //Do this if single site standard install + BInstallation::installer(); + BInstallation::initdb(); + } + + public static function installer() { + global $wpdb; + require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); + + $charset_collate = ''; + if (!empty($wpdb->charset)){ + $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset"; + }else{ + $charset_collate = "DEFAULT CHARSET=utf8"; + } + if (!empty($wpdb->collate)){ + $charset_collate .= " COLLATE $wpdb->collate"; + } + + $sql = "CREATE TABLE " . $wpdb->prefix . "swpm_members_tbl ( + member_id int(12) NOT NULL PRIMARY KEY AUTO_INCREMENT, + user_name varchar(32) NOT NULL, + first_name varchar(32) DEFAULT '', + last_name varchar(32) DEFAULT '', + password varchar(64) NOT NULL, + member_since date NOT NULL DEFAULT '0000-00-00', + membership_level smallint(6) NOT NULL, + more_membership_levels VARCHAR(100) DEFAULT NULL, + account_state enum('active','inactive','expired','pending','unsubscribed') DEFAULT 'pending', + last_accessed datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + last_accessed_from_ip varchar(64) NOT NULL, + email varchar(64) DEFAULT NULL, + phone varchar(64) DEFAULT NULL, + address_street varchar(255) DEFAULT NULL, + address_city varchar(255) DEFAULT NULL, + address_state varchar(255) DEFAULT NULL, + address_zipcode varchar(255) DEFAULT NULL, + home_page varchar(255) DEFAULT NULL, + country varchar(255) DEFAULT NULL, + gender enum('male','female','not specified') DEFAULT 'not specified', + referrer varchar(255) DEFAULT NULL, + extra_info text, + reg_code varchar(255) DEFAULT NULL, + subscription_starts date DEFAULT NULL, + initial_membership_level smallint(6) DEFAULT NULL, + txn_id varchar(64) DEFAULT '', + subscr_id varchar(32) DEFAULT '', + company_name varchar(100) DEFAULT '', + notes text DEFAULT NULL, + flags int(11) DEFAULT '0', + profile_image varchar(255) DEFAULT '' + )" . $charset_collate . ";"; + dbDelta($sql); + + $sql = "CREATE TABLE " . $wpdb->prefix . "swpm_membership_tbl ( + id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT, + alias varchar(127) NOT NULL, + role varchar(255) NOT NULL DEFAULT 'subscriber', + permissions tinyint(4) NOT NULL DEFAULT '0', + subscription_period varchar(11) NOT NULL DEFAULT '-1', + subscription_duration_type tinyint NOT NULL default 0, + subscription_unit VARCHAR(20) NULL, + loginredirect_page text NULL, + category_list longtext, + page_list longtext, + post_list longtext, + comment_list longtext, + attachment_list longtext, + custom_post_list longtext, + disable_bookmark_list longtext, + options longtext, + protect_older_posts tinyint(1) NOT NULL DEFAULT '0', + campaign_name varchar(60) NOT NULL DEFAULT '' + )" . $charset_collate . " AUTO_INCREMENT=1 ;"; + dbDelta($sql); + $sql = "SELECT * FROM " . $wpdb->prefix . "swpm_membership_tbl WHERE id = 1"; + $results = $wpdb->get_row($sql); + if (is_null($results)) { + $sql = "INSERT INTO " . $wpdb->prefix . "swpm_membership_tbl ( + id , + alias , + role , + permissions , + subscription_period , + subscription_unit, + loginredirect_page, + category_list , + page_list , + post_list , + comment_list, + disable_bookmark_list, + options, + campaign_name + )VALUES (1 , 'Content Protection', 'administrator', '15', '0',NULL,NULL, NULL , NULL , NULL , NULL,NULL,NULL,'');"; + $wpdb->query($sql); + } + $sql = "UPDATE " . $wpdb->prefix . "swpm_membership_tbl SET subscription_duration_type = 1 WHERE subscription_unit='days' AND subscription_duration_type = 0"; + $wpdb->query($sql); + + $sql = "UPDATE " . $wpdb->prefix . "swpm_membership_tbl SET subscription_duration_type = 2 WHERE subscription_unit='weeks' AND subscription_duration_type = 0"; + $wpdb->query($sql); + + $sql = "UPDATE " . $wpdb->prefix . "swpm_membership_tbl SET subscription_duration_type = 3 WHERE subscription_unit='months' AND subscription_duration_type = 0"; + $wpdb->query($sql); + + $sql = "UPDATE " . $wpdb->prefix . "swpm_membership_tbl SET subscription_duration_type = 4 WHERE subscription_unit='years' AND subscription_duration_type = 0"; + $wpdb->query($sql); + $sql = "CREATE TABLE " . $wpdb->prefix . "swpm_membership_meta_tbl ( + id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, + level_id int(11) NOT NULL, + meta_key varchar(255) NOT NULL, + meta_label varchar(255) NULL, + meta_value text, + meta_type varchar(255) NOT NULL DEFAULT 'text', + meta_default text, + meta_context varchar(255) NOT NULL DEFAULT 'default', + KEY level_id (level_id), + UNIQUE KEY meta_key_id (level_id,meta_key) + )" . $charset_collate . " AUTO_INCREMENT=1 ;"; + dbDelta($sql); + + $sql = "CREATE TABLE " . $wpdb->prefix . "swpm_payments_tbl ( + id int(12) NOT NULL PRIMARY KEY AUTO_INCREMENT, + email varchar(64) DEFAULT NULL, + first_name varchar(32) DEFAULT '', + last_name varchar(32) DEFAULT '', + member_id varchar(16) DEFAULT '', + membership_level varchar(16) DEFAULT '', + txn_date date NOT NULL default '0000-00-00', + txn_id varchar(128) NOT NULL default '', + subscr_id varchar(128) NOT NULL default '', + reference varchar(128) NOT NULL default '', + payment_amount varchar(32) NOT NULL default '', + gateway varchar(16) DEFAULT '', + status varchar(16) DEFAULT '', + ip_address varchar(64) default '' + )" . $charset_collate . ";"; + dbDelta($sql); + + //Save the current DB version + update_option("swpm_db_version", SIMPLE_WP_MEMBERSHIP_DB_VER); + } + + public static function initdb() { + $settings = BSettings::get_instance(); + + $installed_version = $settings->get_value('swpm-active-version'); + + //Set other default settings values + $reg_prompt_email_subject = "Complete your registration"; + $reg_prompt_email_body = "Dear {first_name} {last_name}" . + "\n\nThank you for joining us!" . + "\n\nPlease complete your registration by visiting the following link:" . + "\n\n{reg_link}" . + "\n\nThank You"; + $reg_email_subject = "Your registration is complete"; + $reg_email_body = "Dear {first_name} {last_name}\n\n" . + "Your registration is now complete!\n\n" . + "Registration details:\n" . + "Username: {user_name}\n" . + "Password: {password}\n\n" . + "Please login to the member area at the following URL:\n\n" . + "{login_link}\n\n" . + "Thank You"; + + $upgrade_email_subject = "Subject for email sent after account upgrade"; + $upgrade_email_body = "Dear {first_name} {last_name}" . + "\n\nYour Account Has Been Upgraded." . + "\n\nThank You"; + $reset_email_subject = get_bloginfo('name') . ": New Password"; + $reset_email_body = "Dear {first_name} {last_name}" . + "\n\nHere is your new password" . + "\n\nUser name: {user_name}" . + "\n\nPassword: {password}" . + "\n\nThank You"; + + $status_change_email_subject = "Account Updated!"; + $status_change_email_body = "Dear {first_name} {last_name}," . + "\n\n Your account status has been updated!" . + " Please login to the member area at the following URL:" . + "\n\n {login_link}" . + "\n\nThank You"; + + if (empty($installed_version)) { + //Do fresh install tasks + + /* * * Create the mandatory pages (if they are not there) ** */ + miscUtils::create_mandatory_wp_pages(); + /* * * End of page creation ** */ + $settings->set_value('reg-complete-mail-subject', stripslashes($reg_email_subject)) + ->set_value('reg-complete-mail-body', stripslashes($reg_email_body)) + ->set_value('reg-prompt-complete-mail-subject', stripslashes($reg_prompt_email_subject)) + ->set_value('reg-prompt-complete-mail-body', stripslashes($reg_prompt_email_body)) + ->set_value('upgrade-complete-mail-subject', stripslashes($upgrade_email_subject)) + ->set_value('upgrade-complete-mail-body', stripslashes($upgrade_email_body)) + ->set_value('reset-mail-subject', stripslashes($reset_email_subject)) + ->set_value('reset-mail-body', stripslashes($reset_email_body)) + ->set_value('account-change-email-subject', stripslashes($status_change_email_subject)) + ->set_value('account-change-email-body', stripslashes($status_change_email_body)) + ->set_value('email-from', trim(get_option('admin_email'))); + } + if (version_compare($installed_version, SIMPLE_WP_MEMBERSHIP_VER) == -1) { + //Do upgrade tasks + } + + $settings->set_value('swpm-active-version', SIMPLE_WP_MEMBERSHIP_VER)->save(); //save everything. + } +} diff --git a/classes/class.bLevelForm.php b/classes/class.bLevelForm.php new file mode 100644 index 0000000..709046c --- /dev/null +++ b/classes/class.bLevelForm.php @@ -0,0 +1,126 @@ +fields = $fields; + $this->sanitized = array(); + foreach ($fields as $key => $value) + $this->$key(); + } + + protected function id() { + + } + + protected function alias() { + $alias = filter_input(INPUT_POST, 'alias'); + $this->sanitized['alias'] = sanitize_text_field($alias); + } + + protected function role() { + $role = filter_input(INPUT_POST, 'role'); + $this->sanitized['role'] = sanitize_text_field($role); + } + + protected function permissions() { + $this->sanitized['permissions'] = 63; + } + + protected function subscription_period() { + $subscript_duration_type = filter_input(INPUT_POST, 'subscription_duration_type'); + + if ($subscript_duration_type == BMembershipLevel::NO_EXPIRY) { + $this->sanitized['subscription_period'] = ""; + return; + } + + $subscription_period = filter_input(INPUT_POST, 'subscription_period_'. $subscript_duration_type); + if (($subscript_duration_type == BMembershipLevel::FIXED_DATE)){ + $dateinfo = date_parse($subscription_period); + if ($dateinfo['warning_count']|| $dateinfo['error_count']){ + $this->errors['subscription_period'] = BUtils::_("Date format is not valid."); + return; + } + $this->sanitized['subscription_period'] = sanitize_text_field($subscription_period); + return; + } + + if (!is_numeric($subscription_period)) { + $this->errors['subscription_period'] = BUtils::_("Access duration must be > 0."); + return; + } + $this->sanitized['subscription_period'] = sanitize_text_field($subscription_period); + } + + protected function subscription_duration_type(){ + $subscription_duration_type = filter_input(INPUT_POST, 'subscription_duration_type'); + $this->sanitized['subscription_duration_type'] = $subscription_duration_type; + return; + } + protected function subscription_unit(){ + + } + protected function loginredirect_page() { + + } + + protected function category_list() { + + } + + protected function page_list() { + + } + + protected function post_list() { + + } + + protected function comment_list() { + + } + + protected function attachment_list() { + + } + + protected function custom_post_list() { + + } + + protected function disable_bookmark_list() { + + } + + protected function options() { + + } + + protected function campaign_name() { + + } + + protected function protect_older_posts() { + $checked = filter_input(INPUT_POST, 'protect_older_posts'); + $this->sanitized['protect_older_posts'] = empty($checked) ? 0 : 1; + } + + public function is_valid() { + return count($this->errors) < 1; + } + + public function get_sanitized() { + return $this->sanitized; + } + + public function get_errors() { + return $this->errors; + } + +} diff --git a/classes/class.bLog.php b/classes/class.bLog.php new file mode 100644 index 0000000..3f81e88 --- /dev/null +++ b/classes/class.bLog.php @@ -0,0 +1,77 @@ +error = array(); + $this->warn = array(); + $this->notice = array(); + } + public static function get_logger($context = ''){ + $context = empty($context)? 'default': $context; + if (!isset(self::$intance[$context])){ + self::$intance[$context] = new BLog(); + } + return self::$intance[$context]; + } + public function error($msg){ + $this->error[] = $msg; + } + public function warn($msg){ + $this->warn[] = $msg; + } + public function debug($msg){ + $this->notice[] = $msg; + } + public function get($to_screen = false){ + $msg = ''; + foreach ($this->error as $error ){ + $msg .= 'ERROR: ' . $error . ($to_screen?"
":"\n"); + } + foreach($this->warn as $warn){ + $msg .= 'WARN: ' . $warn . ($to_screen?"
":"\n"); + } + foreach ($this->notice as $notice){ + $msg = 'NOTICE: ' . $notice . ($to_screen?"
":"\n"); + } + return $msg; + } + public static function writeall($path = ''){ + if (empty($path)) {$path = SIMPLE_WP_MEMBERSHIP_PATH . 'log.txt';} + $fp = fopen($path, 'a'); + $date = date("Y-m-d H:i:s"); + fwrite($fp, strtoupper($date) . ":\n"); + fwrite($fp, str_repeat('-=', (strlen($date)+1.0)/2.0) . "\n"); + foreach (self::$intance as $context=>$intance){ + fwrite($fp, strtoupper($context) . ":\n"); + fwrite($fp, str_repeat('=', strlen($context)+1) . "\n"); + fwrite($fp, $intance->get()); + } + fclose($fp); + } + + public static function log_simple_debug($message, $success, $end = false) { + $settings = BSettings::get_instance(); + $debug_enabled = $settings->get_value('enable-debug'); + if (empty($debug_enabled)) {//Debug is not enabled + return; + } + + //Lets write to the log file + $debug_log_file_name = SIMPLE_WP_MEMBERSHIP_PATH . 'log.txt'; + + // Timestamp + $text = '[' . date('m/d/Y g:i A') . '] - ' . (($success) ? 'SUCCESS :' : 'FAILURE :') . $message . "\n"; + if ($end) { + $text .= "\n------------------------------------------------------------------\n\n"; + } + // Write to log + $fp = fopen($debug_log_file_name, 'a'); + fwrite($fp, $text); + fclose($fp); // close file + } + +} diff --git a/classes/class.bMemberUtils.php b/classes/class.bMemberUtils.php new file mode 100644 index 0000000..60ce8fe --- /dev/null +++ b/classes/class.bMemberUtils.php @@ -0,0 +1,35 @@ +is_logged_in()) { + return true; + } else { + return false; + } + } + + public static function get_logged_in_members_id() { + $auth = BAuth::get_instance(); + if (!$auth->is_logged_in()) { + return bUtils::_("User is not logged in."); + } + return $auth->userData->member_id; + } + + public static function get_logged_in_members_level() { + $auth = BAuth::get_instance(); + if (!$auth->is_logged_in()) { + return bUtils::_("User is not logged in."); + } + return $auth->userData->membership_level; + } + +} diff --git a/classes/class.bMembers.php b/classes/class.bMembers.php new file mode 100644 index 0000000..7311dd0 --- /dev/null +++ b/classes/class.bMembers.php @@ -0,0 +1,198 @@ + BUtils::_('Member'), + 'plural' => BUtils::_('Members'), + 'ajax' => false + )); + } + + function get_columns() { + return array( + 'cb' => '' + , 'member_id' => BUtils::_('ID') + , 'user_name' => BUtils::_('User Name') + , 'first_name' => BUtils::_('First Name') + , 'last_name' => BUtils::_('Last Name') + , 'email' => BUtils::_('Email') + , 'alias' => BUtils::_('Membership Level') + , 'subscription_starts' => BUtils::_('Access Starts') + , 'account_state' => BUtils::_('Account State') + ); + } + + function get_sortable_columns() { + return array( + 'member_id' => array('member_id', true), + 'user_name' => array('user_name', true) + ); + } + + function get_bulk_actions() { + $actions = array( + 'bulk_delete' => BUtils::_('Delete') + ); + return $actions; + } + + function column_default($item, $column_name) { + return $item[$column_name]; + } + + function column_member_id($item) { + $actions = array( + 'edit' => sprintf('Edit', $_REQUEST['page'], $item['member_id']), + 'delete' => sprintf('Delete', $_REQUEST['page'], $item['member_id']), + ); + return $item['member_id'] . $this->row_actions($actions); + } + + function column_cb($item) { + return sprintf( + '', $item['member_id'] + ); + } + + function prepare_items() { + global $wpdb; + $query = "SELECT * FROM " . $wpdb->prefix . "swpm_members_tbl"; + $query .= " LEFT JOIN " . $wpdb->prefix . "swpm_membership_tbl"; + $query .= " ON ( membership_level = id ) "; + $s = filter_input(INPUT_POST, 's'); + if (!empty($s)){ + $query .= " WHERE user_name LIKE '%" . strip_tags($s) . "%' " + . " OR first_name LIKE '%" . strip_tags($s) . "%' " + . " OR last_name LIKE '%" . strip_tags($s) . "%' "; + } + $orderby = filter_input(INPUT_GET, 'orderby'); + $orderby = empty($orderby) ? 'user_name' : $orderby ; + $order = filter_input(INPUT_GET, 'order'); + $order = empty($order) ? 'DESC' : $order; + + $sortable_columns = $this->get_sortable_columns(); + $orderby = BUtils::sanitize_value_by_array($orderby, $sortable_columns); + $order = BUtils::sanitize_value_by_array($order, array('DESC' => '1', 'ASC' => '1')); + + $query.=' ORDER BY ' . $orderby . ' ' . $order; + $totalitems = $wpdb->query($query); //return the total number of affected rows + $perpage = 20; + $paged = filter_input(INPUT_GET, 'paged'); + if (empty($paged) || !is_numeric($paged) || $paged <= 0) { + $paged = 1; + } + $totalpages = ceil($totalitems / $perpage); + if (!empty($paged) && !empty($perpage)) { + $offset = ($paged - 1) * $perpage; + $query.=' LIMIT ' . (int) $offset . ',' . (int) $perpage; + } + $this->set_pagination_args(array( + "total_items" => $totalitems, + "total_pages" => $totalpages, + "per_page" => $perpage, + )); + + $columns = $this->get_columns(); + $hidden = array(); + $sortable = $this->get_sortable_columns(); + + $this->_column_headers = array($columns, $hidden, $sortable); + $this->items = $wpdb->get_results($query, ARRAY_A); + } + + function no_items() { + _e('No Member found.'); + } + + function process_form_request() { + if (isset($_REQUEST['member_id'])) + return $this->edit(absint($_REQUEST['member_id'])); + return $this->add(); + } + + function add() { + $form = apply_filters('swpm_admin_registration_form_override', ''); + if (!empty($form)) {echo $form;return;} + global $wpdb; + $member = BTransfer::$default_fields; + $member['member_since'] = date('Y-m-d'); + $member['subscription_starts'] = date('Y-m-d'); + if (isset($_POST['createswpmuser'])) { + $member = $_POST; + } + extract($member, EXTR_SKIP); + $query = "SELECT * FROM " . $wpdb->prefix . "swpm_membership_tbl WHERE id !=1 "; + $levels = $wpdb->get_results($query, ARRAY_A); + include_once(SIMPLE_WP_MEMBERSHIP_PATH . 'views/admin_add.php'); + return false; + } + + function edit($id) { + global $wpdb; + $id = absint($id); + $query = "SELECT * FROM {$wpdb->prefix}swpm_members_tbl WHERE member_id = $id"; + $member = $wpdb->get_row($query, ARRAY_A); + if (isset($_POST["editswpmuser"])) { + $_POST['user_name'] = $member['user_name']; + $_POST['email'] = $member['email']; + $member = $_POST; + } + extract($member, EXTR_SKIP); + $query = "SELECT * FROM " . $wpdb->prefix . "swpm_membership_tbl WHERE id !=1 "; + $levels = $wpdb->get_results($query, ARRAY_A); + include_once(SIMPLE_WP_MEMBERSHIP_PATH . 'views/admin_edit.php'); + return false; + } + + function delete() { + global $wpdb; + if (isset($_REQUEST['members'])) { + $members = $_REQUEST['members']; + if (!empty($members)) { + $members = array_map('absint', $members); + foreach ($members as $swpm_id) { + $user_name = BUtils::get_user_by_id(absint($swpm_id)); + BMembers::delete_wp_user($user_name); + } + $query = "DELETE FROM " . $wpdb->prefix . "swpm_members_tbl WHERE member_id IN (" . implode(',', $members) . ")"; + $wpdb->query($query); + } + } + else if (isset($_REQUEST['member_id'])) { + $id = absint($_REQUEST['member_id']); + BMembers::delete_user_by_id($id); + } + } + public static function delete_user_by_id($id){ + $user_name = BUtils::get_user_by_id($id); + BMembers::delete_wp_user($user_name); + BMembers::delete_swpm_user_by_id($id); + } + + public static function delete_swpm_user_by_id($id){ + global $wpdb; + $query = "DELETE FROM " . $wpdb->prefix . "swpm_members_tbl WHERE member_id = $id"; + $wpdb->query($query); + } + function show() { + include_once(SIMPLE_WP_MEMBERSHIP_PATH . 'views/admin_members.php'); + } + + public static function delete_wp_user($user_name) { + $wp_user_id = username_exists($user_name); + $ud = get_userdata($wp_user_id); + if (!empty($ud) && (isset($ud->wp_capabilities['administrator']) || $ud->wp_user_level == 10)) { + BTransfer::get_instance()->set('status', 'For consistency, we do not allow deleting any associated wordpress account with administrator role.
' + . 'Please delete from Users menu.'); + return; + } + if ($wp_user_id) { + include_once(ABSPATH . 'wp-admin/includes/user.php'); + wp_delete_user($wp_user_id, 1); //assigns all related to this user to admin. + } + } + +} diff --git a/classes/class.bMembershipLevel.php b/classes/class.bMembershipLevel.php new file mode 100644 index 0000000..747c1d0 --- /dev/null +++ b/classes/class.bMembershipLevel.php @@ -0,0 +1,70 @@ +is_valid()) { + $level_info = $form->get_sanitized(); + $wpdb->insert($wpdb->prefix . "swpm_membership_tbl", $level_info); + $id = $wpdb->insert_id; + $custom = apply_filters('swpm_admin_add_membership_level', array()); + $this->save_custom_fields($id, $custom); + $message = array('succeeded' => true, 'message' => BUtils::_('Membership Level Creation Successful.')); + BTransfer::get_instance()->set('status', $message); + wp_redirect('admin.php?page=simple_wp_membership_levels'); + return; + } + $message = array('succeeded' => false, 'message' => BUtils::_('Please correct the following:'), 'extra' => $form->get_errors()); + BTransfer::get_instance()->set('status', $message); + } + + public function edit($id) { + global $wpdb; + $query = $wpdb->prepare("SELECT * FROM " . $wpdb->prefix . "swpm_membership_tbl WHERE id = %d", $id); + $level = $wpdb->get_row($query, ARRAY_A); + $form = new BLevelForm($level); + if ($form->is_valid()) { + $wpdb->update($wpdb->prefix . "swpm_membership_tbl", $form->get_sanitized(), array('id' => $id)); + //@todo meta table and collect all relevant info and pass as argument + $custom = apply_filters('swpm_admin_edit_membership_level', array(), $id); + $this->save_custom_fields($id, $custom); + $message = array('succeeded' => true, 'message' => BUtils::_('Updated Successfully.')); + BTransfer::get_instance()->set('status', $message); + wp_redirect('admin.php?page=simple_wp_membership_levels'); + return; + } + $message = array('succeeded' => false, 'message' => BUtils::_('Please correct the following:'), 'extra' => $form->get_errors()); + BTransfer::get_instance()->set('status', $message); + } + private function save_custom_fields($level_id, $data){ + $custom_obj = BMembershipLevelCustom::get_instance_by_id($level_id); + foreach ($data as $item){ + $custom_obj->set($item); + } + } +} diff --git a/classes/class.bMembershipLevelCustom.php b/classes/class.bMembershipLevelCustom.php new file mode 100644 index 0000000..5ac7952 --- /dev/null +++ b/classes/class.bMembershipLevelCustom.php @@ -0,0 +1,93 @@ +fields = array(); + } + public static function get_instance_by_id($level_id){ + if (!isset(self::$instances[$level_id])){ + self::$instances[$level_id] = new BMembershipLevelCustom(); + self::$instances[$level_id]->level_id = $level_id; + self::$instances[$level_id]->load_by_id($level_id); + } + return self::$instances[$level_id]; + } + public function load_by_id($level_id){ + global $wpdb; + $query = 'SELECT * FROM ' . $wpdb->prefix . 'swpm_membership_meta_tbl WHERE level_id=%d'; + $results = $wpdb->get_results($wpdb->prepare($query, $level_id), ARRAY_A); + foreach($results as $result){ + $this->fields[$result['meta_key']] = $result; + } + } + public function set($item){ + $meta_key = preg_replace('|[^A-Z0-9_]|i', '', $item['meta_key']); + $new = array( + 'meta_key'=>$meta_key, + 'level_id'=>$this->level_id, + 'meta_label'=> isset($item['meta_label'])?$item['meta_label']:'', + 'meta_value'=>$item['meta_value'], + 'meta_type'=> isset($item['meta_type'])?$item['meta_type']:'text', + 'meta_default'=> isset($item['meta_default'])?$item['meta_default']:'', + 'meta_context'=> $item['meta_context'], + ); + if (isset($this->fields[$meta_key])){ + $new['id'] = $this->fields[$meta_key]['id']; + $this->fields[$meta_key] = $new; + } + else{ + $this->fields[$meta_key] = $new; + } + $this->save($this->fields[$meta_key]); + return $this; + } + public function get($meta_key, $default=''){ + $meta_key = preg_replace('|[^A-Z0-9_]|i', '', $meta_key); + if (isset($this->fields[$meta_key])){ + return maybe_unserialize($this->fields[$meta_key]['meta_value']); + + } + return $default; + } + public function get_by_context($context){ + $result = array(); + foreach ($this->fields as $key=>$field){ + if ($field['meta_context'] == $context){ + $result[$key] = $field; + } + } + return $result; + } + private function save($field){ + global $wpdb; + if (!isset($field['meta_key'])){retern;} // cannot continue without key field. + $meta_key = preg_replace('|[^A-Z0-9_]|i', '', $field['meta_key']); + $query = $wpdb->prepare( + 'REPLACE INTO ' . $wpdb->prefix. 'swpm_membership_meta_tbl + (level_id, meta_key, meta_label, meta_value, meta_type, meta_default, meta_context) + VALUES(%d, %s, %s, %s, %s, %s, %s); ', + $this->level_id, + $meta_key, + isset($field['meta_label'])? sanitize_text_field($field['meta_label']): '', + isset($field['meta_value'])? sanitize_text_field($field['meta_value']): '', + 'text', // at the moment we have only one type + '', + isset($field['meta_context'])? sanitize_text_field($field['meta_context']): 'default' + ); + + $wpdb->query($query); + } + public static function get_value_by_key($level_id, $key, $default= ''){ + return BMembershipLevelCustom::get_instance_by_id($level_id)->get($key, $default); + } + public static function get_value_by_context($level_id, $context){ + return BMembershipLevelCustom::get_instance_by_id($level_id)->get_by_context($context); + } +} diff --git a/classes/class.bMembershipLevelUtils.php b/classes/class.bMembershipLevelUtils.php new file mode 100644 index 0000000..0a81afb --- /dev/null +++ b/classes/class.bMembershipLevelUtils.php @@ -0,0 +1,10 @@ +BUtils::_('Membership Level'), + 'plural' => BUtils::_('Membership Levels'), + 'ajax' => false + )); + } + function get_columns(){ + return array( + 'cb' => '' + ,'id'=>BUtils::_('ID') + ,'alias'=>BUtils::_('Membership Level') + ,'role'=>BUtils::_('Role') + ,'valid_for'=>BUtils::_('Access Valid For/Until') + ); + } + function get_sortable_columns(){ + return array( + 'id' => array('id',true), + 'alias' => array('alias',true) + ); + } + function get_bulk_actions() { + $actions = array( + 'bulk_delete' => BUtils::_('Delete') + ); + return $actions; + } + function column_default($item, $column_name){ + if($column_name == 'valid_for'){ + if($item['subscription_duration_type'] == BMembershipLevel::NO_EXPIRY) {return 'No Expiry';} + if($item['subscription_duration_type'] == BMembershipLevel::FIXED_DATE) {return date(get_option('date_format'), strtotime($item['subscription_period']));} + if($item['subscription_duration_type'] == BMembershipLevel::DAYS) {return $item['subscription_period'] ." Day(s)";} + if($item['subscription_duration_type'] == BMembershipLevel::WEEKS) {return $item['subscription_period'] ." Week(s)";} + if($item['subscription_duration_type'] == BMembershipLevel::MONTHS) {return $item['subscription_period'] ." Month(s)";} + if($item['subscription_duration_type'] == BMembershipLevel::YEARS) {return $item['subscription_period'] ." Year(s)";} + } + if($column_name == 'role') {return ucfirst($item['role']);} + return stripslashes($item[$column_name]); + } + function column_id($item){ + $actions = array( + 'edit' => sprintf('Edit', + $_REQUEST['page'],$item['id']), + 'delete' => sprintf('Delete', + $_REQUEST['page'],$item['id']), + ); + return $item['id'] . $this->row_actions($actions); + } + function column_cb($item) { + return sprintf( + '', $item['id'] + ); + } + function prepare_items() { + global $wpdb; + $query = "SELECT * FROM " .$wpdb->prefix . "swpm_membership_tbl WHERE id !=1 "; + if(isset($_POST['s'])) $query .= " AND alias LIKE '%" . strip_tags($_POST['s']). "%' "; + $orderby = !empty($_GET["orderby"]) ? mysql_real_escape_string($_GET["orderby"]) : 'id'; + $order = !empty($_GET["order"]) ? mysql_real_escape_string($_GET["order"]) : 'DESC'; + + $sortable_columns = $this->get_sortable_columns(); + $orderby = BUtils::sanitize_value_by_array($orderby, $sortable_columns); + $order = BUtils::sanitize_value_by_array($order, array('DESC' => '1', 'ASC' => '1')); + + if(!empty($orderby) && !empty($order)){ $query.=' ORDER BY '.$orderby.' '.$order; } + + $totalitems = $wpdb->query($query); //return the total number of affected rows + $perpage = 20; + $paged = !empty($_GET["paged"]) ? mysql_real_escape_string($_GET["paged"]) : ''; + if(empty($paged) || !is_numeric($paged) || $paged<=0 ){ $paged=1; } + $totalpages = ceil($totalitems/$perpage); + if(!empty($paged) && !empty($perpage)){ + $offset=($paged-1)*$perpage; + $query.=' LIMIT '.(int)$offset.','.(int)$perpage; + } + $this->set_pagination_args( array( + "total_items" => $totalitems, + "total_pages" => $totalpages, + "per_page" => $perpage, + ) ); + + $columns = $this->get_columns(); + $hidden = array(); + $sortable = $this->get_sortable_columns(); + + $this->_column_headers = array($columns, $hidden, $sortable); + $this->items = $wpdb->get_results($query, ARRAY_A); + } + function no_items() { + BUtils::e( 'No membership levels found.' ); + } + function process_form_request(){ + if(isset($_REQUEST['id'])){ + return $this->edit($_REQUEST['id']); + } + return $this->add(); + + } + function add(){ + global $wpdb; + $member = BTransfer::$default_fields; + if(isset($_POST['createswpmlevel'])){ + $member = $_POST; + } + extract($member, EXTR_SKIP); + include_once(SIMPLE_WP_MEMBERSHIP_PATH.'views/admin_add_level.php'); + return false; + } + function edit($id){ + global $wpdb; + $query = $wpdb->prepare("SELECT * FROM {$wpdb->prefix}swpm_membership_tbl WHERE id = %d", absint($id)); + $membership = $wpdb->get_row($query, ARRAY_A); + extract($membership, EXTR_SKIP); + include_once(SIMPLE_WP_MEMBERSHIP_PATH.'views/admin_edit_level.php'); + return false; + } + function delete(){ + global $wpdb; + if (isset($_REQUEST['ids'])){ + $members = $_REQUEST['ids']; + if(!empty($members)){ + $members = array_map('absint', $members); + $members = implode(',', $members); + $query = "DELETE FROM " .$wpdb->prefix . "swpm_membership_tbl WHERE id IN (" . $members . ")"; + $wpdb->query($query); + } + } + else if(isset($_REQUEST['id'])){ + $id = absint($_REQUEST['id']); + $query = $wpdb->prepare("DELETE FROM " .$wpdb->prefix . "swpm_membership_tbl WHERE id = %d", $id); + $wpdb->query($query); + } + } + function show(){ + $selected = 1; + include_once(SIMPLE_WP_MEMBERSHIP_PATH.'views/admin_membership_levels.php'); + } + function manage(){ + $selected = 2; + include_once(SIMPLE_WP_MEMBERSHIP_PATH.'views/admin_membership_manage.php'); + } + function manage_categroy(){ + $selected = 3; + include_once('class.bCategoryList.php'); + $category_list = new BCategoryList(); + include_once(SIMPLE_WP_MEMBERSHIP_PATH.'views/admin_category_list.php'); + } +} + diff --git a/classes/class.bMessages.php b/classes/class.bMessages.php new file mode 100644 index 0000000..9bfac9f --- /dev/null +++ b/classes/class.bMessages.php @@ -0,0 +1,23 @@ +messages = array(); + } + public function get($key){ + if(isset($this->messages[$key])){ + $m = $this->messages[$key]; + $this->messages[$key] =''; + return $m; + } + return ''; + } + public function set($key, $value){ + $this->messages[$key] = $value; + } +} diff --git a/classes/class.bPermission.php b/classes/class.bPermission.php new file mode 100644 index 0000000..d1c8642 --- /dev/null +++ b/classes/class.bPermission.php @@ -0,0 +1,60 @@ +init($level_id); + } + + public static function get_instance($level_id) { + if ($level_id ==1 || $level_id == md5(1)){ + wp_die('Invalid Membership level!'); + } + $key = is_numeric($level_id)? md5($level_id): $level_id; + if (!isset(self::$_this[$key])){ + self::$_this[$key] = new BPermission($level_id); + } + + return self::$_this[$key]; + } + + public function is_permitted($id) { + return $this->post_in_parent_categories($id) || $this->post_in_categories($id) || $this->in_posts($id) || $this->in_pages($id) || $this->in_attachments($id) || $this->in_custom_posts($id); + } + + public function is_permitted_attachment($id) { + return (($this->bitmap & 16) === 16) && $this->in_attachments($id); + } + + public function is_permitted_custom_post($id) { + return (($this->bitmap & 32) === 32) && $this->in_custom_posts($id); + } + + public function is_permitted_category($id) { + return (($this->bitmap & 1) === 1) && $this->in_categories($id); + } + + public function is_post_in_permitted_category($post_id) { + return (($this->bitmap & 1) === 1) && $this->post_in_categories($post_id); + } + + public function is_permitted_post($id) { + return (($this->bitmap & 4) === 4) && $this->in_posts($id); + } + + public function is_permitted_page($id) { + return (($this->bitmap & 8) === 8) && $this->in_pages($id); + } + + public function is_permitted_comment($id) { + return (($this->bitmap & 2) === 2) && $this->in_comments($id); + } + + public function is_post_in_permitted_parent_category($post_id) { + return (($this->bitmap & 1) === 1) && $this->post_in_parent_categories($post_id); + } + + public function is_permitted_parent_category($id) { + return (($this->bitmap & 1) === 1) && $this->in_parent_categories($id); + } +} diff --git a/classes/class.bPermissionCollection.php b/classes/class.bPermissionCollection.php new file mode 100644 index 0000000..d0c1366 --- /dev/null +++ b/classes/class.bPermissionCollection.php @@ -0,0 +1,49 @@ +permissions = array(); + } + + public static function get_instance(){ + self::$_this = empty(self::$_this)? new BPermissionCollection():self::$_this; + return self::$_this; + } + + public function load($level_ids = array()){ + if (empty($level_ids)){ + global $wpdb; + $level_ids = $wpdb->get_col("SELECT id FROM {$wpdb->prefix}swpm_membership_tbl WHERE id != 1"); + } + + foreach($level_ids as $id){ + $this->permissions[] = BPermission::get_instance($id); + } + } + + public function get_permitted_levels($post_id){ + $levels = array(); + + foreach($this->permissions as $permission){ + if ($permission->is_permitted($post_id)){ + $levels[$permission->get($id)] = $permission->get('alias'); + } + } + + return $levels; + } +} diff --git a/classes/class.bProtection.php b/classes/class.bProtection.php new file mode 100644 index 0000000..be1f8b2 --- /dev/null +++ b/classes/class.bProtection.php @@ -0,0 +1,66 @@ +msg = ""; + $this->init(1); + } + + public static function get_instance() { + self::$_this = empty(self::$_this) ? (new BProtection()) : self::$_this; + return self::$_this; + } + + public function is_protected($id) { + if ($this->post_in_parent_categories($id) || $this->post_in_categories($id)) { + $this->msg = '

+ The category or parent category of this post is protected. You can change the category protection settings from the manage content protection menu. +

'; + return true; + } + return $this->in_posts($id) || $this->in_pages($id) || $this->in_attachments($id) || $this->in_custom_posts($id); + } + + public function get_last_message() { + return $this->msg; + } + + public function is_protected_post($id) { + return /* (($this->bitmap&4) != 4) && */ $this->in_posts($id); + } + + public function is_protected_page($id) { + return /* (($this->bitmap&4) != 4) && */ $this->in_pages($id); + } + + public function is_protected_attachment($id) { + return /* (($this->bitmap&16)!=16) && */ $this->in_attachments($id); + } + + public function is_protected_custom_post($id) { + return /* (($this->bitmap&32)!=32) && */ $this->in_custom_posts($id); + } + + public function is_protected_comment($id) { + return /* (($this->bitmap&2)!=2) && */ $this->in_comments($id); + } + + public function is_post_in_protected_category($post_id) { + return /* (($this->bitmap&1)!=1) && */ $this->post_in_categories($post_id); + } + + public function is_post_in_protected_parent_category($post_id) { + return /* (($this->bitmap&1)!=1) && */ $this->post_in_parent_categories($post_id); + } + + public function is_protected_category($id) { + return /* (($this->bitmap&1)!=1) && */ $this->in_categories($id); + } + + public function is_protected_parent_category($id) { + return /* (($this->bitmap&1)!=1) && */ $this->in_parent_categories($id); + } +} diff --git a/classes/class.bProtectionBase.php b/classes/class.bProtectionBase.php new file mode 100644 index 0000000..065de48 --- /dev/null +++ b/classes/class.bProtectionBase.php @@ -0,0 +1,296 @@ +owning_level_id = $level_id; + $query = $wpdb->prepare("SELECT * FROM {$wpdb->prefix}swpm_membership_tbl WHERE " + . (is_numeric($level_id) ? 'id = %d' : 'md5(id) = %s' ), $level_id); + $result = $wpdb->get_row($query); + + $this->bitmap = isset($result->permissions) ? $result->permissions : 0; + $this->posts = isset($result->post_list) ? (array) unserialize($result->post_list) : array(); + $this->pages = isset($result->page_list) ? (array) unserialize($result->page_list) : array(); + $this->comments = isset($result->comment_list) ? (array) unserialize($result->comment_list) : array(); + $this->categories = isset($result->category_list) ? (array) unserialize($result->category_list) : array(); + $this->attachments = isset($result->attachment_list) ? (array) unserialize($result->attachment_list) : array(); + $this->custom_posts = isset($result->custom_post_list) ? (array) unserialize($result->custom_post_list) : array(); + $this->options = isset($result->options) ? (array) unserialize($result->options) : array(); + $this->disable_bookmark = isset($result->disable_bookmark_list) ? (array) unserialize($result->disable_bookmark_list) : array(); + $this->details = (array) $result; + } + + public function apply($ids, $type) { + $post_types = get_post_types(array('public' => true, '_builtin' => false)); + if (in_array($type, $post_types)) { + $type = 'custom_post'; + } + return $this->update_perms($ids, true, $type); + } + + public function remove($ids, $type) { + $post_types = get_post_types(array('public' => true, '_builtin' => false)); + if (in_array($type, $post_types)) { + $type = 'custom_post'; + } + return $this->update_perms($ids, false, $type); + } + + public function get_options() { + return $this->options; + } + + public function get_posts() { + return $this->posts; + } + + public function get_pages() { + return $this->pages; + } + + public function get_comments() { + return $this->comments; + } + + public function get_categories() { + return $this->categories; + } + + public function get_attachments() { + return $this->attachments; + } + + public function get_custom_posts() { + return $this->custom_posts; + } + + public function is_bookmark_disabled($id) { + $posts = isset($this->disable_bookmark['posts']) ? + (array) $this->disable_bookmark['posts'] : array(); + $pages = isset($this->disable_bookmark['pages']) ? + (array) $this->disable_bookmark['pages'] : array(); + return in_array($id, $pages) || in_array($id, $posts); + } + + public function in_posts($id) { + return (/* ($this->bitmap&4)===4) && */in_array($id, (array) $this->posts)); + } + + public function in_pages($id) { + return (/* ($this->bitmap&8)===8) && */ in_array($id, (array) $this->pages)); + } + + public function in_attachments($id) { + return (/* ($this->bitmap&16)===16) && */in_array($id, (array) $this->attachments)); + } + + public function in_custom_posts($id) { + return (/* ($this->bitmap&32)===32) && */ in_array($id, (array) $this->custom_posts)); + } + + public function in_comments($id) { + return (/* ($this->bitmap&2)===2) && */ in_array($id, (array) $this->comments)); + } + + public function in_categories($id) { + if (empty($this->categories)) + return false; + return (/* ($this->bitmap&1)===1) && */ in_array($id, (array) $this->categories)); + } + + public function post_in_categories($post_id) { + if (empty($this->categories)) + return false; + return (/* ($this->bitmap&1)===1) && */ in_category((array) $this->categories, $post_id)); + } + + public function in_parent_categories($id) { + if (empty($this->categories)) + return false; + $parents = explode(',', get_category_parents($id, false, ',')); + $parents = array_unique($parents); + foreach ($parents as $parent) { + if (empty($parent)) + continue; + if (/* (($this->bitmap&1)===1) && */(in_array($parent, (array) $this->categories))) + return true; + } + return false; + } + + public function post_in_parent_categories($post_id) { + if (empty($this->categories)) + return false; + $cats = get_the_category($post_id); + $parents = array(); + foreach ($cats as $key => $cat) { + $parents = array_merge($parents, explode(',', get_category_parents($cat->cat_ID, false, ','))); + } + $parents = array_unique($parents); + foreach ($parents as $parent) { + if (empty($parent)) + continue; + if (/* (($this->bitmap&1)===1) && */(in_array(get_cat_ID($parent), (array) $this->categories))) + return true; + } + return false; + } + + public function add_posts($ids) { + return $this->update_perms($ids, true, 'post'); + } + + public function add_pages($ids) { + return $this->update_perms($ids, true, 'page'); + } + + public function add_attachments($ids) { + return $this->update_perms($ids, true, 'attachment'); + } + + public function add_comments($ids) { + return $this->update_perms($ids, true, 'comment'); + } + + public function add_categories($ids) { + return $this->update_perms($ids, true, 'category'); + } + + public function add_custom_posts($ids) { + return $this->update_perms($ids, true, 'custom_post'); + } + + public function remove_posts($ids) { + return $this->update_perms($ids, false, 'post'); + } + + public function remove_pages($ids) { + return $this->update_perms($ids, false, 'page'); + } + + public function remove_attachments($ids) { + return $this->update_perms($ids, false, 'attachment'); + } + + public function remove_comments($ids) { + return $this->update_perms($ids, false, 'comment'); + } + + public function remove_categories($ids) { + return $this->update_perms($ids, false, 'category'); + } + + public function remove_custom_posts($ids) { + return $this->update_perms($ids, false, 'custom_post'); + } + + private function update_perms($ids, $set, $type) { + $list = null; + $index = ''; + if (empty($ids)) { + return $this; + } + $ids = (array) $ids; + switch ($type) { + case 'page': + $list = $this->pages; + $index = 'page_list'; + break; + case 'post': + $list = $this->posts; + $index = 'post_list'; + break; + case 'attachment': + $list = $this->attachments; + $index = 'attachment_list'; + break; + case 'comment': + $list = $this->comments; + $index = 'comment_list'; + break; + case 'category': + $list = $this->categories; + $index = 'category_list'; + break; + case 'custom_post': + $list = $this->custom_posts; + $index = 'custom_post_list'; + break; + default: + break; + } + + if (!empty($index)) { + if ($set) { + $list = array_merge($list, $ids); + $list = array_unique($list); + } else { + $list = array_diff($list, $ids); + } + switch ($type) { + case 'page': + $this->pages = $list; + break; + case 'post': + $this->posts = $list; + break; + case 'attachment': + $this->attachments = $list; + break; + case 'comment': + $this->comments = $list; + break; + case 'category': + $this->categories = $list; + break; + case 'custom_post': + $this->custom_posts = $list; + break; + default: + break; + } + $this->details[$index] = $list; + } + return $this; + } + + public function save() { + global $wpdb; + $data = array(); + + $list_type = array('page_list', 'post_list', 'attachment_list', + 'custom_post_list', 'comment_list', 'category_list'); + foreach ($this->details as $key => $value) { + if ($key == 'id') + continue; + if (is_serialized($value) || !in_array($key, $list_type)) + $data[$key] = $value; + else + $data[$key] = serialize($value); + } + $wpdb->update($wpdb->prefix . "swpm_membership_tbl", $data, array('id' => $this->owning_level_id)); + } + + public function get($key, $default = '') { + if (isset($this->details[$key])) { + return $this->details[$key]; + } + return $default; + } + +} diff --git a/classes/class.bRegistration.php b/classes/class.bRegistration.php new file mode 100644 index 0000000..ecb3aaa --- /dev/null +++ b/classes/class.bRegistration.php @@ -0,0 +1,42 @@ +member_info)) {return false;} + $member_info = $this->member_info; + $settings = BSettings::get_instance(); + $subject = $settings->get_value('reg-complete-mail-subject'); + $body = $settings->get_value('reg-complete-mail-body'); + $from_address = $settings->get_value('email-from'); + $login_link = $settings->get_value('login-page-url'); + $headers = 'From: ' . $from_address . "\r\n"; + $member_info['membership_level_name'] = BPermission::get_instance($member_info['membership_level'])->get('alias'); + $member_info['password'] = $member_info['plain_password']; + $member_info['login_link'] = $login_link; + $values = array_values($member_info); + $keys = array_map('swpm_enclose_var', array_keys($member_info)); + $body = str_replace($keys, $values, $body); + $email = sanitize_email(filter_input(INPUT_POST, 'email', FILTER_UNSAFE_RAW)); + wp_mail(trim($email), $subject, $body, $headers); + if ($settings->get_value('enable-admin-notification-after-reg')) { + $subject = "Notification of New Member Registration"; + $body = "A new member has registered. The following email was sent to the member." . + "\n\n-------Member Email----------\n" . $body . + "\n\n------End------\n"; + wp_mail($from_address, $subject, $body, $headers); + } + return true; + } +} +function swpm_enclose_var($n){ + return '{'.$n .'}'; +} diff --git a/classes/class.bSession.php b/classes/class.bSession.php new file mode 100644 index 0000000..e69de29 diff --git a/classes/class.bSettings.php b/classes/class.bSettings.php new file mode 100644 index 0000000..be49a41 --- /dev/null +++ b/classes/class.bSettings.php @@ -0,0 +1,395 @@ +settings = (array) get_option('swpm-settings'); + } + public function init_config_hooks(){ + $page = filter_input(INPUT_GET, 'page'); +// if($page == 'simple_wp_membership_settings'){ + if(is_admin()){ // for frontend just load settings but dont try to render settings page. + $tab = filter_input(INPUT_GET, 'tab'); + $tab = empty($tab)?filter_input(INPUT_POST, 'tab'):$tab; + $this->current_tab = empty($tab) ? 1 : $tab; + $this->tabs = array(1=> 'General Settings', 2=> 'Payment Settings', + 3=> 'Email Settings', 4=> 'Tools', 5=>'Advanced Settings', 6=> 'Addons Settings'); + add_action('swpm-draw-tab', array(&$this, 'draw_tabs')); + $method = 'tab_' . $this->current_tab; + if (method_exists($this, $method)){ + $this->$method(); + } + } + } + private function tab_1() { + + register_setting('swpm-settings-tab-1', 'swpm-settings', array(&$this, 'sanitize_tab_1')); + + //This settings section has no heading + add_settings_section('swpm-general-post-submission-check', '', + array(&$this, 'swpm_general_post_submit_check_callback'), 'simple_wp_membership_settings'); + + add_settings_section('swpm-documentation', BUtils::_('Plugin Documentation'), + array(&$this, 'swpm_documentation_callback'), 'simple_wp_membership_settings'); + add_settings_section('general-settings', BUtils::_('General Settings'), + array(&$this, 'general_settings_callback'), 'simple_wp_membership_settings'); + add_settings_field('enable-free-membership', BUtils::_('Enable Free Membership'), + array(&$this, 'checkbox_callback'), 'simple_wp_membership_settings', 'general-settings', + array('item' => 'enable-free-membership', + 'message'=> BUtils::_('Enable/disable registration for free membership level. When you enable this option, make sure to specify a free membership level ID in the field below.'))); + add_settings_field('free-membership-id', BUtils::_('Free Membership Level ID'), + array(&$this, 'textfield_small_callback'), 'simple_wp_membership_settings', 'general-settings', + array('item' => 'free-membership-id', + 'message'=> BUtils::_('Assign free membership level ID'))); + add_settings_field('enable-moretag', BUtils::_('Enable More Tag Protection'), + array(&$this, 'checkbox_callback'), 'simple_wp_membership_settings', 'general-settings', + array('item' => 'enable-moretag', + 'message'=> BUtils::_('Enables or disables "more" tag protection in the posts and pages. Anything after the More tag is protected. Anything before the more tag is teaser content.'))); + add_settings_field('hide-adminbar', BUtils::_('Hide Adminbar'), + array(&$this, 'checkbox_callback'), 'simple_wp_membership_settings', 'general-settings', + array('item' => 'hide-adminbar', + 'message'=>BUtils::_('WordPress shows an admin toolbar to the logged in users of the site. Check this box if you want to hide that admin toolbar in the fronend of your site.'))); + + add_settings_field('default-account-status', BUtils::_('Default Account Status'), + array(&$this, 'selectbox_callback'), 'simple_wp_membership_settings', 'general-settings', + array('item' => 'default-account-status', + 'options'=> BUtils::get_account_state_options(), + 'default'=>'active', + 'message'=>BUtils::_('Select the default account status for newly registered users. If you want to manually approve the members then you can set the status to "Pending".'))); + add_settings_field('allow-account-deletion', BUtils::_('Allow Account Deletion'), + array(&$this, 'checkbox_callback'), 'simple_wp_membership_settings', 'general-settings', + array('item' => 'allow-account-deletion', + 'options'=> BUtils::get_account_state_options(), + 'message'=>BUtils::_('Allow users to delete their accounts.'))); + add_settings_field('delete-pending-account', BUtils::_('Auto Delete Pending Account'), + array(&$this, 'selectbox_callback'), 'simple_wp_membership_settings', 'general-settings', + array('item' => 'delete-pending-account', + 'options'=> array(0 => 'Do not delete', 1=>'Older than 1 month', 2=> 'Older than 2 months'), + 'default'=>'0', + 'message'=>BUtils::_('Select how long you want to keep "pending" account.'))); + /*add_settings_field('protect-everything', BUtils::_('Protect Everything'), + array(&$this, 'checkbox_callback'), 'simple_wp_membership_settings', 'general-settings', + array('item' => 'protect-everything', + 'message'=>BUtils::_('Check this box if you want to protect all posts/pages by default.')));*/ + + add_settings_section('pages-settings', BUtils::_('Pages Settings'), + array(&$this, 'pages_settings_callback'), 'simple_wp_membership_settings'); + add_settings_field('login-page-url', BUtils::_('Login Page URL'), + array(&$this, 'textfield_long_callback'), 'simple_wp_membership_settings', 'pages-settings', + array('item' => 'login-page-url', + 'message'=>'')); + add_settings_field('registration-page-url', BUtils::_('Registration Page URL'), + array(&$this, 'textfield_long_callback'), 'simple_wp_membership_settings', 'pages-settings', + array('item' => 'registration-page-url', + 'message'=>'')); + add_settings_field('join-us-page-url', BUtils::_('Join Us Page URL'), + array(&$this, 'textfield_long_callback'), 'simple_wp_membership_settings', 'pages-settings', + array('item' => 'join-us-page-url', + 'message'=>'')); + add_settings_field('profile-page-url', BUtils::_('Edit Profile Page URL'), + array(&$this, 'textfield_long_callback'), 'simple_wp_membership_settings', 'pages-settings', + array('item' => 'profile-page-url', + 'message'=>'')); + add_settings_field('reset-page-url', BUtils::_('Password Reset Page URL'), + array(&$this, 'textfield_long_callback'), 'simple_wp_membership_settings', 'pages-settings', + array('item' => 'reset-page-url', + 'message'=>'')); + + add_settings_section('debug-settings', BUtils::_('Test & Debug Settings'), + array(&$this, 'testndebug_settings_callback'), 'simple_wp_membership_settings'); + + $debug_field_help_text = BUtils::_('Check this option to enable debug logging.'); + $debug_field_help_text .= '
- View debug log file by clicking here.'; + $debug_field_help_text .= '
- Reset debug log file by clicking here.'; + add_settings_field('enable-debug', 'Enable Debug', + array(&$this, 'checkbox_callback'), 'simple_wp_membership_settings', 'debug-settings', + array('item' => 'enable-debug', + 'message'=> $debug_field_help_text)); + add_settings_field('enable-sandbox-testing', BUtils::_('Enable Sandbox Testing'), + array(&$this, 'checkbox_callback'), 'simple_wp_membership_settings', 'debug-settings', + array('item' => 'enable-sandbox-testing', + 'message'=>BUtils::_('Enable this option if you want to do sandbox payment testing.'))); + + } + + private function tab_2() { + } + + private function tab_3() { + register_setting('swpm-settings-tab-3', 'swpm-settings', array(&$this, 'sanitize_tab_3')); + + add_settings_section('email-misc-settings', BUtils::_('Email Misc. Settings'), + array(&$this, 'email_misc_settings_callback'), 'simple_wp_membership_settings'); + add_settings_field('email-misc-from', BUtils::_('From Email Address'), + array(&$this, 'textfield_callback'), 'simple_wp_membership_settings', 'email-misc-settings', + array('item' => 'email-from', + 'message'=>'')); + + add_settings_section('reg-prompt-email-settings', BUtils::_('Email Settings (Prompt to Complete Registration )'), + array(&$this, 'reg_prompt_email_settings_callback'), 'simple_wp_membership_settings'); + add_settings_field('reg-prompt-complete-mail-subject', BUtils::_('Email Subject'), + array(&$this, 'textfield_callback'), 'simple_wp_membership_settings', 'reg-prompt-email-settings', + array('item' => 'reg-prompt-complete-mail-subject', + 'message'=>'')); + add_settings_field('reg-prompt-complete-mail-body', BUtils::_('Email Body'), + array(&$this, 'textarea_callback'), 'simple_wp_membership_settings', 'reg-prompt-email-settings', + array('item' => 'reg-prompt-complete-mail-body', + 'message'=>'')); + + add_settings_section('reg-email-settings', BUtils::_('Email Settings (Registration Complete)'), + array(&$this, 'reg_email_settings_callback'), 'simple_wp_membership_settings'); + add_settings_field('reg-complete-mail-subject', BUtils::_('Email Subject'), + array(&$this, 'textfield_callback'), 'simple_wp_membership_settings', 'reg-email-settings', + array('item' => 'reg-complete-mail-subject', + 'message'=>'')); + add_settings_field('reg-complete-mail-body', BUtils::_('Email Body'), + array(&$this, 'textarea_callback'), 'simple_wp_membership_settings', 'reg-email-settings', + array('item' => 'reg-complete-mail-body', + 'message'=>'')); + add_settings_field('enable-admin-notification-after-reg', BUtils::_('Send Notification To Admin'), + array(&$this, 'checkbox_callback'), 'simple_wp_membership_settings', 'reg-email-settings', + array('item' => 'enable-admin-notification-after-reg', + 'message'=>'')); + add_settings_field('enable-notification-after-manual-user-add', BUtils::_('Send Email to Member When Added via Admin Dashboard'), + array(&$this, 'checkbox_callback'), 'simple_wp_membership_settings', 'reg-email-settings', + array('item' => 'enable-notification-after-manual-user-add', + 'message'=>'')); + + add_settings_section('upgrade-email-settings', BUtils::_(' Email Settings (Account Upgrade Notification)'), + array(&$this, 'upgrade_email_settings_callback'), 'simple_wp_membership_settings'); + add_settings_field('upgrade-complete-mail-subject', BUtils::_('Email Subject'), + array(&$this, 'textfield_callback'), 'simple_wp_membership_settings', 'upgrade-email-settings', + array('item' => 'upgrade-complete-mail-subject', + 'message'=>'')); + add_settings_field('upgrade-complete-mail-body', BUtils::_('Email Body'), + array(&$this, 'textarea_callback'), 'simple_wp_membership_settings', 'upgrade-email-settings', + array('item' => 'upgrade-complete-mail-body', + 'message'=>'')); + } + + private function tab_4(){ + } + + private function tab_5(){ + register_setting('swpm-settings-tab-5', 'swpm-settings', array(&$this, 'sanitize_tab_5')); + + add_settings_section('advanced-settings', BUtils::_('Advanced Settings'), + array(&$this, 'advanced_settings_callback'), 'simple_wp_membership_settings'); + + add_settings_field('enable-expired-account-login', BUtils::_('Enable Expired Account Login'), + array(&$this, 'checkbox_callback'), 'simple_wp_membership_settings', 'advanced-settings', + array('item' => 'enable-expired-account-login', + 'message'=>BUtils::_("When enabled, expired members will be able to log into the system but won't be able to view any protected content. This allows them to easily renew their account by making another payment."))); + } + + private function tab_6(){ + } + + public static function get_instance() { + self::$_this = empty(self::$_this) ? new BSettings() : self::$_this; + return self::$_this; + } + public function selectbox_callback($args){ + $item = $args['item']; + $options = $args['options']; + $default = $args['default']; + $msg = isset($args['message'])?$args['message']: ''; + $selected = esc_attr($this->get_value($item), $default); + echo "'; + echo '
'.$msg.''; + } + public function checkbox_callback($args) { + $item = $args['item']; + $msg = isset($args['message'])?$args['message']: ''; + $is = esc_attr($this->get_value($item)); + echo ""; + echo '
'.$msg.''; + } + + public function textarea_callback($args) { + $item = $args['item']; + $msg = isset($args['message'])?$args['message']: ''; + $text = esc_attr($this->get_value($item)); + echo ""; + echo '
'.$msg.''; + } + + public function textfield_small_callback($args) { + $item = $args['item']; + $msg = isset($args['message'])?$args['message']: ''; + $text = esc_attr($this->get_value($item)); + echo ""; + echo '
'.$msg.''; + } + + public function textfield_callback($args) { + $item = $args['item']; + $msg = isset($args['message'])?$args['message']: ''; + $text = esc_attr($this->get_value($item)); + echo ""; + echo '
'.$msg.''; + } + + public function textfield_long_callback($args) { + $item = $args['item']; + $msg = isset($args['message'])?$args['message']: ''; + $text = esc_attr($this->get_value($item)); + echo ""; + echo '
'.$msg.''; + } + + public function swpm_documentation_callback() { + ?> +
+

Visit the + Simple Membership Plugin Site + to read setup and configuration documentation. Please give us a rating if you like the plugin. +

+
+

Debug log files have been reset!

'; + } + else{ + echo '

Debug log files could not be reset!

'; + } + } + + //Show settings updated message + if(isset($_REQUEST['settings-updated'])){ + echo '

' . BUtils::_('Settings updated!') . '

'; + } + } + + public function general_settings_callback() { + BUtils::e('General Plugin Settings.'); + } + + public function pages_settings_callback() { + BUtils::e('Page Setup and URL Related settings.'); + } + public function testndebug_settings_callback(){ + BUtils::e('Testing and Debug Related Settings.'); + } + public function reg_email_settings_callback() { + BUtils::e('This email will be sent to your users when they complete the registration and become a member.'); + } + public function email_misc_settings_callback(){ + BUtils::e('Settings in this section apply to all emails.'); + } + public function upgrade_email_settings_callback() { + BUtils::e('This email will be sent to your users after account upgrade.'); + } + public function reg_prompt_email_settings_callback() { + BUtils::e('This email will be sent to prompt user to complete registration.'); + } + public function advanced_settings_callback(){ + BUtils::e('This page allows you to configure some advanced features of the plugin.'); + } + + public function sanitize_tab_1($input) { + if (empty($this->settings)){ + $this->settings = (array) get_option('swpm-settings'); + } + $output = $this->settings; + //general settings block + + $output['hide-adminbar'] = isset($input['hide-adminbar'])? esc_attr($input['hide-adminbar']) : ""; + $output['protect-everything'] = isset($input['protect-everything'])? esc_attr($input['protect-everything']) : ""; + $output['enable-free-membership'] = isset($input['enable-free-membership'])? esc_attr($input['enable-free-membership']) : ""; + $output['enable-moretag'] = isset($input['enable-moretag'])? esc_attr($input['enable-moretag']) : ""; + $output['enable-debug'] = isset($input['enable-debug'])? esc_attr($input['enable-debug']) : ""; + $output['enable-sandbox-testing'] = isset($input['enable-sandbox-testing'])? esc_attr($input['enable-sandbox-testing']) : ""; + $output['allow-account-deletion'] = isset($input['allow-account-deletion'])? esc_attr($input['allow-account-deletion']) : ""; + + $output['free-membership-id'] = ($input['free-membership-id'] != 1) ? absint($input['free-membership-id']) : ''; + $output['login-page-url'] = esc_url($input['login-page-url']); + $output['registration-page-url'] = esc_url($input['registration-page-url']); + $output['profile-page-url'] = esc_url($input['profile-page-url']); + $output['reset-page-url'] = esc_url($input['reset-page-url']); + $output['join-us-page-url'] = esc_url($input['join-us-page-url']); + $output['default-account-status'] = esc_attr($input['default-account-status']); + return $output; + } + + public function sanitize_tab_3($input) { + if (empty($this->settings)){ + $this->settings = (array) get_option('swpm-settings'); + } + $output = $this->settings; + $output['reg-complete-mail-subject'] = sanitize_text_field($input['reg-complete-mail-subject']); + $output['reg-complete-mail-body'] = wp_kses_data(force_balance_tags($input['reg-complete-mail-body'])); + + $output['upgrade-complete-mail-subject'] = sanitize_text_field($input['upgrade-complete-mail-subject']); + $output['upgrade-complete-mail-body'] = wp_kses_data(force_balance_tags($input['upgrade-complete-mail-body'])); + + $output['reg-prompt-complete-mail-subject'] = sanitize_text_field($input['reg-prompt-complete-mail-subject']); + $output['reg-prompt-complete-mail-body'] = wp_kses_data(force_balance_tags($input['reg-prompt-complete-mail-body'])); + $output['email-from'] = trim($input['email-from']); + $output['enable-admin-notification-after-reg'] = isset($input['enable-admin-notification-after-reg'])? esc_attr($input['enable-admin-notification-after-reg']) : ""; + $output['enable-notification-after-manual-user-add'] = isset($input['enable-notification-after-manual-user-add'])? esc_attr($input['enable-notification-after-manual-user-add']) : ""; + + return $output; + } + + public function sanitize_tab_5($input){ + if (empty($this->settings)){ + $this->settings = (array) get_option('swpm-settings'); + } + $output = $this->settings; + $output['enable-expired-account-login'] = isset($input['enable-expired-account-login'])? esc_attr($input['enable-expired-account-login']) : ""; + + return $output; + } + public function get_value($key, $default = "") { + if (isset($this->settings[$key])){ + return $this->settings[$key]; + } + return $default; + } + + public function set_value($key, $value) { + $this->settings[$key] = $value; + return $this; + } + + public function save() { + update_option('swpm-settings', $this->settings); + } + + public function draw_tabs() { + $current = $this->current_tab; + ?> + + get_value('login-page-url'); + $joinus = $this->get_value('join-us-page-url'); + if (empty ($login) || empty($joinus)){ + return 'Simple Membership is not configured correctly.' + . 'Please contact Admin'; + } + return BUtils::_('Please'). ' . '. BUtils::_('Not a Member?').' '.BUtils::_('Join Us').''; + } + +} diff --git a/classes/class.bTransactions.php b/classes/class.bTransactions.php new file mode 100644 index 0000000..1336de9 --- /dev/null +++ b/classes/class.bTransactions.php @@ -0,0 +1,55 @@ +insert($wpdb->prefix . "swpm_payments_tbl", $txn_data); + + } + + static function parse_custom_var($custom) { + $delimiter = "&"; + $customvariables = array(); + + $namevaluecombos = explode($delimiter, $custom); + foreach ($namevaluecombos as $keyval_unparsed) { + $equalsignposition = strpos($keyval_unparsed, '='); + if ($equalsignposition === false) { + $customvariables[$keyval_unparsed] = ''; + continue; + } + $key = substr($keyval_unparsed, 0, $equalsignposition); + $value = substr($keyval_unparsed, $equalsignposition + 1); + $customvariables[$key] = $value; + } + + return $customvariables; + } + +} \ No newline at end of file diff --git a/classes/class.bTransfer.php b/classes/class.bTransfer.php new file mode 100644 index 0000000..e77722b --- /dev/null +++ b/classes/class.bTransfer.php @@ -0,0 +1,65 @@ + '', 'last_name' => '', + 'user_name' => '', 'email' => '', + 'password' => '', + 'phone' => '', 'account_state' => '', + 'member_since' => '', 'subscription_starts' => '', + 'address_street' => '', 'address_city' => '', + 'address_state' => '', 'address_zipcode' => '', + 'company_name' => '', 'country' => '', + 'gender' => 'not specified', + 'membership_level' => '2'); + public static $default_level_fields = array( + 'alias' => '', 'role' => '', + 'subscription_period' => '', 'subscription_duration_type' => BMembershipLevel::NO_EXPIRY); + public static $admin_messages = array(); + private static $_this; + private $message; + + private function __contruct() { + $this->message = get_option('swpm-messages'); + } + + public static function get_instance() { + self::$_this = empty(self::$_this) ? new BTransfer() : self::$_this; + self::$_this->message = get_option('swpm-messages'); + return self::$_this; + } + + public function get($key) { + $sesion_key = $_COOKIE['swpm_session']; + $m = ''; + if (isset($this->message[$sesion_key])){ + $m = $this->message[$sesion_key]->get($key); + } + update_option('swpm-messages', $this->message); + return $m; + } + + public function set($key, $value) { + $sesion_key = $_COOKIE['swpm_session']; + if (!isset($this->message[$sesion_key])){ + $this->message[$sesion_key] = new BMessages(); + } + $this->message[$sesion_key]->set($key,$value); + update_option('swpm-messages', $this->message); + } + + public static function get_real_ip_addr() { + if (!empty($_SERVER['HTTP_CLIENT_IP'])){ + $ip = $_SERVER['HTTP_CLIENT_IP']; + } + else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){ + $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; + } + else{ + $ip = $_SERVER['REMOTE_ADDR']; + } + return $ip; + } + +} diff --git a/classes/class.bUtils.php b/classes/class.bUtils.php new file mode 100644 index 0000000..bfcd0ec --- /dev/null +++ b/classes/class.bUtils.php @@ -0,0 +1,385 @@ +No Expiry' . + '' . + '' . + '' . + '' . + ''; + } + + // $subscript_period must be integer. + public static function calculate_subscription_period_days($subcript_period, $subscription_duration_type) { + if ($subscription_duration_type == BMembershipLevel::NO_EXPIRY) { + return 'noexpire'; + } + if (!is_numeric($subcript_period)) { + throw new Exception(" subcript_period parameter must be integer in BUtils::calculate_subscription_period_days method"); + } + switch (strtolower($subscription_duration_type)) { + case BMembershipLevel::DAYS: + break; + case BMembershipLevel::WEEKS: + $subcript_period = $subcript_period * 7; + break; + case BMembershipLevel::MONTHS: + $subcript_period = $subcript_period * 30; + break; + case BMembershipLevel::YEARS: + $subcript_period = $subcript_period * 365; + break; + } + return $subcript_period; + } + + public static function get_expiration_timestamp($user) { + $permission = BPermission::get_instance($user->membership_level); + if (BMembershipLevel::FIXED_DATE == $permission->get('subscription_duration_type')) { + return strtotime($permission->get('subscription_period')); + } + $days = self::calculate_subscription_period_days( + $permission->get('subscription_period'), $permission->get('subscription_duration_type')); + if ($days == 'noexpire') { + return PHP_INT_MAX; // which is equivalent to + } + return strtotime($user->subscription_starts . ' ' . $days . ' days'); + } + + public static function is_subscription_expired($user) { + $expiration_timestamp = BUtils::get_expiration_timestamp($user); + return $expiration_timestamp < time(); + } + + public static function gender_dropdown($selected = 'not specified') { + return '' . + '' . + ''; + } + + public static function get_account_state_options() { + return array('active' => BUtils::_('Active'), + 'inactive' => BUtils::_('Inactive'), + 'pending' => BUtils::_('Pending'), + 'expired' => BUtils::_('Expired'),); + } + + public static function account_state_dropdown($selected = 'active') { + $options = self::get_account_state_options(); + $html = ''; + foreach ($options as $key => $value) { + $html .= ''; + } + return $html; + } + + public static function membership_level_dropdown($selected = 0) { + $options = ''; + global $wpdb; + $query = "SELECT alias, id FROM " . $wpdb->prefix . "swpm_membership_tbl WHERE id != 1"; + $levels = $wpdb->get_results($query); + foreach ($levels as $level) { + $options .= ''; + } + return $options; + } + + public static function get_all_membership_level_ids() { + global $wpdb; + $query = "SELECT id FROM " . $wpdb->prefix . "swpm_membership_tbl WHERE id != 1"; + return $wpdb->get_col($query); + } + + public static function get_user_by_id($swpm_id) { + global $wpdb; + $query = $wpdb->prepare("SELECT user_name FROM {$wpdb->prefix}swpm_members_tbl WHERE member_id = %d", $swpm_id); + return $wpdb->get_var($query); + } + + public static function get_user_by_user_name($swpm_user_name) { + global $wpdb; + $query = $wpdb->prepare("SELECT member_id FROM {$wpdb->prefix}swpm_members_tbl WHERE user_name = %s", $swpm_user_name); + return $wpdb->get_var($query); + } + + public static function get_registration_link($for = 'all', $send_email = false, $member_id = '') { + $members = array(); + global $wpdb; + switch ($for) { + case 'one': + if (empty($member_id)) { + return array(); + } + $query = $wpdb->prepare("SELECT * FROM {$wpdb->prefix}swpm_members_tbl WHERE member_id = %d", $member_id); + $members = $wpdb->get_results($query); + break; + case 'all': + $query = "SELECT * FROM {$wpdb->prefix}swpm_members_tbl WHERE reg_code != '' "; + $members = $wpdb->get_results($query); + break; + } + $settings = BSettings::get_instance(); + $separator = '?'; + $url = $settings->get_value('registration-page-url'); + if (strpos($url, '?') !== false) { + $separator = '&'; + } + $subject = $settings->get_value('reg-complete-mail-subject'); + if (empty($subject)) { + $subject = "Please complete your registration"; + } + $body = $settings->get_value('reg-complete-mail-body'); + if (empty($body)) { + $body = "Please use the following link to complete your registration. \n {reg_link}"; + } + $from_address = $settings->get_value('email-from'); + $links = array(); + foreach ($members as $member) { + $reg_url = $url . $separator . 'member_id=' . $member->member_id . '&code=' . $member->reg_code; + if (!empty($send_email) && empty($member->user_name)) { + $tags = array("{first_name}", "{last_name}", "{reg_link}"); + $vals = array($member->first_name, $member->last_name, $reg_url); + $email_body = str_replace($tags, $vals, $body); + $headers = 'From: ' . $from_address . "\r\n"; + wp_mail($member->email, $subject, $email_body, $headers); + } + $links[] = $reg_url; + } + return $links; + } + + public static function update_wp_user_Role($wp_user_id, $role) { + $preserve_role = 'yes'; + if ($preserve_role) { + return; + } + if (self::is_multisite_install()) {//MS install + return; //TODO - don't do this for MS install + } + $caps = get_user_meta($wp_user_id, 'wp_capabilities', true); + if (in_array('administrator', array_keys((array) $caps))) { + return; + } + do_action('set_user_role', $wp_user_id, $role); //Fire the action for other plugin(s) + wp_update_user(array('ID' => $wp_user_id, 'role' => $role)); + $roles = new WP_Roles(); + $level = $roles->roles[$role]['capabilities']; + if (isset($level['level_10']) && $level['level_10']) { + update_user_meta($wp_user_id, 'wp_user_level', 10); + return; + } + if (isset($level['level_9']) && $level['level_9']) { + update_user_meta($wp_user_id, 'wp_user_level', 9); + return; + } + if (isset($level['level_8']) && $level['level_8']) { + update_user_meta($wp_user_id, 'wp_user_level', 8); + return; + } + if (isset($level['level_7']) && $level['level_7']) { + update_user_meta($wp_user_id, 'wp_user_level', 7); + return; + } + if (isset($level['level_6']) && $level['level_6']) { + update_user_meta($wp_user_id, 'wp_user_level', 6); + return; + } + if (isset($level['level_5']) && $level['level_5']) { + update_user_meta($wp_user_id, 'wp_user_level', 5); + return; + } + if (isset($level['level_4']) && $level['level_4']) { + update_user_meta($wp_user_id, 'wp_user_level', 4); + return; + } + if (isset($level['level_3']) && $level['level_3']) { + update_user_meta($wp_user_id, 'wp_user_level', 3); + return; + } + if (isset($level['level_2']) && $level['level_2']) { + update_user_meta($wp_user_id, 'wp_user_level', 2); + return; + } + if (isset($level['level_1']) && $level['level_1']) { + update_user_meta($wp_user_id, 'wp_user_level', 1); + return; + } + if (isset($level['level_0']) && $level['level_0']) { + update_user_meta($wp_user_id, 'wp_user_level', 0); + return; + } + } + + public static function update_wp_user($wp_user_name, $swpm_data) { + $wp_user_info = array(); + if (isset($swpm_data['email'])) { + $wp_user_info['user_email'] = $swpm_data['email']; + } + if (isset($swpm_data['first_name'])) { + $wp_user_info['first_name'] = $swpm_data['first_name']; + } + if (isset($swpm_data['last_name'])) { + $wp_user_info['last_name'] = $swpm_data['last_name']; + } + if (isset($swpm_data['plain_password'])) { + $wp_user_info['user_pass'] = $swpm_data['plain_password']; + } + + $wp_user = get_user_by('login', $wp_user_name); + + if ($wp_user) { + $wp_user_info['ID'] = $wp_user->ID; + return wp_update_user($wp_user_info); + } + return false; + } + + public static function create_wp_user($wp_user_data) { + if (self::is_multisite_install()) {//MS install + global $blog_id; + if ($wp_user_id = email_exists($wp_user_data['user_email'])) {// if user exists then just add him to current blog. + add_existing_user_to_blog(array('user_id' => $wp_user_id, 'role' => 'subscriber')); + return $wp_user_id; + } + $wp_user_id = wpmu_create_user($wp_user_data['user_login'], $wp_user_data['password'], $wp_user_data['user_email']); + $role = 'subscriber'; //TODO - add user as a subscriber first. The subsequent update user role function to update the role to the correct one + add_user_to_blog($blog_id, $wp_user_id, $role); + } else {//Single site install + $wp_user_id = email_exists($wp_user_data['user_email']); + if ($wp_user_id) { + return $wp_user_id; + } + $wp_user_id = wp_create_user($wp_user_data['user_login'], $wp_user_data['password'], $wp_user_data['user_email']); + } + $wp_user_data['ID'] = $wp_user_id; + wp_update_user($wp_user_data); + $user_info = get_userdata($wp_user_id); + $user_cap = (isset($user_info->wp_capabilities) && is_array($user_info->wp_capabilities)) ? array_keys($user_info->wp_capabilities) : array(); + if (!in_array('administrator', $user_cap)) { + BUtils::update_wp_user_Role($wp_user_id, $wp_user_data['role']); + } + return $wp_user_id; + } + + public static function is_multisite_install() { + if (function_exists('is_multisite') && is_multisite()) { + return true; + } else { + return false; + } + } + + public static function _($msg) { + return __($msg, 'swpm'); + } + + public static function e($msg) { + _e($msg, 'swpm'); + } + + public static function is_admin() { + return current_user_can('manage_options'); + } + + public static function get_expire_date($start_date, $subscription_duration, $subscription_duration_type) { + if ($subscription_duration_type == BMembershipLevel::FIXED_DATE) { //will expire after a fixed date. + return date(get_option('date_format'), strtotime($subscription_duration)); + } + $expires = self::calculate_subscription_period_days($subscription_duration, $subscription_duration_type); + if ($expires == 'noexpire') {// its set to no expiry until cancelled + return BUtils::_('Never'); + } + + return date(get_option('date_format'), strtotime($start_date . ' ' . $expires . ' days')); + } + + public static function swpm_username_exists($user_name) { + global $wpdb; + $member_table = $wpdb->prefix . 'swpm_members_tbl'; + $query = $wpdb->prepare('SELECT member_id FROM ' . $member_table . ' WHERE user_name=%s', sanitize_user($user_name)); + return $wpdb->get_var($query); + } + + public static function get_free_level() { + $encrypted = filter_input(INPUT_POST, 'level_identifier'); + global $wpdb; + if (!empty($encrypted)) { + return BPermission::get_instance($encrypted)->get('id'); + } + + $is_free = BSettings::get_instance()->get_value('enable-free-membership'); + $free_level = absint(BSettings::get_instance()->get_value('free-membership-id')); + + return ($is_free) ? $free_level : null; + } + + public static function is_paid_registration() { + $member_id = filter_input(INPUT_GET, 'member_id', FILTER_SANITIZE_NUMBER_INT); + $code = filter_input(INPUT_GET, 'code', FILTER_SANITIZE_STRING); + return !empty($member_id) && !empty($code); + } + + public static function get_paid_member_info() { + $member_id = filter_input(INPUT_GET, 'member_id', FILTER_SANITIZE_NUMBER_INT); + $code = filter_input(INPUT_GET, 'code', FILTER_SANITIZE_STRING); + global $wpdb; + if (!empty($member_id) && !empty($code)) { + $query = 'SELECT * FROM ' . $wpdb->prefix . 'swpm_members_tbl WHERE member_id= %d AND reg_code=%s'; + $query = $wpdb->prepare($query, $member_id, $code); + return $wpdb->get_row($query); + } + return null; + } + + public static function account_delete_confirmation_ui($msg = "") { + ob_start(); + include(SIMPLE_WP_MEMBERSHIP_PATH . 'views/account_delete_warning.php'); + ob_get_flush(); + wp_die("", "", array('back_link' => true)); + } + + public static function delete_account_button() { + $allow_account_deletion = BSettings::get_instance()->get_value('allow-account-deletion'); + if (empty($allow_account_deletion)) { + return ""; + } + + return ''; + } + + public static function encrypt_password($plain_password) { + include_once(ABSPATH . WPINC . '/class-phpass.php'); + $wp_hasher = new PasswordHash(8, TRUE); + $password_hash = $wp_hasher->HashPassword(trim($plain_password)); + return $password_hash; + } + + public static function get_restricted_image_url() { + return SIMPLE_WP_MEMBERSHIP_URL . '/images/restricted-icon.png'; + } + + /* + * Checks if the string exists in the array key value of the provided array. If it doesn't exist, it returns the first key element from the valid values. + */ + + public static function sanitize_value_by_array($val_to_check, $valid_values) { + $keys = array_keys($valid_values); + $keys = array_map('strtolower', $keys); + if (in_array($val_to_check, $keys)) { + return $val_to_check; + } + return reset($keys); //Return he first element from the valid values + } + +} diff --git a/classes/class.miscUtils.php b/classes/class.miscUtils.php new file mode 100644 index 0000000..de16ab7 --- /dev/null +++ b/classes/class.miscUtils.php @@ -0,0 +1,167 @@ +This page and the content has been automatically generated for you to give you a basic idea of how a "Join Us" page should look like. You can customize this page however you like it by editing this page from your WordPress page editor.

'; + $swpm_join_page_content .= '

If you end up changing the URL of this page then make sure to update the URL value in the settings menu of the plugin.

'; + $swpm_join_page_content .= '

+ Free Membership +
+ You get unlimited access to free membership content +
+ Price: Free! +

Link the following image to go to the Registration Page if you want your visitors to be able to create a free membership account

+ Join Now Button +

'; + $swpm_join_page_content .= '

You can register for a Free Membership or pay for one of the following membership options

'; + $swpm_join_page_content .= '

+ [ ==> Insert Payment Button For Your Paid Membership Levels Here <== ] +

'; + + $swpm_join_page = array( + 'post_title' => 'Join Us', + 'post_name' => 'membership-join', + 'post_content' => $swpm_join_page_content, + 'post_parent' => 0, + 'post_status' => 'publish', + 'post_type' => 'page', + 'comment_status' => 'closed', + 'ping_status' => 'closed' + ); + + $join_page_obj = get_page_by_path('membership-join'); + if (!$join_page_obj) { + $join_page_id = wp_insert_post($swpm_join_page); + } else { + $join_page_id = $join_page_obj->ID; + if ($join_page_obj->post_status == 'trash') { //For cases where page may be in trash, bring it out of trash + wp_update_post(array('ID' => $join_page_obj->ID, 'post_status' => 'publish')); + } + } + $swpm_join_page_permalink = get_permalink($join_page_id); + $settings->set_value('join-us-page-url', $swpm_join_page_permalink); + + //Create registration page + $swpm_rego_page = array( + 'post_title' => BUtils::_('Registration'), + 'post_name' => 'membership-registration', + 'post_content' => '[swpm_registration_form]', + 'post_parent' => $join_page_id, + 'post_status' => 'publish', + 'post_type' => 'page', + 'comment_status' => 'closed', + 'ping_status' => 'closed' + ); + $rego_page_obj = get_page_by_path('membership-registration'); + if (!$rego_page_obj) { + $rego_page_id = wp_insert_post($swpm_rego_page); + } else { + $rego_page_id = $rego_page_obj->ID; + if ($rego_page_obj->post_status == 'trash') { //For cases where page may be in trash, bring it out of trash + wp_update_post(array('ID' => $rego_page_obj->ID, 'post_status' => 'publish')); + } + } + $swpm_rego_page_permalink = get_permalink($rego_page_id); + $settings->set_value('registration-page-url', $swpm_rego_page_permalink); + + //Create login page + $swpm_login_page = array( + 'post_title' => BUtils::_('Member Login'), + 'post_name' => 'membership-login', + 'post_content' => '[swpm_login_form]', + 'post_parent' => 0, + 'post_status' => 'publish', + 'post_type' => 'page', + 'comment_status' => 'closed', + 'ping_status' => 'closed' + ); + $login_page_obj = get_page_by_path('membership-login'); + if (!$login_page_obj) { + $login_page_id = wp_insert_post($swpm_login_page); + } else { + $login_page_id = $login_page_obj->ID; + if ($login_page_obj->post_status == 'trash') { //For cases where page may be in trash, bring it out of trash + wp_update_post(array('ID' => $login_page_obj->ID, 'post_status' => 'publish')); + } + } + $swpm_login_page_permalink = get_permalink($login_page_id); + $settings->set_value('login-page-url', $swpm_login_page_permalink); + + //Create profile page + $swpm_profile_page = array( + 'post_title' => BUtils::_('Profile'), + 'post_name' => 'membership-profile', + 'post_content' => '[swpm_profile_form]', + 'post_parent' => $login_page_id, + 'post_status' => 'publish', + 'post_type' => 'page', + 'comment_status' => 'closed', + 'ping_status' => 'closed' + ); + $profile_page_obj = get_page_by_path('membership-profile'); + if (!$profile_page_obj) { + $profile_page_id = wp_insert_post($swpm_profile_page); + } else { + $profile_page_id = $profile_page_obj->ID; + if ($profile_page_obj->post_status == 'trash') { //For cases where page may be in trash, bring it out of trash + wp_update_post(array('ID' => $profile_page_obj->ID, 'post_status' => 'publish')); + } + } + $swpm_profile_page_permalink = get_permalink($profile_page_id); + $settings->set_value('profile-page-url', $swpm_profile_page_permalink); + + //Create reset page + $swpm_reset_page = array( + 'post_title' => BUtils::_('Password Reset'), + 'post_name' => 'password-reset', + 'post_content' => '[swpm_reset_form]', + 'post_parent' => $login_page_id, + 'post_status' => 'publish', + 'post_type' => 'page', + 'comment_status' => 'closed', + 'ping_status' => 'closed' + ); + $reset_page_obj = get_page_by_path('password-reset'); + if (!$profile_page_obj) { + $reset_page_id = wp_insert_post($swpm_reset_page); + } else { + $reset_page_id = $reset_page_obj->ID; + if ($reset_page_obj->post_status == 'trash') { //For cases where page may be in trash, bring it out of trash + wp_update_post(array('ID' => $reset_page_obj->ID, 'post_status' => 'publish')); + } + } + $swpm_reset_page_permalink = get_permalink($reset_page_id); + $settings->set_value('reset-page-url', $swpm_reset_page_permalink); + + $settings->save(); //Save all settings object changes + } + + public static function reset_swmp_log_files() { + $log_reset = true; + $logfile_list = array( + SIMPLE_WP_MEMBERSHIP_PATH.'/log.txt', + ); + + foreach ($logfile_list as $logfile) { + if (empty($logfile)) { + continue; + } + + $text = '[' . date('m/d/Y g:i A') . '] - SUCCESS : Log file reset'; + $text .= "\n------------------------------------------------------------------\n\n"; + $fp = fopen($logfile, 'w'); + if ($fp != FALSE) { + @fwrite($fp, $text); + @fclose($fp); + } else { + $log_reset = false; + } + } + return $log_reset; + } + +} \ No newline at end of file diff --git a/classes/class.simple-wp-membership.php b/classes/class.simple-wp-membership.php new file mode 100644 index 0000000..879c887 --- /dev/null +++ b/classes/class.simple-wp-membership.php @@ -0,0 +1,687 @@ +user_login); + if (!empty($swpm_id)){ + $password_hash = BUtils::encrypt_password($pass); + global $wpdb; + $wpdb->update($wpdb->prefix . "swpm_members_tbl", array('password' => $password_hash), array('member_id' => $swpm_id)); + } + } + + public function save_attachment_extra($post, $attachment) { + $this->save_postdata($post['ID']); + return $post; + } + public function filter_attachment($content, $post_id){ + if(is_admin()){//No need to filter on the admin side + return $content; + } + + $acl = BAccessControl::get_instance(); + if (has_post_thumbnail($post_id)){ return $content;} + if ($acl->can_i_read_post($post_id)) {return $content;} + + + if (isset($content['file'])){ + $content['file'] = 'restricted-icon.png'; + $content['width'] = '400'; + $content['height'] = '400'; + } + + if (isset($content['sizes'])){ + if ($content['sizes']['thumbnail']){ + $content['sizes']['thumbnail']['file'] = 'restricted-icon.png'; + $content['sizes']['thumbnail']['mime-type'] = 'image/png'; + } + if ($content['sizes']['medium']){ + $content['sizes']['medium']['file'] = 'restricted-icon.png'; + $content['sizes']['medium']['mime-type'] = 'image/png'; + } + if ($content['sizes']['post-thumbnail']){ + $content['sizes']['post-thumbnail']['file'] = 'restricted-icon.png'; + $content['sizes']['post-thumbnail']['mime-type'] = 'image/png'; + } + } + return $content; + } + + public function filter_attachment_url($content, $post_id){ + if(is_admin()){//No need to filter on the admin side + return $content; + } + $acl = BAccessControl::get_instance(); + if (has_post_thumbnail($post_id)){return $content;} + + if ($acl->can_i_read_post($post_id)){return $content;} + + return BUtils::get_restricted_image_url(); + } + + public function admin_init_hook(){ + BSettings::get_instance()->init_config_hooks(); + $addon_saved = filter_input(INPUT_POST, 'swpm-addon-settings'); + if(!empty($addon_saved)){ + do_action('swpm_addon_settings_save'); + } + } + + public function hide_adminbar(){ + if (!is_user_logged_in()){//Never show admin bar if the user is not even logged in + return false; + } + $hide = BSettings::get_instance()->get_value('hide-adminbar'); + return $hide? FALSE: TRUE; + } + public function shutdown(){ + BLog::writeall(); + } + public static function swpm_login($user, $pass, $rememberme = true) { + if (is_user_logged_in()) { + $current_user = wp_get_current_user(); + if ($current_user->user_login == $user){ + return; + } + } + $user = wp_signon(array('user_login' => $user, 'user_password' => $pass, 'remember' => $rememberme), is_ssl()); + if ( is_a( $user, 'WP_User' ) ) { + wp_set_current_user( $user->ID, $user->user_login ); + } + do_action('swpm_after_login'); + if (!BUtils::is_ajax()) { + wp_redirect(site_url()); + } + } + + public function swpm_logout() { + if (is_user_logged_in()) { + wp_logout(); + wp_set_current_user(0); + } + } + + public function wp_login($username, $password) { + $auth = BAuth::get_instance(); + if (($auth->is_logged_in() &&($auth->userData->user_name == $username))) { + return; + } + if(!empty($username)) {$auth->login($username, $password, true);} + } + + public function wp_logout() { + $auth = BAuth::get_instance(); + if ($auth->is_logged_in()){ + $auth->logout(); + } + } + + public function sync_with_wp_profile($wp_user_id) { + global $wpdb; + $wp_user_data = get_userdata($wp_user_id); + $query = $wpdb->prepare("SELECT * FROM " . $wpdb->prefix . "swpm_members_tbl WHERE " . ' user_name=%s', $wp_user_data->user_login); + $profile = $wpdb->get_row($query, ARRAY_A); + $profile = (array) $profile; + if (empty($profile)){ + return; + } + $profile['user_name'] = $wp_user_data->user_login; + $profile['email'] = $wp_user_data->user_email; + $profile['password'] = $wp_user_data->user_pass; + $profile['first_name'] = $wp_user_data->user_firstname; + $profile['last_name'] = $wp_user_data->user_lastname; + $wpdb->update($wpdb->prefix . "swpm_members_tbl", $profile, array('member_id' => $profile['member_id'])); + } + + public function login() { + ob_start(); + $auth = BAuth::get_instance(); + if ($auth->is_logged_in()){ + include(SIMPLE_WP_MEMBERSHIP_PATH . 'views/loggedin.php'); + } + else { + $setting = BSettings::get_instance(); + $password_reset_url = $setting->get_value('reset-page-url'); + $join_url = $setting->get_value('join-us-page-url'); + + include(SIMPLE_WP_MEMBERSHIP_PATH . 'views/login.php'); + + } + return ob_get_clean(); + } + + public function reset() { + $succeeded = $this->notices(); + if($succeeded){ + return ''; + } + ob_start(); + include(SIMPLE_WP_MEMBERSHIP_PATH . 'views/forgot_password.php'); + return ob_get_clean(); + } + public function profile_form() { + $auth = BAuth::get_instance(); + $this->notices(); + if ($auth->is_logged_in()) { + $out = apply_filters('swpm_profile_form_override', ''); + if (!empty($out)){return $out;} + $user_data = (array) $auth->userData; + $user_data['membership_level_alias'] = $auth->get('alias'); + ob_start(); + extract($user_data, EXTR_SKIP); + include(SIMPLE_WP_MEMBERSHIP_PATH . 'views/edit.php'); + return ob_get_clean(); + } + return BUtils::_( 'You are not logged in.'); + } + + public function notices() { + $message = BTransfer::get_instance()->get('status'); + $succeeded = false; + if (empty($message)) { return false;} + if ($message['succeeded']) { + echo "
"; + $succeeded = true; + } else{ + echo "
"; + } + echo $message['message']; + $extra = isset($message['extra']) ? $message['extra'] : array(); + if (is_string($extra)){ + echo $extra; + } + else if (is_array($extra)) { + echo '
    '; + foreach ($extra as $key => $value){ + echo '
  • ' . $value . '
  • '; + } + echo '
'; + } + echo "
"; + return $succeeded; + } + + public function meta_box() { + if (function_exists('add_meta_box')) { + $post_types = get_post_types(); + foreach ($post_types as $post_type => $post_type){ + add_meta_box('swpm_sectionid', + __('Simple WP Membership Protection', 'swpm'), + array(&$this, 'inner_custom_box'), $post_type, 'advanced'); + } + } else {//older version doesn't have custom post type so modification isn't needed. + add_action('dbx_post_advanced', array(&$this, 'show_old_custom_box')); + add_action('dbx_page_advanced', array(&$this, 'show_old_custom_box')); + } + } + + public function show_old_custom_box() { + echo '
' . "\n"; + echo '
' . "\n"; + echo '

' . + __('Simple Membership Protection options', 'swpm') . "

"; + echo '
'; + // output editing form + $this->inner_custom_box(); + // end wrapper + echo "
\n"; + } + + public function inner_custom_box() { + global $post, $wpdb; + $id = $post->ID; + // Use nonce for verification + $is_protected = BProtection::get_instance()->is_protected($id); + echo ''; + // The actual fields for data entry + echo '

' . __("Do you want to protect this content?", 'swpm') . '

'; + echo ' No, Do not protect this content.
'; + echo ' Yes, Protect this content.
'; + echo '

' . __("Select the membership level that can access this content:", 'swpm') . "

"; + $query = "SELECT * FROM " . $wpdb->prefix . "swpm_membership_tbl WHERE id !=1 "; + $levels = $wpdb->get_results($query, ARRAY_A); + foreach ($levels as $level) { + echo 'is_permitted($id) ? "checked='checked'" : "") . + ' name="swpm_protection_level[' . $level['id'] . ']" value="' . $level['id'] . '" /> ' . $level['alias'] . "
"; + } + } + + public function save_postdata($post_id) { + global $wpdb; + $post_type = filter_input(INPUT_POST,'post_type'); + $swpm_protect_post = filter_input(INPUT_POST,'swpm_protect_post'); + $swpm_noncename = filter_input(INPUT_POST, 'swpm_noncename'); + if (wp_is_post_revision($post_id)){ + return; + } + if (!wp_verify_nonce($swpm_noncename, plugin_basename(__FILE__))){ + return $post_id; + } + if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE){ + return $post_id; + } + if ('page' == $post_type ) { + if (!current_user_can('edit_page', $post_id)){ + return $post_id; + } + } else { + if (!current_user_can('edit_post', $post_id)){ + return $post_id; + } + } + if (empty($swpm_protect_post)){ + return; + } + // OK, we're authenticated: we need to find and save the data + $isprotected = ($swpm_protect_post == 2); + $args = array('swpm_protection_level'=>array( + 'filter' => FILTER_VALIDATE_INT, + 'flags' => FILTER_REQUIRE_ARRAY, + )); + $swpm_protection_level = filter_input_array(INPUT_POST, $args); + $swpm_protection_level = $swpm_protection_level['swpm_protection_level']; + if (!empty($post_type)) { + if($isprotected){ + BProtection::get_instance()->apply(array($post_id),$post_type); + } + else{ + BProtection::get_instance()->remove(array($post_id),$post_type); + } + BProtection::get_instance()->save(); + $query = "SELECT id FROM " . $wpdb->prefix . "swpm_membership_tbl WHERE id !=1 "; + $level_ids = $wpdb->get_col($query); + foreach ($level_ids as $level){ + if(isset($swpm_protection_level[$level])){ + BPermission::get_instance($level)->apply(array($post_id), $post_type)->save(); + } + else{ + BPermission::get_instance($level)->remove(array($post_id), $post_type)->save(); + } + } + } + $enable_protection = array(); + $enable_protection['protect'] = $swpm_protect_post; + $enable_protection['level'] = $swpm_protection_level; + return $enable_protection; + } + + public function filter_comment($content) { + $acl = BAccessControl::get_instance(); + global $comment; + return $acl->filter_post($comment->comment_post_ID, $content); + } + + public function filter_content($content) { + if (is_preview()) {return $content;} + $acl = BAccessControl::get_instance(); + global $post; + return $acl->filter_post($post->ID, $content); + } + + public function filter_moretag($more_link, $more_link_text = "More") { + $moretag = BSettings::get_instance()->get_value('enable-moretag'); + if (empty($moretag)) {return $more_link;} + $acl = BAccessControl::get_instance(); + global $post; + return $acl->filter_post_with_moretag($post->ID, $more_link, $more_link_text); + } + + public function admin_init() { + $createswpmuser = filter_input(INPUT_POST, 'createswpmuser'); + if (!empty($createswpmuser)) { + BAdminRegistration::get_instance()->register(); + } + $editswpmuser = filter_input(INPUT_POST, 'editswpmuser'); + if (!empty($editswpmuser)) { + $id = filter_input(INPUT_GET, 'member_id', FILTER_VALIDATE_INT); + BAdminRegistration::get_instance()->edit($id); + } + $createswpmlevel = filter_input(INPUT_POST, 'createswpmlevel'); + if (!empty($createswpmlevel)) { + BMembershipLevel::get_instance()->create(); + } + $editswpmlevel = filter_input(INPUT_POST, 'editswpmlevel'); + if (!empty($editswpmlevel)) { + $id = filter_input(INPUT_GET, 'id'); + BMembershipLevel::get_instance()->edit($id); + } + } + + public function init() { + + //Set up localisation. First loaded ones will override strings present in later loaded file. + //Allows users to have a customized language in a different folder. + $locale = apply_filters( 'plugin_locale', get_locale(), 'swpm' ); + load_textdomain( 'swpm', WP_LANG_DIR . "/swpm-$locale.mo" ); + load_plugin_textdomain('swpm', false, SIMPLE_WP_MEMBERSHIP_DIRNAME. '/languages/'); + + if (!isset($_COOKIE['swpm_session'])) { // give a unique ID to current session. + $uid = md5(microtime()); + $_COOKIE['swpm_session'] = $uid; // fake it for current session/ + setcookie('swpm_session', $uid, 0, '/'); + } + + if(current_user_can('edit_pages')){ // admin stuff + $this->admin_init(); + } + if (!is_admin()){ //frontend stuff + BAuth::get_instance(); + $this->verify_and_delete_account(); + $swpm_logout = filter_input(INPUT_GET, 'swpm-logout'); + if (!empty($swpm_logout)) { + BAuth::get_instance()->logout(); + wp_redirect(home_url()); + } + $this->process_password_reset(); + $this->register_member(); + $this->edit_profile(); + } + $this->swpm_ipn_listener(); + } + + public function swpm_ipn_listener() { + $swpm_process_ipn = filter_input(INPUT_GET, 'swpm_process_ipn'); + if ($swpm_process_ipn == '1') { + include(SIMPLE_WP_MEMBERSHIP_PATH.'ipn/swpm_handle_pp_ipn.php'); + exit; + } + } + + public function process_password_reset() { + $message = ""; + $swpm_reset = filter_input(INPUT_POST, 'swpm-reset'); + $swpm_reset_email = filter_input(INPUT_POST, 'swpm_reset_email', FILTER_UNSAFE_RAW); + if (!empty($swpm_reset)) { + BFrontRegistration::get_instance()->reset_password($swpm_reset_email); + } + } + + private function edit_profile() { + $swpm_editprofile_submit = filter_input(INPUT_POST, 'swpm_editprofile_submit'); + if (!empty($swpm_editprofile_submit)) { + BFrontRegistration::get_instance()->edit(); + //todo: do a redirect + } + } + + public function admin_library() { + $this->common_library(); + wp_enqueue_script('password-strength-meter'); + wp_enqueue_script('swpm.password-meter', SIMPLE_WP_MEMBERSHIP_URL . '/js/swpm.password-meter.js'); + wp_enqueue_style('jquery.tools.dateinput', SIMPLE_WP_MEMBERSHIP_URL . '/css/jquery.tools.dateinput.css'); + wp_enqueue_script('jquery.tools', SIMPLE_WP_MEMBERSHIP_URL . '/js/jquery.tools18.min.js'); + $settings = array('statusChangeEmailHead'=> BSettings::get_instance()->get_value('account-change-email-subject'), + 'statusChangeEmailBody'=> BSettings::get_instance()->get_value('account-change-email-body')); + wp_localize_script( 'swpm.password-meter', 'SwpmSettings', $settings ); + } + + public function front_library() { + $this->common_library(); + } + + private function common_library() { + wp_enqueue_script('jquery'); + wp_enqueue_style('swpm.common', SIMPLE_WP_MEMBERSHIP_URL . '/css/swpm.common.css'); + wp_enqueue_style('validationEngine.jquery', SIMPLE_WP_MEMBERSHIP_URL . '/css/validationEngine.jquery.css'); + wp_enqueue_script('jquery.validationEngine-en', SIMPLE_WP_MEMBERSHIP_URL . '/js/jquery.validationEngine-en.js'); + wp_enqueue_script('jquery.validationEngine', SIMPLE_WP_MEMBERSHIP_URL . '/js/jquery.validationEngine.js'); + } + + public function registration_form($atts) { + $succeeded = $this->notices(); + if($succeeded){ + return; + } + $is_free = BSettings::get_instance()->get_value('enable-free-membership'); + $free_level = absint(BSettings::get_instance()->get_value('free-membership-id')); + $level = isset($atts['level'])? absint($atts['level']): ($is_free? $free_level: null); + return BFrontRegistration::get_instance()->regigstration_ui($level); + } + + private function register_member() { + $registration = filter_input(INPUT_POST, 'swpm_registration_submit'); + if (!empty($registration)) { + BFrontRegistration::get_instance()->register(); + } + } + + public function menu() { + $menu_parent_slug = 'simple_wp_membership'; + + add_menu_page(__("WP Membership", 'swpm'), __("WP Membership", 'swpm') + , 'edit_pages', $menu_parent_slug, array(&$this, "admin_members") + , SIMPLE_WP_MEMBERSHIP_URL . '/images/logo.png'); + add_submenu_page($menu_parent_slug, __("Members", 'swpm'), __('Members', 'swpm'), + 'edit_pages', 'simple_wp_membership', array(&$this, "admin_members")); + add_submenu_page($menu_parent_slug, __("Membership Levels", 'swpm'), __("Membership Levels", 'swpm'), + 'manage_options', 'simple_wp_membership_levels', array(&$this, "admin_membership_levels")); + add_submenu_page($menu_parent_slug, __("Settings", 'swpm'), __("Settings", 'swpm'), + 'manage_options', 'simple_wp_membership_settings', array(&$this, "admin_settings")); + add_submenu_page($menu_parent_slug, __("Payments", 'swpm'), __("Payments", 'swpm'), + 'manage_options', 'simple_wp_membership_payments', array(&$this, "payments_menu")); + add_submenu_page($menu_parent_slug, __("Add-ons", 'swpm'), __("Add-ons", 'swpm'), + 'manage_options', 'simple_wp_membership_addons', array(&$this, "add_ons_menu")); + + do_action('swpm_after_main_admin_menu', $menu_parent_slug); + + $this->meta_box(); + } + + public function admin_membership_levels() { + include_once(SIMPLE_WP_MEMBERSHIP_PATH . 'classes/class.bMembershipLevels.php'); + $levels = new BMembershipLevels(); + $level_action = filter_input(INPUT_GET, 'level_action'); + $action2 = filter_input(INPUT_GET, 'action2'); + $action = $level_action ? $level_action : ($action2 ? $action2 : ""); + switch ($action) { + case 'add': + case 'edit': + $levels->process_form_request(); + break; + case 'manage': + $levels->manage(); + break; + case 'category_list': + $levels->manage_categroy(); + break; + case 'delete': + case 'bulk_delete': + $levels->delete(); + default: + $levels->show(); + break; + } + } + + public function admin_members() { + include_once(SIMPLE_WP_MEMBERSHIP_PATH . 'classes/class.bMembers.php'); + $members = new BMembers(); + $action = filter_input(INPUT_GET, 'member_action'); + $action = empty($action)? filter_input(INPUT_POST, 'action') : $action; + switch ($action) { + case 'add': + case 'edit': + $members->process_form_request(); + break; + case 'delete': + case 'bulk_delete': + $members->delete(); + default: + $members->show(); + break; + } + } + + public function admin_settings() { + $current_tab = BSettings::get_instance()->current_tab; + switch ($current_tab) { + case 6: + include(SIMPLE_WP_MEMBERSHIP_PATH . 'views/admin_addon_settings.php'); + break; + case 4: + $link_for = filter_input(INPUT_POST, 'swpm_link_for',FILTER_SANITIZE_STRING); + $member_id = filter_input(INPUT_POST, 'member_id',FILTER_SANITIZE_NUMBER_INT); + $send_email = filter_input(INPUT_POST, 'swpm_reminder_email',FILTER_SANITIZE_NUMBER_INT); + $links = BUtils::get_registration_link($link_for, $send_email, $member_id); + include(SIMPLE_WP_MEMBERSHIP_PATH . 'views/admin_tools_settings.php'); + break; + case 2: + include(SIMPLE_WP_MEMBERSHIP_PATH . 'views/admin_payment_settings.php'); + break; + default: + include(SIMPLE_WP_MEMBERSHIP_PATH . 'views/admin_settings.php'); + break; + } + } + + public function payments_menu(){ + include(SIMPLE_WP_MEMBERSHIP_PATH . 'views/admin_payments_page.php'); + } + + public function add_ons_menu(){ + include(SIMPLE_WP_MEMBERSHIP_PATH . 'views/admin_add_ons_page.php'); + } + + public function plugins_loaded(){ + //Runs when plugins_loaded action gets fired + if(is_admin()){ + //Check and run DB upgrade operation (if needed) + if (get_option('swpm_db_version') != SIMPLE_WP_MEMBERSHIP_DB_VER) { + include_once('class.bInstallation.php'); + BInstallation::run_safe_installer(); + } + } + } + + public static function activate() { + wp_schedule_event(time(), 'daily', 'swpm_account_status_event'); + wp_schedule_event(time(), 'daily', 'swpm_delete_pending_account_event'); + include_once('class.bInstallation.php'); + BInstallation::run_safe_installer(); + } + + public function deactivate() { + wp_clear_scheduled_hook('swpm_account_status_event'); + wp_clear_scheduled_hook('swpm_delete_pending_account_event'); + } + private function verify_and_delete_account(){ + include_once(SIMPLE_WP_MEMBERSHIP_PATH . 'classes/class.bMembers.php'); + $delete_account = filter_input(INPUT_GET, 'delete_account'); + if (empty($delete_account)) {return; } + $password = filter_input(INPUT_POST, 'account_delete_confirm_pass',FILTER_UNSAFE_RAW); + + $auth = BAuth::get_instance(); + if (!$auth->is_logged_in()){return;} + if (empty($password)){ + BUtils::account_delete_confirmation_ui(); + } + + $nonce_field = filter_input(INPUT_POST, 'account_delete_confirm_nonce'); + if (empty($nonce_field) || !wp_verify_nonce($nonce_field, 'swpm_account_delete_confirm')){ + BUtils::account_delete_confirmation_ui(BUtils::_("Sorry, Nonce verification failed.")); + } + if ($auth->match_password($password)){ + $auth->delete(); + wp_redirect(home_url()); + } + else{ + BUtils::account_delete_confirmation_ui(BUtils::_("Sorry, Password didn't match.")); + } + } + + public function list_members() { + + $currentThemeDirectory = get_template_directory(); + if (file_exists($currentThemeDirectory.'/simple-wp-membership/methods.php')) { + + $auth = BAuth::get_instance(); + $this->notices(); + if ($auth->is_logged_in()) { + + ob_start(); + + if ($themeExtDir !== false) { + include_once($currentThemeDirectory.'/simple-wp-membership/methods.php'); + } + + return ob_get_clean(); + } + return BUtils::_( 'You are not logged in.'); + } + } + + + + +} diff --git a/classes/index.html b/classes/index.html new file mode 100644 index 0000000..e69de29 diff --git a/css/index.html b/css/index.html new file mode 100644 index 0000000..e69de29 diff --git a/css/jquery.tools.dateinput.css b/css/jquery.tools.dateinput.css new file mode 100644 index 0000000..49a0e27 --- /dev/null +++ b/css/jquery.tools.dateinput.css @@ -0,0 +1,159 @@ +/* get rid of those system borders being generated for A tags */ +a:active { + outline:none; +} + +:focus { + -moz-outline-style:none; +} +/* For the details, see: http://flowplayer.org/tools/dateinput/index.html#skinning */ + +/* the input field */ +.date { + border:1px solid #ccc; + font-size:13px; + padding:4px; + text-align:center; + width:178px; + + -moz-box-shadow:0 0 10px #eee inset; + -webkit-box-shadow:0 0 10px #eee inset; +} + +/* calendar root element */ +#calroot { + /* place on top of other elements. set a higher value if nessessary */ + z-index:10000; + + margin-top:-1px; + width:198px; + padding:2px; + background-color:#fff; + font-size:11px; + border:1px solid #ccc; + + -moz-border-radius:5px; + -webkit-border-radius:5px; + + -moz-box-shadow: 0 0 15px #666; + -webkit-box-shadow: 0 0 15px #666; +} + +/* head. contains title, prev/next month controls and possible month/year selectors */ +#calhead { + padding:2px 0; + height:22px; +} + +#caltitle { + font-size:14px; + color:#0150D1; + float:left; + text-align:center; + width:155px; + line-height:20px; + text-shadow:0 1px 0 #ddd; +} + +#calnext, #calprev { + display:block; + width:20px; + height:20px; + background:transparent url(../images/prev.gif) no-repeat scroll center center; + float:left; + cursor:pointer; +} + +#calnext { + background-image:url(../images/next.gif); + float:right; +} + +#calprev.caldisabled, #calnext.caldisabled { + visibility:hidden; +} + +/* year/month selector */ +#caltitle select { + font-size:10px; +} + +/* names of the days */ +#caldays { + height:14px; + border-bottom:1px solid #ddd; +} + +#caldays span { + display:block; + float:left; + width:28px; + text-align:center; +} + +/* container for weeks */ +#calweeks { + background-color:#fff; + margin-top:4px; +} + +/* single week */ +.calweek { + clear:left; + height:22px; +} + +/* single day */ +.calweek a { + display:block; + float:left; + width:27px; + height:20px; + text-decoration:none; + font-size:11px; + margin-left:1px; + text-align:center; + line-height:20px; + color:#666; + -moz-border-radius:3px; + -webkit-border-radius:3px; +} + +/* different states */ +.calweek a:hover, .calfocus { + background-color:#ddd; +} + +/* sunday */ +a.calsun { + color:red; +} + +/* offmonth day */ +a.caloff { + color:#ccc; +} + +a.caloff:hover { + background-color:rgb(245, 245, 250); +} + + +/* unselecteble day */ +a.caldisabled { + background-color:#efefef !important; + color:#ccc !important; + cursor:default; +} + +/* current day */ +#calcurrent { + background-color:#498CE2; + color:#fff; +} + +/* today */ +#caltoday { + background-color:#333; + color:#fff; +} diff --git a/css/swpm.addons.listing.css b/css/swpm.addons.listing.css new file mode 100644 index 0000000..04d84f2 --- /dev/null +++ b/css/swpm.addons.listing.css @@ -0,0 +1,34 @@ +.swpm_addon_item_canvas{ + background-color:#fff; + font-family:sans-serif,arial; + font-size:12px; + border:1px solid #ccc; + display:block; + float:left; + margin:3px 12px 12px 0; + padding:10px 0px 10px 10px; + position:relative; + width:222px; + height:340px; +} +.swpm_addon_item_canvas:hover{border-color:#999;} +.swpm_addon_item_thumb img {height: 150px; width: 200px; padding: 5px; border: 1px solid #ccc;} +.swpm_addon_item_thumb a img {border: 1px solid #ccc;} +.swpm_addon_item_body{line-height:22px;height:170px;overflow:hidden;} +.swpm_addon_item_name{font-size:16px;font-weight:bold;text-align: center;margin:10px 10px 10px 0px;} +.swpm_addon_item_description{margin:10px 10px 5px 0px;text-align:justify;overflow:hidden;height:70px;} +.swpm_addon_clear{clear:both;} +.swpm_addon_item_details_link{ + text-align: center; +} +.swpm_addon_item_details_link a{ + border: 3px solid #2d3140; + color: #2d3140; + display: inline-block; + padding: 5px 15px; + text-decoration: none !important; +} +.swpm_addon_item_details_link a:hover{ + background-color: #2d3140; + color: #FFF; +} diff --git a/css/swpm.common.css b/css/swpm.common.css new file mode 100644 index 0000000..eb33179 --- /dev/null +++ b/css/swpm.common.css @@ -0,0 +1,101 @@ +/* General CSS */ +.swpm-margin-10{ + margin: 10px; +} +.swpm-margin-top-10{ + margin-top: 10px; +} +.swpm-margin-bottom-10{ + margin-bottom: 10px; +} + +.swpm-yellow-box{ + margin: 10px 0 15px; + padding: 10px; + background-color: #FFFFE0; + border-color: #E6DB55; + border-radius: 3px 3px 3px 3px; + border-style: solid; + border-width: 1px; +} + +.swpm-grey-box{ + margin: 10px 0 15px; + padding: 10px; + background-color: #DDDDDD; + border-color: #CCCCCC; + border-radius: 3px 3px 3px 3px; + border-style: solid; + border-width: 1px; +} +.swpm-green-box { + margin: 10px 0 15px; + padding: 10px; + background-color: #CCF4D6; + border-color: #059B53; + color: #043B14; + border-radius: 3px 3px 3px 3px; + border-style: solid; + border-width: 1px; +} + +.swpm-red-box { + margin: 10px 0 15px; + padding: 10px; + background-color: #FFEBE8; + border-color: #CC0000; + color: #333333; + border-radius: 3px 3px 3px 3px; + border-style: solid; + border-width: 1px; +} + +/* Login form CSS */ +.swpm-login-widget-form input,.swpm-login-widget-form checkbox{ + width: auto; +} +.swpm-username-input, .swpm-password-input{ + margin-bottom: 10px; +} +.swpm-login-submit{ + margin-bottom: 10px; +} +.swpm-login-widget-action-msg{ + font-weight: bold; +} +.swpm-logged-label{ + font-weight: bold; +} + +/* Password reset form CSS */ +.swpm-password-reset-widget-form table{ + border: none; +} +swpm-password-reset-widget-form tr{ + border: none; +} +.swpm-password-reset-widget-form td{ + border: none; +} + +/* Registration form CSS */ +.swpm-registration-widget-form td{ + min-width: 100px; +} + +.swpm-restricted{ + font-weight: bold; + color:red; +} +.swpm-select-box-left{ + margin: 0; + padding-bottom: 5px; +} + +/* Edit profile form CSS */ +.swpm-account-delete-button{ + text-align: center; +} +.swpm-account-delete-button a{ + color: red !important; +} \ No newline at end of file diff --git a/css/validationEngine.jquery.css b/css/validationEngine.jquery.css new file mode 100644 index 0000000..51a3e4b --- /dev/null +++ b/css/validationEngine.jquery.css @@ -0,0 +1,143 @@ +.inputContainer { + position: relative; + float: left; +} + +.formError { + position: absolute; + top: 300px; + left: 300px; + display: block; + z-index: 5000; + cursor: pointer; +} + +.ajaxSubmit { + padding: 20px; + background: #55ea55; + border: 1px solid #999; + display: none +} + +.formError .formErrorContent { + width: 100%; + background: #ee0101; + position:relative; + z-index:5001; + color: #fff; + font-weight: bolder; + width: 150px; + font-family: tahoma; + font-size: 11px; + border: 2px solid #ddd; + box-shadow: 0 0 6px #000; + -moz-box-shadow: 0 0 6px #000; + -webkit-box-shadow: 0 0 6px #000; + padding: 4px 10px 4px 10px; + border-radius: 6px; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; +} + +.greenPopup .formErrorContent { + background: #33be40; +} + +.blackPopup .formErrorContent { + background: #393939; + color: #FFF; +} + +.formError .formErrorArrow { + width: 15px; + margin: -2px 0 0 13px; + position:relative; + z-index: 5006; +} + +.formError .formErrorArrowBottom { + box-shadow: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + margin: 0px 0 0 12px; + top:2px; +} + +.formError .formErrorArrow div { + border-left: 2px solid #ddd; + border-right: 2px solid #ddd; + box-shadow: 0 2px 3px #444; + -moz-box-shadow: 0 2px 3px #444; + -webkit-box-shadow: 0 2px 3px #444; + font-size: 0px; + height: 1px; + background: #ee0101; + margin: 0 auto; + line-height: 0; + font-size: 0; + display: block; +} + +.formError .formErrorArrowBottom div { + box-shadow: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; +} + +.greenPopup .formErrorArrow div { + background: #33be40; +} + +.blackPopup .formErrorArrow div { + background: #393939; + color: #FFF; +} + +.formError .formErrorArrow .line10 { + width: 15px; + border: none; +} + +.formError .formErrorArrow .line9 { + width: 13px; + border: none; +} + +.formError .formErrorArrow .line8 { + width: 11px; +} + +.formError .formErrorArrow .line7 { + width: 9px; +} + +.formError .formErrorArrow .line6 { + width: 7px; +} + +.formError .formErrorArrow .line5 { + width: 5px; +} + +.formError .formErrorArrow .line4 { + width: 3px; +} + +.formError .formErrorArrow .line3 { + width: 1px; + border-left: 2px solid #ddd; + border-right: 2px solid #ddd; + border-bottom: 0 solid #ddd; +} + +.formError .formErrorArrow .line2 { + width: 3px; + border: none; + background: #ddd; +} + +.formError .formErrorArrow .line1 { + width: 1px; + border: none; + background: #ddd; +} \ No newline at end of file diff --git a/images/addons/form-shortcode-generator.png b/images/addons/form-shortcode-generator.png new file mode 100644 index 0000000..086e958 Binary files /dev/null and b/images/addons/form-shortcode-generator.png differ diff --git a/images/addons/mailchimp-integration.png b/images/addons/mailchimp-integration.png new file mode 100644 index 0000000..267278a Binary files /dev/null and b/images/addons/mailchimp-integration.png differ diff --git a/images/addons/swpm-custom-messages.png b/images/addons/swpm-custom-messages.png new file mode 100644 index 0000000..cf2828f Binary files /dev/null and b/images/addons/swpm-custom-messages.png differ diff --git a/images/addons/swpm-form-builder.png b/images/addons/swpm-form-builder.png new file mode 100644 index 0000000..fa28181 Binary files /dev/null and b/images/addons/swpm-form-builder.png differ diff --git a/images/addons/swpm-login-redirection.png b/images/addons/swpm-login-redirection.png new file mode 100644 index 0000000..69b535b Binary files /dev/null and b/images/addons/swpm-login-redirection.png differ diff --git a/images/addons/swpm-older-posts-protection.png b/images/addons/swpm-older-posts-protection.png new file mode 100644 index 0000000..f694467 Binary files /dev/null and b/images/addons/swpm-older-posts-protection.png differ diff --git a/images/addons/wp-user-import.png b/images/addons/wp-user-import.png new file mode 100644 index 0000000..9a78550 Binary files /dev/null and b/images/addons/wp-user-import.png differ diff --git a/images/index.html b/images/index.html new file mode 100644 index 0000000..e69de29 diff --git a/images/join-now-button-image.gif b/images/join-now-button-image.gif new file mode 100644 index 0000000..6ef5bb8 Binary files /dev/null and b/images/join-now-button-image.gif differ diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 0000000..6b3875c Binary files /dev/null and b/images/logo.png differ diff --git a/images/logo2.png b/images/logo2.png new file mode 100644 index 0000000..eb9243d Binary files /dev/null and b/images/logo2.png differ diff --git a/images/next.gif b/images/next.gif new file mode 100644 index 0000000..730fc3e Binary files /dev/null and b/images/next.gif differ diff --git a/images/prev.gif b/images/prev.gif new file mode 100644 index 0000000..7ec2d6c Binary files /dev/null and b/images/prev.gif differ diff --git a/images/restricted-icon.png b/images/restricted-icon.png new file mode 100644 index 0000000..fc0c6d1 Binary files /dev/null and b/images/restricted-icon.png differ diff --git a/images/simple-membership-content-protection-usage.png b/images/simple-membership-content-protection-usage.png new file mode 100644 index 0000000..f1822a2 Binary files /dev/null and b/images/simple-membership-content-protection-usage.png differ diff --git a/includes/class-swpm-list-table.php b/includes/class-swpm-list-table.php new file mode 100644 index 0000000..38a8142 --- /dev/null +++ b/includes/class-swpm-list-table.php @@ -0,0 +1,1138 @@ +get_column_info() + * + * @var array + */ + protected $_column_headers; + + protected $compat_fields = array( '_args', '_pagination_args', 'screen', '_actions', '_pagination' ); + + protected $compat_methods = array( 'set_pagination_args', 'get_views', 'get_bulk_actions', 'bulk_actions', + 'row_actions', 'months_dropdown', 'view_switcher', 'comments_bubble', 'get_items_per_page', 'pagination', + 'get_sortable_columns', 'get_column_info', 'get_table_classes', 'display_tablenav', 'extra_tablenav', + 'single_row_columns' ); + + /** + * Constructor. + * + * The child class should call this constructor from its own constructor to override + * the default $args. + * + * @since 3.1.0 + * @access public + * + * @param array|string $args { + * Array or string of arguments. + * + * @type string $plural Plural value used for labels and the objects being listed. + * This affects things such as CSS class-names and nonces used + * in the list table, e.g. 'posts'. Default empty. + * @type string $singular Singular label for an object being listed, e.g. 'post'. + * Default empty + * @type bool $ajax Whether the list table supports AJAX. This includes loading + * and sorting data, for example. If true, the class will call + * the {@see _js_vars()} method in the footer to provide variables + * to any scripts handling AJAX events. Default false. + * @type string $screen String containing the hook name used to determine the current + * screen. If left null, the current screen will be automatically set. + * Default null. + * } + */ + public function __construct( $args = array() ) { + $args = wp_parse_args( $args, array( + 'plural' => '', + 'singular' => '', + 'ajax' => false, + 'screen' => null, + ) ); + + $this->screen = convert_to_screen( $args['screen'] ); + + add_filter( "manage_{$this->screen->id}_columns", array( $this, 'get_columns' ), 0 ); + + if ( !$args['plural'] ) + $args['plural'] = $this->screen->base; + + $args['plural'] = sanitize_key( $args['plural'] ); + $args['singular'] = sanitize_key( $args['singular'] ); + + $this->_args = $args; + + if ( $args['ajax'] ) { + // wp_enqueue_script( 'list-table' ); + add_action( 'admin_footer', array( $this, '_js_vars' ) ); + } + + if ( empty( $this->modes ) ) { + $this->modes = array( + 'list' => __( 'List View' ), + 'excerpt' => __( 'Excerpt View' ) + ); + } + } + + /** + * Make private properties readable for backwards compatibility. + * + * @since 4.0.0 + * @access public + * + * @param string $name Property to get. + * @return mixed Property. + */ + public function __get( $name ) { + if ( in_array( $name, $this->compat_fields ) ) { + return $this->$name; + } + } + + /** + * Make private properties settable for backwards compatibility. + * + * @since 4.0.0 + * @access public + * + * @param string $name Property to check if set. + * @param mixed $value Property value. + * @return mixed Newly-set property. + */ + public function __set( $name, $value ) { + if ( in_array( $name, $this->compat_fields ) ) { + return $this->$name = $value; + } + } + + /** + * Make private properties checkable for backwards compatibility. + * + * @since 4.0.0 + * @access public + * + * @param string $name Property to check if set. + * @return bool Whether the property is set. + */ + public function __isset( $name ) { + if ( in_array( $name, $this->compat_fields ) ) { + return isset( $this->$name ); + } + } + + /** + * Make private properties un-settable for backwards compatibility. + * + * @since 4.0.0 + * @access public + * + * @param string $name Property to unset. + */ + public function __unset( $name ) { + if ( in_array( $name, $this->compat_fields ) ) { + unset( $this->$name ); + } + } + + /** + * Make private/protected methods readable for backwards compatibility. + * + * @since 4.0.0 + * @access public + * + * @param callable $name Method to call. + * @param array $arguments Arguments to pass when calling. + * @return mixed|bool Return value of the callback, false otherwise. + */ + public function __call( $name, $arguments ) { + if ( in_array( $name, $this->compat_methods ) ) { + return call_user_func_array( array( $this, $name ), $arguments ); + } + return false; + } + + /** + * Checks the current user's permissions + * + * @since 3.1.0 + * @access public + * @abstract + */ + public function ajax_user_can() { + die( 'function WP_List_Table::ajax_user_can() must be over-ridden in a sub-class.' ); + } + + /** + * Prepares the list of items for displaying. + * @uses WP_List_Table::set_pagination_args() + * + * @since 3.1.0 + * @access public + * @abstract + */ + public function prepare_items() { + die( 'function WP_List_Table::prepare_items() must be over-ridden in a sub-class.' ); + } + + /** + * An internal method that sets all the necessary pagination arguments + * + * @param array $args An associative array with information about the pagination + * @access protected + */ + protected function set_pagination_args( $args ) { + $args = wp_parse_args( $args, array( + 'total_items' => 0, + 'total_pages' => 0, + 'per_page' => 0, + ) ); + + if ( !$args['total_pages'] && $args['per_page'] > 0 ) + $args['total_pages'] = ceil( $args['total_items'] / $args['per_page'] ); + + // Redirect if page number is invalid and headers are not already sent. + if ( ! headers_sent() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) && $args['total_pages'] > 0 && $this->get_pagenum() > $args['total_pages'] ) { + wp_redirect( add_query_arg( 'paged', $args['total_pages'] ) ); + exit; + } + + $this->_pagination_args = $args; + } + + /** + * Access the pagination args. + * + * @since 3.1.0 + * @access public + * + * @param string $key Pagination argument to retrieve. Common values include 'total_items', + * 'total_pages', 'per_page', or 'infinite_scroll'. + * @return int Number of items that correspond to the given pagination argument. + */ + public function get_pagination_arg( $key ) { + if ( 'page' == $key ) + return $this->get_pagenum(); + + if ( isset( $this->_pagination_args[$key] ) ) + return $this->_pagination_args[$key]; + } + + /** + * Whether the table has items to display or not + * + * @since 3.1.0 + * @access public + * + * @return bool + */ + public function has_items() { + return !empty( $this->items ); + } + + /** + * Message to be displayed when there are no items + * + * @since 3.1.0 + * @access public + */ + public function no_items() { + _e( 'No items found.' ); + } + + /** + * Display the search box. + * + * @since 3.1.0 + * @access public + * + * @param string $text The search button text + * @param string $input_id The search input id + */ + public function search_box( $text, $input_id ) { + if ( empty( $_REQUEST['s'] ) && !$this->has_items() ) + return; + + $input_id = $input_id . '-search-input'; + + if ( ! empty( $_REQUEST['orderby'] ) ) + echo ''; + if ( ! empty( $_REQUEST['order'] ) ) + echo ''; + if ( ! empty( $_REQUEST['post_mime_type'] ) ) + echo ''; + if ( ! empty( $_REQUEST['detached'] ) ) + echo ''; +?> + + link ) with the list + * of views available on this table. + * + * @since 3.1.0 + * @access protected + * + * @return array + */ + protected function get_views() { + return array(); + } + + /** + * Display the list of views available on this table. + * + * @since 3.1.0 + * @access public + */ + public function views() { + $views = $this->get_views(); + /** + * Filter the list of available list table views. + * + * The dynamic portion of the hook name, `$this->screen->id`, refers + * to the ID of the current screen, usually a string. + * + * @since 3.5.0 + * + * @param array $views An array of available list table views. + */ + $views = apply_filters( "views_{$this->screen->id}", $views ); + + if ( empty( $views ) ) + return; + + echo "
    \n"; + foreach ( $views as $class => $view ) { + $views[ $class ] = "\t
  • $view"; + } + echo implode( " |
  • \n", $views ) . "\n"; + echo "
"; + } + + /** + * Get an associative array ( option_name => option_title ) with the list + * of bulk actions available on this table. + * + * @since 3.1.0 + * @access protected + * + * @return array + */ + protected function get_bulk_actions() { + return array(); + } + + /** + * Display the bulk actions dropdown. + * + * @since 3.1.0 + * @access protected + * + * @param string $which The location of the bulk actions: 'top' or 'bottom'. + * This is designated as optional for backwards-compatibility. + */ + protected function bulk_actions( $which = '' ) { + if ( is_null( $this->_actions ) ) { + $no_new_actions = $this->_actions = $this->get_bulk_actions(); + /** + * Filter the list table Bulk Actions drop-down. + * + * The dynamic portion of the hook name, `$this->screen->id`, refers + * to the ID of the current screen, usually a string. + * + * This filter can currently only be used to remove bulk actions. + * + * @since 3.5.0 + * + * @param array $actions An array of the available bulk actions. + */ + $this->_actions = apply_filters( "bulk_actions-{$this->screen->id}", $this->_actions ); + $this->_actions = array_intersect_assoc( $this->_actions, $no_new_actions ); + $two = ''; + } else { + $two = '2'; + } + + if ( empty( $this->_actions ) ) + return; + + echo ""; + echo "\n"; + + submit_button( __( 'Apply' ), 'action', '', false, array( 'id' => "doaction$two" ) ); + echo "\n"; + } + + /** + * Get the current action selected from the bulk actions dropdown. + * + * @since 3.1.0 + * @access public + * + * @return string|bool The action name or False if no action was selected + */ + public function current_action() { + if ( isset( $_REQUEST['filter_action'] ) && ! empty( $_REQUEST['filter_action'] ) ) + return false; + + if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] ) + return $_REQUEST['action']; + + if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] ) + return $_REQUEST['action2']; + + return false; + } + + /** + * Generate row actions div + * + * @since 3.1.0 + * @access protected + * + * @param array $actions The list of actions + * @param bool $always_visible Whether the actions should be always visible + * @return string + */ + protected function row_actions( $actions, $always_visible = false ) { + $action_count = count( $actions ); + $i = 0; + + if ( !$action_count ) + return ''; + + $out = '
'; + foreach ( $actions as $action => $link ) { + ++$i; + ( $i == $action_count ) ? $sep = '' : $sep = ' | '; + $out .= "$link$sep"; + } + $out .= '
'; + + return $out; + } + + /** + * Display a monthly dropdown for filtering items + * + * @since 3.1.0 + * @access protected + * + * @param string $post_type + */ + protected function months_dropdown( $post_type ) { + global $wpdb, $wp_locale; + + /** + * Filter whether to remove the 'Months' drop-down from the post list table. + * + * @since 4.2.0 + * + * @param bool $disable Whether to disable the drop-down. Default false. + * @param string $post_type The post type. + */ + if ( apply_filters( 'disable_months_dropdown', false, $post_type ) ) { + return; + } + + $months = $wpdb->get_results( $wpdb->prepare( " + SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month + FROM $wpdb->posts + WHERE post_type = %s + ORDER BY post_date DESC + ", $post_type ) ); + + /** + * Filter the 'Months' drop-down results. + * + * @since 3.7.0 + * + * @param object $months The months drop-down query results. + * @param string $post_type The post type. + */ + $months = apply_filters( 'months_dropdown_results', $months, $post_type ); + + $month_count = count( $months ); + + if ( !$month_count || ( 1 == $month_count && 0 == $months[0]->month ) ) + return; + + $m = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0; +?> + + + + +
+modes as $mode => $title ) { + $classes = array( 'view-' . $mode ); + if ( $current_mode == $mode ) + $classes[] = 'current'; + printf( + "%s\n", + esc_url( add_query_arg( 'mode', $mode ) ), + implode( ' ', $classes ), + $title + ); + } + ?> +
+'; + + echo "" . number_format_i18n( get_comments_number() ) . ""; + + if ( $pending_comments ) + echo ''; + } + + /** + * Get the current page number + * + * @since 3.1.0 + * @access public + * + * @return int + */ + public function get_pagenum() { + $pagenum = isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 0; + + if( isset( $this->_pagination_args['total_pages'] ) && $pagenum > $this->_pagination_args['total_pages'] ) + $pagenum = $this->_pagination_args['total_pages']; + + return max( 1, $pagenum ); + } + + /** + * Get number of items to display on a single page + * + * @since 3.1.0 + * @access protected + * + * @param string $option + * @param int $default + * @return int + */ + protected function get_items_per_page( $option, $default = 20 ) { + $per_page = (int) get_user_option( $option ); + if ( empty( $per_page ) || $per_page < 1 ) + $per_page = $default; + + /** + * Filter the number of items to be displayed on each page of the list table. + * + * The dynamic hook name, $option, refers to the `per_page` option depending + * on the type of list table in use. Possible values include: 'edit_comments_per_page', + * 'sites_network_per_page', 'site_themes_network_per_page', 'themes_network_per_page', + * 'users_network_per_page', 'edit_post_per_page', 'edit_page_per_page', + * 'edit_{$post_type}_per_page', etc. + * + * @since 2.9.0 + * + * @param int $per_page Number of items to be displayed. Default 20. + */ + return (int) apply_filters( $option, $per_page ); + } + + /** + * Display the pagination. + * + * @since 3.1.0 + * @access protected + * + * @param string $which + */ + protected function pagination( $which ) { + if ( empty( $this->_pagination_args ) ) { + return; + } + + $total_items = $this->_pagination_args['total_items']; + $total_pages = $this->_pagination_args['total_pages']; + $infinite_scroll = false; + if ( isset( $this->_pagination_args['infinite_scroll'] ) ) { + $infinite_scroll = $this->_pagination_args['infinite_scroll']; + } + + $output = '' . sprintf( _n( '1 item', '%s items', $total_items ), number_format_i18n( $total_items ) ) . ''; + + $current = $this->get_pagenum(); + + $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); + + $current_url = remove_query_arg( array( 'hotkeys_highlight_last', 'hotkeys_highlight_first' ), $current_url ); + + $page_links = array(); + + $disable_first = $disable_last = ''; + if ( $current == 1 ) { + $disable_first = ' disabled'; + } + if ( $current == $total_pages ) { + $disable_last = ' disabled'; + } + $page_links[] = sprintf( "%s", + 'first-page' . $disable_first, + esc_attr__( 'Go to the first page' ), + esc_url( remove_query_arg( 'paged', $current_url ) ), + '«' + ); + + $page_links[] = sprintf( "%s", + 'prev-page' . $disable_first, + esc_attr__( 'Go to the previous page' ), + esc_url( add_query_arg( 'paged', max( 1, $current-1 ), $current_url ) ), + '‹' + ); + + if ( 'bottom' == $which ) { + $html_current_page = $current; + } else { + $html_current_page = sprintf( "%s", + '', + esc_attr__( 'Current page' ), + $current, + strlen( $total_pages ) + ); + } + $html_total_pages = sprintf( "%s", number_format_i18n( $total_pages ) ); + $page_links[] = '' . sprintf( _x( '%1$s of %2$s', 'paging' ), $html_current_page, $html_total_pages ) . ''; + + $page_links[] = sprintf( "%s", + 'next-page' . $disable_last, + esc_attr__( 'Go to the next page' ), + esc_url( add_query_arg( 'paged', min( $total_pages, $current+1 ), $current_url ) ), + '›' + ); + + $page_links[] = sprintf( "%s", + 'last-page' . $disable_last, + esc_attr__( 'Go to the last page' ), + esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ), + '»' + ); + + $pagination_links_class = 'pagination-links'; + if ( ! empty( $infinite_scroll ) ) { + $pagination_links_class = ' hide-if-js'; + } + $output .= "\n" . join( "\n", $page_links ) . ''; + + if ( $total_pages ) { + $page_class = $total_pages < 2 ? ' one-page' : ''; + } else { + $page_class = ' no-pages'; + } + $this->_pagination = "
$output
"; + + echo $this->_pagination; + } + + /** + * Get a list of columns. The format is: + * 'internal-name' => 'Title' + * + * @since 3.1.0 + * @access public + * @abstract + * + * @return array + */ + public function get_columns() { + die( 'function WP_List_Table::get_columns() must be over-ridden in a sub-class.' ); + } + + /** + * Get a list of sortable columns. The format is: + * 'internal-name' => 'orderby' + * or + * 'internal-name' => array( 'orderby', true ) + * + * The second format will make the initial sorting order be descending + * + * @since 3.1.0 + * @access protected + * + * @return array + */ + protected function get_sortable_columns() { + return array(); + } + + /** + * Get a list of all, hidden and sortable columns, with filter applied + * + * @since 3.1.0 + * @access protected + * + * @return array + */ + protected function get_column_info() { + if ( isset( $this->_column_headers ) ) + return $this->_column_headers; + + $columns = get_column_headers( $this->screen ); + $hidden = get_hidden_columns( $this->screen ); + + $sortable_columns = $this->get_sortable_columns(); + /** + * Filter the list table sortable columns for a specific screen. + * + * The dynamic portion of the hook name, `$this->screen->id`, refers + * to the ID of the current screen, usually a string. + * + * @since 3.5.0 + * + * @param array $sortable_columns An array of sortable columns. + */ + $_sortable = apply_filters( "manage_{$this->screen->id}_sortable_columns", $sortable_columns ); + + $sortable = array(); + foreach ( $_sortable as $id => $data ) { + if ( empty( $data ) ) + continue; + + $data = (array) $data; + if ( !isset( $data[1] ) ) + $data[1] = false; + + $sortable[$id] = $data; + } + + $this->_column_headers = array( $columns, $hidden, $sortable ); + + return $this->_column_headers; + } + + /** + * Return number of visible columns + * + * @since 3.1.0 + * @access public + * + * @return int + */ + public function get_column_count() { + list ( $columns, $hidden ) = $this->get_column_info(); + $hidden = array_intersect( array_keys( $columns ), array_filter( $hidden ) ); + return count( $columns ) - count( $hidden ); + } + + /** + * Print column headers, accounting for hidden and sortable columns. + * + * @since 3.1.0 + * @access public + * + * @param bool $with_id Whether to set the id attribute or not + */ + public function print_column_headers( $with_id = true ) { + list( $columns, $hidden, $sortable ) = $this->get_column_info(); + + $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); + $current_url = remove_query_arg( 'paged', $current_url ); + + if ( isset( $_GET['orderby'] ) ) + $current_orderby = $_GET['orderby']; + else + $current_orderby = ''; + + if ( isset( $_GET['order'] ) && 'desc' == $_GET['order'] ) + $current_order = 'desc'; + else + $current_order = 'asc'; + + if ( ! empty( $columns['cb'] ) ) { + static $cb_counter = 1; + $columns['cb'] = '' + . ''; + $cb_counter++; + } + + foreach ( $columns as $column_key => $column_display_name ) { + $class = array( 'manage-column', "column-$column_key" ); + + $style = ''; + if ( in_array( $column_key, $hidden ) ) + $style = 'display:none;'; + + $style = ' style="' . $style . '"'; + + if ( 'cb' == $column_key ) + $class[] = 'check-column'; + elseif ( in_array( $column_key, array( 'posts', 'comments', 'links' ) ) ) + $class[] = 'num'; + + if ( isset( $sortable[$column_key] ) ) { + list( $orderby, $desc_first ) = $sortable[$column_key]; + + if ( $current_orderby == $orderby ) { + $order = 'asc' == $current_order ? 'desc' : 'asc'; + $class[] = 'sorted'; + $class[] = $current_order; + } else { + $order = $desc_first ? 'desc' : 'asc'; + $class[] = 'sortable'; + $class[] = $desc_first ? 'asc' : 'desc'; + } + + $column_display_name = '' . $column_display_name . ''; + } + + $id = $with_id ? "id='$column_key'" : ''; + + if ( !empty( $class ) ) + $class = "class='" . join( ' ', $class ) . "'"; + + echo "$column_display_name"; + } + } + + /** + * Display the table + * + * @since 3.1.0 + * @access public + */ + public function display() { + $singular = $this->_args['singular']; + + $this->display_tablenav( 'top' ); + +?> + + + + print_column_headers(); ?> + + + + > + display_rows_or_placeholder(); ?> + + + + + print_column_headers( false ); ?> + + + +
+display_tablenav( 'bottom' ); + } + + /** + * Get a list of CSS classes for the list table table tag. + * + * @since 3.1.0 + * @access protected + * + * @return array List of CSS classes for the table tag. + */ + protected function get_table_classes() { + return array( 'widefat', 'fixed', 'striped', $this->_args['plural'] ); + } + + /** + * Generate the table navigation above or below the table + * + * @since 3.1.0 + * @access protected + * @param string $which + */ + protected function display_tablenav( $which ) { + if ( 'top' == $which ) + wp_nonce_field( 'bulk-' . $this->_args['plural'] ); +?> +
+ +
+ bulk_actions( $which ); ?> +
+extra_tablenav( $which ); + $this->pagination( $which ); +?> + +
+
+has_items() ) { + $this->display_rows(); + } else { + echo ''; + $this->no_items(); + echo ''; + } + } + + /** + * Generate the table rows + * + * @since 3.1.0 + * @access public + */ + public function display_rows() { + foreach ( $this->items as $item ) + $this->single_row( $item ); + } + + /** + * Generates content for a single row of the table + * + * @since 3.1.0 + * @access public + * + * @param object $item The current item + */ + public function single_row( $item ) { + echo ''; + $this->single_row_columns( $item ); + echo ''; + } + + protected function column_default( $item, $column_name ) {} + + protected function column_cb( $item ) {} + + /** + * Generates the columns for a single row of the table + * + * @since 3.1.0 + * @access protected + * + * @param object $item The current item + */ + protected function single_row_columns( $item ) { + list( $columns, $hidden ) = $this->get_column_info(); + + foreach ( $columns as $column_name => $column_display_name ) { + $class = "class='$column_name column-$column_name'"; + + $style = ''; + if ( in_array( $column_name, $hidden ) ) + $style = ' style="display:none;"'; + + $attributes = "$class$style"; + + if ( 'cb' == $column_name ) { + echo ''; + echo $this->column_cb( $item ); + echo ''; + } + elseif ( method_exists( $this, 'column_' . $column_name ) ) { + echo ""; + echo call_user_func( array( $this, 'column_' . $column_name ), $item ); + echo ""; + } + else { + echo ""; + echo $this->column_default( $item, $column_name ); + echo ""; + } + } + } + + /** + * Handle an incoming ajax request (called from admin-ajax.php) + * + * @since 3.1.0 + * @access public + */ + public function ajax_response() { + $this->prepare_items(); + + ob_start(); + if ( ! empty( $_REQUEST['no_placeholder'] ) ) { + $this->display_rows(); + } else { + $this->display_rows_or_placeholder(); + } + + $rows = ob_get_clean(); + + $response = array( 'rows' => $rows ); + + if ( isset( $this->_pagination_args['total_items'] ) ) { + $response['total_items_i18n'] = sprintf( + _n( '1 item', '%s items', $this->_pagination_args['total_items'] ), + number_format_i18n( $this->_pagination_args['total_items'] ) + ); + } + if ( isset( $this->_pagination_args['total_pages'] ) ) { + $response['total_pages'] = $this->_pagination_args['total_pages']; + $response['total_pages_i18n'] = number_format_i18n( $this->_pagination_args['total_pages'] ); + } + + die( wp_json_encode( $response ) ); + } + + /** + * Send required variables to JavaScript land + * + * @access public + */ + public function _js_vars() { + $args = array( + 'class' => get_class( $this ), + 'screen' => array( + 'id' => $this->screen->id, + 'base' => $this->screen->base, + ) + ); + + printf( "\n", wp_json_encode( $args ) ); + } +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..e69de29 diff --git a/ipn/index.html b/ipn/index.html new file mode 100644 index 0000000..e69de29 diff --git a/ipn/swpm_handle_pp_ipn.php b/ipn/swpm_handle_pp_ipn.php new file mode 100644 index 0000000..b54d73d --- /dev/null +++ b/ipn/swpm_handle_pp_ipn.php @@ -0,0 +1,354 @@ +paypal_url = 'https://www.paypal.com/cgi-bin/webscr'; + $this->last_error = ''; + $this->ipn_log_file = 'ipn_handle_debug_swpm.log'; + $this->ipn_response = ''; + } + + function swpm_validate_and_create_membership() + { + // Check Product Name , Price , Currency , Receivers email , + $error_msg = ""; + + // Read the IPN and validate + $gross_total = $this->ipn_data['mc_gross']; + $transaction_type = $this->ipn_data['txn_type']; + $txn_id = $this->ipn_data['txn_id']; + $payment_status = $this->ipn_data['payment_status']; + + //Check payment status + if (!empty($payment_status)) + { + if ($payment_status == "Denied") { + $this->debug_log("Payment status for this transaction is DENIED. You denied the transaction... most likely a cancellation of an eCheque. Nothing to do here.", false); + return false; + } + if ($payment_status == "Canceled_Reversal") { + $this->debug_log("This is a dispute closed notification in your favour. The plugin will not do anyting.", false); + return true; + } + if ($payment_status != "Completed" && $payment_status != "Processed" && $payment_status != "Refunded" && $payment_status != "Reversed") + { + $error_msg .= 'Funds have not been cleared yet. Transaction will be processed when the funds clear!'; + $this->debug_log($error_msg,false); + return false; + } + } + + //Check txn type + if ($transaction_type == "new_case") { + $this->debug_log('This is a dispute case. Nothing to do here.', true); + return true; + } + + $custom = $this->ipn_data['custom']; + $delimiter = "&"; + $customvariables = array(); + + $namevaluecombos = explode($delimiter, $custom); + foreach ($namevaluecombos as $keyval_unparsed) + { + $equalsignposition = strpos($keyval_unparsed, '='); + if ($equalsignposition === false) + { + $customvariables[$keyval_unparsed] = ''; + continue; + } + $key = substr($keyval_unparsed, 0, $equalsignposition); + $value = substr($keyval_unparsed, $equalsignposition + 1); + $customvariables[$key] = $value; + } + + //Handle refunds + if ($gross_total < 0) + { + // This is a refund or reversal + $this->debug_log('This is a refund notification. Refund amount: '.$gross_total,true); + swpm_handle_subsc_cancel_stand_alone($this->ipn_data,true); + return true; + } + if (isset($this->ipn_data['reason_code']) && $this->ipn_data['reason_code'] == 'refund'){ + $this->debug_log('This is a refund notification. Refund amount: '.$gross_total,true); + swpm_handle_subsc_cancel_stand_alone($this->ipn_data,true); + return true; + } + + if (($transaction_type == "subscr_signup")) + { + $this->debug_log('Subscription signup IPN received... nothing to do here(handled by the subscription IPN handler)',true); + // Code to handle the signup IPN for subscription + $subsc_ref = $customvariables['subsc_ref']; + + if (!empty($subsc_ref)) + { + $this->debug_log('swpm integration is being used... creating member account... see the "subscription_handle_debug.log" file for details',true); + $swpm_id = $customvariables['swpm_id']; + swpm_handle_subsc_signup_stand_alone($this->ipn_data,$subsc_ref,$this->ipn_data['subscr_id'],$swpm_id); + //Handle customized subscription signup + } + return true; + } + else if (($transaction_type == "subscr_cancel") || ($transaction_type == "subscr_eot") || ($transaction_type == "subscr_failed")) + { + // Code to handle the IPN for subscription cancellation + swpm_handle_subsc_cancel_stand_alone($this->ipn_data); + $this->debug_log('Subscription cancellation IPN received... nothing to do here(handled by the subscription IPN handler)',true); + return true; + } + else + { + $cart_items = array(); + $this->debug_log('Transaction Type: Buy Now/Subscribe',true); + $item_number = $this->ipn_data['item_number']; + $item_name = $this->ipn_data['item_name']; + $quantity = $this->ipn_data['quantity']; + $mc_gross = $this->ipn_data['mc_gross']; + $mc_currency = $this->ipn_data['mc_currency']; + + $current_item = array( + 'item_number' => $item_number, + 'item_name' => $item_name, + 'quantity' => $quantity, + 'mc_gross' => $mc_gross, + 'mc_currency' => $mc_currency, + ); + + array_push($cart_items, $current_item); + } + + $counter = 0; + foreach ($cart_items as $current_cart_item) + { + $cart_item_data_num = $current_cart_item['item_number']; + $cart_item_data_name = trim($current_cart_item['item_name']); + $cart_item_data_quantity = $current_cart_item['quantity']; + $cart_item_data_total = $current_cart_item['mc_gross']; + $cart_item_data_currency = $current_cart_item['mc_currency']; + if(empty($cart_item_data_quantity)) + { + $cart_item_data_quantity = 1; + } + $this->debug_log('Item Number: '.$cart_item_data_num,true); + $this->debug_log('Item Name: '.$cart_item_data_name,true); + $this->debug_log('Item Quantity: '.$cart_item_data_quantity,true); + $this->debug_log('Item Total: '.$cart_item_data_total,true); + $this->debug_log('Item Currency: '.$cart_item_data_currency,true); + + + //*** Handle Membership Payment *** + //-------------------------------------------------------------------------------------- + // ========= Need to find the (level ID) in the custom variable ============ + $subsc_ref = $customvariables['subsc_ref'];//Membership level ID + $this->debug_log('Membership payment paid for membership level ID: '.$subsc_ref,true); + if (!empty($subsc_ref)) + { + $swpm_id = ""; + if(isset($customvariables['swpm_id'])){ + $swpm_id = $customvariables['swpm_id']; + } + if ($transaction_type == "web_accept") + { + $this->debug_log('swpm integration is being used... creating member account... see the "subscription_handle_debug.log" file for details',true); + swpm_handle_subsc_signup_stand_alone($this->ipn_data,$subsc_ref,$this->ipn_data['txn_id'],$swpm_id); + } + else if($transaction_type == "subscr_payment"){ + //swpm_update_member_subscription_start_date_if_applicable($this->ipn_data); + } + } + else + { + $this->debug_log('Membership level ID is missing in the payment notification! Cannot process this notification.',false); + } + //== End of Membership payment handling == + $counter++; + } + + /*** Do Post payment operation and cleanup ***/ + //Save the transaction data + $this->debug_log('Saving transaction data to the database table.', true); + $this->ipn_data['gateway'] = 'paypal'; + $this->ipn_data['status'] = $this->ipn_data['payment_status']; + BTransactions::save_txn_record($this->ipn_data, $cart_items); + $this->debug_log('Transaction data saved.', true); + + + //WP Affiliate Plugin integration + if (function_exists('wp_aff_platform_install')) + { + $this->debug_log('WP Affiliate Platform is installed, checking if custom field has affiliate data...',true); + //It expects the value of the custom field to be like the following: + // + + $custom_field_val = $this->ipn_data['custom']; + $this->debug_log('Custom field value: '.$custom_field_val,true); + $findme = 'ap_id'; + $pos = strpos($custom_field_val, $findme); + if($pos !== false){ + parse_str($custom_field_val); + $referrer = $ap_id; + }else{ + $this->debug_log('Could not find affiliate ID (ap_id) data in the custom field',true); + } + + if(!empty($referrer)) + { + $total_tax = $this->ipn_data['tax']; + if(empty($total_tax)){$total_tax = 0;} + $total_shipping = 0; + if(!empty($this->ipn_data['shipping'])){ + $total_shipping = $this->ipn_data['shipping']; + }else if (!empty($this->ipn_data['mc_shipping'])){ + $total_shipping = $this->ipn_data['mc_shipping']; + } + $gross_sale_amt = $this->ipn_data['mc_gross']; + $this->debug_log('Gross sale amount: '.$gross_sale_amt.' Tax: '.$total_tax.' Shipping: '.$total_shipping,true); + $sale_amount = $gross_sale_amt - $total_shipping - $total_tax; + + $txn_id = $this->ipn_data['txn_id']; + $item_id = $this->ipn_data['item_number']; + $buyer_email = $this->ipn_data['payer_email']; + $buyer_name = $this->ipn_data['first_name'] . " " .$this->ipn_data['last_name']; + wp_aff_award_commission_unique($referrer,$sale_amount,$txn_id,$item_id,$buyer_email,'','',$buyer_name); + $aff_details_debug = "Referrer: ".$referrer." Sale Amt: ".$sale_amount." Buyer Email: ".$buyer_email." Txn ID: ".$txn_id; + $this->debug_log('Affiliate Commission Details => '.$aff_details_debug,true); + } + else + { + $this->debug_log("Referrer value is empty! No commission will be awarded for this sale",true); + } + + do_action('swpm_paypal_ipn_processed', $this->ipn_data); + } + return true; + } + + function swpm_validate_ipn() + { + // parse the paypal URL + $url_parsed=parse_url($this->paypal_url); + + // generate the post string from the _POST vars aswell as load the _POST vars into an arry + $post_string = ''; + foreach ($_POST as $field=>$value) { + $this->ipn_data["$field"] = $value; + $post_string .= $field.'='.urlencode(stripslashes($value)).'&'; + } + + $this->post_string = $post_string; + $this->debug_log('Post string : '. $this->post_string,true); + + $post_string.="cmd=_notify-validate"; // append ipn command + + // open the connection to paypal + if($this->sandbox_mode){//connect to PayPal sandbox + $uri = 'ssl://'.$url_parsed['host']; + $port = '443'; + $fp = fsockopen($uri,$port,$err_num,$err_str,30); + } + else{//connect to live PayPal site using standard approach + $fp = fsockopen($url_parsed['host'],"80",$err_num,$err_str,30); + } + + if(!$fp) + { + // could not open the connection. If loggin is on, the error message + // will be in the log. + $this->debug_log('Connection to '.$url_parsed['host']." failed.fsockopen error no. $errnum: $errstr",false); + return false; + + } + else + { + // Post the data back to paypal + fputs($fp, "POST $url_parsed[path] HTTP/1.1\r\n"); + fputs($fp, "Host: $url_parsed[host]\r\n"); + fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n"); + fputs($fp, "Content-length: ".strlen($post_string)."\r\n"); + fputs($fp, "Connection: close\r\n\r\n"); + fputs($fp, $post_string . "\r\n\r\n"); + + // loop through the response from the server and append to variable + while(!feof($fp)) { + $this->ipn_response .= fgets($fp, 1024); + } + + fclose($fp); // close connection + + $this->debug_log('Connection to '.$url_parsed['host'].' successfuly completed.',true); + } + + //if (eregi("VERIFIED",$this->ipn_response)) + if (strpos($this->ipn_response, "VERIFIED") !== false) + { + // Valid IPN transaction. + $this->debug_log('IPN successfully verified.',true); + return true; + + } + else + { + // Invalid IPN transaction. Check the log for details. + $this->debug_log('IPN validation failed.',false); + return false; + } + } + + function debug_log($message,$success,$end=false) + { + BLog::log_simple_debug($message, $success, $end); + } +} + +// Start of IPN handling (script execution) + +$ipn_handler_instance = new swpm_paypal_ipn_handler(); + +$settings = BSettings::get_instance(); +$debug_enabled = $settings->get_value('enable-debug'); +if(!empty($debug_enabled))//debug is enabled in the system +{ + $debug_log = "log.txt"; // Debug log file name + echo 'Debug logging is enabled. Check the '.$debug_log.' file for debug output.'; + $ipn_handler_instance->ipn_log = true; + $ipn_handler_instance->ipn_log_file = $debug_log; + if(empty($_POST)) + { + $ipn_handler_instance->debug_log('This debug line was generated because you entered the URL of the ipn handling script in the browser.',true,true); + exit; + } +} + +$sandbox_enabled = $settings->get_value('enable-sandbox-testing'); +if(!empty($sandbox_enabled)) // Sandbox testing enabled +{ + $ipn_handler_instance->paypal_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr'; + $ipn_handler_instance->sandbox_mode = true; +} + +$ipn_handler_instance->debug_log('Paypal Class Initiated by '.$_SERVER['REMOTE_ADDR'],true); + +// Validate the IPN +if ($ipn_handler_instance->swpm_validate_ipn()) +{ + $ipn_handler_instance->debug_log('Creating product Information to send.',true); + + if(!$ipn_handler_instance->swpm_validate_and_create_membership()){ + $ipn_handler_instance->debug_log('IPN product validation failed.',false); + } +} +$ipn_handler_instance->debug_log('Paypal class finished.',true,true); diff --git a/ipn/swpm_handle_subsc_ipn.php b/ipn/swpm_handle_subsc_ipn.php new file mode 100644 index 0000000..45b9a5d --- /dev/null +++ b/ipn/swpm_handle_subsc_ipn.php @@ -0,0 +1,222 @@ +prefix . "swpm_members_tbl"; + $membership_level_table = $wpdb->prefix . "swpm_membership_tbl"; + $membership_level = $subsc_ref; + + if(empty($swpm_id)) + { + //Lets try to find an existing user profile for this payment + $email = $ipn_data['payer_email']; + $query_db = $wpdb->get_row($wpdb->prepare("SELECT * FROM $members_table_name WHERE email = %s", $email), OBJECT); + if(!$query_db){//try to retrieve the member details based on the unique_ref + swpm_debug_log_subsc("Could not find any record using the given email address (".$email."). Attempting to query database using the unique reference: ".$unique_ref,true); + if(!empty($unique_ref)){ + $query_db = $wpdb->get_row($wpdb->prepare("SELECT * FROM $members_table_name WHERE subscr_id = %s", $unique_ref), OBJECT); + $swpm_id = $query_db->member_id; + } + else{ + swpm_debug_log_subsc("Unique reference is missing in the notification so we have to assume that this is not a payment for an existing member.",true); + } + } + else + { + $swpm_id = $query_db->member_id; + swpm_debug_log_subsc("Found a match in the member database. Member ID: ".$swpm_id,true); + } + } + + if (!empty($swpm_id)) + { + //This is payment from an existing member/user. Update the existing member account + swpm_debug_log_subsc("Modifying the existing membership profile... Member ID: ".$swpm_id,true); + + //Upgrade the member account + $account_state = 'active';//This is renewal or upgrade of a previously active account. So the status should be set to active + $subscription_starts = (date ("Y-m-d")); + $subscr_id = $unique_ref; + + $resultset = $wpdb->get_row($wpdb->prepare("SELECT * FROM $members_table_name where member_id=%d", $swpm_id), OBJECT); + if(!$resultset){ + swpm_debug_log_subsc("ERROR! Could not find a member account record for the given Member ID: ".$swpm_id,false); + return; + } + $old_membership_level = $resultset->membership_level; + + swpm_debug_log_subsc("Not using secondary membership level feature... upgrading the current membership level.",true); + $updatedb = $wpdb->prepare("UPDATE $members_table_name SET account_state=%s, membership_level=%d,subscription_starts=%s,subscr_id=%s WHERE member_id=%d", $account_state, $membership_level, $subscription_starts, $subscr_id, $swpm_id); + $results = $wpdb->query($updatedb); + do_action('swpm_membership_changed', array('member_id'=>$swpm_id, 'from_level'=>$old_membership_level, 'to_level'=>$membership_level)); + + //Set Email details for the account upgrade notification + $email = $ipn_data['payer_email']; + $subject = $settings->get_value('upgrade-complete-mail-subject'); + if (empty($subject)){ + $subject = "Member Account Upgraded"; + } + $body = $settings->get_value('upgrade-complete-mail-body'); + if (empty($body)){ + $body = "Your account has been upgraded successfully"; + } + $from_address = get_option('admin_email'); + $login_link = $settings->get_value('login-page-url'); + + $tags1 = array("{first_name}","{last_name}","{user_name}","{login_link}"); + $vals1 = array($resultset->first_name,$resultset->last_name,$resultset->user_name,$login_link); + $email_body = str_replace($tags1,$vals1,$body); + $headers = 'From: '.$from_address . "\r\n"; + }// End of existing user account upgrade + else + { + $default_account_status = $settings->get_value('default-account-status', 'active'); + // create new member account + $data = array(); + $data['user_name'] =''; + $data['password'] = ''; + + $data['first_name'] = $ipn_data['first_name']; + $data['last_name'] = $ipn_data['last_name']; + $data['email'] = $ipn_data['payer_email']; + $data['membership_level'] = $membership_level; + $data['subscr_id'] = $unique_ref; + $data['gender'] = 'not specified'; + + swpm_debug_log_subsc("Creating new member account. Membership level ID: ".$membership_level,true); + + $data['address_street'] = $ipn_data['address_street']; + $data['address_city'] = $ipn_data['address_city']; + $data['address_state'] = $ipn_data['address_state']; + $data['address_zipcode'] = $ipn_data['address_zip']; + $data['country'] = $ipn_data['address_country']; + $data['member_since'] = $data['subscription_starts'] = $data['last_accessed'] = date ("Y-m-d"); + $data['account_state'] = $default_account_status; + $reg_code = uniqid();//rand(10, 1000); + $md5_code = md5($reg_code); + $data['reg_code'] = $md5_code; + $data['referrer'] = $data['extra_info'] = $data['txn_id'] = ''; + $data['subscr_id']= $subscr_id; + + $wpdb->insert($members_table_name, $data);//Create the member record + $results = $wpdb->get_row($wpdb->prepare("SELECT * FROM $members_table_name where subscr_id=%s and reg_code=%s",$subscr_id, $md5_code), OBJECT); + $id = $results->member_id; //Alternatively use $wpdb->insert_id; + if(empty($id)){ + swpm_debug_log_subsc("Error! Failed to insert a new member record. This request will fail.",false); + return; + } + + $separator='?'; + $url = $settings->get_value('registration-page-url'); + if(strpos($url,'?')!==false){$separator='&';} + + $reg_url = $url.$separator.'member_id='.$id.'&code='.$md5_code; + swpm_debug_log_subsc("Member signup URL: ".$reg_url,true); + + $subject = $settings->get_value('reg-prompt-complete-mail-subject'); + if (empty($subject)){ + $subject = "Please complete your registration"; + } + $body = $settings->get_value('reg-prompt-complete-mail-body'); + if (empty($body)){ + $body = "Please use the following link to complete your registration. \n {reg_link}"; + } + $from_address = $settings->get_value('email-from'); + + $tags = array("{first_name}","{last_name}","{reg_link}"); + $vals = array($data['first_name'],$data['last_name'],$reg_url); + $email_body = str_replace($tags,$vals,$body); + $headers = 'From: '.$from_address . "\r\n"; + } + + wp_mail($email,$subject,$email_body,$headers); + swpm_debug_log_subsc("Member signup/upgrade completion email successfully sent to: ".$email,true); +} + +function swpm_handle_subsc_cancel_stand_alone($ipn_data,$refund=false) +{ + if($refund) + { + $subscr_id = $ipn_data['parent_txn_id']; + swpm_debug_log_subsc("Refund notification check - check if a member account needs to be deactivated... parent_txn_id: ".$ipn_data['parent_txn_id'],true); + } + else + { + $subscr_id = $ipn_data['subscr_id']; + } + + if(empty($subscr_id)){ + swpm_debug_log_subsc("No subscr_id associated with this transaction. Nothing to do here.",true); + return; + } + + global $wpdb; + $members_table_name = $wpdb->prefix . "swpm_members_tbl"; + + swpm_debug_log_subsc("Retrieving member account from the database. Subscr_id: ".$subscr_id, true); + $resultset = $wpdb->get_row($wpdb->prepare("SELECT * FROM $members_table_name where subscr_id=%s", $subscr_id), OBJECT); + if($resultset) + { + //Deactivate this account as it is a refund or cancellation + $member_id = $resultset->member_id; + $account_state = 'inactive'; + $updatedb = $wpdb->prepare("UPDATE $members_table_name SET account_state=%s WHERE member_id=%s", $account_state, $member_id); + $resultset = $wpdb->query($updatedb); + swpm_debug_log_subsc("Subscription cancellation received! Member account deactivated. Member ID: ".$member_id, true); + } + else + { + swpm_debug_log_subsc("No member found for the given subscriber ID: ".$subscr_id,false); + return; + } +} + +function swpm_update_member_subscription_start_date_if_applicable($ipn_data) +{ + global $wpdb; + $members_table_name = $wpdb->prefix . "swpm_members_tbl"; + $membership_level_table = $wpdb->prefix . "swpm_membership_tbl"; + $email = $ipn_data['payer_email']; + $subscr_id = $ipn_data['subscr_id']; + $account_state = BSettings::get_instance()->get_value('default-account-status', 'active'); + swpm_debug_log_subsc("Updating subscription start date if applicable for this subscription payment. Subscriber ID: ".$subscr_id." Email: ".$email,true); + + //We can also query using the email address + $query_db = $wpdb->get_row($wpdb->prepare("SELECT * FROM $members_table_name WHERE subscr_id = %s", $subscr_id), OBJECT); + if($query_db){ + $swpm_id = $query_db->member_id; + $current_primary_level = $query_db->membership_level; + swpm_debug_log_subsc("Found a record in the member table. The Member ID of the account to check is: ".$swpm_id." Membership Level: ".$current_primary_level,true); + + $subscription_starts = (date ("Y-m-d")); + + $updatedb = $wpdb->prepare("UPDATE $members_table_name SET account_state=%s,subscription_starts=%s WHERE member_id=%d", $account_state, $subscription_starts, $swpm_id); + $resultset = $wpdb->query($updatedb); + swpm_debug_log_subsc("Updated the member profile with current date as the subscription start date.",true); + }else{ + swpm_debug_log_subsc("Did not find a record in the members table for subscriber ID: ".$subscr_id,true); + } +} + +function swpm_debug_log_subsc($message,$success,$end=false) +{ + $settings = BSettings::get_instance(); + $debug_enabled = $settings->get_value('enable-debug'); + if (empty($debug_enabled)) {//Debug is not enabled + return; + } + + $debug_log_file_name = SIMPLE_WP_MEMBERSHIP_PATH . 'log.txt'; + + // Timestamp + $text = '['.date('m/d/Y g:i A').'] - '.(($success)?'SUCCESS :':'FAILURE :').$message. "\n"; + if ($end) { + $text .= "\n------------------------------------------------------------------\n\n"; + } + // Write to log + $fp=fopen($debug_log_file_name,'a'); + fwrite($fp, $text ); + fclose($fp); // close file +} diff --git a/js/index.html b/js/index.html new file mode 100644 index 0000000..e69de29 diff --git a/js/jquery.tools18.min.js b/js/jquery.tools18.min.js new file mode 100644 index 0000000..5a50446 --- /dev/null +++ b/js/jquery.tools18.min.js @@ -0,0 +1,51 @@ +/*! + * jQuery Tools v1.2.5 - The missing UI library for the Web + * + * dateinput/dateinput.js + * overlay/overlay.js + * overlay/overlay.apple.js + * rangeinput/rangeinput.js + * scrollable/scrollable.js + * scrollable/scrollable.autoscroll.js + * scrollable/scrollable.navigator.js + * tabs/tabs.js + * tabs/tabs.slideshow.js + * toolbox/toolbox.expose.js + * toolbox/toolbox.flashembed.js + * toolbox/toolbox.history.js + * toolbox/toolbox.mousewheel.js + * tooltip/tooltip.js + * tooltip/tooltip.dynamic.js + * tooltip/tooltip.slide.js + * validator/validator.js + * + * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE. + * + * http://flowplayer.org/tools/ + * + * jquery.event.wheel.js - rev 1 + * Copyright (c) 2008, Three Dub Media (http://threedubmedia.com) + * Liscensed under the MIT License (MIT-LICENSE.txt) + * http://www.opensource.org/licenses/mit-license.php + * Created: 2008-07-01 | Updated: 2008-07-14 + * + * ----- + * + */ +(function(a){a.tools=a.tools||{version:"v1.2.5"};var b=[],c,d=[75,76,38,39,74,72,40,37],e={};c=a.tools.dateinput={conf:{format:"mm/dd/yy",selectors:!1,yearRange:[-5,5],lang:"en",offset:[0,0],speed:0,firstDay:0,min:undefined,max:undefined,trigger:!1,css:{prefix:"cal",input:"date",root:0,head:0,title:0,prev:0,next:0,month:0,year:0,days:0,body:0,weeks:0,today:0,current:0,week:0,off:0,sunday:0,focus:0,disabled:0,trigger:0}},localize:function(b,c){a.each(c,function(a,b){c[a]=b.split(",")}),e[b]=c}},c.localize("en",{months:"January,February,March,April,May,June,July,August,September,October,November,December",shortMonths:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",days:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday",shortDays:"Sun,Mon,Tue,Wed,Thu,Fri,Sat"});function f(a,b){return 32-(new Date(a,b,32)).getDate()}function g(a,b){a=""+a,b=b||2;while(a.length");function j(a,b,c){var d=a.getDate(),f=a.getDay(),j=a.getMonth(),k=a.getFullYear(),l={d:d,dd:g(d),ddd:e[c].shortDays[f],dddd:e[c].days[f],m:j+1,mm:g(j+1),mmm:e[c].shortMonths[j],mmmm:e[c].months[j],yy:String(k).slice(2),yyyy:k},m=b.replace(h,function(a){return a in l?l[a]:a.slice(1,a.length-1)});return i.html(m).html()}function k(a){return parseInt(a,10)}function l(a,b){return a.getFullYear()===b.getFullYear()&&a.getMonth()==b.getMonth()&&a.getDate()==b.getDate()}function m(a){if(a){if(a.constructor==Date)return a;if(typeof a=="string"){var b=a.split("-");if(b.length==3)return new Date(k(b[0]),k(b[1])-1,k(b[2]));if(!/^-?\d+$/.test(a))return;a=k(a)}var c=new Date;c.setDate(c.getDate()+a);return c}}function n(c,g){var h=this,i=new Date,n=g.css,o=e[g.lang],p=a("#"+n.root),q=p.find("#"+n.title),r,s,t,u,v,w,x=c.attr("data-value")||g.value||c.val(),y=c.attr("min")||g.min,z=c.attr("max")||g.max,A;y===0&&(y="0"),x=m(x)||i,y=m(y||g.yearRange[0]*365),z=m(z||g.yearRange[1]*365);if(!o)throw"Dateinput: invalid language: "+g.lang;if(c.attr("type")=="date"){var B=a("");a.each("class,disabled,id,maxlength,name,readonly,required,size,style,tabindex,title,value".split(","),function(a,b){B.attr(b,c.attr(b))}),c.replaceWith(B),c=B}c.addClass(n.input);var C=c.add(h);if(!p.length){p=a("
").hide().css({position:"absolute"}).attr("id",n.root),p.children().eq(0).attr("id",n.head).end().eq(1).attr("id",n.body).children().eq(0).attr("id",n.days).end().eq(1).attr("id",n.weeks).end().end().end().find("a").eq(0).attr("id",n.prev).end().eq(1).attr("id",n.next),q=p.find("#"+n.head).find("div").attr("id",n.title);if(g.selectors){var D=a("").attr("id",n.year);q.html(D.add(E))}var F=p.find("#"+n.days);for(var G=0;G<7;G++)F.append(a("").text(o.shortDays[(G+g.firstDay)%7]));a("body").append(p)}g.trigger&&(r=a("").attr("href","#").addClass(n.trigger).click(function(a){h.show();return a.preventDefault()}).insertAfter(c));var H=p.find("#"+n.weeks);E=p.find("#"+n.year),D=p.find("#"+n.month);function I(b,d,e){x=b,u=b.getFullYear(),v=b.getMonth(),w=b.getDate(),e=e||a.Event("api"),e.type="change",C.trigger(e,[b]);e.isDefaultPrevented()||(c.val(j(b,d.format,d.lang)),c.data("date",b),h.hide(e))}function J(b){b.type="onShow",C.trigger(b),a(document).bind("keydown.d",function(b){if(b.ctrlKey)return!0;var e=b.keyCode;if(e==8){c.val("");return h.hide(b)}if(e==27)return h.hide(b);if(a(d).index(e)>=0){if(!A){h.show(b);return b.preventDefault()}var f=a("#"+n.weeks+" a"),g=a("."+n.focus),i=f.index(g);g.removeClass(n.focus);if(e==74||e==40)i+=7;else if(e==75||e==38)i-=7;else if(e==76||e==39)i+=1;else if(e==72||e==37)i-=1;i>41?(h.addMonth(),g=a("#"+n.weeks+" a:eq("+(i-42)+")")):i<0?(h.addMonth(-1),g=a("#"+n.weeks+" a:eq("+(i+42)+")")):g=f.eq(i),g.addClass(n.focus);return b.preventDefault()}if(e==34)return h.addMonth();if(e==33)return h.addMonth(-1);if(e==36)return h.today();e==13&&(a(b.target).is("select")||a("."+n.focus).click());return a([16,17,18,9]).index(e)>=0}),a(document).bind("click.d",function(b){var d=b.target;!a(d).parents("#"+n.root).length&&d!=c[0]&&(!r||d!=r[0])&&(d!=document)&&h.hide(b)})}a.extend(h,{show:function(d){if(!(c.attr("readonly")||c.attr("disabled")||A)){d=d||a.Event(),d.type="onBeforeShow",C.trigger(d);if(d.isDefaultPrevented())return;a.each(b,function(){this.hide()}),A=!0,D.unbind("change").change(function(){h.setValue(E.val(),a(this).val())}),E.unbind("change").change(function(){h.setValue(a(this).val(),D.val())}),s=p.find("#"+n.prev).unbind("click").click(function(a){s.hasClass(n.disabled)||h.addMonth(-1);return!1}),t=p.find("#"+n.next).unbind("click").click(function(a){t.hasClass(n.disabled)||h.addMonth();return!1}),h.setValue(x);var e=c.offset();/iPad/i.test(navigator.userAgent)&&(e.top-=a(window).scrollTop()),p.css({top:e.top+c.outerHeight(true)+g.offset[0],left:e.left+g.offset[1]}),g.speed?p.show(g.speed,function(){J(d)}):(p.show(),J(d));return h}},setValue:function(b,c,d){var e=k(c)>=-1?new Date(k(b),k(c),k(d||1)):b||x;ez&&(e=z),b=e.getFullYear(),c=e.getMonth(),d=e.getDate(),c==-1?(c=11,b--):c==12&&(c=0,b++);if(!A){I(e,g);return h}v=c,u=b;var j=new Date(b,c,1-g.firstDay),m=j.getDay(),p=f(b,c),r=f(b,c-1),w;if(g.selectors){D.empty(),a.each(o.months,function(c,d){ynew Date(b,c,0)&&D.append(a(""),F%7===0&&(w=a("
").addClass(n.week),H.append(w)),Fz&&G.add(t).addClass(n.disabled),G.attr("href","#"+J).text(J).data("date",e),w.append(G);H.find("a").click(function(b){var c=a(this);c.hasClass(n.disabled)||(a("#"+n.current).removeAttr("id"),c.attr("id",n.current),I(c.data("date"),g,b));return!1}),n.sunday&&H.find(n.week).each(function(){var b=g.firstDay?7-g.firstDay:0;a(this).children().slice(b,b+1).addClass(n.sunday)});return h},setMin:function(a,b){y=m(a),b&&xz&&h.setValue(z);return h},today:function(){return h.setValue(i)},addDay:function(a){return this.setValue(u,v,w+(a||1))},addMonth:function(a){return this.setValue(u,v+(a||1),w)},addYear:function(a){return this.setValue(u+(a||1),v,w)},hide:function(b){if(A){b=a.Event(),b.type="onHide",C.trigger(b),a(document).unbind("click.d").unbind("keydown.d");if(b.isDefaultPrevented())return;p.hide(),A=!1}return h},getConf:function(){return g},getInput:function(){return c},getCalendar:function(){return p},getValue:function(a){return a?j(x,a,g.lang):x},isOpen:function(){return A}}),a.each(["onBeforeShow","onShow","change","onHide"],function(b,c){a.isFunction(g[c])&&a(h).bind(c,g[c]),h[c]=function(b){b&&a(h).bind(c,b);return h}}),c.bind("focus click",h.show).keydown(function(b){var c=b.keyCode;if(!A&&a(d).index(c)>=0){h.show(b);return b.preventDefault()}return b.shiftKey||b.ctrlKey||b.altKey||c==9?!0:b.preventDefault()}),m(c.val())&&I(x,g)}a.expr[":"].date=function(b){var c=b.getAttribute("type");return c&&c=="date"||a(b).data("dateinput")},a.fn.dateinput=function(d){if(this.data("dateinput"))return this;d=a.extend(!0,{},c.conf,d),a.each(d.css,function(a,b){!b&&a!="prefix"&&(d.css[a]=(d.css.prefix||"")+(b||a))});var e;this.each(function(){var c=new n(a(this),d);b.push(c);var f=c.getInput().data("dateinput",c);e=e?e.add(f):f});return e?e:this}})(jQuery); +(function(a){a.tools=a.tools||{version:"v1.2.5"},a.tools.overlay={addEffect:function(a,b,d){c[a]=[b,d]},conf:{close:null,closeOnClick:!0,closeOnEsc:!0,closeSpeed:"fast",effect:"default",fixed:!a.browser.msie||a.browser.version>6,left:"center",load:!1,mask:null,oneInstance:!0,speed:"normal",target:null,top:"10%"}};var b=[],c={};a.tools.overlay.addEffect("default",function(b,c){var d=this.getConf(),e=a(window);d.fixed||(b.top+=e.scrollTop(),b.left+=e.scrollLeft()),b.position=d.fixed?"fixed":"absolute",this.getOverlay().css(b).fadeIn(d.speed,c)},function(a){this.getOverlay().fadeOut(this.getConf().closeSpeed,a)});function d(d,e){var f=this,g=d.add(f),h=a(window),i,j,k,l=a.tools.expose&&(e.mask||e.expose),m=Math.random().toString().slice(10);l&&(typeof l=="string"&&(l={color:l}),l.closeOnClick=l.closeOnEsc=!1);var n=e.target||d.attr("rel");j=n?a(n):null||d;if(!j.length)throw"Could not find Overlay: "+n;d&&d.index(j)==-1&&d.click(function(a){f.load(a);return a.preventDefault()}),a.extend(f,{load:function(d){if(f.isOpened())return f;var i=c[e.effect];if(!i)throw"Overlay: cannot find effect : \""+e.effect+"\"";e.oneInstance&&a.each(b,function(){this.close(d)}),d=d||a.Event(),d.type="onBeforeLoad",g.trigger(d);if(d.isDefaultPrevented())return f;k=!0,l&&a(j).expose(l);var n=e.top,o=e.left,p=j.outerWidth(true),q=j.outerHeight(true);typeof n=="string"&&(n=n=="center"?Math.max((h.height()-q)/2,0):parseInt(n,10)/100*h.height()),o=="center"&&(o=Math.max((h.width()-p)/2,0)),i[0].call(f,{top:n,left:o},function(){k&&(d.type="onLoad",g.trigger(d))}),l&&e.closeOnClick&&a.mask.getMask().one("click",f.close),e.closeOnClick&&a(document).bind("click."+m,function(b){a(b.target).parents(j).length||f.close(b)}),e.closeOnEsc&&a(document).bind("keydown."+m,function(a){a.keyCode==27&&f.close(a)});return f},close:function(b){if(!f.isOpened())return f;b=b||a.Event(),b.type="onBeforeClose",g.trigger(b);if(!b.isDefaultPrevented()){k=!1,c[e.effect][1].call(f,function(){b.type="onClose",g.trigger(b)}),a(document).unbind("click."+m).unbind("keydown."+m),l&&a.mask.close();return f}},getOverlay:function(){return j},getTrigger:function(){return d},getClosers:function(){return i},isOpened:function(){return k},getConf:function(){return e}}),a.each("onBeforeLoad,onStart,onLoad,onBeforeClose,onClose".split(","),function(b,c){a.isFunction(e[c])&&a(f).bind(c,e[c]),f[c]=function(b){b&&a(f).bind(c,b);return f}}),i=j.find(e.close||".close"),!i.length&&!e.close&&(i=a(""),j.prepend(i)),i.click(function(a){f.close(a)}),e.load&&f.load()}a.fn.overlay=function(c){var e=this.data("overlay");if(e)return e;a.isFunction(c)&&(c={onBeforeLoad:c}),c=a.extend(!0,{},a.tools.overlay.conf,c),this.each(function(){e=new d(a(this),c),b.push(e),a(this).data("overlay",e)});return c.api?e:this}})(jQuery); +(function(a){var b=a.tools.overlay,c=a(window);a.extend(b.conf,{start:{top:null,left:null},fadeInSpeed:"fast",zIndex:9999});function d(a){var b=a.offset();return{top:b.top+a.height()/2,left:b.left+a.width()/2}}var e=function(b,e){var f=this.getOverlay(),g=this.getConf(),h=this.getTrigger(),i=this,j=f.outerWidth(true),k=f.data("img"),l=g.fixed?"fixed":"absolute";if(!k){var m=f.css("backgroundImage");if(!m)throw"background-image CSS property not set for overlay";m=m.slice(m.indexOf("(")+1,m.indexOf(")")).replace(/\"/g,""),f.css("backgroundImage","none"),k=a(""),k.css({border:0,display:"none"}).width(j),a("body").append(k),f.data("img",k)}var n=g.start.top||Math.round(c.height()/2),o=g.start.left||Math.round(c.width()/2);if(h){var p=d(h);n=p.top,o=p.left}g.fixed?(n-=c.scrollTop(),o-=c.scrollLeft()):(b.top+=c.scrollTop(),b.left+=c.scrollLeft()),k.css({position:"absolute",top:n,left:o,width:0,zIndex:g.zIndex}).show(),b.position=l,f.css(b),k.animate({top:f.css("top"),left:f.css("left"),width:j},g.speed,function(){f.css("zIndex",g.zIndex+1).fadeIn(g.fadeInSpeed,function(){i.isOpened()&&!a(this).index(f)?e.call():f.hide()})}).css("position",l)},f=function(b){var e=this.getOverlay().hide(),f=this.getConf(),g=this.getTrigger(),h=e.data("img"),i={top:f.start.top,left:f.start.left,width:0};g&&a.extend(i,d(g)),f.fixed&&h.css({position:"absolute"}).animate({top:"+="+c.scrollTop(),left:"+="+c.scrollLeft()},0),h.animate(i,f.closeSpeed,b)};b.addEffect("apple",e,f)})(jQuery); +(function(a){a.tools=a.tools||{version:"v1.2.5"};var b;b=a.tools.rangeinput={conf:{min:0,max:100,step:"any",steps:0,value:0,precision:undefined,vertical:0,keyboard:!0,progress:!1,speed:100,css:{input:"range",slider:"slider",progress:"progress",handle:"handle"}}};var c,d;a.fn.drag=function(b){document.ondragstart=function(){return!1},b=a.extend({x:!0,y:!0,drag:!0},b),c=c||a(document).bind("mousedown mouseup",function(e){var f=a(e.target);if(e.type=="mousedown"&&f.data("drag")){var g=f.position(),h=e.pageX-g.left,i=e.pageY-g.top,j=!0;c.bind("mousemove.drag",function(a){var c=a.pageX-h,e=a.pageY-i,g={};b.x&&(g.left=c),b.y&&(g.top=e),j&&(f.trigger("dragStart"),j=!1),b.drag&&f.css(g),f.trigger("drag",[e,c]),d=f}),e.preventDefault()}else try{d&&d.trigger("dragEnd")}finally{c.unbind("mousemove.drag"),d=null}});return this.data("drag",!0)};function e(a,b){var c=Math.pow(10,b);return Math.round(a*c)/c}function f(a,b){var c=parseInt(a.css(b),10);if(c)return c;var d=a[0].currentStyle;return d&&d.width&&parseInt(d.width,10)}function g(a){var b=a.data("events");return b&&b.onSlide}function h(b,c){var d=this,h=c.css,i=a("
").data("rangeinput",d),j,k,l,m,n;b.before(i);var o=i.addClass(h.slider).find("a").addClass(h.handle),p=i.find("div").addClass(h.progress);a.each("min,max,step,value".split(","),function(a,d){var e=b.attr(d);parseFloat(e)&&(c[d]=parseFloat(e,10))});var q=c.max-c.min,r=c.step=="any"?0:c.step,s=c.precision;if(s===undefined)try{s=r.toString().split(".")[1].length}catch(t){s=0}if(b.attr("type")=="range"){var u=a("");a.each("class,disabled,id,maxlength,name,readonly,required,size,style,tabindex,title,value".split(","),function(a,c){u.attr(c,b.attr(c))}),u.val(c.value),b.replaceWith(u),b=u}b.addClass(h.input);var v=a(d).add(b),w=!0;function x(a,f,g,h){g===undefined?g=f/m*q:h&&(g-=c.min),r&&(g=Math.round(g/r)*r);if(f===undefined||r)f=g*m/q;if(isNaN(g))return d;f=Math.max(0,Math.min(f,m)),g=f/m*q;if(h||!j)g+=c.min;j&&(h?f=m-f:g=c.max-g),g=e(g,s);var i=a.type=="click";if(w&&k!==undefined&&!i){a.type="onSlide",v.trigger(a,[g,f]);if(a.isDefaultPrevented())return d}var l=i?c.speed:0,t=i?function(){a.type="change",v.trigger(a,[g])}:null;j?(o.animate({top:f},l,t),c.progress&&p.animate({height:m-f+o.width()/2},l)):(o.animate({left:f},l,t),c.progress&&p.animate({width:f+o.width()/2},l)),k=g,n=f,b.val(g);return d}a.extend(d,{getValue:function(){return k},setValue:function(b,c){y();return x(c||a.Event("api"),undefined,b,!0)},getConf:function(){return c},getProgress:function(){return p},getHandle:function(){return o},getInput:function(){return b},step:function(b,e){e=e||a.Event();var f=c.step=="any"?1:c.step;d.setValue(k+f*(b||1),e)},stepUp:function(a){return d.step(a||1)},stepDown:function(a){return d.step(-a||-1)}}),a.each("onSlide,change".split(","),function(b,e){a.isFunction(c[e])&&a(d).bind(e,c[e]),d[e]=function(b){b&&a(d).bind(e,b);return d}}),o.drag({drag:!1}).bind("dragStart",function(){y(),w=g(a(d))||g(b)}).bind("drag",function(a,c,d){if(b.is(":disabled"))return!1;x(a,j?c:d)}).bind("dragEnd",function(a){a.isDefaultPrevented()||(a.type="change",v.trigger(a,[k]))}).click(function(a){return a.preventDefault()}),i.click(function(a){if(b.is(":disabled")||a.target==o[0])return a.preventDefault();y();var c=o.width()/2;x(a,j?m-l-c+a.pageY:a.pageX-l-c)}),c.keyboard&&b.keydown(function(c){if(!b.attr("readonly")){var e=c.keyCode,f=a([75,76,38,33,39]).index(e)!=-1,g=a([74,72,40,34,37]).index(e)!=-1;if((f||g)&&!(c.shiftKey||c.altKey||c.ctrlKey)){f?d.step(e==33?10:1,c):g&&d.step(e==34?-10:-1,c);return c.preventDefault()}}}),b.blur(function(b){var c=a(this).val();c!==k&&d.setValue(c,b)}),a.extend(b[0],{stepUp:d.stepUp,stepDown:d.stepDown});function y(){j=c.vertical||f(i,"height")>f(i,"width"),j?(m=f(i,"height")-f(o,"height"),l=i.offset().top+m):(m=f(i,"width")-f(o,"width"),l=i.offset().left)}function z(){y(),d.setValue(c.value!==undefined?c.value:c.min)}z(),m||a(window).load(z)}a.expr[":"].range=function(b){var c=b.getAttribute("type");return c&&c=="range"||a(b).filter("input").data("rangeinput")},a.fn.rangeinput=function(c){if(this.data("rangeinput"))return this;c=a.extend(!0,{},b.conf,c);var d;this.each(function(){var b=new h(a(this),a.extend(!0,{},c)),e=b.getInput().data("rangeinput",b);d=d?d.add(e):e});return d?d:this}})(jQuery); +(function(a){a.tools=a.tools||{version:"v1.2.5"},a.tools.scrollable={conf:{activeClass:"active",circular:!1,clonedClass:"cloned",disabledClass:"disabled",easing:"swing",initialIndex:0,item:null,items:".items",keyboard:!0,mousewheel:!1,next:".next",prev:".prev",speed:400,vertical:!1,touch:!0,wheelSpeed:0}};function b(a,b){var c=parseInt(a.css(b),10);if(c)return c;var d=a[0].currentStyle;return d&&d.width&&parseInt(d.width,10)}function c(b,c){var d=a(c);return d.length<2?d:b.parent().find(c)}var d;function e(b,e){var f=this,g=b.add(f),h=b.children(),i=0,j=e.vertical;d||(d=f),h.length>1&&(h=a(e.items,b)),a.extend(f,{getConf:function(){return e},getIndex:function(){return i},getSize:function(){return f.getItems().size()},getNaviButtons:function(){return m.add(n)},getRoot:function(){return b},getItemWrap:function(){return h},getItems:function(){return h.children(e.item).not("."+e.clonedClass)},move:function(a,b){return f.seekTo(i+a,b)},next:function(a){return f.move(1,a)},prev:function(a){return f.move(-1,a)},begin:function(a){return f.seekTo(0,a)},end:function(a){return f.seekTo(f.getSize()-1,a)},focus:function(){d=f;return f},addItem:function(b){b=a(b),e.circular?(h.children("."+e.clonedClass+":last").before(b),h.children("."+e.clonedClass+":first").replaceWith(b.clone().addClass(e.clonedClass))):h.append(b),g.trigger("onAddItem",[b]);return f},seekTo:function(b,c,k){b.jquery||(b*=1);if(e.circular&&b===0&&i==-1&&c!==0)return f;if(!e.circular&&b<0||b>f.getSize()||b<-1)return f;var l=b;b.jquery?b=f.getItems().index(b):l=f.getItems().eq(b);var m=a.Event("onBeforeSeek");if(!k){g.trigger(m,[b,c]);if(m.isDefaultPrevented()||!l.length)return f}var n=j?{top:-l.position().top}:{left:-l.position().left};i=b,d=f,c===undefined&&(c=e.speed),h.animate(n,c,e.easing,k||function(){g.trigger("onSeek",[b])});return f}}),a.each(["onBeforeSeek","onSeek","onAddItem"],function(b,c){a.isFunction(e[c])&&a(f).bind(c,e[c]),f[c]=function(b){b&&a(f).bind(c,b);return f}});if(e.circular){var k=f.getItems().slice(-1).clone().prependTo(h),l=f.getItems().eq(1).clone().appendTo(h);k.add(l).addClass(e.clonedClass),f.onBeforeSeek(function(a,b,c){if(!a.isDefaultPrevented()){if(b==-1){f.seekTo(k,c,function(){f.end(0)});return a.preventDefault()}b==f.getSize()&&f.seekTo(l,c,function(){f.begin(0)})}}),f.seekTo(0,0,function(){})}var m=c(b,e.prev).click(function(){f.prev()}),n=c(b,e.next).click(function(){f.next()});!e.circular&&f.getSize()>1&&(f.onBeforeSeek(function(a,b){setTimeout(function(){a.isDefaultPrevented()||(m.toggleClass(e.disabledClass,b<=0),n.toggleClass(e.disabledClass,b>=f.getSize()-1))},1)}),e.initialIndex||m.addClass(e.disabledClass)),e.mousewheel&&a.fn.mousewheel&&b.mousewheel(function(a,b){if(e.mousewheel){f.move(b<0?1:-1,e.wheelSpeed||50);return!1}});if(e.touch){var o={};h[0].ontouchstart=function(a){var b=a.touches[0];o.x=b.clientX,o.y=b.clientY},h[0].ontouchmove=function(a){if(a.touches.length==1&&!h.is(":animated")){var b=a.touches[0],c=o.x-b.clientX,d=o.y-b.clientY;f[j&&d>0||!j&&c>0?"next":"prev"](),a.preventDefault()}}}e.keyboard&&a(document).bind("keydown.scrollable",function(b){if(e.keyboard&&!b.altKey&&!b.ctrlKey&&!a(b.target).is(":input")){if(e.keyboard!="static"&&d!=f)return;var c=b.keyCode;if(j&&(c==38||c==40)){f.move(c==38?-1:1);return b.preventDefault()}if(!j&&(c==37||c==39)){f.move(c==37?-1:1);return b.preventDefault()}}}),e.initialIndex&&f.seekTo(e.initialIndex,0,function(){})}a.fn.scrollable=function(b){var c=this.data("scrollable");if(c)return c;b=a.extend({},a.tools.scrollable.conf,b),this.each(function(){c=new e(a(this),b),a(this).data("scrollable",c)});return b.api?c:this}})(jQuery); +(function(a){var b=a.tools.scrollable;b.autoscroll={conf:{autoplay:!0,interval:3e3,autopause:!0}},a.fn.autoscroll=function(c){typeof c=="number"&&(c={interval:c});var d=a.extend({},b.autoscroll.conf,c),e;this.each(function(){var b=a(this).data("scrollable");b&&(e=b);var c,f=!0;b.play=function(){c||(f=!1,c=setInterval(function(){b.next()},d.interval))},b.pause=function(){c=clearInterval(c)},b.stop=function(){b.pause(),f=!0},d.autopause&&b.getRoot().add(b.getNaviButtons()).hover(b.pause,b.play),d.autoplay&&b.play()});return d.api?e:this}})(jQuery); +(function(a){var b=a.tools.scrollable;b.navigator={conf:{navi:".navi",naviItem:null,activeClass:"active",indexed:!1,idPrefix:null,history:!1}};function c(b,c){var d=a(c);return d.length<2?d:b.parent().find(c)}a.fn.navigator=function(d){typeof d=="string"&&(d={navi:d}),d=a.extend({},b.navigator.conf,d);var e;this.each(function(){var b=a(this).data("scrollable"),f=d.navi.jquery?d.navi:c(b.getRoot(),d.navi),g=b.getNaviButtons(),h=d.activeClass,i=d.history&&a.fn.history;b&&(e=b),b.getNaviButtons=function(){return g.add(f)};function j(a,c,d){b.seekTo(c);if(i)location.hash&&(location.hash=a.attr("href").replace("#",""));else return d.preventDefault()}function k(){return f.find(d.naviItem||"> *")}function l(b){var c=a("<"+(d.naviItem||"a")+"/>").click(function(c){j(a(this),b,c)}).attr("href","#"+b);b===0&&c.addClass(h),d.indexed&&c.text(b+1),d.idPrefix&&c.attr("id",d.idPrefix+b);return c.appendTo(f)}k().length?k().each(function(b){a(this).click(function(c){j(a(this),b,c)})}):a.each(b.getItems(),function(a){l(a)}),b.onBeforeSeek(function(a,b){setTimeout(function(){if(!a.isDefaultPrevented()){var c=k().eq(b);!a.isDefaultPrevented()&&c.length&&k().removeClass(h).eq(b).addClass(h)}},1)});function m(a,b){var c=k().eq(b.replace("#",""));c.length||(c=k().filter("[href="+b+"]")),c.click()}b.onAddItem(function(a,c){c=l(b.getItems().index(c)),i&&c.history(m)}),i&&k().history(m)});return d.api?e:this}})(jQuery); +(function(a){a.tools=a.tools||{version:"v1.2.5"},a.tools.tabs={conf:{tabs:"a",current:"current",onBeforeClick:null,onClick:null,effect:"default",initialIndex:0,event:"click",rotate:!1,history:!1},addEffect:function(a,c){b[a]=c}};var b={"default":function(a,b){this.getPanes().hide().eq(a).show(),b.call()},fade:function(a,b){var c=this.getConf(),d=c.fadeOutSpeed,e=this.getPanes();d?e.fadeOut(d):e.hide(),e.eq(a).fadeIn(c.fadeInSpeed,b)},slide:function(a,b){this.getPanes().slideUp(200),this.getPanes().eq(a).slideDown(400,b)},ajax:function(a,b){this.getPanes().eq(0).load(this.getTabs().eq(a).attr("href"),b)}},c;a.tools.tabs.addEffect("horizontal",function(b,d){c||(c=this.getPanes().eq(0).width()),this.getCurrentPane().animate({width:0},function(){a(this).hide()}),this.getPanes().eq(b).animate({width:c},function(){a(this).show(),d.call()})});function d(c,d,e){var f=this,g=c.add(this),h=c.find(e.tabs),i=d.jquery?d:c.children(d),j;h.length||(h=c.children()),i.length||(i=c.parent().find(d)),i.length||(i=a(d)),a.extend(this,{click:function(c,d){var i=h.eq(c);typeof c=="string"&&c.replace("#","")&&(i=h.filter("[href*="+c.replace("#","")+"]"),c=Math.max(h.index(i),0));if(e.rotate){var k=h.length-1;if(c<0)return f.click(k,d);if(c>k)return f.click(0,d)}if(!i.length){if(j>=0)return f;c=e.initialIndex,i=h.eq(c)}if(c===j)return f;d=d||a.Event(),d.type="onBeforeClick",g.trigger(d,[c]);if(!d.isDefaultPrevented()){b[e.effect].call(f,c,function(){d.type="onClick",g.trigger(d,[c])}),j=c,h.removeClass(e.current),i.addClass(e.current);return f}},getConf:function(){return e},getTabs:function(){return h},getPanes:function(){return i},getCurrentPane:function(){return i.eq(j)},getCurrentTab:function(){return h.eq(j)},getIndex:function(){return j},next:function(){return f.click(j+1)},prev:function(){return f.click(j-1)},destroy:function(){h.unbind(e.event).removeClass(e.current),i.find("a[href^=#]").unbind("click.T");return f}}),a.each("onBeforeClick,onClick".split(","),function(b,c){a.isFunction(e[c])&&a(f).bind(c,e[c]),f[c]=function(b){b&&a(f).bind(c,b);return f}}),e.history&&a.fn.history&&(a.tools.history.init(h),e.event="history"),h.each(function(b){a(this).bind(e.event,function(a){f.click(b,a);return a.preventDefault()})}),i.find("a[href^=#]").bind("click.T",function(b){f.click(a(this).attr("href"),b)}),location.hash&&e.tabs=="a"&&c.find("[href="+location.hash+"]").length?f.click(location.hash):(e.initialIndex===0||e.initialIndex>0)&&f.click(e.initialIndex)}a.fn.tabs=function(b,c){var e=this.data("tabs");e&&(e.destroy(),this.removeData("tabs")),a.isFunction(c)&&(c={onBeforeClick:c}),c=a.extend({},a.tools.tabs.conf,c),this.each(function(){e=new d(a(this),b,c),a(this).data("tabs",e)});return c.api?e:this}})(jQuery); +(function(a){var b;b=a.tools.tabs.slideshow={conf:{next:".forward",prev:".backward",disabledClass:"disabled",autoplay:!1,autopause:!0,interval:3e3,clickable:!0,api:!1}};function c(b,c){var d=this,e=b.add(this),f=b.data("tabs"),g,h=!0;function i(c){var d=a(c);return d.length<2?d:b.parent().find(c)}var j=i(c.next).click(function(){f.next()}),k=i(c.prev).click(function(){f.prev()});a.extend(d,{getTabs:function(){return f},getConf:function(){return c},play:function(){if(g)return d;var b=a.Event("onBeforePlay");e.trigger(b);if(b.isDefaultPrevented())return d;g=setInterval(f.next,c.interval),h=!1,e.trigger("onPlay");return d},pause:function(){if(!g)return d;var b=a.Event("onBeforePause");e.trigger(b);if(b.isDefaultPrevented())return d;g=clearInterval(g),e.trigger("onPause");return d},stop:function(){d.pause(),h=!0}}),a.each("onBeforePlay,onPlay,onBeforePause,onPause".split(","),function(b,e){a.isFunction(c[e])&&a(d).bind(e,c[e]),d[e]=function(b){return a(d).bind(e,b)}}),c.autopause&&f.getTabs().add(j).add(k).add(f.getPanes()).hover(d.pause,function(){h||d.play()}),c.autoplay&&d.play(),c.clickable&&f.getPanes().click(function(){f.next()});if(!f.getConf().rotate){var l=c.disabledClass;f.getIndex()||k.addClass(l),f.onBeforeClick(function(a,b){k.toggleClass(l,!b),j.toggleClass(l,b==f.getTabs().length-1)})}}a.fn.slideshow=function(d){var e=this.data("slideshow");if(e)return e;d=a.extend({},b.conf,d),this.each(function(){e=new c(a(this),d),a(this).data("slideshow",e)});return d.api?e:this}})(jQuery); +(function(a){a.tools=a.tools||{version:"v1.2.5"};var b;b=a.tools.expose={conf:{maskId:"exposeMask",loadSpeed:"slow",closeSpeed:"fast",closeOnClick:!0,closeOnEsc:!0,zIndex:9998,opacity:.8,startOpacity:0,color:"#fff",onLoad:null,onClose:null}};function c(){if(a.browser.msie){var b=a(document).height(),c=a(window).height();return[window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,b-c<20?c:b]}return[a(document).width(),a(document).height()]}function d(b){if(b)return b.call(a.mask)}var e,f,g,h,i;a.mask={load:function(j,k){if(g)return this;typeof j=="string"&&(j={color:j}),j=j||h,h=j=a.extend(a.extend({},b.conf),j),e=a("#"+j.maskId),e.length||(e=a("
").attr("id",j.maskId),a("body").append(e));var l=c();e.css({position:"absolute",top:0,left:0,width:l[0],height:l[1],display:"none",opacity:j.startOpacity,zIndex:j.zIndex}),j.color&&e.css("backgroundColor",j.color);if(d(j.onBeforeLoad)===!1)return this;j.closeOnEsc&&a(document).bind("keydown.mask",function(b){b.keyCode==27&&a.mask.close(b)}),j.closeOnClick&&e.bind("click.mask",function(b){a.mask.close(b)}),a(window).bind("resize.mask",function(){a.mask.fit()}),k&&k.length&&(i=k.eq(0).css("zIndex"),a.each(k,function(){var b=a(this);/relative|absolute|fixed/i.test(b.css("position"))||b.css("position","relative")}),f=k.css({zIndex:Math.max(j.zIndex+1,i=="auto"?0:i)})),e.css({display:"block"}).fadeTo(j.loadSpeed,j.opacity,function(){a.mask.fit(),d(j.onLoad),g="full"}),g=!0;return this},close:function(){if(g){if(d(h.onBeforeClose)===!1)return this;e.fadeOut(h.closeSpeed,function(){d(h.onClose),f&&f.css({zIndex:i}),g=!1}),a(document).unbind("keydown.mask"),e.unbind("click.mask"),a(window).unbind("resize.mask")}return this},fit:function(){if(g){var a=c();e.css({width:a[0],height:a[1]})}},getMask:function(){return e},isLoaded:function(a){return a?g=="full":g},getConf:function(){return h},getExposed:function(){return f}},a.fn.mask=function(b){a.mask.load(b);return this},a.fn.expose=function(b){a.mask.load(b,this);return this}})(jQuery); +(function(){var a=document.all,b="http://www.adobe.com/go/getflashplayer",c=typeof jQuery=="function",d=/(\d+)[^\d]+(\d+)[^\d]*(\d*)/,e={width:"100%",height:"100%",id:"_"+(""+Math.random()).slice(9),allowfullscreen:!0,allowscriptaccess:"always",quality:"high",version:[3,0],onFail:null,expressInstall:null,w3c:!1,cachebusting:!1};window.attachEvent&&window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){},__flash_savedUnloadHandler=function(){}});function f(a,b){if(b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function g(a,b){var c=[];for(var d in a)a.hasOwnProperty(d)&&(c[d]=b(a[d]));return c}window.flashembed=function(a,b,c){typeof a=="string"&&(a=document.getElementById(a.replace("#","")));if(a){typeof b=="string"&&(b={src:b});return new j(a,f(f({},e),b),c)}};var h=f(window.flashembed,{conf:e,getVersion:function(){var a,b;try{b=navigator.plugins["Shockwave Flash"].description.slice(16)}catch(c){try{a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"),b=a&&a.GetVariable("$version")}catch(e){try{a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6"),b=a&&a.GetVariable("$version")}catch(f){}}}b=d.exec(b);return b?[b[1],b[3]]:[0,0]},asString:function(a){if(a===null||a===undefined)return null;var b=typeof a;b=="object"&&a.push&&(b="array");switch(b){case"string":a=a.replace(new RegExp("([\"\\\\])","g"),"\\$1"),a=a.replace(/^\s?(\d+\.?\d+)%/,"$1pct");return"\""+a+"\"";case"array":return"["+g(a,function(a){return h.asString(a)}).join(",")+"]";case"function":return"\"function()\"";case"object":var c=[];for(var d in a)a.hasOwnProperty(d)&&c.push("\""+d+"\":"+h.asString(a[d]));return"{"+c.join(",")+"}"}return String(a).replace(/\s/g," ").replace(/\'/g,"\"")},getHTML:function(b,c){b=f({},b);var d="";if(b.w3c||a)d+="";b.width=b.height=b.id=b.w3c=b.src=null,b.onFail=b.version=b.expressInstall=null;for(var e in b)b[e]&&(d+="");var g="";if(c){for(var i in c)if(c[i]){var j=c[i];g+=i+"="+(/function|object/.test(typeof j)?h.asString(j):j)+"&"}g=g.slice(0,-1),d+=""}d+="";return d},isSupported:function(a){return i[0]>a[0]||i[0]==a[0]&&i[1]>=a[1]}}),i=h.getVersion();function j(c,d,e){if(h.isSupported(d.version))c.innerHTML=h.getHTML(d,e);else if(d.expressInstall&&h.isSupported([6,65]))c.innerHTML=h.getHTML(f(d,{src:d.expressInstall}),{MMredirectURL:location.href,MMplayerType:"PlugIn",MMdoctitle:document.title});else{c.innerHTML.replace(/\s/g,"")||(c.innerHTML="

Flash version "+d.version+" or greater is required

"+(i[0]>0?"Your version is "+i:"You have no flash plugin installed")+"

"+(c.tagName=="A"?"

Click here to download latest version

":"

Download latest version from here

"),c.tagName=="A"&&(c.onclick=function(){location.href=b}));if(d.onFail){var g=d.onFail.call(this);typeof g=="string"&&(c.innerHTML=g)}}a&&(window[d.id]=document.getElementById(d.id)),f(this,{getRoot:function(){return c},getOptions:function(){return d},getConf:function(){return e},getApi:function(){return c.firstChild}})}c&&(jQuery.tools=jQuery.tools||{version:"v1.2.5"},jQuery.tools.flashembed={conf:e},jQuery.fn.flashembed=function(a,b){return this.each(function(){$(this).data("flashembed",flashembed(this,a,b))})})})(); +(function(a){var b,c,d,e;a.tools=a.tools||{version:"v1.2.5"},a.tools.history={init:function(g){e||(a.browser.msie&&a.browser.version<"8"?c||(c=a("