├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── includes ├── helpers.php ├── migrate-options.php └── wp-session-manager │ ├── .gitignore │ ├── README.md │ ├── composer.json │ ├── includes │ ├── class-recursive-arrayaccess.php │ ├── class-wp-session-utils.php │ ├── class-wp-session.php │ ├── wp-cli.php │ └── wp-session.php │ ├── readme.txt │ └── wp-session-manager.php ├── options ├── options.php ├── options_deprecated.php ├── security.php └── user-access.php ├── shortcodes ├── delete-account.php ├── email-change.php ├── login.php ├── navigation.php ├── password-change.php ├── password-reset.php └── signup.php └── wordpress-for-web-apps.php /.gitignore: -------------------------------------------------------------------------------- 1 | # Node 2 | node_modules 3 | test/results 4 | test/coverage 5 | 6 | ## OS X 7 | .DS_Store 8 | ._* 9 | .Spotlight-V100 10 | .Trashes -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | I'm delighted that you're helping make this open source project better. Here are a few quick guidelines to make this an easier and better process for everyone. 4 | 5 | ## Reporting a bug 6 | 7 | First, **make sure the bug hasn't already been reported** by searching GitHub's issues section. 8 | 9 | If no existing issue exists, go ahead and create one. **Please be sure to include all of the following:** 10 | 11 | 1. A clear, descriptive title (ie. "A bug" is *not* a good title). 12 | 2. [A reduced test case.](https://css-tricks.com/reduced-test-cases/) In order to debug code issues, I need to see actual code in a browser. 13 | 3. The browser and OS that you're using. 14 | 15 | ## Asking a question 16 | 17 | Before asking, please **make sure the question hasn't already been asked** by searching GitHub's issues section. 18 | 19 | ## Submitting a Pull Request 20 | 21 | Please make sure your code meets the following code standards: 22 | 23 | - Camel case for JavaScript variables. 24 | - [Object-Oriented CSS](http://www.slideshare.net/stubbornella/object-oriented-css) for CSS selectors. 25 | - Favor readable code over brevity. The build process will reduce size, so opt for readability. (ex. `var navigation` is better than `var n`) 26 | - Order CSS properties alphabetically. 27 | - Hard tabs. 28 | 29 | Before submitting, make sure that you've updated the version number using semantic versioning. -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) Go Make Things, LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [DEPRECATED] WordPress for Web Apps 2 | 3 | *__Deprecation Notice:__ This plugin is no longer be maintained or updated.* 4 | 5 | A plugin that provides the essential components you need to power your web app with WordPress. 6 | 7 | - Front-end forms: 8 | - Login 9 | - Sign-up 10 | - Password reset 11 | - Email change 12 | - Password change 13 | - Delete account 14 | - User access settings, so you can selectively hide content from logged-out or logged-in users. 15 | - Security settings let you set password requirements, hide the admin bar, and force password resets. 16 | - The web app settings panel lets you easily configure error messages, button text, and more. 17 | 18 | [Download WordPress for Web Apps](https://github.com/cferdinandi/wordpress-for-web-apps/archive/master.zip) 19 | 20 | 21 | 22 | ## Getting Started 23 | 24 | Getting started with WordPress for Web Apps is as simple as installing a plugin: 25 | 26 | 1. Upload the `wordpress-for-web-apps` folder to the `/wp-content/plugins/` directory. 27 | 2. Activate the plugin through the Plugins menu in WordPress. 28 | 29 | To make sure you always get the latest updates, it’s recommended that you also install the [GitHub Updater plugin](https://github.com/afragen/github-updater). 30 | 31 | 32 | 33 | ## Using WordPress for Web Apps 34 | 35 | Configure all of your settings under `Settings` > `Web Apps` in the WordPress Dashboard. 36 | 37 | ### Shortcodes 38 | 39 | - `[wpwa_login]` - Login form 40 | - `[wpwa_signup]` - Sign up form 41 | - `[wpwa_change_email]` - Change email form 42 | - `[wpwa_change_password]` - Change password form 43 | - `[wpwa_forgot_password]` - Forgot password/password reset form 44 | - `[wpwa_delete_account]` - Delete account form 45 | - `[wpwa_logout]` - Logout URL (can be included as a `wp_nav_menu()` URL) 46 | - `[wpwa_username]` - The current user's username (can be included as the text in a `wp_nav_menu()` link) 47 | - `[wpwa_referrer]` - Adds `referrer={{current page URL}}`, handy for login/signup redirects (can be included in a `wp_nav_menu()` URL) 48 | 49 | ### User Access 50 | 51 | All pages will now include a metabox labeled *User Access*. Select `Everyone`, `Only Logged In Users`, or `Only Logged Out Users` as desired and publish or update your page. 52 | 53 | ### Action Hooks 54 | 55 | #### wpwebapp_after_login 56 | 57 | Runs after a user has logged in. Passes in the user's `$username` as an argument. 58 | 59 | ```php 60 | do_action( 'wpwebapp_after_login', $username ); 61 | ``` 62 | 63 | #### wpwebapp_after_signup 64 | 65 | Runs after a user has signed up. Passes in the new user's `$username` and `$email` as arguments. 66 | 67 | ```php 68 | do_action( 'wpwebapp_after_signup', $username, $email ); 69 | ``` 70 | 71 | #### wpwebapp_after_email_change 72 | 73 | Runs after a user has changed their email address. Passes in the user's `$user_id` and `$old_email` as arguments. 74 | 75 | ```php 76 | do_action( 'wpwebapp_after_email_change', $user_id, $old_email ); 77 | ``` 78 | 79 | #### wpwebapp_after_password_change 80 | 81 | Runs after a user's password has been changed. Passes in the user's `$user_id` as an argument. 82 | 83 | ```php 84 | do_action( 'wpwebapp_after_password_change', $user_id ); 85 | ``` 86 | 87 | #### wpwebapp_after_password_forgot_email_sent 88 | 89 | Runs after a password reset email is sent to a user. Passes in the user's `$user_id` as an argument. 90 | 91 | ```php 92 | do_action( 'wpwebapp_after_password_forgot_email_sent', $user_id ); 93 | ``` 94 | 95 | #### wpwebapp_after_password_reset 96 | 97 | Runs after a user's password has been reset. Passes in the user's `$user_id` as an argument. 98 | 99 | ```php 100 | do_action( 'wpwebapp_after_password_reset', $user_id ); 101 | ``` 102 | 103 | #### wpwebapp_after_delete_user 104 | 105 | Runs after a user deletes their account. Passes in the former user's `$username` and `$email` as arguments. 106 | 107 | ```php 108 | do_action( 'wpwebapp_after_delete_user', $username, $email ); 109 | ``` 110 | 111 | ### Redirecting after login or signup 112 | 113 | To redirect a user back to their current page after login or sign up, add the `referrer={{current URL}}` query string to the login or sign up page URL, where `{{current URL}}` is the URL of the page the user is currently on. You can also use the `[wpwa_referrer]` shortcode to handle this dynamically. 114 | 115 | 116 | 117 | ## CSS Hooks 118 | 119 | Every form and input includes a unique `id` you can hook into for styling. Additionally, form element categories also include shared classes you can use to easily style like elements in a consistent way. 120 | 121 | - `.wpwebapp-form-label` - Form labels 122 | - `.wpwebapp-form-input` - Text inputs 123 | - `.wpwebaspp-form-password` - Password inputs 124 | - `.wpwebapp-form-button` - Form buttons and input[type="submit"] 125 | - `.wpwebapp-form-label-checkbox` - Labels for checkboxes 126 | - `.wpwebapp-form-checkbox` - Checkboxes 127 | 128 | 129 | 130 | ## How to Contribute 131 | 132 | To contribute to this project, please consult the [Contribution Guidelines](CONTRIBUTING.md). 133 | 134 | 135 | 136 | ## License 137 | 138 | The code is available under the [MIT License](LICENSE.md). 139 | -------------------------------------------------------------------------------- /includes/helpers.php: -------------------------------------------------------------------------------- 1 | toArray(); 42 | } 43 | 44 | // Unset session value 45 | if ( $unset ) { 46 | unset( $wp_session[$name] ); 47 | } 48 | 49 | return $value; 50 | 51 | } 52 | 53 | 54 | 55 | /** 56 | * URL Helpers 57 | * Get, sanitize, and process URLs. 58 | */ 59 | 60 | // Get and sanitize the current URL 61 | function wpwebapp_get_url() { 62 | $url = @( $_SERVER['HTTPS'] != 'on' ) ? 'http://' . $_SERVER['SERVER_NAME'] : 'https://' . $_SERVER['SERVER_NAME']; 63 | $url .= ( $_SERVER['SERVER_PORT'] !== 80 ) ? ":" . $_SERVER['SERVER_PORT'] : ''; 64 | $url .= $_SERVER['REQUEST_URI']; 65 | return $url; 66 | } 67 | 68 | // Get the site domain and remove the www. 69 | function wpwebapp_get_site_domain() { 70 | $sitename = strtolower( $_SERVER['SERVER_NAME'] ); 71 | if ( substr( $sitename, 0, 4 ) == 'www.' ) { 72 | $sitename = substr( $sitename, 4 ); 73 | } 74 | return $sitename; 75 | } 76 | 77 | // Prepare URL for status string 78 | function wpwebapp_prepare_url( $url ) { 79 | 80 | // If URL has a '?', add an '&'. 81 | // Otherwise, add a '?'. 82 | $url_status = strpos($url, '?'); 83 | if ( $url_status === false ) { 84 | $concate = '?'; 85 | } 86 | else { 87 | $concate = '&'; 88 | } 89 | 90 | return $url . $concate; 91 | 92 | } 93 | 94 | // Remove a $_GET variable from the URL 95 | function wpwebapp_clean_url( $variable, $url ) { 96 | $new_url = preg_replace('/(?:&|(\?))' . $variable . '=[^&]*(?(1)&|)?/i', '$1', $url); 97 | $last_char = substr( $new_url, -1 ); 98 | if ( $last_char == '?' ) { 99 | $new_url = substr($new_url, 0, -1); 100 | } 101 | return $new_url; 102 | } 103 | 104 | // Get the proper redirect URL 105 | function wpwebapp_get_redirect_url( $id, $refer = 'off' ) { 106 | $url = $id === 0 || $id === '0' ? get_home_url() : get_permalink( $id ); 107 | if ( $refer === 'on' ) { 108 | $url = wpwebapp_prepare_url( $url ) . 'referrer=' . wpwebapp_get_url(); 109 | } 110 | return esc_url_raw( $url ); 111 | } 112 | 113 | // Set a password reset key 114 | function wpwebapp_set_reset_key( $user_id, $url, $expires ) { 115 | 116 | // Add a secret, temporary key to the database 117 | $key = wp_generate_password( 48, false ); 118 | set_transient( 'wpwebapp_forgot_password_key_' . $key . $user_id, $key, 60 * 60 * $expires ); 119 | 120 | // Return a URL with the reset key 121 | return wpwebapp_prepare_url( $url ) . 'reset_pw=' . $key . $user_id; 122 | } 123 | 124 | 125 | 126 | /** 127 | * String tests 128 | * Test strings for letters, numbers, and special characters. 129 | * @link http://stackoverflow.com/a/9588010/1293256 130 | */ 131 | 132 | // Does string contain letter? 133 | function wpwebapp_has_letters( $string ) { 134 | return preg_match( '/[a-zA-Z]/', $string ); 135 | } 136 | 137 | // Does string contain numbers? 138 | function wpwebapp_has_numbers( $string ) { 139 | return preg_match( '/\d/', $string ); 140 | } 141 | 142 | // Does string contain special characters? 143 | function wpwebapp_has_special_chars( $string ) { 144 | return preg_match('/[^a-zA-Z\d]/', $string); 145 | } 146 | 147 | // Does string contain mixed case? 148 | function wpwebapp_has_mixed_case( $string ) { 149 | if ( empty( preg_match('/[a-z]/', $string) ) ) return false; 150 | if ( empty( preg_match('/[A-Z]/', $string) ) ) return false; 151 | return true; 152 | } -------------------------------------------------------------------------------- /includes/migrate-options.php: -------------------------------------------------------------------------------- 1 | $saved['signup_username_label'], 23 | 'signup_email_label' => $saved['signup_email_label'], 24 | 'signup_password_label' => $saved['signup_password_label'], 25 | 'signup_submit_text' => $saved['signup_submit_text'], 26 | 'signup_show_requirements' => ( array_key_exists('signup_show_requirements', $saved) ? $saved['signup_show_requirements'] : 'off' ), 27 | 'signup_username_field_empty_error' => $saved['signup_username_field_empty_error'], 28 | 'signup_email_field_empty_error' => $saved['signup_email_field_empty_error'], 29 | 'signup_password_field_empty_error' => $saved['signup_password_field_empty_error'], 30 | 'signup_username_invalid_error' => $saved['signup_username_invalid_error'], 31 | 'signup_username_exists_error' => $saved['signup_username_exists_error'], 32 | 'signup_email_invalid_error' => $saved['signup_email_invalid_error'], 33 | 'signup_email_exists_error' => $saved['signup_email_exists_error'], 34 | 'signup_login_failed_error' => $saved['signup_login_failed_error'], 35 | 'signup_receive_notifications' => ( array_key_exists('signup_receive_notifications', $saved) ? $saved['signup_receive_notifications'] : 'off' ), 36 | 'signup_notification_to_admin' => $saved['signup_notification_to_admin'], 37 | 'signup_send_notifications' => ( array_key_exists('signup_send_notifications', $saved) ? $saved['signup_send_notifications'] : 'off' ), 38 | 'signup_notification_to_user' => $saved['signup_notification_to_user'], 39 | 'create_user_password_time_valid' => $saved['create_user_password_time_valid'], 40 | 'create_user_send_notifications' => ( array_key_exists('create_user_send_notifications', $saved) ? $saved['create_user_send_notifications'] : 'off' ), 41 | 'create_user_notification' => $saved['create_user_notification'], 42 | )); 43 | 44 | update_option('wpwebapp_theme_options_login', array( 45 | 'login_username_label' => $saved['login_username_label'], 46 | 'login_password_label' => $saved['login_password_label'], 47 | 'login_rememberme_label' => $saved['login_rememberme_label'], 48 | 'login_submit_text' => $saved['login_submit_text'], 49 | 'login_username_field_empty_error' => $saved['login_username_field_empty_error'], 50 | 'login_password_field_empty_error' => $saved['login_password_field_empty_error'], 51 | 'login_failed_error' => $saved['login_failed_error'], 52 | )); 53 | 54 | update_option('wpwebapp_theme_options_redirects', array( 55 | 'login_redirect' => $saved['login_redirect'], 56 | 'logout_redirect' => $saved['logout_redirect'], 57 | 'password_reset_redirect' => $saved['password_reset_redirect'], 58 | 'add_redirect_referrer' => ( array_key_exists('add_redirect_referrer', $saved) ? $saved['add_redirect_referrer'] : 'off' ), 59 | )); 60 | 61 | update_option('wpwebapp_theme_options_change_email', array( 62 | 'email_change_current_email_label' => $saved['email_change_current_email_label'], 63 | 'email_change_password_label' => $saved['email_change_password_label'], 64 | 'email_change_submit_text' => $saved['email_change_submit_text'], 65 | 'email_change_email_field_empty_error' => $saved['email_change_email_field_empty_error'], 66 | 'email_change_password_field_empty_error' => $saved['email_change_password_field_empty_error'], 67 | 'email_change_password_error' => $saved['email_change_password_error'], 68 | 'email_change_success' => $saved['email_change_success'], 69 | )); 70 | 71 | update_option('wpwebapp_theme_options_change_password', array( 72 | 'password_change_current_password_label' => $saved['password_change_current_password_label'], 73 | 'password_change_new_password_label' => $saved['password_change_new_password_label'], 74 | 'password_change_submit_text' => $saved['password_change_submit_text'], 75 | 'password_change_show_requirements' => ( array_key_exists('password_change_show_requirements', $saved) ? $saved['password_change_show_requirements'] : 'off' ), 76 | 'password_change_forced_reset_error' => $saved['password_change_forced_reset_error'], 77 | 'password_change_current_password_field_empty_error' => $saved['password_change_current_password_field_empty_error'], 78 | 'password_change_new_password_field_empty_error' => $saved['password_change_new_password_field_empty_error'], 79 | 'password_change_password_error' => $saved['password_change_password_error'], 80 | 'password_change_success' => $saved['password_change_success'], 81 | 'password_change_receive_notifications' => ( array_key_exists('password_change_receive_notifications', $saved) ? $saved['password_change_receive_notifications'] : 'off' ), 82 | 'password_change_notification_to_admin' => $saved['password_change_notification_to_admin'], 83 | 'password_change_send_notifications' => ( array_key_exists('password_change_send_notifications', $saved) ? $saved['password_change_send_notifications'] : 'off' ), 84 | 'password_change_notification_to_user' => $saved['password_change_notification_to_user'], 85 | )); 86 | 87 | update_option('wpwebapp_theme_options_forgot_password', array( 88 | 'password_reset_url' => $saved['password_reset_url'], 89 | 'password_forgot_label' => $saved['password_forgot_label'], 90 | 'password_forgot_submit_text' => $saved['password_forgot_submit_text'], 91 | 'password_reset_label' => $saved['password_reset_label'], 92 | 'password_reset_submit_text' => $saved['password_reset_submit_text'], 93 | 'password_reset_show_requirements' => ( array_key_exists('password_reset_show_requirements', $saved) ? $saved['password_reset_show_requirements'] : 'off' ), 94 | 'password_forgot_password_field_empty_error' => $saved['password_forgot_password_field_empty_error'], 95 | 'password_forgot_password_invalid_user_error' => $saved['password_forgot_password_invalid_user_error'], 96 | 'password_forgot_password_is_admin_error' => $saved['password_forgot_password_is_admin_error'], 97 | 'password_forgot_password_email_error' => $saved['password_forgot_password_email_error'], 98 | 'password_forgot_password_reset_key_expired_error' => $saved['password_forgot_password_reset_key_expired_error'], 99 | 'password_forgot_password_success' => $saved['password_forgot_password_success'], 100 | 'password_reset_password_field_empty_error' => $saved['password_reset_password_field_empty_error'], 101 | 'password_reset_time_valid' => $saved['password_reset_time_valid'], 102 | 'password_reset_notification_email' => $saved['password_reset_notification_email'], 103 | )); 104 | 105 | update_option('wpwebapp_theme_options_delete_account', array( 106 | 'delete_account_password_label' => $saved['delete_account_password_label'], 107 | 'delete_account_submit_text' => $saved['delete_account_submit_text'], 108 | 'delete_account_password_error' => $saved['delete_account_password_error'], 109 | 'delete_account_redirect' => $saved['delete_account_redirect'], 110 | )); 111 | 112 | update_option('wpwebapp_theme_options_security', array( 113 | 'password_minimum_length' => $saved['password_minimum_length'], 114 | 'password_requires_letters' => ( array_key_exists('password_requires_letters', $saved) ? $saved['password_requires_letters'] : 'off' ), 115 | 'password_requires_numbers' => ( array_key_exists('password_requires_numbers', $saved) ? $saved['password_requires_numbers'] : 'off' ), 116 | 'password_requires_special_characters' => ( array_key_exists('password_requires_special_characters', $saved) ? $saved['password_requires_special_characters'] : 'off' ), 117 | 'password_requires_mixed_case' => ( array_key_exists('password_requires_mixed_case', $saved) ? $saved['password_requires_mixed_case'] : 'off' ), 118 | 'show_admin_bar' => ( array_key_exists('show_admin_bar', $saved) ? $saved['show_admin_bar'] : 'off' ), 119 | )); 120 | 121 | // Remove the old settings 122 | delete_option( 'wpwebapp_theme_options' ); 123 | 124 | } 125 | add_action( 'plugins_loaded', 'wpwebapp_migrate_settings' ); -------------------------------------------------------------------------------- /includes/wp-session-manager/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | -------------------------------------------------------------------------------- /includes/wp-session-manager/README.md: -------------------------------------------------------------------------------- 1 | WP Session Manager 2 | ================== 3 | 4 | Prototype session management for WordPress. 5 | 6 | Description 7 | ----------- 8 | 9 | Adds `$_SESSION`-like functionality to WordPress. 10 | 11 | Every visitor, logged in or not, will be issued an instance of `WP_Session`. Their instance will be identified by an ID 12 | stored in the `_wp_session` cookie. Typically, session data will be stored in a WordPress transient, but if your 13 | installation has a caching system in-place (i.e. memcached), the session data might be stored in memory. 14 | 15 | This provides plugin and theme authors the ability to use WordPress-managed session variables without having to use the 16 | standard PHP `$_SESSION` superglobal. 17 | 18 | Installation 19 | ------------ 20 | 21 | **Manual Installation** 22 | 23 | 1. Upload the entire `/wp-session-manager` folder to the `/wp-content/plugins/` directory. 24 | 1. Activate the plugin through the 'Plugins' menu in WordPress. 25 | 1. Use `WP_Session::get_instance();` in your code. 26 | 27 | Frequently Asked Questions 28 | -------------------------- 29 | 30 | **How do I add session variables?** 31 | 32 | First, make a reference to the WP_Session instance. Then, use it like an associative array, just like `$_SESSION`: 33 | 34 | `$wp_session = WP_Session::get_instance(); 35 | $wp_session['user_name'] = 'User Name'; // A string 36 | $wp_session['user_contact'] = array( 'email' => 'user@name.com' ); // An array 37 | $wp_session['user_obj'] = new WP_User( 1 ); // An object` 38 | 39 | **How long do session variables live?** 40 | 41 | By default, session variables will live for 24 minutes from the last time they were accessed - either read or write. 42 | 43 | This value can be changed by using the `wp_session_expiration` filter: 44 | 45 | `add_filter( 'wp_session_expiration', function() { return 60 * 60; } ); // Set expiration to 1 hour` 46 | 47 | Screenshots 48 | ----------- 49 | 50 | None 51 | 52 | Changelog 53 | --------- 54 | 55 | **1.2.0** 56 | 57 | - Update: Enhanced plugin organization 58 | - Update: Added WP_CLI support for session management 59 | - Update: Add Composer definitions 60 | - Fix: Break up the deletion of old sessions so queries don't time out under load 61 | 62 | **1.1.2** 63 | 64 | - Fix a race condition where session expiration options could accidentally be set to autoload 65 | - Make the garbage collection routine run hourly to alleviate long-running tasks on larger sites 66 | 67 | **1.1.1** 68 | 69 | - Fix a bug where session expiration was not properly set upon instantiation 70 | 71 | **1.1** 72 | 73 | - Implement Recursive_ArrayAccess to provide multidimensional array support 74 | - Better expiration for session data 75 | - Implement garbage collection to keep the database clean 76 | 77 | **1.0.2** 78 | 79 | - Switch to object persistence rather than transients 80 | 81 | **1.0.1** 82 | 83 | - Changes implementation to avoid the use of a global variable (still registered for convenience) 84 | 85 | **1.0** 86 | 87 | - First version 88 | 89 | Upgrade Notice 90 | -------------- 91 | 92 | **1.0** 93 | 94 | First version 95 | 96 | Additional Information 97 | ---------------------- 98 | 99 | **Contributors:** ericmann 100 | **Donate link:** http://jumping-duck.com/wordpress/plugins 101 | **Tags:** session 102 | **Requires at least:** 3.4.2 103 | **Tested up to:** 4.0 104 | **Stable tag:** 1.2.0 105 | **License:** GPLv2 or later 106 | **License URI:** http://www.gnu.org/licenses/gpl-2.0.html -------------------------------------------------------------------------------- /includes/wp-session-manager/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "ericmann/wp-session-manager", 3 | "type" : "wordpress-plugin", 4 | "minimum-stability": "dev", 5 | "require-dev" : {}, 6 | "require" : {} 7 | } -------------------------------------------------------------------------------- /includes/wp-session-manager/includes/class-recursive-arrayaccess.php: -------------------------------------------------------------------------------- 1 | $value ) { 41 | $this[ $key ] = $value; 42 | } 43 | } 44 | 45 | /** 46 | * Allow deep copies of objects 47 | */ 48 | public function __clone() { 49 | foreach ( $this->container as $key => $value ) { 50 | if ( $value instanceof self ) { 51 | $this[ $key ] = clone $value; 52 | } 53 | } 54 | } 55 | 56 | /** 57 | * Output the data container as a multidimensional array. 58 | * 59 | * @return array 60 | */ 61 | public function toArray() { 62 | $data = $this->container; 63 | foreach ( $data as $key => $value ) { 64 | if ( $value instanceof self ) { 65 | $data[ $key ] = $value->toArray(); 66 | } 67 | } 68 | return $data; 69 | } 70 | 71 | /*****************************************************************/ 72 | /* ArrayAccess Implementation */ 73 | /*****************************************************************/ 74 | 75 | /** 76 | * Whether a offset exists 77 | * 78 | * @link http://php.net/manual/en/arrayaccess.offsetexists.php 79 | * 80 | * @param mixed $offset An offset to check for. 81 | * 82 | * @return boolean true on success or false on failure. 83 | */ 84 | public function offsetExists( $offset ) { 85 | return isset( $this->container[ $offset ]) ; 86 | } 87 | 88 | /** 89 | * Offset to retrieve 90 | * 91 | * @link http://php.net/manual/en/arrayaccess.offsetget.php 92 | * 93 | * @param mixed $offset The offset to retrieve. 94 | * 95 | * @return mixed Can return all value types. 96 | */ 97 | public function offsetGet( $offset ) { 98 | return isset( $this->container[ $offset ] ) ? $this->container[ $offset ] : null; 99 | } 100 | 101 | /** 102 | * Offset to set 103 | * 104 | * @link http://php.net/manual/en/arrayaccess.offsetset.php 105 | * 106 | * @param mixed $offset The offset to assign the value to. 107 | * @param mixed $value The value to set. 108 | * 109 | * @return void 110 | */ 111 | public function offsetSet( $offset, $data ) { 112 | if ( is_array( $data ) ) { 113 | $data = new self( $data ); 114 | } 115 | if ( $offset === null ) { // don't forget this! 116 | $this->container[] = $data; 117 | } else { 118 | $this->container[ $offset ] = $data; 119 | } 120 | 121 | $this->dirty = true; 122 | } 123 | 124 | /** 125 | * Offset to unset 126 | * 127 | * @link http://php.net/manual/en/arrayaccess.offsetunset.php 128 | * 129 | * @param mixed $offset The offset to unset. 130 | * 131 | * @return void 132 | */ 133 | public function offsetUnset( $offset ) { 134 | unset( $this->container[ $offset ] ); 135 | 136 | $this->dirty = true; 137 | } 138 | 139 | 140 | /*****************************************************************/ 141 | /* Iterator Implementation */ 142 | /*****************************************************************/ 143 | 144 | /** 145 | * Current position of the array. 146 | * 147 | * @link http://php.net/manual/en/iterator.current.php 148 | * 149 | * @return mixed 150 | */ 151 | public function current() { 152 | return current( $this->container ); 153 | } 154 | 155 | /** 156 | * Key of the current element. 157 | * 158 | * @link http://php.net/manual/en/iterator.key.php 159 | * 160 | * @return mixed 161 | */ 162 | public function key() { 163 | return key( $this->container ); 164 | } 165 | 166 | /** 167 | * Move the internal point of the container array to the next item 168 | * 169 | * @link http://php.net/manual/en/iterator.next.php 170 | * 171 | * @return void 172 | */ 173 | public function next() { 174 | next( $this->container ); 175 | } 176 | 177 | /** 178 | * Rewind the internal point of the container array. 179 | * 180 | * @link http://php.net/manual/en/iterator.rewind.php 181 | * 182 | * @return void 183 | */ 184 | public function rewind() { 185 | reset( $this->container ); 186 | } 187 | 188 | /** 189 | * Is the current key valid? 190 | * 191 | * @link http://php.net/manual/en/iterator.rewind.php 192 | * 193 | * @return bool 194 | */ 195 | public function valid() { 196 | return $this->offsetExists( $this->key() ); 197 | } 198 | 199 | /*****************************************************************/ 200 | /* Countable Implementation */ 201 | /*****************************************************************/ 202 | 203 | /** 204 | * Get the count of elements in the container array. 205 | * 206 | * @link http://php.net/manual/en/countable.count.php 207 | * 208 | * @return int 209 | */ 210 | public function count() { 211 | return count( $this->container ); 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /includes/wp-session-manager/includes/class-wp-session-utils.php: -------------------------------------------------------------------------------- 1 | options WHERE option_name LIKE '_wp_session_expires_%'"; 20 | 21 | /** 22 | * Filter the query in case tables are non-standard. 23 | * 24 | * @param string $query Database count query 25 | */ 26 | $query = apply_filters( 'wp_session_count_query', $query ); 27 | 28 | $sessions = $wpdb->get_var( $query ); 29 | 30 | return absint( $sessions ); 31 | } 32 | 33 | /** 34 | * Create a new, random session in the database. 35 | * 36 | * @param null|string $date 37 | */ 38 | public static function create_dummy_session( $date = null ) { 39 | // Generate our date 40 | if ( null !== $date ) { 41 | $time = strtotime( $date ); 42 | 43 | if ( false === $time ) { 44 | $date = null; 45 | } else { 46 | $expires = date( 'U', strtotime( $date ) ); 47 | } 48 | } 49 | 50 | // If null was passed, or if the string parsing failed, fall back on a default 51 | if ( null === $date ) { 52 | /** 53 | * Filter the expiration of the session in the database 54 | * 55 | * @param int 56 | */ 57 | $expires = time() + (int) apply_filters( 'wp_session_expiration', 30 * 60 ); 58 | } 59 | 60 | $session_id = self::generate_id(); 61 | 62 | // Store the session 63 | add_option( "_wp_session_{$session_id}", array(), '', 'no' ); 64 | add_option( "_wp_session_expires_{$session_id}", $expires, '', 'no' ); 65 | } 66 | 67 | /** 68 | * Delete old sessions from the database. 69 | * 70 | * @param int $limit Maximum number of sessions to delete. 71 | * 72 | * @global wpdb $wpdb 73 | * 74 | * @return int Sessions deleted. 75 | */ 76 | public static function delete_old_sessions( $limit = 1000 ) { 77 | global $wpdb; 78 | 79 | $limit = absint( $limit ); 80 | $keys = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE option_name LIKE '_wp_session_expires_%' ORDER BY option_value ASC LIMIT 0, {$limit}" ); 81 | 82 | $now = time(); 83 | $expired = array(); 84 | $count = 0; 85 | 86 | foreach( $keys as $expiration ) { 87 | $key = $expiration->option_name; 88 | $expires = $expiration->option_value; 89 | 90 | if ( $now > $expires ) { 91 | $session_id = addslashes( substr( $key, 20 ) ); 92 | 93 | $expired[] = $key; 94 | $expired[] = "_wp_session_{$session_id}"; 95 | 96 | $count += 1; 97 | } 98 | } 99 | 100 | // Delete expired sessions 101 | if ( ! empty( $expired ) ) { 102 | $names = implode( "','", $expired ); 103 | $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name IN ('{$names}')" ); 104 | } 105 | 106 | return $count; 107 | } 108 | 109 | /** 110 | * Remove all sessions from the database, regardless of expiration. 111 | * 112 | * @global wpdb $wpdb 113 | * 114 | * @return int Sessions deleted 115 | */ 116 | public static function delete_all_sessions() { 117 | global $wpdb; 118 | 119 | $count = $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE '_wp_session_%'" ); 120 | 121 | return (int) ( $count / 2 ); 122 | } 123 | 124 | /** 125 | * Generate a new, random session ID. 126 | * 127 | * @return string 128 | */ 129 | public static function generate_id() { 130 | require_once( ABSPATH . 'wp-includes/class-phpass.php' ); 131 | $hash = new PasswordHash( 8, false ); 132 | 133 | return md5( $hash->get_random_bytes( 32 ) ); 134 | } 135 | } -------------------------------------------------------------------------------- /includes/wp-session-manager/includes/class-wp-session.php: -------------------------------------------------------------------------------- 1 | session_id = $cookie_crumbs[0]; 77 | $this->expires = $cookie_crumbs[1]; 78 | $this->exp_variant = $cookie_crumbs[2]; 79 | 80 | // Update the session expiration if we're past the variant time 81 | if ( time() > $this->exp_variant ) { 82 | $this->set_expiration(); 83 | delete_option( "_wp_session_expires_{$this->session_id}" ); 84 | add_option( "_wp_session_expires_{$this->session_id}", $this->expires, '', 'no' ); 85 | } 86 | } else { 87 | $this->session_id = WP_Session_Utils::generate_id(); 88 | $this->set_expiration(); 89 | } 90 | 91 | $this->read_data(); 92 | 93 | $this->set_cookie(); 94 | 95 | } 96 | 97 | /** 98 | * Set both the expiration time and the expiration variant. 99 | * 100 | * If the current time is below the variant, we don't update the session's expiration time. If it's 101 | * greater than the variant, then we update the expiration time in the database. This prevents 102 | * writing to the database on every page load for active sessions and only updates the expiration 103 | * time if we're nearing when the session actually expires. 104 | * 105 | * By default, the expiration time is set to 30 minutes. 106 | * By default, the expiration variant is set to 24 minutes. 107 | * 108 | * As a result, the session expiration time - at a maximum - will only be written to the database once 109 | * every 24 minutes. After 30 minutes, the session will have been expired. No cookie will be sent by 110 | * the browser, and the old session will be queued for deletion by the garbage collector. 111 | * 112 | * @uses apply_filters Calls `wp_session_expiration_variant` to get the max update window for session data. 113 | * @uses apply_filters Calls `wp_session_expiration` to get the standard expiration time for sessions. 114 | */ 115 | protected function set_expiration() { 116 | $this->exp_variant = time() + (int) apply_filters( 'wp_session_expiration_variant', 24 * 60 ); 117 | $this->expires = time() + (int) apply_filters( 'wp_session_expiration', 30 * 60 ); 118 | } 119 | 120 | /** 121 | * Set the session cookie 122 | * @uses apply_filters Calls `wp_session_cookie_secure` to set the $secure parameter of setcookie() 123 | * @uses apply_filters Calls `wp_session_cookie_httponly` to set the $httponly parameter of setcookie() 124 | */ 125 | protected function set_cookie() { 126 | $secure = apply_filters('wp_session_cookie_secure', false); 127 | $httponly = apply_filters('wp_session_cookie_httponly', false); 128 | setcookie( WP_SESSION_COOKIE, $this->session_id . '||' . $this->expires . '||' . $this->exp_variant , $this->expires, COOKIEPATH, COOKIE_DOMAIN, $secure, $httponly ); 129 | } 130 | 131 | /** 132 | * Read data from a transient for the current session. 133 | * 134 | * Automatically resets the expiration time for the session transient to some time in the future. 135 | * 136 | * @return array 137 | */ 138 | protected function read_data() { 139 | $this->container = get_option( "_wp_session_{$this->session_id}", array() ); 140 | 141 | return $this->container; 142 | } 143 | 144 | /** 145 | * Write the data from the current session to the data storage system. 146 | */ 147 | public function write_data() { 148 | $option_key = "_wp_session_{$this->session_id}"; 149 | 150 | if ( false === get_option( $option_key ) ) { 151 | add_option( "_wp_session_{$this->session_id}", $this->container, '', 'no' ); 152 | add_option( "_wp_session_expires_{$this->session_id}", $this->expires, '', 'no' ); 153 | } else { 154 | delete_option( "_wp_session_{$this->session_id}" ); 155 | add_option( "_wp_session_{$this->session_id}", $this->container, '', 'no' ); 156 | } 157 | } 158 | 159 | /** 160 | * Output the current container contents as a JSON-encoded string. 161 | * 162 | * @return string 163 | */ 164 | public function json_out() { 165 | return json_encode( $this->container ); 166 | } 167 | 168 | /** 169 | * Decodes a JSON string and, if the object is an array, overwrites the session container with its contents. 170 | * 171 | * @param string $data 172 | * 173 | * @return bool 174 | */ 175 | public function json_in( $data ) { 176 | $array = json_decode( $data ); 177 | 178 | if ( is_array( $array ) ) { 179 | $this->container = $array; 180 | return true; 181 | } 182 | 183 | return false; 184 | } 185 | 186 | /** 187 | * Regenerate the current session's ID. 188 | * 189 | * @param bool $delete_old Flag whether or not to delete the old session data from the server. 190 | */ 191 | public function regenerate_id( $delete_old = false ) { 192 | if ( $delete_old ) { 193 | delete_option( "_wp_session_{$this->session_id}" ); 194 | } 195 | 196 | $this->session_id = WP_Session_Utils::generate_id(); 197 | 198 | $this->set_cookie(); 199 | } 200 | 201 | /** 202 | * Check if a session has been initialized. 203 | * 204 | * @return bool 205 | */ 206 | public function session_started() { 207 | return !!self::$instance; 208 | } 209 | 210 | /** 211 | * Return the read-only cache expiration value. 212 | * 213 | * @return int 214 | */ 215 | public function cache_expiration() { 216 | return $this->expires; 217 | } 218 | 219 | /** 220 | * Flushes all session variables. 221 | */ 222 | public function reset() { 223 | $this->container = array(); 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /includes/wp-session-manager/includes/wp-cli.php: -------------------------------------------------------------------------------- 1 | ] 39 | * : Set the batch size for deleting old sessions 40 | * 41 | * [--limit=] 42 | * : Delete just this number of old sessions 43 | * 44 | * ## EXAMPLES 45 | * 46 | * wp session delete 47 | * wp session delete [--batch=] 48 | * wp session delete [--limit=] 49 | * wp session delete [--all] 50 | * 51 | * @synopsis [--all] [--batch=] [--limit=] 52 | * 53 | * @param array $args 54 | * @param array $assoc_args 55 | */ 56 | public function delete( $args, $assoc_args ) { 57 | if ( isset( $assoc_args['limit'] ) ) { 58 | $limit = absint( $assoc_args['limit'] ); 59 | 60 | $count = WP_Session_Utils::delete_old_sessions( $limit ); 61 | 62 | if ( $count > 0 ) { 63 | \WP_CLI::line( sprintf( 'Deleted %d sessions.', $count ) ); 64 | } 65 | 66 | // Clear memory 67 | self::free_up_memory(); 68 | return; 69 | } 70 | 71 | // Determine if we're deleting all sessions or just a subset. 72 | $all = isset( $assoc_args['all'] ); 73 | 74 | /** 75 | * Determine the size of each batch for deletion. 76 | * 77 | * @param int 78 | */ 79 | $batch = isset( $assoc_args['batch'] ) ? absint( $assoc_args['batch'] ) : apply_filters( 'wp_session_delete_batch_size', 1000 ); 80 | 81 | switch ( $all ) { 82 | case true: 83 | $count = WP_Session_Utils::delete_all_sessions(); 84 | 85 | \WP_CLI::line( sprintf( 'Deleted all %d sessions.', $count ) ); 86 | break; 87 | case false: 88 | do { 89 | $count = WP_Session_Utils::delete_old_sessions( $batch ); 90 | 91 | if ( $count > 0 ) { 92 | \WP_CLI::line( sprintf( 'Deleted %d sessions.', $count ) ); 93 | } 94 | 95 | // Clear memory 96 | self::free_up_memory(); 97 | } while ( $count > 0 ); 98 | break; 99 | } 100 | } 101 | 102 | /** 103 | * Generate a number of dummy sessions for testing purposes. 104 | * 105 | * ## OPTIONS 106 | * 107 | * 108 | * : Number of sessions to create. 109 | * 110 | * [--expires=] 111 | * : Optional expiration time tagged for each session. Will use WordPress' local time. 112 | * 113 | * ## EXAMPLES 114 | * 115 | * wp session generate 5000 116 | * wp session generate 5000 --expires="2014-11-09T08:00" 117 | * 118 | * @synopsis [--expires=] 119 | * 120 | * @param array $args 121 | * @param array $assoc_args 122 | */ 123 | public function generate( $args, $assoc_args ) { 124 | $count = absint( $args[0] ); 125 | $date = isset( $assoc_args['expires'] ) ? $assoc_args['expires'] : null; 126 | 127 | $notify = \WP_CLI\Utils\make_progress_bar( 'Generating sessions', $count ); 128 | 129 | for ( $i = 0; $i < $count; $i ++ ) { 130 | WP_Session_Utils::create_dummy_session( $date ); 131 | $notify->tick(); 132 | } 133 | 134 | $notify->finish(); 135 | } 136 | 137 | /** 138 | * Free up memory 139 | * 140 | * @global WP_Object_Cache $wp_object_cache 141 | * @global wpdb $wpdb 142 | */ 143 | private function free_up_memory() { 144 | global $wp_object_cache, $wpdb; 145 | $wpdb->queries = array(); 146 | 147 | if ( ! is_object( $wp_object_cache ) ) { 148 | return; 149 | } 150 | 151 | $wp_object_cache->group_ops = array(); 152 | $wp_object_cache->stats = array(); 153 | $wp_object_cache->memcache_debug = array(); 154 | $wp_object_cache->cache = array(); 155 | } 156 | } 157 | 158 | \WP_CLI::add_command( 'session', 'WP_Session_Command' ); -------------------------------------------------------------------------------- /includes/wp-session-manager/includes/wp-session.php: -------------------------------------------------------------------------------- 1 | cache_expiration(); 22 | } 23 | 24 | /** 25 | * Alias of wp_session_write_close() 26 | */ 27 | function wp_session_commit() { 28 | wp_session_write_close(); 29 | } 30 | 31 | /** 32 | * Load a JSON-encoded string into the current session. 33 | * 34 | * @param string $data 35 | */ 36 | function wp_session_decode( $data ) { 37 | $wp_session = WP_Session::get_instance(); 38 | 39 | return $wp_session->json_in( $data ); 40 | } 41 | 42 | /** 43 | * Encode the current session's data as a JSON string. 44 | * 45 | * @return string 46 | */ 47 | function wp_session_encode() { 48 | $wp_session = WP_Session::get_instance(); 49 | 50 | return $wp_session->json_out(); 51 | } 52 | 53 | /** 54 | * Regenerate the session ID. 55 | * 56 | * @param bool $delete_old_session 57 | * 58 | * @return bool 59 | */ 60 | function wp_session_regenerate_id( $delete_old_session = false ) { 61 | $wp_session = WP_Session::get_instance(); 62 | 63 | $wp_session->regenerate_id( $delete_old_session ); 64 | 65 | return true; 66 | } 67 | 68 | /** 69 | * Start new or resume existing session. 70 | * 71 | * Resumes an existing session based on a value sent by the _wp_session cookie. 72 | * 73 | * @return bool 74 | */ 75 | function wp_session_start() { 76 | $wp_session = WP_Session::get_instance(); 77 | do_action( 'wp_session_start' ); 78 | 79 | return $wp_session->session_started(); 80 | } 81 | if ( ! defined( 'WP_CLI' ) || false === WP_CLI ) { 82 | add_action( 'plugins_loaded', 'wp_session_start' ); 83 | } 84 | 85 | /** 86 | * Return the current session status. 87 | * 88 | * @return int 89 | */ 90 | function wp_session_status() { 91 | $wp_session = WP_Session::get_instance(); 92 | 93 | if ( $wp_session->session_started() ) { 94 | return PHP_SESSION_ACTIVE; 95 | } 96 | 97 | return PHP_SESSION_NONE; 98 | } 99 | 100 | /** 101 | * Unset all session variables. 102 | */ 103 | function wp_session_unset() { 104 | $wp_session = WP_Session::get_instance(); 105 | 106 | $wp_session->reset(); 107 | } 108 | 109 | /** 110 | * Write session data and end session 111 | */ 112 | function wp_session_write_close() { 113 | $wp_session = WP_Session::get_instance(); 114 | 115 | $wp_session->write_data(); 116 | do_action( 'wp_session_commit' ); 117 | } 118 | if ( ! defined( 'WP_CLI' ) || false === WP_CLI ) { 119 | add_action( 'shutdown', 'wp_session_write_close' ); 120 | } 121 | 122 | /** 123 | * Clean up expired sessions by removing data and their expiration entries from 124 | * the WordPress options table. 125 | * 126 | * This method should never be called directly and should instead be triggered as part 127 | * of a scheduled task or cron job. 128 | */ 129 | function wp_session_cleanup() { 130 | if ( defined( 'WP_SETUP_CONFIG' ) ) { 131 | return; 132 | } 133 | 134 | if ( ! defined( 'WP_INSTALLING' ) ) { 135 | /** 136 | * Determine the size of each batch for deletion. 137 | * 138 | * @param int 139 | */ 140 | $batch_size = apply_filters( 'wp_session_delete_batch_size', 1000 ); 141 | 142 | // Delete a batch of old sessions 143 | WP_Session_Utils::delete_old_sessions( $batch_size ); 144 | } 145 | 146 | // Allow other plugins to hook in to the garbage collection process. 147 | do_action( 'wp_session_cleanup' ); 148 | } 149 | add_action( 'wp_session_garbage_collection', 'wp_session_cleanup' ); 150 | 151 | /** 152 | * Register the garbage collector as a twice daily event. 153 | */ 154 | function wp_session_register_garbage_collection() { 155 | if ( ! wp_next_scheduled( 'wp_session_garbage_collection' ) ) { 156 | wp_schedule_event( time(), 'hourly', 'wp_session_garbage_collection' ); 157 | } 158 | } 159 | add_action( 'wp', 'wp_session_register_garbage_collection' ); 160 | -------------------------------------------------------------------------------- /includes/wp-session-manager/readme.txt: -------------------------------------------------------------------------------- 1 | === WP Session Manager === 2 | Contributors: ericmann 3 | Donate link: http://jumping-duck.com/wordpress/plugins 4 | Tags: session 5 | Requires at least: 3.4.2 6 | Tested up to: 4.0 7 | Stable tag: 1.2.0 8 | License: GPLv2 or later 9 | License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 | 11 | Prototype session management for WordPress. 12 | 13 | == Description == 14 | 15 | Adds `$_SESSION`-like functionality to WordPress. 16 | 17 | Every visitor, logged in or not, will be issued an instance of `WP_Session`. Their instance will be identified by an ID 18 | stored in the `_wp_session` cookie. Typically, session data will be stored in a WordPress transient, but if your 19 | installation has a caching system in-place (i.e. memcached), the session data might be stored in memory. 20 | 21 | This provides plugin and theme authors the ability to use WordPress-managed session variables without having to use the 22 | standard PHP `$_SESSION` superglobal. 23 | 24 | == Installation == 25 | 26 | = Manual Installation = 27 | 28 | 1. Upload the entire `/wp-session-manager` folder to the `/wp-content/plugins/` directory. 29 | 1. Activate the plugin through the 'Plugins' menu in WordPress. 30 | 1. Use `WP_Session::get_instance()` in your code. 31 | 32 | == Frequently Asked Questions == 33 | 34 | = How do I add session variables? = 35 | 36 | First, make a reference to the WP_Session instance. Then, use it like an associative array, just like `$_SESSION`: 37 | 38 | `$wp_session = WP_Session::get_instance(); 39 | $wp_session['user_name'] = 'User Name'; // A string 40 | $wp_session['user_contact'] = array( 'email' => 'user@name.com' ); // An array 41 | $wp_session['user_obj'] = new WP_User( 1 ); // An object` 42 | 43 | = How long do session variables live? = 44 | 45 | By default, session variables will live for 24 minutes from the last time they were accessed - either read or write. 46 | 47 | This value can be changed by using the `wp_session_expiration` filter: 48 | 49 | `add_filter( 'wp_session_expiration', function() { return 60 * 60; } ); // Set expiration to 1 hour` 50 | 51 | == Screenshots == 52 | 53 | None 54 | 55 | == Changelog == 56 | 57 | = 1.2.0 = 58 | * Update: Enhanced plugin organization 59 | * Update: Added WP_CLI support for session management 60 | * Update: Add Composer definitions 61 | * Fix: Break up the deletion of old sessions so queries don't time out under load 62 | 63 | = 1.1.2 = 64 | * Fix a race condition where session expiration options could accidentally be set to autoload 65 | * Make the garbage collection routine run hourly to alleviate long-running tasks on larger sites 66 | 67 | = 1.1.1 = 68 | * Fix a bug where session expiration was not properly set upon instantiation 69 | 70 | = 1.1 = 71 | * Implement Recursive_ArrayAccess to provide multidimensional array support 72 | * Better expiration for session data 73 | * Implement garbage collection to keep the database clean 74 | 75 | = 1.0.2 = 76 | * Switch to object persistence rather than transients 77 | 78 | = 1.0.1 = 79 | * Changes implementation to avoid the use of a global variable (still registered for convenience) 80 | 81 | = 1.0 = 82 | * First version 83 | 84 | == Upgrade Notice == 85 | 86 | = 1.0 = 87 | First version -------------------------------------------------------------------------------- /includes/wp-session-manager/wp-session-manager.php: -------------------------------------------------------------------------------- 1 | 'asc', 31 | 'sort_column' => 'post_title', 32 | 'post_type' => 'page', 33 | 'post_status' => 'publish' 34 | ) 35 | ); 36 | ?> 37 | $page ) : ?> 38 | 39 | 40 | 47 |
48 | 49 | 50 |
51 | 52 |
53 | 54 | 55 |
56 | 57 |
58 | 59 | 60 |
61 | 68 |
69 | 70 | 71 |
72 | 73 | 80 |
81 | 85 |
86 | 93 |
94 | 95 | 96 |
97 |
98 | 99 |
100 | 101 | 102 |
103 |
104 | 105 |
106 | 107 | 108 |
109 |
110 | 111 |
112 | 113 | 114 |
115 |
116 | 117 |
118 | 119 | 120 |
121 |
122 | 123 |
124 | 125 | 126 |
127 |
128 | 129 |
130 | 131 | 132 |
133 |
134 | 135 |
136 | 137 | 138 |
139 | 146 |
147 | 151 |
152 |
153 | 154 |
155 | 156 | 159 |
160 | 167 |
168 | 172 |
173 |
174 | 175 |
176 | 177 | 180 |
181 | 188 |
189 | 190 | 191 |
192 | 199 |
200 | 204 |
205 |
206 | 207 |
208 | 209 | 212 |
213 | 220 |
221 | 222 | 223 |
224 | 225 |
226 | 227 | 228 |
229 | 230 |
231 | 232 | 233 |
234 | 241 |
242 | 243 | 244 |
245 | 252 |
253 | 254 | 255 |
256 |
257 | 258 |
259 | 260 | 261 |
262 |
263 | 264 |
265 | 266 | 267 |
268 | 275 |
276 |
277 | 281 |
282 |
283 | 284 |
285 |
286 | 290 |
291 |
292 | 293 |
294 |
295 | 299 |
300 |
301 | 302 |
303 | 307 |
308 | 309 | 316 |
317 | 318 | 319 |
320 | 321 |
322 | 323 | 324 |
325 | 332 |
333 | 334 | 335 |
336 | 343 |
344 | 345 | 346 |
347 |
348 | 349 |
350 | 351 | 352 |
353 |
354 | 355 |
356 | 357 | 358 |
359 |
360 | 361 |
362 | 363 | 364 |
365 | 372 |
373 | 374 | 375 |
376 | 377 |
378 | 379 | 380 |
381 | 388 |
389 | 390 | 391 |
392 | 399 |
400 | 404 |
405 | 412 |
413 | 414 | 415 |
416 |
417 | 418 |
419 | 420 | 421 |
422 |
423 | 424 |
425 | 426 | 427 |
428 |
429 | 430 |
431 | 432 | 433 |
434 |
435 | 436 |
437 | 438 | 439 |
440 | 447 |
448 | 452 |
453 |
454 | 455 |
456 | 457 | 460 |
461 | 468 |
469 | 473 |
474 |
475 | 476 |
477 | 478 | 481 |
482 | 489 |
490 |
491 | 495 |
496 | 503 |
504 | 505 | 506 |
507 | 508 |
509 | 510 | 511 |
512 | 519 |
520 | 521 | 522 |
523 | 524 |
525 | 526 | 527 |
528 | 535 |
536 | 540 |
541 | 548 |
549 | 550 | 551 |
552 |
553 | 554 |
555 | 556 | 557 |
558 |
559 | 560 |
561 | 562 | 563 |
564 |
565 | 566 |
567 | 568 | 569 |
570 |
571 | 572 |
573 | 574 | 575 |
576 |
577 | 578 |
579 | 580 | 581 |
582 |
583 | 584 |
585 | 586 | 587 |
588 | 595 |
596 | 597 | 598 |
599 | 606 |
607 | 608 | 611 |
612 | 619 |
620 | 621 | 622 |
623 | 630 |
631 | 632 | 633 |
634 | 641 |
642 | 643 | 644 |
645 | 652 |
653 |
654 | 658 |
659 | 666 |
667 | 668 | 669 |
670 | 677 |
678 | 682 |
683 |
684 | 688 |
689 |
690 | 694 |
695 |
696 | 700 |
701 | 708 |
709 | 713 |
714 | __( 'Username', 'wpwebapp' ), 732 | 'signup_email_label' => __( 'Email', 'wpwebapp' ), 733 | 'signup_password_label' => __( 'Password', 'wpwebapp' ), 734 | 'signup_submit_text' => __( 'Sign Up', 'wpwebapp' ), 735 | 'signup_show_requirements' => 'off', 736 | 'signup_username_field_empty_error' => __( 'Please enter a username.', 'wpwebapp' ), 737 | 'signup_email_field_empty_error' => __( 'Please enter an email address.', 'wpwebapp' ), 738 | 'signup_password_field_empty_error' => __( 'Please enter a password.', 'wpwebapp' ), 739 | 'signup_username_invalid_error' => __( 'Usernames can only contain letters, numbers, and these special characters: _, space, ., -, *, and @.', 'wpwebapp' ), 740 | 'signup_username_exists_error' => __( 'Your chosen username is already in use. Sorry.', 'wpwebapp' ), 741 | 'signup_email_invalid_error' => __( 'Please use a valid email address.', 'wpwebapp' ), 742 | 'signup_email_exists_error' => __( 'Your chosen email is already in use. Sorry.', 'wpwebapp' ), 743 | 'signup_login_failed_error' => __( 'Your account was created by the system failed to log you in. Please try logging in now.', 'wpwebapp' ), 744 | 'signup_receive_notifications' => 'off', 745 | 'signup_notification_to_admin' => 'New user registration for ' . get_bloginfo('name') . '.' . "\r\n\r\n" . 'Username: [username]' . "\r\n" . 'Email: [email]' . "\r\n", 746 | 'signup_send_notifications' => 'off', 747 | 'signup_notification_to_user' => 'Welcome to ' . get_bloginfo('name') . '. Your username is [username]. Log in at [login].', 748 | 'create_user_password_time_valid' => 48, 749 | 'create_user_send_notifications' => 'off', 750 | 'create_user_notification' => 'An account for ' . get_bloginfo('name') . ' has been created for you. Your username is [username]. You can create a password for your account at [pw_reset].'. "\r\n\r\n" . 'This link is good for [expires] hours.', 751 | 752 | // Login 753 | 'login_username_label' => __( 'Username or Email', 'wpwebapp' ), 754 | 'login_password_label' => __( 'Password', 'wpwebapp' ), 755 | 'login_rememberme_label' => __( 'Remember me', 'wpwebapp' ), 756 | 'login_submit_text' => __( 'Login', 'wpwebapp' ), 757 | 'login_username_field_empty_error' => __( 'Please enter a username or email address.', 'wpwebapp' ), 758 | 'login_password_field_empty_error' => __( 'Please enter your password.', 'wpwebapp' ), 759 | 'login_failed_error' => __( 'Login failed. Please try again.', 'wpwebapp' ), 760 | 761 | // Redirect URLs 762 | 'login_redirect' => '0', 763 | 'logout_redirect' => '0', 764 | 'password_reset_redirect' => '', 765 | 'add_redirect_referrer' => 'off', 766 | 767 | // Change email address 768 | 'email_change_current_email_label' => __( 'Email', 'wpwebapp' ), 769 | 'email_change_password_label' => __( 'Password', 'wpwebapp' ), 770 | 'email_change_submit_text' => __( 'Change My Email', 'wpwebapp' ), 771 | 'email_change_email_field_empty_error' => __( 'Please enter a new email address.', 'wpwebapp' ), 772 | 'email_change_password_field_empty_error' => __( 'Please enter your password.', 'wpwebapp' ), 773 | 'email_change_password_error' => __( 'The password you provided is not correct.', 'wpwebapp' ), 774 | 'email_change_success' => __( 'Your email address was updated.', 'wpwebapp' ), 775 | 776 | // Change password 777 | 'password_change_current_password_label' => __( 'Current Password', 'wpwebapp' ), 778 | 'password_change_new_password_label' => __( 'New Password', 'wpwebapp' ), 779 | 'password_change_submit_text' => __( 'Change My Password', 'wpwebapp' ), 780 | 'password_change_show_requirements' => 'off', 781 | 'password_change_forced_reset_error' => __(' You must change your password before you can continue.', 'wpwebapp' ), 782 | 'password_change_current_password_field_empty_error' => __( 'Please enter your current password.', 'wpwebapp' ), 783 | 'password_change_new_password_field_empty_error' => __( 'Please enter a new password.', 'wpwebapp' ), 784 | 'password_change_password_error' => __( 'The current password you provided is not correct.', 'wpwebapp' ), 785 | 'password_change_success' => __( 'Your password was updated.', 'wpwebapp' ), 786 | 'password_change_receive_notifications' => 'off', 787 | 'password_change_notification_to_admin' => 'A user at ' . get_bloginfo('name') . ' changed their password.' . "\r\n\r\n" . 'Username: [username]' . "\r\n" . 'Email: [email]' . "\r\n", 788 | 'password_change_send_notifications' => 'off', 789 | 'password_change_notification_to_user' => 'Your password was changed on ' . get_bloginfo('name') . '. If you did not change your password, please contact your site adminstrator at ' . get_option( 'admin_email' ) . '.', 790 | 791 | // Forgot password 792 | 'password_reset_url' => '', 793 | 'password_forgot_label' => __( 'Username or Email', 'wpwebapp' ), 794 | 'password_forgot_submit_text' => __( 'Reset My Password', 'wpwebapp' ), 795 | 'password_reset_label' => __( 'New Password', 'wpwebapp' ), 796 | 'password_reset_submit_text' => __( 'Update My Password', 'wpwebapp' ), 797 | 'password_reset_show_requirements' => 'off', 798 | 'password_forgot_password_field_empty_error' => __( 'Please enter your username or email.', 'wpwebapp' ), 799 | 'password_forgot_password_invalid_user_error' => __( 'The username or email your entered does not exist.', 'wpwebapp' ), 800 | 'password_forgot_password_is_admin_error' => __( 'This user\'s password cannot be reset.', 'wpwebapp' ), 801 | 'password_forgot_password_email_error' => __( 'Password reset failed. Please try again.', 'wpwebapp' ), 802 | 'password_forgot_password_reset_key_expired_error' => __( 'This link has expired. Please try again.', 'wpwebapp' ), 803 | 'password_forgot_password_success' => __( 'An email has been sent to you with a password reset link.', 'wpwebapp' ), 804 | 'password_reset_password_field_empty_error' => __( 'Please enter a new password.', 'wpwebapp' ), 805 | 'password_reset_time_valid' => 24, 806 | 'password_reset_notification_email' => 'We received a request to reset the password for your ' . get_bloginfo('name') . ' account: [username]. To reset your password, click on this link (or copy and paste the URL into your browser): [reset].' . "\r\n\r\n" . 'This link will expire in [expires] hours. If this was a mistake, please ignore this email.', 807 | 808 | // Delete account 809 | 'delete_account_password_label' => __( 'Confirm Password', 'wpwebapp' ), 810 | 'delete_account_submit_text' => __( 'Delete My Account', 'wpwebapp' ), 811 | 'delete_account_password_error' => __( 'The password you provided is not correct.', 'wpwebapp' ), 812 | 'delete_account_redirect' => '0', 813 | 814 | // Security 815 | 'password_minimum_length' => 8, 816 | 'password_requires_letters' => 'off', 817 | 'password_requires_numbers' => 'off', 818 | 'password_requires_special_characters' => 'off', 819 | 'password_requires_mixed_case' => 'off', 820 | 'show_admin_bar' => 'off', 821 | 822 | ); 823 | 824 | $defaults = apply_filters( 'wpwebapp_default_theme_options', $defaults ); 825 | 826 | $options = wp_parse_args( $saved, $defaults ); 827 | $options = array_intersect_key( $options, $defaults ); 828 | 829 | return $options; 830 | } 831 | 832 | // Sanitize and validate updated theme options 833 | function wpwebapp_theme_options_validate( $input ) { 834 | $output = array(); 835 | 836 | // Sign Up 837 | if ( isset( $input['signup_username_label'] ) && ! empty( $input['signup_username_label'] ) ) 838 | $output['signup_username_label'] = wp_filter_post_kses( $input['signup_username_label'] ); 839 | 840 | if ( isset( $input['signup_email_label'] ) && ! empty( $input['signup_email_label'] ) ) 841 | $output['signup_email_label'] = wp_filter_post_kses( $input['signup_email_label'] ); 842 | 843 | if ( isset( $input['signup_password_label'] ) && ! empty( $input['signup_password_label'] ) ) 844 | $output['signup_password_label'] = wp_filter_post_kses( $input['signup_password_label'] ); 845 | 846 | if ( isset( $input['signup_submit_text'] ) && ! empty( $input['signup_submit_text'] ) ) 847 | $output['signup_submit_text'] = wp_filter_nohtml_kses( $input['signup_submit_text'] ); 848 | 849 | if ( isset( $input['signup_show_requirements'] ) ) 850 | $output['signup_show_requirements'] = 'on'; 851 | 852 | if ( isset( $input['signup_username_field_empty_error'] ) && ! empty( $input['signup_username_field_empty_error'] ) ) 853 | $output['signup_username_field_empty_error'] = wp_filter_nohtml_kses( $input['signup_username_field_empty_error'] ); 854 | 855 | if ( isset( $input['signup_email_field_empty_error'] ) && ! empty( $input['signup_email_field_empty_error'] ) ) 856 | $output['signup_email_field_empty_error'] = wp_filter_nohtml_kses( $input['signup_email_field_empty_error'] ); 857 | 858 | if ( isset( $input['signup_password_field_empty_error'] ) && ! empty( $input['signup_password_field_empty_error'] ) ) 859 | $output['signup_password_field_empty_error'] = wp_filter_nohtml_kses( $input['signup_password_field_empty_error'] ); 860 | 861 | if ( isset( $input['signup_username_invalid_error'] ) && ! empty( $input['signup_username_invalid_error'] ) ) 862 | $output['signup_username_invalid_error'] = wp_filter_nohtml_kses( $input['signup_username_invalid_error'] ); 863 | 864 | if ( isset( $input['signup_username_exists_error'] ) && ! empty( $input['signup_username_exists_error'] ) ) 865 | $output['signup_username_exists_error'] = wp_filter_nohtml_kses( $input['signup_username_exists_error'] ); 866 | 867 | if ( isset( $input['signup_email_invalid_error'] ) && ! empty( $input['signup_email_invalid_error'] ) ) 868 | $output['signup_email_invalid_error'] = wp_filter_nohtml_kses( $input['signup_email_invalid_error'] ); 869 | 870 | if ( isset( $input['signup_email_exists_error'] ) && ! empty( $input['signup_email_exists_error'] ) ) 871 | $output['signup_email_exists_error'] = wp_filter_nohtml_kses( $input['signup_email_exists_error'] ); 872 | 873 | if ( isset( $input['signup_login_failed_error'] ) && ! empty( $input['signup_login_failed_error'] ) ) 874 | $output['signup_login_failed_error'] = wp_filter_nohtml_kses( $input['signup_login_failed_error'] ); 875 | 876 | if ( isset( $input['signup_login_failed_error'] ) && ! empty( $input['signup_login_failed_error'] ) ) 877 | $output['signup_login_failed_error'] = wp_filter_nohtml_kses( $input['signup_login_failed_error'] ); 878 | 879 | if ( isset( $input['signup_receive_notifications'] ) ) 880 | $output['signup_receive_notifications'] = 'on'; 881 | 882 | if ( isset( $input['signup_notification_to_admin'] ) && ! empty( $input['signup_notification_to_admin'] ) ) 883 | $output['signup_notification_to_admin'] = wp_filter_post_kses( $input['signup_notification_to_admin'] ); 884 | 885 | if ( isset( $input['signup_send_notifications'] ) ) 886 | $output['signup_send_notifications'] = 'on'; 887 | 888 | if ( isset( $input['signup_notification_to_user'] ) && ! empty( $input['signup_notification_to_user'] ) ) 889 | $output['signup_notification_to_user'] = wp_filter_post_kses( $input['signup_notification_to_user'] ); 890 | 891 | if ( isset( $input['create_user_password_time_valid'] ) && ! empty( $input['create_user_password_time_valid'] ) && is_numeric( $input['create_user_password_time_valid'] ) && $input['create_user_password_time_valid'] > 0 ) 892 | $output['create_user_password_time_valid'] = wp_filter_nohtml_kses( $input['create_user_password_time_valid'] ); 893 | 894 | if ( isset( $input['create_user_send_notifications'] ) ) 895 | $output['create_user_send_notifications'] = 'on'; 896 | 897 | if ( isset( $input['create_user_notification'] ) && ! empty( $input['create_user_notification'] ) ) 898 | $output['create_user_notification'] = wp_filter_post_kses( $input['create_user_notification'] ); 899 | 900 | // Login 901 | if ( isset( $input['login_username_label'] ) && ! empty( $input['login_username_label'] ) ) 902 | $output['login_username_label'] = wp_filter_post_kses( $input['login_username_label'] ); 903 | 904 | if ( isset( $input['login_password_label'] ) && ! empty( $input['login_password_label'] ) ) 905 | $output['login_password_label'] = wp_filter_post_kses( $input['login_password_label'] ); 906 | 907 | if ( isset( $input['login_rememberme_label'] ) && ! empty( $input['login_rememberme_label'] ) ) 908 | $output['login_rememberme_label'] = wp_filter_nohtml_kses( $input['login_rememberme_label'] ); 909 | 910 | if ( isset( $input['login_submit_text'] ) && ! empty( $input['login_submit_text'] ) ) 911 | $output['login_submit_text'] = wp_filter_nohtml_kses( $input['login_submit_text'] ); 912 | 913 | if ( isset( $input['login_username_field_empty_error'] ) && ! empty( $input['login_username_field_empty_error'] ) ) 914 | $output['login_username_field_empty_error'] = wp_filter_nohtml_kses( $input['login_username_field_empty_error'] ); 915 | 916 | if ( isset( $input['login_password_field_empty_error'] ) && ! empty( $input['login_password_field_empty_error'] ) ) 917 | $output['login_password_field_empty_error'] = wp_filter_nohtml_kses( $input['login_password_field_empty_error'] ); 918 | 919 | if ( isset( $input['login_failed_error'] ) && ! empty( $input['login_failed_error'] ) ) 920 | $output['login_failed_error'] = wp_filter_nohtml_kses( $input['login_failed_error'] ); 921 | 922 | // Redirects 923 | if ( isset( $input['login_redirect'] ) ) 924 | $output['login_redirect'] = wp_filter_nohtml_kses( $input['login_redirect'] ); 925 | 926 | if ( isset( $input['logout_redirect'] ) ) 927 | $output['logout_redirect'] = wp_filter_nohtml_kses( $input['logout_redirect'] ); 928 | 929 | if ( isset( $input['password_reset_redirect'] ) ) 930 | $output['password_reset_redirect'] = wp_filter_nohtml_kses( $input['password_reset_redirect'] ); 931 | 932 | if ( isset( $input['add_redirect_referrer'] ) ) 933 | $output['add_redirect_referrer'] = 'on'; 934 | 935 | // Change email address 936 | if ( isset( $input['email_change_current_email_label'] ) && ! empty( $input['email_change_current_email_label'] ) ) 937 | $output['email_change_current_email_label'] = wp_filter_post_kses( $input['email_change_current_email_label'] ); 938 | 939 | if ( isset( $input['email_change_password_label'] ) && ! empty( $input['email_change_password_label'] ) ) 940 | $output['email_change_password_label'] = wp_filter_post_kses( $input['email_change_password_label'] ); 941 | 942 | if ( isset( $input['email_change_submit_text'] ) && ! empty( $input['email_change_submit_text'] ) ) 943 | $output['email_change_submit_text'] = wp_filter_nohtml_kses( $input['email_change_submit_text'] ); 944 | 945 | if ( isset( $input['email_change_email_field_empty_error'] ) && ! empty( $input['email_change_email_field_empty_error'] ) ) 946 | $output['email_change_email_field_empty_error'] = wp_filter_nohtml_kses( $input['email_change_email_field_empty_error'] ); 947 | 948 | if ( isset( $input['email_change_password_field_empty_error'] ) && ! empty( $input['email_change_password_field_empty_error'] ) ) 949 | $output['email_change_password_field_empty_error'] = wp_filter_nohtml_kses( $input['email_change_password_field_empty_error'] ); 950 | 951 | if ( isset( $input['email_change_password_error'] ) && ! empty( $input['email_change_password_error'] ) ) 952 | $output['email_change_password_error'] = wp_filter_nohtml_kses( $input['email_change_password_error'] ); 953 | 954 | if ( isset( $input['email_change_success'] ) && ! empty( $input['email_change_success'] ) ) 955 | $output['email_change_success'] = wp_filter_nohtml_kses( $input['email_change_success'] ); 956 | 957 | // Change password 958 | if ( isset( $input['password_change_current_password_label'] ) && ! empty( $input['password_change_current_password_label'] ) ) 959 | $output['password_change_current_password_label'] = wp_filter_post_kses( $input['password_change_current_password_label'] ); 960 | 961 | if ( isset( $input['password_change_new_password_label'] ) && ! empty( $input['password_change_new_password_label'] ) ) 962 | $output['password_change_new_password_label'] = wp_filter_post_kses( $input['password_change_new_password_label'] ); 963 | 964 | if ( isset( $input['password_change_submit_text'] ) && ! empty( $input['password_change_submit_text'] ) ) 965 | $output['password_change_submit_text'] = wp_filter_nohtml_kses( $input['password_change_submit_text'] ); 966 | 967 | if ( isset( $input['password_change_show_requirements'] ) ) 968 | $output['password_change_show_requirements'] = 'on'; 969 | 970 | if ( isset( $input['password_change_forced_reset_error'] ) && ! empty( $input['password_change_forced_reset_error'] ) ) 971 | $output['password_change_forced_reset_error'] = wp_filter_nohtml_kses( $input['password_change_forced_reset_error'] ); 972 | 973 | if ( isset( $input['password_change_current_password_field_empty_error'] ) && ! empty( $input['password_change_current_password_field_empty_error'] ) ) 974 | $output['password_change_current_password_field_empty_error'] = wp_filter_nohtml_kses( $input['password_change_current_password_field_empty_error'] ); 975 | 976 | if ( isset( $input['password_change_new_password_field_empty_error'] ) && ! empty( $input['password_change_new_password_field_empty_error'] ) ) 977 | $output['password_change_new_password_field_empty_error'] = wp_filter_nohtml_kses( $input['password_change_new_password_field_empty_error'] ); 978 | 979 | if ( isset( $input['password_change_password_error'] ) && ! empty( $input['password_change_password_error'] ) ) 980 | $output['password_change_password_error'] = wp_filter_nohtml_kses( $input['password_change_password_error'] ); 981 | 982 | if ( isset( $input['password_change_success'] ) && ! empty( $input['password_change_success'] ) ) 983 | $output['password_change_success'] = wp_filter_nohtml_kses( $input['password_change_success'] ); 984 | 985 | if ( isset( $input['password_change_receive_notifications'] ) ) 986 | $output['password_change_receive_notifications'] = 'on'; 987 | 988 | if ( isset( $input['password_change_notification_to_admin'] ) && ! empty( $input['password_change_notification_to_admin'] ) ) 989 | $output['password_change_notification_to_admin'] = wp_filter_post_kses( $input['password_change_notification_to_admin'] ); 990 | 991 | if ( isset( $input['password_change_send_notifications'] ) ) 992 | $output['password_change_send_notifications'] = 'on'; 993 | 994 | if ( isset( $input['password_change_notification_to_user'] ) && ! empty( $input['password_change_notification_to_user'] ) ) 995 | $output['password_change_notification_to_user'] = wp_filter_post_kses( $input['password_change_notification_to_user'] ); 996 | 997 | // Forgot password 998 | if ( isset( $input['password_reset_url'] ) ) 999 | $output['password_reset_url'] = wp_filter_nohtml_kses( $input['password_reset_url'] ); 1000 | 1001 | if ( isset( $input['password_forgot_label'] ) && ! empty( $input['password_forgot_label'] ) ) 1002 | $output['password_forgot_label'] = wp_filter_post_kses( $input['password_forgot_label'] ); 1003 | 1004 | if ( isset( $input['password_forgot_submit_text'] ) && ! empty( $input['password_forgot_submit_text'] ) ) 1005 | $output['password_forgot_submit_text'] = wp_filter_nohtml_kses( $input['password_forgot_submit_text'] ); 1006 | 1007 | if ( isset( $input['password_reset_label'] ) && ! empty( $input['password_reset_label'] ) ) 1008 | $output['password_reset_label'] = wp_filter_post_kses( $input['password_reset_label'] ); 1009 | 1010 | if ( isset( $input['password_reset_submit_text'] ) && ! empty( $input['password_reset_submit_text'] ) ) 1011 | $output['password_reset_submit_text'] = wp_filter_nohtml_kses( $input['password_reset_submit_text'] ); 1012 | 1013 | if ( isset( $input['password_reset_show_requirements'] ) ) 1014 | $output['password_reset_show_requirements'] = 'on'; 1015 | 1016 | if ( isset( $input['password_forgot_password_field_empty_error'] ) && ! empty( $input['password_forgot_password_field_empty_error'] ) ) 1017 | $output['password_forgot_password_field_empty_error'] = wp_filter_nohtml_kses( $input['password_forgot_password_field_empty_error'] ); 1018 | 1019 | if ( isset( $input['password_forgot_password_invalid_user_error'] ) && ! empty( $input['password_forgot_password_invalid_user_error'] ) ) 1020 | $output['password_forgot_password_invalid_user_error'] = wp_filter_nohtml_kses( $input['password_forgot_password_invalid_user_error'] ); 1021 | 1022 | if ( isset( $input['password_forgot_password_is_admin_error'] ) && ! empty( $input['password_forgot_password_is_admin_error'] ) ) 1023 | $output['password_forgot_password_is_admin_error'] = wp_filter_nohtml_kses( $input['password_forgot_password_is_admin_error'] ); 1024 | 1025 | if ( isset( $input['password_forgot_password_email_error'] ) && ! empty( $input['password_forgot_password_email_error'] ) ) 1026 | $output['password_forgot_password_email_error'] = wp_filter_nohtml_kses( $input['password_forgot_password_email_error'] ); 1027 | 1028 | if ( isset( $input['password_forgot_password_reset_key_expired_error'] ) && ! empty( $input['password_forgot_password_reset_key_expired_error'] ) ) 1029 | $output['password_forgot_password_reset_key_expired_error'] = wp_filter_nohtml_kses( $input['password_forgot_password_reset_key_expired_error'] ); 1030 | 1031 | if ( isset( $input['password_forgot_password_success'] ) && ! empty( $input['password_forgot_password_success'] ) ) 1032 | $output['password_forgot_password_success'] = wp_filter_nohtml_kses( $input['password_forgot_password_success'] ); 1033 | 1034 | if ( isset( $input['password_reset_password_field_empty_error'] ) && ! empty( $input['password_reset_password_field_empty_error'] ) ) 1035 | $output['password_reset_password_field_empty_error'] = wp_filter_nohtml_kses( $input['password_reset_password_field_empty_error'] ); 1036 | 1037 | if ( isset( $input['password_reset_time_valid'] ) && ! empty( $input['password_reset_time_valid'] ) && is_numeric( $input['password_reset_time_valid'] ) && $input['password_reset_time_valid'] > 0 ) 1038 | $output['password_reset_time_valid'] = wp_filter_nohtml_kses( $input['password_reset_time_valid'] ); 1039 | 1040 | if ( isset( $input['password_reset_notification_email'] ) && ! empty( $input['password_reset_notification_email'] ) ) 1041 | $output['password_reset_notification_email'] = wp_filter_post_kses( $input['password_reset_notification_email'] ); 1042 | 1043 | // Delete account 1044 | if ( isset( $input['delete_account_password_label'] ) && ! empty( $input['delete_account_password_label'] ) ) 1045 | $output['delete_account_password_label'] = wp_filter_post_kses( $input['delete_account_password_label'] ); 1046 | 1047 | if ( isset( $input['delete_account_submit_text'] ) && ! empty( $input['delete_account_submit_text'] ) ) 1048 | $output['delete_account_submit_text'] = wp_filter_nohtml_kses( $input['delete_account_submit_text'] ); 1049 | 1050 | if ( isset( $input['delete_account_password_error'] ) && ! empty( $input['delete_account_password_error'] ) ) 1051 | $output['delete_account_password_error'] = wp_filter_nohtml_kses( $input['delete_account_password_error'] ); 1052 | 1053 | if ( isset( $input['delete_account_redirect'] ) ) 1054 | $output['delete_account_redirect'] = wp_filter_nohtml_kses( $input['delete_account_redirect'] ); 1055 | 1056 | // Security 1057 | if ( isset( $input['password_minimum_length'] ) && ! empty( $input['password_minimum_length'] ) && is_numeric( $input['password_minimum_length'] ) && $input['password_minimum_length'] > 2 ) 1058 | $output['password_minimum_length'] = wp_filter_nohtml_kses( $input['password_minimum_length'] ); 1059 | 1060 | if ( isset( $input['password_requires_letters'] ) ) 1061 | $output['password_requires_letters'] = 'on'; 1062 | 1063 | if ( isset( $input['password_requires_numbers'] ) ) 1064 | $output['password_requires_numbers'] = 'on'; 1065 | 1066 | if ( isset( $input['password_requires_special_characters'] ) ) 1067 | $output['password_requires_special_characters'] = 'on'; 1068 | 1069 | if ( isset( $input['password_requires_mixed_case'] ) ) { 1070 | $output['password_requires_letters'] = 'on'; 1071 | $output['password_requires_mixed_case'] = 'on'; 1072 | } 1073 | 1074 | if ( isset( $input['show_admin_bar'] ) ) 1075 | $output['show_admin_bar'] = 'on'; 1076 | 1077 | 1078 | return apply_filters( 'wpwebapp_theme_options_validate', $output, $input ); 1079 | } 1080 | 1081 | 1082 | 1083 | /** 1084 | * Theme Options Menu 1085 | * Each option field requires its own add_settings_field function. 1086 | */ 1087 | 1088 | // Create theme options menu 1089 | // The content that's rendered on the menu page. 1090 | function wpwebapp_theme_options_render_page() { 1091 | ?> 1092 |
1093 |

1094 | 1095 | 1096 |
1097 | 1102 |
1103 |
1104 | ID ); 82 | 83 | // Get options 84 | $options = wpwebapp_get_theme_options_redirects(); 85 | 86 | ?> 87 | 88 |

89 | 90 | 91 | 92 | 93 | 94 | 95 | 106 | 107 | 108 |
96 | 97 |
98 |

You have not specified a forced password reset redirect URL yet. The "Force Password Reset" feature will not work unless you do.

99 |
100 | 101 | 105 |
109 | 110 | ID, 'wpwebapp_force_password_reset', true ); 151 | 152 | // Don't run if password reset isn't required 153 | if ( $force_reset !== 'on' ) return; 154 | 155 | // Check that current page isn't the change password page 156 | $options = wpwebapp_get_theme_options_redirects(); 157 | if ( empty( $options['password_reset_redirect'] ) || is_page( $options['password_reset_redirect'] ) ) return; 158 | 159 | // Redirect to change password 160 | wp_safe_redirect( wpwebapp_get_redirect_url( $options['password_reset_redirect'], $options['add_redirect_referrer'] ), 302 ); 161 | exit; 162 | 163 | } 164 | add_action( 'wp', 'wpwebapp_force_password_reset_on_login' ); -------------------------------------------------------------------------------- /options/user-access.php: -------------------------------------------------------------------------------- 1 | ID, 'wpwebapp_user_access', true ); 26 | 27 | ?> 28 | 29 |
30 |
31 | 35 |
36 | 40 |
41 | 45 |
46 |
47 | 48 | ID; 66 | } 67 | 68 | // Verify user has permission to edit post 69 | if ( !current_user_can( 'edit_post', $post->ID )) { 70 | return $post->ID; 71 | } 72 | 73 | // Verify field exists 74 | if ( empty( $_POST['wpwebapp_user_access'] ) ) return; 75 | 76 | // Update metadata 77 | update_post_meta( $post->ID, 'wpwebapp_user_access', $_POST['wpwebapp_user_access'] ); 78 | 79 | } 80 | add_action('save_post', 'wpwebapp_user_access_metabox_process', 1, 2); 81 | 82 | 83 | /** 84 | * Save the data with revisions 85 | * @param number $post_id The post ID 86 | */ 87 | function wpwebapp_user_access_metabox_save_revisions( $post_id ) { 88 | 89 | // Check if it's a revision 90 | $parent_id = wp_is_post_revision( $post_id ); 91 | 92 | // If not a revision, bail 93 | if ( !$parent_id ) return; 94 | 95 | // Get the data 96 | $parent = get_post( $parent_id ); 97 | $user_access = get_post_meta( $parent->ID, 'wpwebapp_user_access', true ); 98 | 99 | // If data exists, add to revision 100 | if ( empty( $user_access ) ) return; 101 | add_metadata( 'post', $post_id, 'wpwebapp_user_access', $user_access ); 102 | 103 | } 104 | add_action( 'save_post', 'wpwebapp_user_access_metabox_save_revisions' ); 105 | 106 | 107 | /** 108 | * Restore the data with revisions 109 | * @param number $post_id The post ID 110 | * @param number $revision_id The revision ID 111 | */ 112 | function wpwebapp_user_access_metabox_restore_revisions( $post_id, $revision_id ) { 113 | 114 | // Variables 115 | $post = get_post( $post_id ); 116 | $revision = get_post( $revision_id ); 117 | $user_access = get_metadata( 'post', $revision->ID, 'wpwebapp_user_access', true ); 118 | 119 | if ( !empty( $width ) ) { 120 | update_post_meta( $post_id, 'wpwebapp_user_access', $user_access ); 121 | } else { 122 | delete_post_meta( $post_id, 'wpwebapp_user_access' ); 123 | } 124 | 125 | } 126 | add_action( 'wp_restore_post_revision', 'wpwebapp_user_access_metabox_restore_revisions', 10, 2 ); 127 | 128 | 129 | /** 130 | * Get the data to display the revisions page 131 | * @param array $fields The revision fields 132 | */ 133 | function wpwebapp_user_access_metabox_get_revisions_field( $fields ) { 134 | $fields['wpwebapp_user_access'] = 'User Access'; 135 | return $fields; 136 | } 137 | add_filter( '_wp_post_revision_fields', 'wpwebapp_user_access_metabox_get_revisions_field' ); 138 | 139 | 140 | /** 141 | * Display the data on the revisions page 142 | */ 143 | function wpwebapp_user_access_metabox_set_revisions_field( $value, $field ) { 144 | global $revision; 145 | return get_metadata( 'post', $revision->ID, $field, true ); 146 | } 147 | add_filter( '_wp_post_revision_field_my_meta', 'wpwebapp_user_access_metabox_set_revisions_field', 10, 2 ); 148 | 149 | 150 | /** 151 | * Redirect users that don't have access to the page 152 | */ 153 | function wpwebapp_control_access() { 154 | 155 | // Don't run on admin page 156 | if ( is_admin() ) return; 157 | 158 | // Variables 159 | global $post; 160 | if ( empty( $post ) ) return; 161 | $options = wpwebapp_get_theme_options_redirects(); 162 | $user_access = get_post_meta( $post->ID, 'wpwebapp_user_access', true ); 163 | 164 | // Bail if no access restrictions 165 | if ( empty( $user_access ) || $user_access === 'everyone' ) return; 166 | 167 | // If user is logged out and page is for logged in users only 168 | if ( $user_access === 'loggedin' && !is_user_logged_in() ) { 169 | wp_safe_redirect( wpwebapp_get_redirect_url( $options['logout_redirect'], $options['add_redirect_referrer'] ), 302 ); 170 | exit; 171 | } 172 | 173 | // If user is logged in and page is for logged out users only 174 | if ( $user_access === 'loggedout' && is_user_logged_in() ) { 175 | wp_safe_redirect( wpwebapp_get_redirect_url( $options['login_redirect'] ), 302 ); 176 | exit; 177 | } 178 | 179 | } 180 | add_action( 'wp', 'wpwebapp_control_access' ); 181 | 182 | 183 | /** 184 | * Redirect users away from wp-login.php after logout 185 | */ 186 | function wpwebapp_logout_redirect() { 187 | $options = wpwebapp_get_theme_options_redirects(); 188 | wp_redirect( wpwebapp_get_redirect_url( $options['logout_redirect'] ) ); 189 | exit(); 190 | } 191 | add_action( 'wp_logout', 'wpwebapp_logout_redirect' ); 192 | 193 | 194 | /** 195 | * Disable the admin bar for all users 196 | */ 197 | function wpwebapp_disable_admin_bar() { 198 | if ( current_user_can( 'edit_themes' ) ) return; 199 | $options = wpwebapp_get_theme_options_security(); 200 | if ( $options['show_admin_bar'] === 'on' ) return; 201 | show_admin_bar( false ); 202 | } 203 | add_filter( 'init' , 'wpwebapp_disable_admin_bar'); -------------------------------------------------------------------------------- /shortcodes/delete-account.php: -------------------------------------------------------------------------------- 1 | ' . stripslashes( $error ) . '' ) . 24 | '
' . 25 | '' . 26 | '' . 27 | '' . 28 | wp_nonce_field( 'wpwebapp_delete_account_nonce', 'wpwebapp_delete_account_process', true, false ) . 29 | '
'; 30 | 31 | } else { 32 | $form = '

' . __( 'You need to be logged in to delete your account.', 'wpwebapp' ) . '

'; 33 | } 34 | 35 | return $form; 36 | 37 | } 38 | add_shortcode( 'wpwa_delete_account', 'wpwebapp_delete_account_form' ); 39 | 40 | // Process account deletion 41 | function wpwebapp_process_delete_account() { 42 | 43 | // Verify data came from form 44 | if ( !isset( $_POST['wpwebapp_delete_account_process'] ) || !wp_verify_nonce( $_POST['wpwebapp_delete_account_process'], 'wpwebapp_delete_account_nonce' ) ) return; 45 | 46 | // Require user.php 47 | require_once( ABSPATH . 'wp-admin/includes/user.php' ); 48 | 49 | // Variables 50 | $current_user = wp_get_current_user(); 51 | $options = wpwebapp_get_theme_options_delete_account(); 52 | $referer = esc_url_raw( wpwebapp_get_url() ); 53 | $redirect = wpwebapp_get_redirect_url( $options['delete_account_redirect'] ); 54 | 55 | // Verify that password matches 56 | if ( !isset( $_POST['wpwebapp_delete_account_password'] ) || !wp_check_password( $_POST['wpwebapp_delete_account_password'], $current_user->user_pass, $current_user->ID ) ) { 57 | wpwebapp_set_session( 'wpwebapp_delete_account_error', $options['delete_account_password_error'] ); 58 | wp_safe_redirect( $referer, 302 ); 59 | exit; 60 | } 61 | 62 | // Verify that user is NOT an admin 63 | if ( current_user_can( 'edit_theme_options' ) ) { 64 | wpwebapp_set_session( 'wpwebapp_delete_account_error', __( 'This account cannot be deleted.', 'wpwebapp' ) ); 65 | wp_safe_redirect( $referer, 302 ); 66 | exit; 67 | } 68 | 69 | // Delete current user's account 70 | wp_delete_user( $current_user->ID ); 71 | 72 | // Run custom WordPress action 73 | do_action( 'wpwebapp_after_delete_user', $current_user->user_login, $current_user->user_email ); 74 | 75 | // Redirect 76 | wp_safe_redirect( $redirect, 302 ); 77 | exit; 78 | 79 | } 80 | add_action( 'init', 'wpwebapp_process_delete_account' ); -------------------------------------------------------------------------------- /shortcodes/email-change.php: -------------------------------------------------------------------------------- 1 | ' . stripslashes( $error ) . '' ) . 26 | ( empty( $success ) ? '' : '
' . stripslashes( $success ) . '
' ) . 27 | 28 | '
' . 29 | 30 | '' . 31 | '' . 32 | 33 | '' . 34 | '' . 35 | 36 | '' . 37 | 38 | wp_nonce_field( 'wpwebapp_email_change_nonce', 'wpwebapp_email_change_process', true, false ) . 39 | 40 | '
'; 41 | 42 | } else { 43 | $form = '

' . __( 'You need to be logged in to change your email address.', 'wpwebapp' ) . '

'; 44 | } 45 | 46 | return $form; 47 | 48 | } 49 | add_shortcode( 'wpwa_change_email', 'wpwebapp_email_change_form' ); 50 | 51 | // Process email change 52 | function wpwebapp_process_email_change() { 53 | 54 | // Verify data came from form 55 | if ( !isset( $_POST['wpwebapp_email_change_process'] ) || !wp_verify_nonce( $_POST['wpwebapp_email_change_process'], 'wpwebapp_email_change_nonce' ) ) return; 56 | 57 | // Variables 58 | $current_user = wp_get_current_user(); 59 | $options = wpwebapp_get_theme_options_change_email(); 60 | $options_signup = wpwebapp_get_theme_options_signup(); 61 | $referer = esc_url_raw( wpwebapp_get_url() ); 62 | 63 | // Check that email is supplied 64 | if ( empty( $_POST['wpwebapp_email_change_current_email'] ) ) { 65 | wpwebapp_set_session( 'wpwebapp_email_change_error', $options['email_change_email_field_empty_error'] ); 66 | wp_safe_redirect( $referer, 302 ); 67 | exit; 68 | } 69 | 70 | // Check that password is provided 71 | if ( empty( $_POST['wpwebapp_email_change_password'] ) ) { 72 | wpwebapp_set_session( 'wpwebapp_email_change_error', $options['email_change_password_field_empty_error'] ); 73 | wp_safe_redirect( $referer, 302 ); 74 | exit; 75 | } 76 | 77 | // Validate and authenticate password 78 | if ( !wp_check_password( $_POST['wpwebapp_email_change_password'], $current_user->user_pass, $current_user->ID ) ) { 79 | wpwebapp_set_session( 'wpwebapp_email_change_error', $options['email_change_password_error'] ); 80 | wp_safe_redirect( $referer, 302 ); 81 | exit; 82 | } 83 | 84 | // Make sure email isn't already taken by another user 85 | if ( email_exists( $_POST['wpwebapp_email_change_current_email'] ) ) { 86 | wpwebapp_set_session( 'wpwebapp_email_change_error', $options_signup['signup_username_exists_error'] ); 87 | wp_safe_redirect( $referer, 302 ); 88 | exit; 89 | } 90 | 91 | // If no errors exist, change the email address 92 | wp_update_user( array( 'ID' => $current_user->ID, 'user_email' => $_POST['wpwebapp_email_change_current_email'] ) ); 93 | wpwebapp_set_session( 'wpwebapp_email_change_success', $options['email_change_success'] ); 94 | 95 | // Run custom WordPress action 96 | do_action( 'wpwebapp_after_email_change', $current_user->ID, $current_user->user_email ); 97 | 98 | // Redirect 99 | wp_safe_redirect( $referer, 302 ); 100 | exit; 101 | 102 | } 103 | add_action( 'init', 'wpwebapp_process_email_change' ); -------------------------------------------------------------------------------- /shortcodes/login.php: -------------------------------------------------------------------------------- 1 | ' . __( 'You\'re already logged in.', 'wpwebapp' ) . '

'; 18 | } else { 19 | 20 | // Variables 21 | $current_user = wp_get_current_user(); 22 | $options = wpwebapp_get_theme_options_login(); 23 | $error = wpwebapp_get_session( 'wpwebapp_login_error', true ); 24 | $credentials = wpwebapp_get_session( 'wpwebapp_login_credentials', true ); 25 | 26 | $form = 27 | ( empty( $error ) ? '' : '
' . stripslashes( $error ) . '
' ) . 28 | 29 | '
' . 30 | 31 | '' . 32 | '' . 33 | 34 | '' . 35 | '' . 36 | 37 | '' . 38 | 39 | '' . 40 | 41 | wp_nonce_field( 'wpwebapp_login_nonce', 'wpwebapp_login_process', true, false ) . 42 | 43 | '
'; 44 | 45 | } 46 | 47 | return $form; 48 | 49 | } 50 | add_shortcode( 'wpwa_login', 'wpwebapp_login_form' ); 51 | 52 | 53 | // Process login 54 | function wpwebapp_process_login() { 55 | 56 | // Verify data came from form 57 | if ( !isset( $_POST['wpwebapp_login_process'] ) || !wp_verify_nonce( $_POST['wpwebapp_login_process'], 'wpwebapp_login_nonce' ) ) return; 58 | 59 | // Variables 60 | $options = wpwebapp_get_theme_options_login(); 61 | $redirects = wpwebapp_get_theme_options_redirects(); 62 | $referer = esc_url_raw( wpwebapp_get_url() ); 63 | $username = isset( $_POST['wpwebapp_login_username'] ) ? $_POST['wpwebapp_login_username'] : ''; 64 | $rememberme = isset( $_POST['wpwebapp_login_rememberme'] ) ? true : false; 65 | 66 | // Check that username is supplied 67 | if ( empty( $_POST['wpwebapp_login_username'] ) ) { 68 | wpwebapp_set_session( 'wpwebapp_login_error', $options['login_username_field_empty_error'] ); 69 | wp_safe_redirect( $referer, 302 ); 70 | exit; 71 | } 72 | 73 | // Check that password is provided 74 | if ( empty( $_POST['wpwebapp_login_password'] ) ) { 75 | wpwebapp_set_session( 'wpwebapp_login_error', $options['login_password_field_empty_error'] ); 76 | wpwebapp_set_session( 'wpwebapp_login_credentials', $username ); 77 | wp_safe_redirect( $referer, 302 ); 78 | exit; 79 | } 80 | 81 | 82 | // If login is an email, get username 83 | if ( is_email( $_POST['wpwebapp_login_username'] ) ) { 84 | $user = get_user_by( 'email', $_POST['wpwebapp_login_username'] ); 85 | $user = get_userdata( $user->ID ); 86 | $_POST['wpwebapp_login_username'] = $user->user_login; 87 | } 88 | 89 | // Authenticate User 90 | $credentials = array( 91 | 'user_login' => $_POST['wpwebapp_login_username'], 92 | 'user_password' => $_POST['wpwebapp_login_password'], 93 | 'remember' => $rememberme, 94 | ); 95 | $login = wp_signon( $credentials ); 96 | 97 | // If errors 98 | if ( is_wp_error( $login ) ) { 99 | wpwebapp_set_session( 'wpwebapp_login_error', $options['login_failed_error'] ); 100 | wpwebapp_set_session( 'wpwebapp_login_credentials', $username ); 101 | wp_safe_redirect( $referer, 302 ); 102 | exit; 103 | } 104 | 105 | // Run custom WordPress action 106 | do_action( 'wpwebapp_after_login', $_POST['wpwebapp_login_username'] ); 107 | 108 | // Redirect after login 109 | $redirect = isset( $_GET['referrer'] ) && !empty( $_GET['referrer'] ) ? esc_url_raw( $_GET['referrer'] ) : wpwebapp_get_redirect_url( $redirects['login_redirect'] ); 110 | wp_safe_redirect( $redirect, 302 ); 111 | exit; 112 | 113 | } 114 | add_action( 'init', 'wpwebapp_process_login' ); -------------------------------------------------------------------------------- /shortcodes/navigation.php: -------------------------------------------------------------------------------- 1 | user_login; 28 | } 29 | add_shortcode( 'wpwa_username', 'wpwebapp_get_username' ); 30 | 31 | 32 | // Use the username shortcode with `wp_nav_menu()` 33 | function wpwebapp_menu_username( $menu ) { 34 | $username = wpwebapp_get_username(); 35 | return str_replace( '[wpwa_username]', $username, $menu ); 36 | } 37 | add_filter('wp_nav_menu', 'wpwebapp_menu_username'); 38 | 39 | 40 | // Create referrer URL shortcode 41 | function wpwebapp_get_referrer() { 42 | return 'referrer=' . esc_url_raw( wpwebapp_get_url() ); 43 | } 44 | add_shortcode( 'wpwa_referrer', 'wpwebapp_get_referrer' ); 45 | 46 | 47 | // Use the referrer shortcode with `wp_nav_menu()` 48 | function wpwebapp_menu_referrer( $menu ) { 49 | $referrer = wpwebapp_get_referrer(); 50 | return str_replace( 'wpwa_referrer', $referrer, $menu ); 51 | } 52 | add_filter('wp_nav_menu', 'wpwebapp_menu_referrer'); -------------------------------------------------------------------------------- /shortcodes/password-change.php: -------------------------------------------------------------------------------- 1 | ' . wpwebapp_password_requirements_message() . '' : null; 23 | 24 | // Check if forced reset is required 25 | $current_user = wp_get_current_user(); 26 | $force_reset = get_user_meta( $current_user->ID, 'wpwebapp_force_password_reset', true ); 27 | 28 | $form = 29 | ( $force_reset === 'on' ? '
' . stripslashes( $options['password_change_forced_reset_error'] ) . '
' : '' ) . 30 | ( empty( $error ) ? '' : '
' . stripslashes( $error ) . '
' ) . 31 | ( empty( $success ) ? '' : '
' . stripslashes( $success ) . '
' ) . 32 | 33 | '
' . 34 | 35 | '' . 36 | '' . 37 | 38 | '' . 39 | '' . 40 | $pw_requirements . 41 | 42 | '' . 43 | 44 | wp_nonce_field( 'wpwebapp_password_change_nonce', 'wpwebapp_password_change_process', true, false ) . 45 | 46 | '
'; 47 | 48 | } else { 49 | $form = '

' . __( 'You need to be logged in to change your password.', 'wpwebapp' ) . '

'; 50 | } 51 | 52 | return $form; 53 | 54 | } 55 | add_shortcode( 'wpwa_change_password', 'wpwebapp_password_change_form' ); 56 | 57 | 58 | // Send password change email to the admin 59 | function wpwebapp_send_password_change_email_to_admin( $login, $email ) { 60 | 61 | // Check if admin wants to receive emails 62 | $options = wpwebapp_get_theme_options_change_password(); 63 | if ( $options['password_change_receive_notifications'] === 'off' ) return; 64 | 65 | // Variables 66 | $site_name = get_bloginfo('name'); 67 | $domain = wpwebapp_get_site_domain(); 68 | $headers = 'From: ' . $site_name . ' ' . "\r\n"; 69 | $subject = $site_name . ': User Password Change'; 70 | $message = str_replace( '[email]', sanitize_email( $email ), str_replace( '[username]', esc_attr( $login ), stripslashes( $options['password_change_notification_to_admin'] ) ) ); 71 | 72 | // Send email 73 | @wp_mail( get_option('admin_email'), $subject, $message, $headers ); 74 | 75 | } 76 | 77 | 78 | // Send password change email to the user 79 | function wpwebapp_send_password_change_email_to_user( $login, $email ) { 80 | 81 | // Check if user should receive email 82 | $options = wpwebapp_get_theme_options_change_password(); 83 | if ( $options['password_change_send_notifications'] === 'off' ) return; 84 | 85 | // Variables 86 | $site_name = get_bloginfo('name'); 87 | $domain = wpwebapp_get_site_domain(); 88 | $headers = 'From: ' . $site_name . ' ' . "\r\n"; 89 | $subject = $site_name . ': Your Password Was Changed'; 90 | $message = str_replace( '[username]', esc_attr( $login ), stripslashes( $options['password_change_notification_to_user'] ) ); 91 | 92 | // Send email 93 | @wp_mail( sanitize_email( $email ), $subject, $message, $headers ); 94 | 95 | } 96 | 97 | 98 | // Process password change 99 | function wpwebapp_process_password_change() { 100 | 101 | // Verify data came from form 102 | if ( !isset( $_POST['wpwebapp_password_change_process'] ) || !wp_verify_nonce( $_POST['wpwebapp_password_change_process'], 'wpwebapp_password_change_nonce' ) ) return; 103 | 104 | // Variables 105 | $current_user = wp_get_current_user(); 106 | $force_reset = get_user_meta( $current_user->ID, 'wpwebapp_force_password_reset', true ); 107 | $options = wpwebapp_get_theme_options_change_password(); 108 | $referer = esc_url_raw( wpwebapp_get_url() ); 109 | 110 | // Check that current password is supplied 111 | if ( empty( $_POST['wpwebapp_password_change_current_password'] ) ) { 112 | wpwebapp_set_session( 'wpwebapp_password_change_error', $options['password_change_current_password_field_empty_error'] ); 113 | wp_safe_redirect( $referer, 302 ); 114 | exit; 115 | } 116 | 117 | // Check that new password is provided 118 | if ( empty( $_POST['wpwebapp_password_change_new_password'] ) ) { 119 | wpwebapp_set_session( 'wpwebapp_password_change_error', $options['password_change_new_password_field_empty_error'] ); 120 | wp_safe_redirect( $referer, 302 ); 121 | exit; 122 | } 123 | 124 | // Validate and authenticate current password 125 | if ( !wp_check_password( $_POST['wpwebapp_password_change_current_password'], $current_user->user_pass, $current_user->ID ) ) { 126 | wpwebapp_set_session( 'wpwebapp_password_change_error', $options['password_change_password_error'] ); 127 | wp_safe_redirect( $referer, 302 ); 128 | exit; 129 | } 130 | 131 | // Enforce password requirements 132 | if ( !wpwebapp_test_password_requirements( $_POST['wpwebapp_password_change_new_password'] ) ) { 133 | $message = wpwebapp_password_requirements_message(); 134 | wpwebapp_set_session( 'wpwebapp_password_change_error', $message ); 135 | wp_safe_redirect( $referer, 302 ); 136 | exit; 137 | } 138 | 139 | // Enforce different password on forced password reset 140 | if ( $force_reset === 'on' && $_POST['wpwebapp_password_change_current_password'] === $_POST['wpwebapp_password_change_new_password'] ) { 141 | wp_safe_redirect( $referer, 302 ); 142 | exit; 143 | } 144 | 145 | // If no errors exist, change the password 146 | wp_update_user( array( 'ID' => $current_user->ID, 'user_pass' => $_POST['wpwebapp_password_change_new_password'] ) ); 147 | wpwebapp_set_session( 'wpwebapp_password_change_success', $options['password_change_success'] ); 148 | 149 | // Send password change emails 150 | wpwebapp_send_password_change_email_to_admin( $current_user->user_login, $current_user->user_email ); 151 | wpwebapp_send_password_change_email_to_user( $current_user->user_login, $current_user->user_email ); 152 | 153 | // Remove forced password reset if one was set 154 | update_user_meta( $current_user->ID, 'wpwebapp_force_password_reset', 'off' ); 155 | 156 | // Run custom WordPress action 157 | do_action( 'wpwebapp_after_password_change', $current_user->ID ); 158 | 159 | // Redirect 160 | $redirect = $force_reset === 'on' && isset( $_GET['referrer'] ) && !empty( $_GET['referrer'] ) ? esc_url_raw( $_GET['referrer'] ) : $referer; 161 | wp_safe_redirect( $redirect, 302 ); 162 | exit; 163 | 164 | } 165 | add_action( 'init', 'wpwebapp_process_password_change' ); 166 | 167 | 168 | // Send password change emails when the password is changed from the dashboard or some other method 169 | function wpwebapp_send_dashboard_password_change_emails( $user ) { 170 | 171 | // Don't run if password change happens via a shortcode form 172 | if ( isset( $_POST['wpwebapp_password_change_process'] ) || isset( $_POST['wpwebapp_password_reset_process'] ) ) return; 173 | 174 | // Send password change emails 175 | wpwebapp_send_password_change_email_to_admin( $user->user_login, $user->user_email ); 176 | wpwebapp_send_password_change_email_to_user( $user->user_login, $user->user_email ); 177 | 178 | } 179 | add_action( 'after_password_reset', 'wpwebapp_send_dashboard_password_change_emails' ); 180 | 181 | 182 | // Disable WordPress notifications for password changes 183 | if ( !function_exists( 'wp_password_change_notification' ) ) { 184 | function wp_password_change_notification() {} 185 | } 186 | add_filter( 'send_password_change_email', '__return_false'); -------------------------------------------------------------------------------- /shortcodes/password-reset.php: -------------------------------------------------------------------------------- 1 | ' . __( 'You\'re already logged in.', 'wpwebapp' ) . '

'; 18 | } else { 19 | 20 | // Variables 21 | $options = wpwebapp_get_theme_options_forgot_password(); 22 | $error = wpwebapp_get_session( 'wpwebapp_password_reset_error', true ); 23 | $success = wpwebapp_get_session( 'wpwebapp_password_reset_success', true ); 24 | $credentials = wpwebapp_get_session( 'wpwebapp_password_reset_credentials', true ); 25 | 26 | // Check if there's an expired reset key 27 | if ( isset( $_GET['reset_pw'] ) && empty( get_transient( 'wpwebapp_forgot_password_key_' . $_GET['reset_pw'] ) ) ) { 28 | $error = $options['password_forgot_password_reset_key_expired_error']; 29 | } 30 | 31 | $form = 32 | ( empty( $error ) ? '' : '
' . stripslashes( $error ) . '
' ) . 33 | ( empty( $success ) ? '' : '
' . stripslashes( $success ) . '
' ) . 34 | 35 | '
' . 36 | 37 | '' . 38 | '' . 39 | 40 | '' . 41 | 42 | wp_nonce_field( 'wpwebapp_password_forgot_nonce', 'wpwebapp_password_forgot_process', true, false ) . 43 | 44 | '
'; 45 | 46 | } 47 | 48 | return $form; 49 | 50 | } 51 | 52 | // Reset password form 53 | function wpwebapp_password_reset_form() { 54 | 55 | // Prevent this content from caching 56 | if ( !defined ( 'DONOTCACHEPAGE' ) || !DONOTCACHEPAGE ) { 57 | define('DONOTCACHEPAGE', TRUE); 58 | } 59 | 60 | if ( is_user_logged_in() ) { 61 | $form = '

' . __( 'You\'re already logged in.', 'wpwebapp' ) . '

'; 62 | } else { 63 | 64 | // Variables 65 | $options = wpwebapp_get_theme_options_forgot_password(); 66 | $error = wpwebapp_get_session( 'wpwebapp_password_reset_error', true ); 67 | $pw_requirements = $options['password_reset_show_requirements'] === 'on' ? '
' . wpwebapp_password_requirements_message() . '
' : null; 68 | 69 | $form = 70 | ( empty( $error ) ? '' : '
' . stripslashes( $error ) . '
' ) . 71 | 72 | '
' . 73 | 74 | '' . 75 | '' . 76 | $pw_requirements . 77 | 78 | '' . 79 | 80 | '' . 81 | 82 | wp_nonce_field( 'wpwebapp_password_reset_nonce', 'wpwebapp_password_reset_process', true, false ) . 83 | 84 | '
'; 85 | 86 | } 87 | 88 | return $form; 89 | 90 | } 91 | 92 | // Display password forgot or reset form 93 | function wpwebapp_display_password_reset_form() { 94 | 95 | // If this is password reset URL and key is still valid, return reset form 96 | if ( isset( $_GET['reset_pw'] ) && !empty( get_transient( 'wpwebapp_forgot_password_key_' . $_GET['reset_pw'] ) ) ) { 97 | return wpwebapp_password_reset_form(); 98 | } 99 | 100 | // Otherwise, return the forgot password form 101 | return wpwebapp_password_forgot_form(); 102 | 103 | } 104 | add_shortcode( 'wpwa_forgot_password', 'wpwebapp_display_password_reset_form' ); 105 | 106 | // Send password reset email 107 | function wpwebapp_send_password_reset_email( $to, $login, $reset_url, $expires, $email ) { 108 | 109 | // Variables 110 | $site_name = get_bloginfo('name'); 111 | $domain = wpwebapp_get_site_domain(); 112 | $headers = 'From: ' . $site_name . ' ' . "\r\n"; 113 | $subject = $site_name . ': Password Reset'; 114 | $message = str_replace( '[expires]', $expires, str_replace( '[reset]', esc_url( $reset_url ), str_replace( '[username]', esc_attr( $login ), stripslashes( $email ) ) ) ); 115 | 116 | // Send email 117 | @wp_mail( sanitize_email( $to ), $subject, $message, $headers ); 118 | 119 | } 120 | 121 | // Process password forgot 122 | function wpwebapp_process_password_forgot() { 123 | 124 | // Verify data came from form 125 | if ( !isset( $_POST['wpwebapp_password_forgot_process'] ) || !wp_verify_nonce( $_POST['wpwebapp_password_forgot_process'], 'wpwebapp_password_forgot_nonce' ) ) return; 126 | 127 | // Variables 128 | $options = wpwebapp_get_theme_options_forgot_password(); 129 | $referer = esc_url_raw( wpwebapp_clean_url( 'reset_pw', wpwebapp_get_url() ) ); 130 | 131 | // Check that a username is supplied 132 | if ( empty( $_POST['wpwebapp_password_forgot_username'] ) ) { 133 | wpwebapp_set_session( 'wpwebapp_password_reset_error', $options['password_forgot_password_field_empty_error'] ); 134 | wp_safe_redirect( $referer, 302 ); 135 | exit; 136 | } 137 | 138 | // Get user 139 | $user = is_email( $_POST['wpwebapp_password_forgot_username'] ) ? get_user_by( 'email', $_POST['wpwebapp_password_forgot_username'] ) : get_user_by( 'login', $_POST['wpwebapp_password_forgot_username'] ); 140 | 141 | // Verify that user exists 142 | if ( !$user ) { 143 | wpwebapp_set_session( 'wpwebapp_password_reset_error', $options['password_forgot_password_invalid_user_error'] ); 144 | wpwebapp_set_session( 'wpwebapp_password_reset_credentials', $_POST['wpwebapp_password_forgot_username'] ); 145 | wp_safe_redirect( $referer, 302 ); 146 | exit; 147 | } 148 | 149 | // Verify that user is not admin 150 | if ( user_can( $user->ID, 'edit_theme_options' ) ) { 151 | wpwebapp_set_session( 'wpwebapp_password_reset_error', $options['password_forgot_password_is_admin_error'] ); 152 | wpwebapp_set_session( 'wpwebapp_password_reset_credentials', $_POST['wpwebapp_password_forgot_username'] ); 153 | wp_safe_redirect( $referer, 302 ); 154 | exit; 155 | } 156 | 157 | // Send Password Reset Email 158 | $user_data = get_userdata( $user->ID ); 159 | $reset_url = wpwebapp_set_reset_key( $user->ID, $referer, $options['password_reset_time_valid'] ); 160 | wpwebapp_send_password_reset_email( $user_data->user_email, $user_data->user_login, $reset_url, $options['password_reset_time_valid'], $options['password_reset_notification_email'] ); 161 | 162 | // Run custom WordPress action 163 | do_action( 'wpwebapp_after_password_forgot_email_sent', $user->ID ); 164 | 165 | // Show success message 166 | wpwebapp_set_session( 'wpwebapp_password_reset_success', $options['password_forgot_password_success'] ); 167 | wp_safe_redirect( $referer, 302 ); 168 | exit; 169 | 170 | } 171 | add_action( 'init', 'wpwebapp_process_password_forgot' ); 172 | 173 | 174 | // Process password reset 175 | function wpwebapp_process_password_reset() { 176 | 177 | // Verify data came from form 178 | if ( !isset( $_POST['wpwebapp_password_reset_process'] ) || !wp_verify_nonce( $_POST['wpwebapp_password_reset_process'], 'wpwebapp_password_reset_nonce' ) ) return; 179 | 180 | // Variables 181 | $options = wpwebapp_get_theme_options_forgot_password(); 182 | $redirects = wpwebapp_get_theme_options_redirects(); 183 | $referer = esc_url_raw( wpwebapp_get_url() ); 184 | $redirect = wpwebapp_clean_url( 'reset_pw', wpwebapp_get_url() ); 185 | 186 | // Check that a password is supplied 187 | if ( empty( $_POST['wpwebapp_password_reset_password'] ) ) { 188 | wpwebapp_set_session( 'wpwebapp_password_reset_error', $options['password_reset_password_field_empty_error'] ); 189 | wp_safe_redirect( $referer, 302 ); 190 | exit; 191 | } 192 | 193 | // Get user ID 194 | $user_id = empty( $_POST['wpwebapp_password_reset_key'] ) ? null : substr( $_POST['wpwebapp_password_reset_key'], 48 ); 195 | if ( !$user_id ) { 196 | wpwebapp_set_session( 'wpwebapp_password_reset_error', $options['password_forgot_password_email_error'] ); 197 | wp_safe_redirect( $redirect, 302 ); 198 | exit; 199 | } 200 | 201 | // Enforce password requirements 202 | if ( !wpwebapp_test_password_requirements( $_POST['wpwebapp_password_reset_password'] ) ) { 203 | $message = wpwebapp_password_requirements_message(); 204 | wpwebapp_set_session( 'wpwebapp_password_reset_error', $message ); 205 | wp_safe_redirect( $referer, 302 ); 206 | exit; 207 | } 208 | 209 | // Reset the user's password 210 | wp_update_user( array( 'ID' => $user_id, 'user_pass' => $_POST['wpwebapp_password_reset_password'] ) ); 211 | delete_transient( 'wpwebapp_forgot_password_key_' . $_POST['wpwebapp_password_reset_key'] ); 212 | 213 | // Remove forced password reset if one was set 214 | update_user_meta( $user_id, 'wpwebapp_force_password_reset', 'off' ); 215 | 216 | // Run custom WordPress action 217 | do_action( 'wpwebapp_after_password_reset', $user_id ); 218 | 219 | // Log the user in 220 | $user = get_userdata( $user_id ); 221 | $credentials = array( 222 | 'user_login' => $user->user_login, 223 | 'user_password' => $_POST['wpwebapp_password_reset_password'], 224 | 'remember' => true, 225 | ); 226 | wp_signon( $credentials); 227 | 228 | // Send password change emails 229 | wpwebapp_send_password_change_email_to_admin( $user->user_login, $user->user_email ); 230 | wpwebapp_send_password_change_email_to_user( $user->user_login, $user->user_email ); 231 | 232 | // Redirect and exit 233 | wp_safe_redirect( wpwebapp_get_redirect_url( $redirects['login_redirect'] ), 302 ); 234 | exit; 235 | 236 | } 237 | add_action( 'init', 'wpwebapp_process_password_reset' ); -------------------------------------------------------------------------------- /shortcodes/signup.php: -------------------------------------------------------------------------------- 1 | ' . __( 'You\'re already logged in.', 'wpwebapp' ) . '

'; 18 | } else { 19 | 20 | // Variables 21 | $options = wpwebapp_get_theme_options_signup(); 22 | $error = wpwebapp_get_session( 'wpwebapp_signup_error', true ); 23 | $credentials = wpwebapp_get_session( 'wpwebapp_signup_credentials', true ); 24 | $pw_requirements = $options['signup_show_requirements'] === 'on' ? '
' . wpwebapp_password_requirements_message() . '
' : null; 25 | if ( empty( $credentials ) || !is_object( $credentials ) ) { 26 | $credentials = array( 27 | 'username' => '', 28 | 'email' => '', 29 | ); 30 | } 31 | 32 | $form = 33 | ( empty( $error ) ? '' : '
' . stripslashes( $error ) . '
' ) . 34 | 35 | '
' . 36 | 37 | '' . 38 | '' . 39 | 40 | '' . 41 | '' . 42 | 43 | '' . 44 | '' . 45 | $pw_requirements . 46 | 47 | '' . 48 | '' . 49 | 50 | '' . 51 | 52 | '' . 53 | 54 | wp_nonce_field( 'wpwebapp_signup_nonce', 'wpwebapp_signup_process', true, false ) . 55 | 56 | '
'; 57 | 58 | } 59 | 60 | return $form; 61 | 62 | } 63 | add_shortcode( 'wpwa_signup', 'wpwebapp_signup_form' ); 64 | 65 | // Send notification email to admin when new account created 66 | function wpwebapp_send_user_notification_email( $login, $email ) { 67 | 68 | // Check if admin wants to receive emails 69 | $options = wpwebapp_get_theme_options_signup(); 70 | if ( $options['signup_receive_notifications'] === 'off' ) return; 71 | 72 | // Variables 73 | $site_name = get_bloginfo('name'); 74 | $domain = wpwebapp_get_site_domain(); 75 | $headers = 'From: ' . $site_name . ' ' . "\r\n"; 76 | $subject = $site_name . ': New User Registration'; 77 | $message = str_replace( '[email]', sanitize_email( $email ), str_replace( '[username]', esc_attr( $login ), stripslashes( $options['signup_notification_to_admin'] ) ) ); 78 | 79 | // Send email 80 | @wp_mail( get_option('admin_email'), $subject, $message, $headers ); 81 | 82 | } 83 | 84 | // Send notification email to member when new account created 85 | function wpwebapp_send_user_welcome_email( $login, $email ) { 86 | 87 | // Check if user should receive emails 88 | $options = wpwebapp_get_theme_options_signup(); 89 | $redirects = wpwebapp_get_theme_options_redirects(); 90 | if ( $options['signup_send_notifications'] === 'off' ) return; 91 | 92 | // Variables 93 | $site_name = get_bloginfo('name'); 94 | $domain = wpwebapp_get_site_domain(); 95 | $headers = 'From: ' . $site_name . ' ' . "\r\n"; 96 | $subject = 'Welcome to ' . $site_name; 97 | $message = str_replace( '[login]', $redirects['logout_redirect'], str_replace( '[username]', esc_attr( $login ), stripslashes( $options['signup_notification_to_user'] ) ) ); 98 | 99 | // Send email 100 | $email = @wp_mail( sanitize_email( $email ), $subject, $message, $headers ); 101 | 102 | } 103 | 104 | // Create new user account 105 | function wpwebapp_create_new_user() { 106 | // @todo include an option to select the type of user role to assign member to (allows for custom roles) 107 | 108 | // Verify data came from form 109 | if ( !isset( $_POST['wpwebapp_signup_process'] ) || !wp_verify_nonce( $_POST['wpwebapp_signup_process'], 'wpwebapp_signup_nonce' ) ) return; 110 | 111 | // Variables 112 | $options = wpwebapp_get_theme_options_signup(); 113 | $redirects = wpwebapp_get_theme_options_redirects(); 114 | $referer = esc_url_raw( wpwebapp_get_url() ); 115 | $credentials = array( 116 | 'username' => $_POST['wpwebapp_signup_username'], 117 | 'email' => $_POST['wpwebapp_signup_email'], 118 | ); 119 | 120 | // Check that username is supplied 121 | if ( empty( $_POST['wpwebapp_signup_username'] ) ) { 122 | wpwebapp_set_session( 'wpwebapp_signup_error', $options['signup_username_field_empty_error'] ); 123 | wpwebapp_set_session( 'wpwebapp_signup_credentials', $credentials ); 124 | wp_safe_redirect( $referer, 302 ); 125 | exit; 126 | } 127 | 128 | // Check that email is supplied 129 | if ( empty( $_POST['wpwebapp_signup_email'] ) ) { 130 | wpwebapp_set_session( 'wpwebapp_signup_error', $options['signup_email_field_empty_error'] ); 131 | wpwebapp_set_session( 'wpwebapp_signup_credentials', $credentials ); 132 | wp_safe_redirect( $referer, 302 ); 133 | exit; 134 | } 135 | 136 | // Check that password is supplied 137 | if ( empty( $_POST['wpwebapp_signup_password'] ) ) { 138 | wpwebapp_set_session( 'wpwebapp_signup_error', $options['signup_password_field_empty_error'] ); 139 | wpwebapp_set_session( 'wpwebapp_signup_credentials', $credentials ); 140 | wp_safe_redirect( $referer, 302 ); 141 | exit; 142 | } 143 | 144 | // Check that username is valid 145 | if ( !validate_username( $_POST['wpwebapp_signup_username'] ) ) { 146 | wpwebapp_set_session( 'wpwebapp_signup_error', $options['signup_username_invalid_error'] ); 147 | wpwebapp_set_session( 'wpwebapp_signup_credentials', $credentials ); 148 | wp_safe_redirect( $referer, 302 ); 149 | exit; 150 | } 151 | 152 | // Check that username isn't already taken 153 | if ( username_exists( $_POST['wpwebapp_signup_username'] ) ) { 154 | wpwebapp_set_session( 'wpwebapp_signup_error', $options['signup_username_exists_error'] ); 155 | wpwebapp_set_session( 'wpwebapp_signup_credentials', $credentials ); 156 | wp_safe_redirect( $referer, 302 ); 157 | exit; 158 | } 159 | 160 | // Check that email address is valid 161 | if ( !is_email( $_POST['wpwebapp_signup_email'] ) ) { 162 | wpwebapp_set_session( 'wpwebapp_signup_error', $options['signup_email_invalid_error'] ); 163 | wpwebapp_set_session( 'wpwebapp_signup_credentials', $credentials ); 164 | wp_safe_redirect( $referer, 302 ); 165 | exit; 166 | } 167 | 168 | // Check that email isn't already taken 169 | if ( email_exists( $_POST['wpwebapp_signup_email'] ) ) { 170 | wpwebapp_set_session( 'wpwebapp_signup_error', $options['signup_email_exists_error'] ); 171 | wpwebapp_set_session( 'wpwebapp_signup_credentials', $credentials ); 172 | wp_safe_redirect( $referer, 302 ); 173 | exit; 174 | } 175 | 176 | // Enforce password requirements 177 | if ( !wpwebapp_test_password_requirements( $_POST['wpwebapp_signup_password'] ) ) { 178 | $message = wpwebapp_password_requirements_message(); 179 | wpwebapp_set_session( 'wpwebapp_signup_error', $message ); 180 | wpwebapp_set_session( 'wpwebapp_signup_credentials', $credentials ); 181 | wp_safe_redirect( $referer, 302 ); 182 | exit; 183 | } 184 | 185 | // Honeypots 186 | if ( !empty( $_POST['wpwebapp_signup_password_confirm'] ) || !isset( $_POST['wpwebapp_signup_tarpit_time'] ) || current_time( 'timestamp' ) - $_POST['wpwebapp_signup_tarpit_time'] < 2 ) { 187 | $message = __( 'We are unable to create your account. Sorry.', 'beacon' ); 188 | wpwebapp_set_session( 'wpwebapp_signup_error', $message ); 189 | wpwebapp_set_session( 'wpwebapp_signup_credentials', $credentials ); 190 | wp_safe_redirect( $referer, 302 ); 191 | exit; 192 | } 193 | 194 | // If no errors exist, create an account and send notification emails 195 | wp_create_user( $_POST['wpwebapp_signup_username'], $_POST['wpwebapp_signup_password'], sanitize_email( $_POST['wpwebapp_signup_email'] ) ); 196 | wpwebapp_send_user_notification_email( $_POST['wpwebapp_signup_username'], $_POST['wpwebapp_signup_email'] ); 197 | wpwebapp_send_user_welcome_email( $_POST['wpwebapp_signup_username'], $_POST['wpwebapp_signup_email'] ); 198 | 199 | // Run custom WordPress action 200 | do_action( 'wpwebapp_after_signup', $_POST['wpwebapp_signup_username'], sanitize_email( $_POST['wpwebapp_signup_email'] ) ); 201 | 202 | // Log user in 203 | $credentials = array( 204 | 'user_login' => $_POST['wpwebapp_signup_username'], 205 | 'user_password' => $_POST['wpwebapp_signup_password'], 206 | 'remember' => true, 207 | ); 208 | $login = wp_signon( $credentials ); 209 | 210 | // If errors 211 | if ( is_wp_error( $login ) ) { 212 | wpwebapp_set_session( 'wpwebapp_signup_error', $options['signup_login_failed_error'] ); 213 | wpwebapp_set_session( 'wpwebapp_signup_credentials', $credentials ); 214 | wp_safe_redirect( $referer, 302 ); 215 | exit; 216 | } 217 | 218 | // Redirect after login 219 | $redirect = isset( $_GET['referrer'] ) && !empty( $_GET['referrer'] ) ? esc_url_raw( $_GET['referrer'] ) : wpwebapp_get_redirect_url( $redirects['login_redirect'] ); 220 | wp_safe_redirect( $redirect, 302 ); 221 | exit; 222 | 223 | } 224 | add_action( 'init', 'wpwebapp_create_new_user' ); 225 | 226 | // Add honeypot classes to the header 227 | function beacon_load_honeypot_styles() { 228 | ?> 229 | 236 | ' . "\r\n"; 263 | $subject = 'Welcome to ' . $site_name; 264 | $message = str_replace( '[expires]', $options['create_user_password_time_valid'], str_replace( '[pw_reset]', $pw_reset, str_replace( '[username]', esc_attr( $user->user_login ), stripslashes( $options['create_user_notification'] ) ) ) ); 265 | 266 | // Send email 267 | @wp_mail( $user->user_email, $subject, $message, $headers ); 268 | 269 | } 270 | add_action( 'user_register', 'wpwebapp_create_user_notification_email', 10, 1 ); -------------------------------------------------------------------------------- /wordpress-for-web-apps.php: -------------------------------------------------------------------------------- 1 | Web App Options. 8 | * Version: 8.0.8 9 | * Author: Chris Ferdinandi 10 | * Author URI: http://gomakethings.com 11 | * License: MIT 12 | */ 13 | 14 | // Includes 15 | require_once( plugin_dir_path( __FILE__ ) . 'includes/wp-session-manager/wp-session-manager.php' ); 16 | require_once( plugin_dir_path( __FILE__ ) . 'includes/helpers.php' ); 17 | require_once( plugin_dir_path( __FILE__ ) . 'includes/migrate-options.php' ); 18 | 19 | // Options 20 | require_once( plugin_dir_path( __FILE__ ) . 'options/options.php' ); 21 | 22 | // Shortcodes 23 | require_once( plugin_dir_path( __FILE__ ) . 'shortcodes/signup.php' ); // Sign up for an account 24 | require_once( plugin_dir_path( __FILE__ ) . 'shortcodes/login.php' ); // Login 25 | require_once( plugin_dir_path( __FILE__ ) . 'shortcodes/password-reset.php' ); // Reset Password 26 | require_once( plugin_dir_path( __FILE__ ) . 'shortcodes/password-change.php' ); // Change Password 27 | require_once( plugin_dir_path( __FILE__ ) . 'shortcodes/email-change.php' ); // Change Email 28 | require_once( plugin_dir_path( __FILE__ ) . 'shortcodes/delete-account.php' ); // Delete Account 29 | require_once( plugin_dir_path( __FILE__ ) . 'shortcodes/navigation.php' ); // Nav menu shortcodes 30 | 31 | // Security and Access 32 | require_once( plugin_dir_path( __FILE__ ) . 'options/security.php' ); 33 | require_once( plugin_dir_path( __FILE__ ) . 'options/user-access.php' ); --------------------------------------------------------------------------------