From 15d781c5975416734ab76397d22ca1750c95e168 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 14 Jun 2016 18:18:20 -0500 Subject: [PATCH 001/157] Add a warning message when the user is editing the administrator role. Fixes: https://github.com/justintadlock/members/issues/98 --- admin/class-role-edit.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/admin/class-role-edit.php b/admin/class-role-edit.php index 00c76dd..b770f5b 100644 --- a/admin/class-role-edit.php +++ b/admin/class-role-edit.php @@ -192,6 +192,10 @@ public function load() { if ( ! $this->is_editable ) add_settings_error( 'members_edit_role', 'role_uneditable', sprintf( esc_html__( 'The %s role is not editable. This means that it is most likely added via another plugin for a special use or that you do not have permission to edit it.', 'members' ), members_get_role_name( $this->role->name ) ) ); + // If editing the core administrator role. + if ( 'administrator' === $this->role->name ) + add_settings_error( 'members_edit_role', 'role_is_admin', sprintf( esc_html__( 'The %s role is typically the most important role on the site. Please take extreme caution that you do no inadvertently remove necessary capabilities.', 'members' ), members_get_role_name( $this->role->name ) ) ); + // If a new role was added (redirect from new role screen). if ( isset( $_GET['message'] ) && 'role_added' === $_GET['message'] ) add_settings_error( 'members_edit_role', 'role_added', sprintf( esc_html__( 'The %s role has been created.', 'members' ), members_get_role_name( $this->role->name ) ), 'updated' ); From 7db33f0fcbb996bd76d0fabb5ecc1f926dce1efe Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 14 Jun 2016 18:39:20 -0500 Subject: [PATCH 002/157] Whitelist the BuddyPress activation page in private site mode. Props @turtlepod Fixes: https://github.com/justintadlock/members/issues/83 --- inc/functions-private-site.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/functions-private-site.php b/inc/functions-private-site.php index 0773612..134242c 100644 --- a/inc/functions-private-site.php +++ b/inc/functions-private-site.php @@ -65,7 +65,7 @@ function members_please_log_in() { if ( members_is_private_blog() && ! is_user_logged_in() ) { // If using BuddyPress and on the register page, don't do anything. - if ( function_exists( 'bp_is_current_component' ) && bp_is_current_component( 'register' ) ) + if ( function_exists( 'bp_is_current_component' ) && ( bp_is_current_component( 'register' ) || bp_is_current_component( 'activate' ) ) ) return; // Redirect to the login page. From f30a01b0c80c79f9dc257cea7c620703a4c7ccd6 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 14 Jun 2016 18:46:02 -0500 Subject: [PATCH 003/157] Introduce the `members_is_public_page()` and accompanying filter hook. This will allow plugin developers to whitelist custom pages if they need them to be public while Members is set to private site mode. --- inc/functions-private-site.php | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/inc/functions-private-site.php b/inc/functions-private-site.php index 134242c..bb43f61 100644 --- a/inc/functions-private-site.php +++ b/inc/functions-private-site.php @@ -62,18 +62,31 @@ function members_is_private_feed() { function members_please_log_in() { // Check if the private blog feature is active and if the user is not logged in. - if ( members_is_private_blog() && ! is_user_logged_in() ) { + if ( members_is_private_blog() && ! is_user_logged_in() && ! members_is_public_page() ) { - // If using BuddyPress and on the register page, don't do anything. - if ( function_exists( 'bp_is_current_component' ) && ( bp_is_current_component( 'register' ) || bp_is_current_component( 'activate' ) ) ) - return; - - // Redirect to the login page. auth_redirect(); exit; } } +/** + * Function for determining whether a page should be public even though we're in private + * site mode. Plugin devs can filter this to make specific pages public. + * + * @since 1.2.0 + * @access public + * @return bool + */ +function members_is_public_page() { + + $is_public = false; + + if ( function_exists( 'bp_is_current_component' ) && ( bp_is_current_component( 'register' ) || bp_is_current_component( 'activate' ) ) ) + $is_public = true; + + return apply_filters( 'members_is_public_page', $is_public ); +} + /** * Blocks feed items if the user has selected the private feed feature. * From 2f632b20545b0e1704262c32a8b9465df1cd2db5 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 14 Jun 2016 18:54:55 -0500 Subject: [PATCH 004/157] Change `members_is_public_page()` to `members_is_private_page()`. That seems more consistent with the naming scheme. This also fixes https://github.com/justintadlock/members/issues/95 --- inc/functions-private-site.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/inc/functions-private-site.php b/inc/functions-private-site.php index bb43f61..5017c46 100644 --- a/inc/functions-private-site.php +++ b/inc/functions-private-site.php @@ -62,7 +62,7 @@ function members_is_private_feed() { function members_please_log_in() { // Check if the private blog feature is active and if the user is not logged in. - if ( members_is_private_blog() && ! is_user_logged_in() && ! members_is_public_page() ) { + if ( members_is_private_blog() && ! is_user_logged_in() && members_is_private_page() ) { auth_redirect(); exit; @@ -77,14 +77,14 @@ function members_please_log_in() { * @access public * @return bool */ -function members_is_public_page() { +function members_is_private_page() { - $is_public = false; + $is_private = true; if ( function_exists( 'bp_is_current_component' ) && ( bp_is_current_component( 'register' ) || bp_is_current_component( 'activate' ) ) ) - $is_public = true; + $is_private = false; - return apply_filters( 'members_is_public_page', $is_public ); + return apply_filters( 'members_is_private_page', $is_private ); } /** From 0468077888402245892791142d43b9bdfe9806e2 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 4 Oct 2016 11:39:22 -0500 Subject: [PATCH 005/157] Adds WooCommerce account page support to the private site feature. Don't redirect when attempting to visit the account page when site is private. Props @turtlepod Fixes https://github.com/justintadlock/members/issues/111 --- inc/functions-private-site.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/inc/functions-private-site.php b/inc/functions-private-site.php index 5017c46..003b8ef 100644 --- a/inc/functions-private-site.php +++ b/inc/functions-private-site.php @@ -84,6 +84,14 @@ function members_is_private_page() { if ( function_exists( 'bp_is_current_component' ) && ( bp_is_current_component( 'register' ) || bp_is_current_component( 'activate' ) ) ) $is_private = false; + // WooCommerce support. + if ( class_exists( 'WooCommerce' ) ) { + $page_id = get_option( 'woocommerce_myaccount_page_id' ); + + if ( is_page( $page_id ) ) + $is_private = false; + } + return apply_filters( 'members_is_private_page', $is_private ); } From bf0f3ba51f2b48970f46b67ebccbf2aa6f56acc8 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 4 Oct 2016 11:45:52 -0500 Subject: [PATCH 006/157] Use `

` instead of `

` for proper admin heading hierarchy. Props @lutrov Fixes https://github.com/justintadlock/members/issues/100 --- admin/class-cap-tabs.php | 2 +- admin/class-user-edit.php | 2 +- css/admin.css | 2 +- css/admin.min.css | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/admin/class-cap-tabs.php b/admin/class-cap-tabs.php index 6c728c9..3cad8f4 100644 --- a/admin/class-cap-tabs.php +++ b/admin/class-cap-tabs.php @@ -171,7 +171,7 @@ public function display() { ?>
-

' ); ?>

+

' ); ?>

diff --git a/admin/class-user-edit.php b/admin/class-user-edit.php index b8ad4c7..a808f2d 100644 --- a/admin/class-user-edit.php +++ b/admin/class-user-edit.php @@ -84,7 +84,7 @@ public function profile_fields( $user ) { wp_nonce_field( 'new_user_roles', 'members_new_user_roles_nonce' ); ?> -

+

diff --git a/css/admin.css b/css/admin.css index cb89050..707a7c8 100644 --- a/css/admin.css +++ b/css/admin.css @@ -38,7 +38,7 @@ #tabcapsdiv { margin-top: 1em; } - #tabcapsdiv > h3 { + #tabcapsdiv > .hndle { padding: 10px; border-bottom: 1px solid #eee; } diff --git a/css/admin.min.css b/css/admin.min.css index a7704e9..4ce7ec6 100644 --- a/css/admin.min.css +++ b/css/admin.min.css @@ -1 +1 @@ -@media only screen and (min-width:783px){.users_page_roles .column-users,.users_page_roles .column-granted_caps,.users_page_roles .column-denied_caps{width:125px;text-align:center}}.members-title-div #titlewrap input{padding:0 8px;font-size:1.7em;line-height:normal;height:1.7em;width:100%;outline:0;margin:0 0 3px;background-color:#fff}.members-title-div input[name=role]{font-size:13px;height:22px;margin:0;width:16em}#tabcapsdiv{margin-top:1em}#tabcapsdiv>h3{padding:10px;border-bottom:1px solid #eee}#tabcapsdiv .inside{margin:0;padding:0}.members-cap-tabs{overflow:hidden;background:#fff;background:linear-gradient(90deg,#fafafa 0,#fafafa 20%,#fff 20%,#fff 100%)}@media only screen and (max-width:782px){.members-cap-tabs{background:linear-gradient(90deg,#fafafa 0,#fafafa 48px,#fff 48px,#fff 100%)}}.members-cap-tabs .members-tab-nav{position:relative;float:left;list-style:none;width:20%;line-height:1em;margin:0 0 -1px 0;padding:0;background-color:#fafafa;border-right:1px solid #eee;box-sizing:border-box}.members-cap-tabs .members-tab-nav li{display:block;position:relative;margin:0;padding:0;line-height:20px}.members-cap-tabs .members-tab-nav li a{display:block;margin:0;padding:10px;line-height:20px!important;text-decoration:none;border-bottom:1px solid #eee;box-shadow:none}.members-cap-tabs .members-tab-nav li a .dashicons{line-height:20px;margin-right:3px}.members-cap-tabs .members-tab-nav li[aria-selected=true] a{position:relative;font-weight:700;color:#555;background-color:#e0e0e0}@media only screen and (max-width:782px){.members-cap-tabs .members-tab-nav{width:48px}.members-cap-tabs .members-tab-nav li a .dashicons{width:24px;height:24px;font-size:24px;line-height:24px}.members-tab-nav li .dashicons::before{width:24px;height:24px}.members-tab-nav li .label{overflow:hidden;position:absolute;top:-1000em;left:-1000em;width:1px;height:1px}}.members-cap-tabs .members-tab-wrap{float:left;width:80%;margin-left:-1px}@media only screen and (max-width:782px){.members-cap-tabs .members-tab-wrap{width:calc(100% - 48px)}}#tabcapsdiv table{border-right:0;border-top:0;border-bottom:0}#tabcapsdiv table td,#tabcapsdiv table th{padding:10px;padding-bottom:10px;border-bottom:1px solid #eee;font-size:13px;line-height:20px}#tabcapsdiv table td{padding:9px}#tabcapsdiv tbody tr:last-of-type td{border-bottom:0}#tabcapsdiv tfoot th{border-color:#eee}@media only screen and (max-width:782px){#tabcapsdiv table td,#tabcapsdiv table th{line-height:24px}}.members-roles-select .column-grant,.members-roles-select .column-deny{width:70px!important;text-align:center;display:table-cell!important;clear:none!important}.members-cap-tabs button{display:inline;margin:-4px;line-height:inherit;padding:4px 8px;border:1px solid transparent;background:transparent;border-radius:0;outline:0;-webkit-transition:all .25s ease-out;-moz-transition:all .25s ease-out;-o-transition:all .25s ease-out;transition:all .25s ease-out}.members-cap-tabs button:hover,.members-cap-tabs button:focus{border-color:#eee;background:#fafafa;cursor:pointer}.members-cap-tabs button:active{color:#0073aa;border-color:#0073aa}.members-cap-tabs button+.dashicons{display:none;margin-top:1px;margin-bottom:-1px;line-height:inherit}.members-cap-tabs button:hover+.dashicons,.members-cap-tabs button:focus+.dashicons{display:inline-block}.members-tab-content .members-highlight{background-color:rgba(0,115,170,.05)}.members-tab-content tbody{-webkit-transition:all 2s ease-in-out;-moz-transition:all 2s ease-in-out;-o-transition:all 2s ease-in-out;transition:all 2s ease-in-out}.members-cp-role-list-wrap{overflow:auto;min-height:42px;max-height:200px;padding:0 .9em;border:solid 1px #dfdfdf;background-color:#fdfdfd} \ No newline at end of file +@media only screen and (min-width:783px){.users_page_roles .column-users,.users_page_roles .column-granted_caps,.users_page_roles .column-denied_caps{width:100px;text-align:center}}.members-title-div #titlewrap input{padding:0 8px;font-size:1.7em;line-height:normal;height:1.7em;width:100%;outline:0;margin:0 0 3px;background-color:#fff}.members-title-div input[name=role]{font-size:13px;height:22px;margin:0;width:16em}#tabcapsdiv{margin-top:1em}#tabcapsdiv>.hndle{padding:10px;border-bottom:1px solid #eee}#tabcapsdiv .inside{margin:0;padding:0}.members-cap-tabs{overflow:hidden;background:#fff;background:linear-gradient(90deg,#fafafa 0,#fafafa 20%,#fff 20%,#fff 100%)}@media only screen and (max-width:782px){.members-cap-tabs{background:linear-gradient(90deg,#fafafa 0,#fafafa 48px,#fff 48px,#fff 100%)}}.members-cap-tabs .members-tab-nav{position:relative;float:left;list-style:none;width:20%;line-height:1em;margin:0 0 -1px 0;padding:0;background-color:#fafafa;border-right:1px solid #eee;box-sizing:border-box}.members-cap-tabs .members-tab-nav li{display:block;position:relative;margin:0;padding:0;line-height:20px}.members-cap-tabs .members-tab-nav li a{display:block;margin:0;padding:10px;line-height:20px!important;text-decoration:none;border-bottom:1px solid #eee;box-shadow:none}.members-cap-tabs .members-tab-nav li a .dashicons{line-height:20px;margin-right:3px}.members-cap-tabs .members-tab-nav li[aria-selected=true] a{position:relative;font-weight:700;color:#555;background-color:#e0e0e0}@media only screen and (max-width:782px){.members-cap-tabs .members-tab-nav{width:48px}.members-cap-tabs .members-tab-nav li a .dashicons{width:24px;height:24px;font-size:24px;line-height:24px}.members-tab-nav li .dashicons::before{width:24px;height:24px}.members-tab-nav li .label{overflow:hidden;position:absolute;top:-1000em;left:-1000em;width:1px;height:1px}}.members-cap-tabs .members-tab-wrap{float:left;width:80%;margin-left:-1px}@media only screen and (max-width:782px){.members-cap-tabs .members-tab-wrap{width:calc(100% - 48px)}}#tabcapsdiv table{border-right:0;border-top:0;border-bottom:0}#tabcapsdiv table td,#tabcapsdiv table th{padding:10px;padding-bottom:10px;border-bottom:1px solid #eee;font-size:13px;line-height:20px}#tabcapsdiv table td{padding:9px}#tabcapsdiv tbody tr:last-of-type td{border-bottom:0}#tabcapsdiv tfoot th{border-color:#eee}@media only screen and (max-width:782px){#tabcapsdiv table td,#tabcapsdiv table th{line-height:24px}}.members-roles-select .column-grant,.members-roles-select .column-deny{width:70px!important;text-align:center;display:table-cell!important;clear:none!important}.members-cap-tabs button{display:inline;margin:-4px;line-height:inherit;padding:4px 8px;border:1px solid transparent;background:transparent;border-radius:0;outline:0;-webkit-transition:all .25s ease-out;-moz-transition:all .25s ease-out;-o-transition:all .25s ease-out;transition:all .25s ease-out}.members-cap-tabs button:hover,.members-cap-tabs button:focus{border-color:#eee;background:#fafafa;cursor:pointer}.members-cap-tabs button:active{color:#0073aa;border-color:#0073aa}.members-cap-tabs button+.dashicons{display:none;margin-top:1px;margin-bottom:-1px;line-height:inherit}.members-cap-tabs button:hover+.dashicons,.members-cap-tabs button:focus+.dashicons{display:inline-block}.members-tab-content .members-highlight{background-color:rgba(0,115,170,.05)}.members-tab-content tbody{-webkit-transition:all 2s ease-in-out;-moz-transition:all 2s ease-in-out;-o-transition:all 2s ease-in-out;transition:all 2s ease-in-out}.members-cp-role-list-wrap{overflow:auto;min-height:42px;max-height:200px;padding:0 .9em;border:solid 1px #dfdfdf;background-color:#fdfdfd} \ No newline at end of file From f2232648aaaacb8b8e0779f78afd9687c77dd784 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 4 Oct 2016 12:00:25 -0500 Subject: [PATCH 007/157] Adds the `members_enable_{$post_type}_content_permissions` filter hook to allow plugin devs to enable/disable the Content Permissions meta box for certain post types. Fixes https://github.com/justintadlock/members/issues/77 --- admin/class-meta-box-content-permissions.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/admin/class-meta-box-content-permissions.php b/admin/class-meta-box-content-permissions.php index 354d00e..080e556 100644 --- a/admin/class-meta-box-content-permissions.php +++ b/admin/class-meta-box-content-permissions.php @@ -54,6 +54,10 @@ protected function __construct() { */ public function load() { + // Make sure meta box is allowed for this post type. + if ( ! $this->maybe_enable() ) + return; + // Enqueue scripts/styles. add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) ); @@ -99,6 +103,20 @@ public function add_meta_boxes( $post_type ) { add_meta_box( 'members-cp', esc_html__( 'Content Permissions', 'members' ), array( $this, 'meta_box' ), $post_type, 'advanced', 'high' ); } + /** + * Checks if Content Permissions should appear for the given post type. + * + * @since 1.2.0 + * @access public + * @return bool + */ + public function maybe_enable() { + + $post_type = get_current_screen()->post_type; + + return apply_filters( "members_enable_{$post_type}_content_permissions", true ); + } + /** * Outputs the meta box HTML. * From e822ea6742441c616292af0edda1e6ef6e591277 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 7 Oct 2016 14:14:52 -0500 Subject: [PATCH 008/157] Add context for the "Add New" text string to differentiate between adding a new role and a new capability. Fixes: https://github.com/justintadlock/members/pull/107 Props @pedro-mendonca --- admin/class-meta-box-custom-cap.php | 2 +- admin/class-role-edit.php | 2 +- admin/class-roles.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/admin/class-meta-box-custom-cap.php b/admin/class-meta-box-custom-cap.php index 54884d2..30a39c9 100644 --- a/admin/class-meta-box-custom-cap.php +++ b/admin/class-meta-box-custom-cap.php @@ -85,7 +85,7 @@ public function meta_box() { ?>

- +

- %s', esc_url( members_get_new_role_url() ), esc_html__( 'Add New', 'members' ) ); ?> + %s', esc_url( members_get_new_role_url() ), esc_html_x( 'Add New', 'role', 'members' ) ); ?> diff --git a/admin/class-roles.php b/admin/class-roles.php index 96db209..8b5fe3d 100644 --- a/admin/class-roles.php +++ b/admin/class-roles.php @@ -168,7 +168,7 @@ public function page() { - + From 36236b652987d6704ccd1f67e25c32ea66506c3d Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 7 Oct 2016 14:20:32 -0500 Subject: [PATCH 009/157] Fix switched `id_remember` and `id_submit` keys from the `$instance` variable in the login widget. Also, use `id_remember` rather than `remember`. Fixes: https://github.com/justintadlock/members/pull/84 Props @m-e-h --- inc/class-widget-login.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/inc/class-widget-login.php b/inc/class-widget-login.php index 67c544f..654f9be 100644 --- a/inc/class-widget-login.php +++ b/inc/class-widget-login.php @@ -54,11 +54,11 @@ public function __construct() { // Set up the defaults. $this->defaults = array( - 'title' => esc_attr__( 'Log In', 'members' ), - 'label_username' => esc_attr__( 'Username', 'members' ), - 'label_password' => esc_attr__( 'Password', 'members' ), - 'label_log_in' => esc_attr__( 'Log In', 'members' ), - 'label_remember' => esc_attr__('Remember Me', 'members' ), + 'title' => esc_attr__( 'Log In', 'members' ), + 'label_username' => esc_attr__( 'Username', 'members' ), + 'label_password' => esc_attr__( 'Password', 'members' ), + 'label_log_in' => esc_attr__( 'Log In', 'members' ), + 'label_remember' => esc_attr__( 'Remember Me', 'members' ), 'form_id' => 'loginform', 'id_username' => 'user_login', 'id_password' => 'user_pass', @@ -97,8 +97,8 @@ function widget( $sidebar, $instance ) { 'label_log_in' => esc_html( $instance['label_log_in'] ), 'id_username' => esc_attr( $instance['id_username'] ), 'id_password' => esc_attr( $instance['id_password'] ), - 'id_remember' => esc_attr( $instance['id_submit'] ), - 'id_submit' => esc_attr( $instance['remember'] ), + 'id_remember' => esc_attr( $instance['id_remember'] ), + 'id_submit' => esc_attr( $instance['id_submit'] ), 'value_username' => esc_attr( $instance['value_username'] ), 'remember' => ! empty( $instance['remember'] ) ? true : false, From 44a5e0e3a97f84a11400b5b806e6a39631c7999f Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 6 Feb 2017 10:01:34 -0600 Subject: [PATCH 010/157] Remove core customize changeset and custom CSS post types from the cap groups. --- admin/functions-cap-groups.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/functions-cap-groups.php b/admin/functions-cap-groups.php index 28edb60..edd9926 100644 --- a/admin/functions-cap-groups.php +++ b/admin/functions-cap-groups.php @@ -123,7 +123,7 @@ function members_register_cap_groups() { foreach ( get_post_types( array(), 'objects' ) as $type ) { // Skip revisions and nave menu items. - if ( in_array( $type->name, array( 'revision', 'nav_menu_item' ) ) ) + if ( in_array( $type->name, array( 'revision', 'nav_menu_item', 'custom_css', 'customize_changeset' ) ) ) continue; // Get the caps for the post type. From 4d919bfe7a792940a5fa3ed7a0bfd519e55064ca Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 6 Feb 2017 10:06:52 -0600 Subject: [PATCH 011/157] Make sure the role is editable before attempting to add a new role to a user on the user edit screen when the multiple roles features is active. --- admin/class-user-edit.php | 2 +- changelog.md | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/admin/class-user-edit.php b/admin/class-user-edit.php index b8ad4c7..99951f0 100644 --- a/admin/class-user-edit.php +++ b/admin/class-user-edit.php @@ -144,7 +144,7 @@ public function role_update( $user_id ) { foreach ( $new_roles as $new_role ) { // If the user doesn't already have the role, add it. - if ( ! in_array( $new_role, (array) $user->roles ) ) + if ( members_is_role_editable( $new_role ) && ! in_array( $new_role, (array) $user->roles ) ) $user->add_role( $new_role ); } diff --git a/changelog.md b/changelog.md index 10753f6..590e31f 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,11 @@ # Change Log +## [1.1.3] - 2016-02-06 + +### Security + +* Added a check that the role is editable before attempting to add a new role to a user. + ## [1.1.2] - 2016-06-20 ### Fixed From 37618dd43195f7f1f9d1e98675e01b7c7ba01ab6 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 6 Feb 2017 11:10:31 -0600 Subject: [PATCH 012/157] Remove `customize_changeset` and `custom_css` from the post type cap groups. Pulling this from the current `dev` branch. --- admin/functions-cap-groups.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/functions-cap-groups.php b/admin/functions-cap-groups.php index 28edb60..edd9926 100644 --- a/admin/functions-cap-groups.php +++ b/admin/functions-cap-groups.php @@ -123,7 +123,7 @@ function members_register_cap_groups() { foreach ( get_post_types( array(), 'objects' ) as $type ) { // Skip revisions and nave menu items. - if ( in_array( $type->name, array( 'revision', 'nav_menu_item' ) ) ) + if ( in_array( $type->name, array( 'revision', 'nav_menu_item', 'custom_css', 'customize_changeset' ) ) ) continue; // Get the caps for the post type. From 31fa346d68cc7f867c18b3b6b6967116fa71bca0 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 6 Feb 2017 11:11:58 -0600 Subject: [PATCH 013/157] Update changelog.md. --- changelog.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/changelog.md b/changelog.md index 590e31f..f33cb55 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,10 @@ ## [1.1.3] - 2016-02-06 +### Fixed + +* Removes the `customize_changeset` and `custom_css` post type cap groups so that they don't appear in the capability tabs on the edit role screen. + ### Security * Added a check that the role is editable before attempting to add a new role to a user. From cda54181776ba22a321ab934aaad289f9ea2534a Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 6 Feb 2017 11:13:34 -0600 Subject: [PATCH 014/157] Update readme.txt. --- readme.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/readme.txt b/readme.txt index 4a23997..8cc8a48 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,8 @@ Contributors: greenshady Donate link: http://themehybrid.com/donate Tags: admin, role, roles, member, members, profile, shortcode, user, users, widget, widgets Requires at least: 4.3 -Stable tag: 1.1.2 +Tested up to: 4.7.2 +Stable tag: 1.1.3 The most powerful user, role, and capability management plugin for WordPress. @@ -42,7 +43,7 @@ If you need professional plugin support from me, the plugin author, you can acce ### Plugin Development -If you're a theme author, plugin author, or just a code hobbyist, you can follow the development of this plugin on it's [GitHub repository](https://github.com/justintadlock/members). +If you're a theme author, plugin author, or just a code hobbyist, you can follow the development of this plugin on it's [GitHub repository](https://github.com/justintadlock/members). == Installation == From 08c0509a4ec555ef4e52a3a00b173dde57b87f6a Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 6 Feb 2017 11:21:44 -0600 Subject: [PATCH 015/157] Version bump to 1.1.3. --- members.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/members.php b/members.php index 04989e2..f0d9cec 100644 --- a/members.php +++ b/members.php @@ -3,7 +3,7 @@ * Plugin Name: Members * Plugin URI: http://themehybrid.com/plugins/members * Description: A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private. - * Version: 1.1.2 + * Version: 1.1.3 * Author: Justin Tadlock * Author URI: http://themehybrid.com * Text Domain: members @@ -25,7 +25,7 @@ * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * @package Members - * @version 1.1.2 + * @version 1.1.3 * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2016, Justin Tadlock * @link http://themehybrid.com/plugins/members From a3a1ce00a562fc41931433314931bcb3f89ec0e5 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 7 Feb 2017 16:47:28 -0600 Subject: [PATCH 016/157] Bug fix: Separate multiple role states with a comma. Currently, there's no separation. --- admin/class-role-list-table.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/admin/class-role-list-table.php b/admin/class-role-list-table.php index 3801a54..d0e8225 100644 --- a/admin/class-role-list-table.php +++ b/admin/class-role-list-table.php @@ -238,10 +238,10 @@ protected function column_title( $role ) { // If we have states, string them together. if ( ! empty( $states ) ) { - foreach ( $states as $state ) - $role_states .= sprintf( '%s', $state ); + foreach ( $states as $state => $label ) + $states[ $state ] = sprintf( '%s', $label ); - $role_states = ' – ' . $role_states; + $role_states = ' – ' . join( ', ', $states ); } // Add the title and role states. From eb1653d4a67820528d7367205095cf5a91341f69 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 7 Feb 2017 16:51:45 -0600 Subject: [PATCH 017/157] Role states array values should have hardcoded keys so that they can more easily be unset via a filter. --- admin/class-role-list-table.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/class-role-list-table.php b/admin/class-role-list-table.php index d0e8225..990e326 100644 --- a/admin/class-role-list-table.php +++ b/admin/class-role-list-table.php @@ -226,11 +226,11 @@ protected function column_title( $role ) { // If the role is the default role. if ( $role == get_option( 'default_role' ) ) - $states[] = esc_html__( 'Default Role', 'members' ); + $states['default'] = esc_html__( 'Default Role', 'members' ); // If the current user has this role. if ( members_current_user_has_role( $role ) ) - $states[] = esc_html__( 'Your Role', 'members' ); + $states['mine'] = esc_html__( 'Your Role', 'members' ); // Allow devs to filter the role states. $states = apply_filters( 'members_role_states', $states, $role ); From 168bae8858bc5d6f43053e79bdcb4b8f9309643b Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 22 Jun 2017 17:32:07 -0500 Subject: [PATCH 018/157] First pass at creating a settings page view system where there can be sub-pages of the Members Settings admin page. Note that this may change to "admin views" for more flexibility in the future. --- admin/class-settings.php | 490 +++++++------------- admin/functions-settings.php | 114 +++++ admin/views/class-settings-view-add-ons.php | 161 +++++++ admin/views/class-settings-view-general.php | 425 +++++++++++++++++ admin/views/class-settings-view.php | 143 ++++++ img/add-ons/icon-members-role-hierarchy.png | Bin 0 -> 6006 bytes img/add-ons/icon-members-role-levels.png | Bin 0 -> 6006 bytes 7 files changed, 999 insertions(+), 334 deletions(-) create mode 100644 admin/functions-settings.php create mode 100644 admin/views/class-settings-view-add-ons.php create mode 100644 admin/views/class-settings-view-general.php create mode 100644 admin/views/class-settings-view.php create mode 100644 img/add-ons/icon-members-role-hierarchy.png create mode 100644 img/add-ons/icon-members-role-levels.png diff --git a/admin/class-settings.php b/admin/class-settings.php index 61257b2..e84ed87 100644 --- a/admin/class-settings.php +++ b/admin/class-settings.php @@ -18,15 +18,6 @@ */ final class Members_Settings_Page { - /** - * Holds the instances of this class. - * - * @since 1.0.0 - * @access private - * @var object - */ - private static $instance; - /** * Settings page name. * @@ -37,316 +28,225 @@ final class Members_Settings_Page { public $settings_page = ''; /** - * Holds an array the plugin settings. + * Holds an array the settings page views. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @var array */ - public $settings = array(); + public $views = array(); /** - * Sets up the needed actions for adding and saving the meta boxes. - * - * @since 1.0.0 - * @access public - * @return void - */ - private function __construct() { - add_action( 'admin_menu', array( $this, 'admin_menu' ) ); - } - - /** - * Sets up custom admin menus. + * Returns the instance. * * @since 1.0.0 * @access public - * @return void + * @return object */ - public function admin_menu() { - - // Create the settings page. - $this->settings_page = add_options_page( - esc_html__( 'Members Settings', 'members' ), - esc_html_x( 'Members', 'admin screen', 'members' ), - apply_filters( 'members_settings_capability', 'manage_options' ), - 'members-settings', - array( $this, 'settings_page' ) - ); - - if ( $this->settings_page ) { - - // Register setings. - add_action( 'admin_init', array( $this, 'register_settings' ) ); + public static function get_instance() { - // Add help tabs. - add_action( "load-{$this->settings_page}", array( $this, 'add_help_tabs' ) ); + static $instance = null; - // Enqueue scripts/styles. - add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) ); + if ( is_null( $instance ) ) { + $instance = new self; + $instance->includes(); + $instance->setup_actions(); } + + return $instance; } /** - * Enqueue scripts/styles. + * Constructor method. * * @since 1.0.0 * @access public - * @param string $hook_suffix * @return void */ - public function enqueue( $hook_suffix ) { - - if ( $this->settings_page !== $hook_suffix ) - return; - - wp_enqueue_script( 'members-settings' ); - } + private function __construct() {} /** - * Registers the plugin settings. + * Loads settings files. * - * @since 1.0.0 - * @access public + * @since 1.2.0 + * @access private * @return void */ - function register_settings() { - - // Get the current plugin settings w/o the defaults. - $this->settings = get_option( 'members_settings' ); - - // Register the setting. - register_setting( 'members_settings', 'members_settings', array( $this, 'validate_settings' ) ); - - /* === Settings Sections === */ - - // Add settings sections. - add_settings_section( 'roles_caps', esc_html__( 'Roles and Capabilities', 'members' ), array( $this, 'section_roles_caps' ), $this->settings_page ); - add_settings_section( 'content_permissions', esc_html__( 'Content Permissions', 'members' ), '__return_false', $this->settings_page ); - add_settings_section( 'sidebar_widgets', esc_html__( 'Sidebar Widgets', 'members' ), '__return_false', $this->settings_page ); - add_settings_section( 'private_site', esc_html__( 'Private Site', 'members' ), '__return_false', $this->settings_page ); - - /* === Settings Fields === */ + private function includes() { - // Role manager fields. - add_settings_field( 'enable_role_manager', esc_html__( 'Role Manager', 'members' ), array( $this, 'field_enable_role_manager' ), $this->settings_page, 'roles_caps' ); - add_settings_field( 'explicit_denied_caps', esc_html__( 'Capabilities', 'members' ), array( $this, 'field_explicit_denied_caps' ), $this->settings_page, 'roles_caps' ); - add_settings_field( 'enable_multi_roles', esc_html__( 'Multiple User Roles', 'members' ), array( $this, 'field_enable_multi_roles' ), $this->settings_page, 'roles_caps' ); + // Include the settings functions. + require_once( members_plugin()->admin_dir . 'functions-settings.php' ); - // Content permissions fields. - add_settings_field( 'enable_content_permissions', esc_html__( 'Enable Permissions', 'members' ), array( $this, 'field_enable_content_permissions' ), $this->settings_page, 'content_permissions' ); - add_settings_field( 'content_permissions_error', esc_html__( 'Error Message', 'members' ), array( $this, 'field_content_permissions_error' ), $this->settings_page, 'content_permissions' ); - - // Widgets fields. - add_settings_field( 'widget_login', esc_html__( 'Login Widget', 'members' ), array( $this, 'field_widget_login' ), $this->settings_page, 'sidebar_widgets' ); - add_settings_field( 'widget_users', esc_html__( 'Users Widget', 'members' ), array( $this, 'field_widget_users' ), $this->settings_page, 'sidebar_widgets' ); - - // Private site fields. - add_settings_field( 'enable_private_site', esc_html__( 'Enable Private Site', 'members' ), array( $this, 'field_enable_private_site' ), $this->settings_page, 'private_site' ); - add_settings_field( 'enable_private_feed', esc_html__( 'Disable Feed', 'members' ), array( $this, 'field_enable_private_feed' ), $this->settings_page, 'private_site' ); - add_settings_field( 'private_feed_error', esc_html__( 'Feed Error Message', 'members' ), array( $this, 'field_private_feed_error' ), $this->settings_page, 'private_site' ); + // Load settings view classes. + require_once( members_plugin()->admin_dir . 'views/class-settings-view.php' ); + require_once( members_plugin()->admin_dir . 'views/class-settings-view-general.php' ); + require_once( members_plugin()->admin_dir . 'views/class-settings-view-add-ons.php' ); } /** - * Validates the plugin settings. + * Sets up initial actions. * - * @since 1.0.0 - * @access public - * @param array $input - * @return array - */ - function validate_settings( $settings ) { - - // Validate true/false checkboxes. - $settings['role_manager'] = ! empty( $settings['role_manager'] ) ? true : false; - $settings['explicit_denied_caps'] = ! empty( $settings['explicit_denied_caps'] ) ? true : false; - $settings['multi_roles'] = ! empty( $settings['multi_roles'] ) ? true : false; - $settings['content_permissions'] = ! empty( $settings['content_permissions'] ) ? true : false; - $settings['login_form_widget'] = ! empty( $settings['login_form_widget'] ) ? true : false; - $settings['users_widget'] = ! empty( $settings['users_widget'] ) ? true : false; - $settings['private_blog'] = ! empty( $settings['private_blog'] ) ? true : false; - $settings['private_feed'] = ! empty( $settings['private_feed'] ) ? true : false; - - // Kill evil scripts. - $settings['content_permissions_error'] = stripslashes( wp_filter_post_kses( addslashes( $settings['content_permissions_error'] ) ) ); - $settings['private_feed_error'] = stripslashes( wp_filter_post_kses( addslashes( $settings['private_feed_error'] ) ) ); - - // Return the validated/sanitized settings. - return $settings; - } - - /** - * Role/Caps section callback. - * - * @since 1.0.0 - * @access public + * @since 1.2.0 + * @access private * @return void */ - public function section_roles_caps() { ?> + private function setup_actions() { -

- -

- + public function register_view( $view ) { - - view_exists( $view->name ) ) + $this->views[ $view->name ] = $view; + } /** - * Explicit denied caps field callback. + * Unregister a view. * - * @since 1.0.0 + * @since 1.2.0 * @access public + * @param string $name * @return void */ - public function field_explicit_denied_caps() { ?> + public function unregister_view( $name ) { - - view_exists( $name ) ) + unset( $this->view[ $name ] ); + } /** - * Multiple roles field callback. + * Get a view object * - * @since 1.0.0 + * @since 1.2.0 * @access public - * @return void + * @param string $name + * @return object */ - public function field_enable_multi_roles() { ?> + public function get_view( $name ) { - - view_exists( $name ) ? $this->views[ $name ] : false; + } /** - * Enable content permissions field callback. + * Check if a view exists. * - * @since 1.0.0 + * @since 1.2.0 * @access public - * @return void + * @param string $name + * @return bool */ - public function field_enable_content_permissions() { ?> + public function view_exists( $name ) { - - views[ $name ] ); + } /** - * Content permissions error message field callback. + * Sets up custom admin menus. * * @since 1.0.0 * @access public * @return void */ - public function field_content_permissions_error() { - - wp_editor( - members_get_setting( 'content_permissions_error' ), - 'members_settings_content_permissions_error', - array( - 'textarea_name' => 'members_settings[content_permissions_error]', - 'drag_drop_upload' => true, - 'editor_height' => 250 - ) + public function admin_menu() { + + // Create the settings page. + $this->settings_page = add_options_page( + esc_html_x( 'Members', 'admin screen', 'members' ), + esc_html_x( 'Members', 'admin screen', 'members' ), + apply_filters( 'members_settings_capability', 'manage_options' ), + 'members-settings', + array( $this, 'settings_page' ) ); + + if ( $this->settings_page ) { + + do_action( 'members_register_settings_views', $this ); + + uasort( $this->views, array( $this, 'priority_sort' ) ); + + // Register setings. + add_action( 'admin_init', array( $this, 'register_settings' ) ); + + // Page load callback. + add_action( "load-{$this->settings_page}", array( $this, 'load' ) ); + + // Enqueue scripts/styles. + add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) ); + } } /** - * Login widget field callback. + * Runs on page load. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @return void */ - public function field_widget_login() { ?> + public function load() { - - + // Add help tabs for the current view. + $view = $this->get_view( members_get_current_settings_view() ); - - add_help_tabs(); + } /** - * Enable private site field callback. + * Print styles to the header. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @return void */ - public function field_enable_private_site() { ?> + public function print_styles() { ?> - + + public function enqueue( $hook_suffix ) { - - settings_page !== $hook_suffix ) + return; + + $view = $this->get_view( members_get_current_settings_view() ); + + if ( $view ) + $view->enqueue(); + } /** - * Private feed error message field callback. + * Registers the plugin settings. * * @since 1.0.0 * @access public * @return void */ - public function field_private_feed_error() { - - wp_editor( - members_get_setting( 'private_feed_error' ), - 'members_settings_private_feed_error', - array( - 'textarea_name' => 'members_settings[private_feed_error]', - 'drag_drop_upload' => true, - 'editor_height' => 250 - ) - ); + function register_settings() { + + foreach ( $this->views as $view ) + $view->register_settings(); } /** @@ -359,152 +259,74 @@ public function field_private_feed_error() { public function settings_page() { ?>
-

+

-
- - settings_page ); ?> - - +
+ filter_links(); ?> +
+ + get_view( members_get_current_settings_view() )->template(); ?>
add_help_tab( - array( - 'id' => 'roles-caps', - 'title' => esc_html__( 'Role and Capabilities', 'members' ), - 'callback' => array( $this, 'help_tab_roles_caps' ) - ) - ); - - // Content Permissions help tab. - $screen->add_help_tab( - array( - 'id' => 'content-permissions', - 'title' => esc_html__( 'Content Permissions', 'members' ), - 'callback' => array( $this, 'help_tab_content_permissions' ) - ) - ); + private function filter_links() { ?> - // Widgets help tab. - $screen->add_help_tab( - array( - 'id' => 'sidebar-widgets', - 'title' => esc_html__( 'Sidebar Widgets', 'members' ), - 'callback' => array( $this, 'help_tab_sidebar_widgets' ) - ) - ); + + protected function priority_sort( $a, $b ) { -

- -

- + if ( $a->priority === $b->priority ) + return $a->instance_number - $b->instance_number; -

- -

- priority - $b->priority; + } /** - * Returns the instance. + * Adds help tabs. * - * @since 1.0.0 - * @access public - * @return object + * @since 1.0.0 + * @deprecated 1.2.0 + * @access public + * @return void */ - public static function get_instance() { - - if ( ! self::$instance ) - self::$instance = new self; - - return self::$instance; - } + public function add_help_tabs() {} } Members_Settings_Page::get_instance(); diff --git a/admin/functions-settings.php b/admin/functions-settings.php new file mode 100644 index 0000000..15d31e9 --- /dev/null +++ b/admin/functions-settings.php @@ -0,0 +1,114 @@ + + * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @link http://themehybrid.com/plugins/members + * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + */ + +# Register settings views. +add_action( 'members_register_settings_views', 'members_register_default_settings_views', 5 ); + +/** + * Registers the plugin's built-in settings views. + * + * @since 1.2.0 + * @access public + * @param object $manager + * @return void + */ +function members_register_default_settings_views( $manager ) { + + // Register general settings view (default view). + $manager->register_view( + new Members_Settings_View_General( + 'general', + array( + 'label' => esc_html__( 'General', 'members' ), + 'priority' => 0 + ) + ) + ); + + // Register add-ons view. + $manager->register_view( + new Members_Settings_View_Add_Ons( + 'add-ons', + array( + 'label' => esc_html__( 'Add-Ons', 'members' ), + 'priority' => 95 + ) + ) + ); +} + +/** + * Conditional function to check if on the plugin's settings page. + * + * @since 1.2.0 + * @access public + * @return bool + */ +function members_is_settings_page() { + + $screen = get_current_screen(); + + return is_object( $screen ) && 'settings_page_members-settings' === $screen->id; +} + +/** + * Returns the URL to the settings page. + * + * @since 1.2.0 + * @access public + * @return string + */ +function members_get_settings_page_url() { + + return add_query_arg( array( 'page' => 'members-settings' ), admin_url( 'options-general.php' ) ); +} + +/** + * Returns the URL to a settings view page. + * + * @since 1.2.0 + * @access public + * @param string $view + * @return string + */ +function members_get_settings_view_url( $view ) { + + return add_query_arg( array( 'view' => sanitize_key( $view ) ), members_get_settings_page_url() ); +} + +/** + * Returns the current settings view name. + * + * @since 1.2.0 + * @access public + * @return string + */ +function members_get_current_settings_view() { + + if ( ! members_is_settings_page() ) + return ''; + + return isset( $_GET['view'] ) ? sanitize_key( $_GET['view'] ) : 'general'; +} + +/** + * Conditional function to check if on a specific settings view page. + * + * @since 1.2.0 + * @access public + * @param string $view + * @return bool + */ +function members_is_settings_view( $view = '' ) { + + return members_is_settings_page() && $view === members_get_current_settings_view(); +} diff --git a/admin/views/class-settings-view-add-ons.php b/admin/views/class-settings-view-add-ons.php new file mode 100644 index 0000000..32ec922 --- /dev/null +++ b/admin/views/class-settings-view-add-ons.php @@ -0,0 +1,161 @@ + + * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @link http://themehybrid.com/plugins/members + * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + */ + +/** + * Sets up and handles the add-ons settings view. + * + * @since 1.2.0 + * @access public + */ +class Members_Settings_View_Add_Ons extends Members_Settings_View { + + /** + * Renders the settings page. + * + * @since 1.2.0 + * @access public + * @return void + */ + public function template() { ?> + +
+ + get_add_ons() as $addon ) : ?> + +
+ +
+ + + + + +
+ excerpt ) ); ?> + +

+ %s', esc_url( $addon->author_url ), esc_html( $addon->author ) ); ?> + + +

+
+
+
+ + + +
+ + add_help_tab( + array( + 'id' => 'roles-caps', + 'title' => esc_html__( 'Role and Capabilities', 'members' ), + 'callback' => array( $this, 'help_tab_roles_caps' ) + ) + ); + */ + // Set the help sidebar. + $screen->set_help_sidebar( members_get_help_sidebar_text() ); + } + + /** + * Returns a list of add-ons for the Members plugin. This function is temporary until + * we can get a proper API set up on Theme Hybrid to allow this data to be sent over. + * + * @since 1.2.0 + * @access private + * @return array + */ + private function get_add_ons() { + + $addons = array(); + + $defaults = array( + 'title' => '', + 'excerpt' => '', + 'url' => '', + 'author' => '', + 'author_url' => '', + 'purchase_url' => '', + 'wporg_slug' => '', + 'download_count' => '', + 'install_count' => '', + 'icon_url' => '', + 'slug' => '' + ); + + $_addons = array( + + 'members-role-hierarchy' => array( + 'title' => 'Members - Role Hierarchy', + 'url' => 'https://themehybrid.com/plugins/members-role-hierarchy', + 'excerpt' => 'Add-on plugin for Members for hierarchical user roles.', + 'icon_url' => members_plugin()->dir_uri . 'img/add-ons/icon-members-role-hierarchy.png', + 'author' => 'Justin Tadlock', + 'author_url' => 'https://themehybrid.com' + ), + + 'members-role-levels' => array( + 'title' => 'Members - Role Levels', + 'url' => 'https://themehybrid.com/plugins/members-role-levels', + 'purchase_url' => 'https://themehybrid.com/plugins/members-role-levels', + 'excerpt' => "Exposes the old user levels system, which fixes the WordPress author drop-down bug.", + 'icon_url' => members_plugin()->dir_uri . 'img/add-ons/icon-members-role-levels.png', + 'author' => 'Justin Tadlock', + 'author_url' => 'https://themehybrid.com' + ) + ); + + foreach ( $_addons as $slug => $args ) { + + $addons[ $slug ] = (object) wp_parse_args( $args, $defaults ); + + $addons[ $slug ]->slug = $slug; + } + + return $addons; + } +} diff --git a/admin/views/class-settings-view-general.php b/admin/views/class-settings-view-general.php new file mode 100644 index 0000000..e1f9823 --- /dev/null +++ b/admin/views/class-settings-view-general.php @@ -0,0 +1,425 @@ + + * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @link http://themehybrid.com/plugins/members + * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + */ + +/** + * Sets up and handles the general settings view. + * + * @since 1.2.0 + * @access public + */ +class Members_Settings_View_General extends Members_Settings_View { + + /** + * Holds an array the plugin settings. + * + * @since 1.2.0 + * @access public + * @var array + */ + public $settings = array(); + + /** + * Enqueue scripts/styles. + * + * @since 1.2.0 + * @access public + * @return void + */ + public function enqueue() { + + wp_enqueue_script( 'members-settings' ); + } + + /** + * Registers the plugin settings. + * + * @since 1.2.0 + * @access public + * @return void + */ + function register_settings() { + + // Get the current plugin settings w/o the defaults. + $this->settings = get_option( 'members_settings' ); + + // Register the setting. + register_setting( 'members_settings', 'members_settings', array( $this, 'validate_settings' ) ); + + /* === Settings Sections === */ + + // Add settings sections. + add_settings_section( 'roles_caps', esc_html__( 'Roles and Capabilities', 'members' ), array( $this, 'section_roles_caps' ), 'members-settings' ); + add_settings_section( 'content_permissions', esc_html__( 'Content Permissions', 'members' ), '__return_false', 'members-settings' ); + add_settings_section( 'sidebar_widgets', esc_html__( 'Sidebar Widgets', 'members' ), '__return_false', 'members-settings' ); + add_settings_section( 'private_site', esc_html__( 'Private Site', 'members' ), '__return_false', 'members-settings' ); + + /* === Settings Fields === */ + + // Role manager fields. + add_settings_field( 'enable_role_manager', esc_html__( 'Role Manager', 'members' ), array( $this, 'field_enable_role_manager' ), 'members-settings', 'roles_caps' ); + add_settings_field( 'explicit_denied_caps', esc_html__( 'Capabilities', 'members' ), array( $this, 'field_explicit_denied_caps' ), 'members-settings', 'roles_caps' ); + add_settings_field( 'enable_multi_roles', esc_html__( 'Multiple User Roles', 'members' ), array( $this, 'field_enable_multi_roles' ), 'members-settings', 'roles_caps' ); + + // Content permissions fields. + add_settings_field( 'enable_content_permissions', esc_html__( 'Enable Permissions', 'members' ), array( $this, 'field_enable_content_permissions' ), 'members-settings', 'content_permissions' ); + add_settings_field( 'content_permissions_error', esc_html__( 'Error Message', 'members' ), array( $this, 'field_content_permissions_error' ), 'members-settings', 'content_permissions' ); + + // Widgets fields. + add_settings_field( 'widget_login', esc_html__( 'Login Widget', 'members' ), array( $this, 'field_widget_login' ), 'members-settings', 'sidebar_widgets' ); + add_settings_field( 'widget_users', esc_html__( 'Users Widget', 'members' ), array( $this, 'field_widget_users' ), 'members-settings', 'sidebar_widgets' ); + + // Private site fields. + add_settings_field( 'enable_private_site', esc_html__( 'Enable Private Site', 'members' ), array( $this, 'field_enable_private_site' ), 'members-settings', 'private_site' ); + add_settings_field( 'enable_private_feed', esc_html__( 'Disable Feed', 'members' ), array( $this, 'field_enable_private_feed' ), 'members-settings', 'private_site' ); + add_settings_field( 'private_feed_error', esc_html__( 'Feed Error Message', 'members' ), array( $this, 'field_private_feed_error' ), 'members-settings', 'private_site' ); + } + + /** + * Validates the plugin settings. + * + * @since 1.2.0 + * @access public + * @param array $input + * @return array + */ + function validate_settings( $settings ) { + + // Validate true/false checkboxes. + $settings['role_manager'] = ! empty( $settings['role_manager'] ) ? true : false; + $settings['explicit_denied_caps'] = ! empty( $settings['explicit_denied_caps'] ) ? true : false; + $settings['multi_roles'] = ! empty( $settings['multi_roles'] ) ? true : false; + $settings['content_permissions'] = ! empty( $settings['content_permissions'] ) ? true : false; + $settings['login_form_widget'] = ! empty( $settings['login_form_widget'] ) ? true : false; + $settings['users_widget'] = ! empty( $settings['users_widget'] ) ? true : false; + $settings['private_blog'] = ! empty( $settings['private_blog'] ) ? true : false; + $settings['private_feed'] = ! empty( $settings['private_feed'] ) ? true : false; + + // Kill evil scripts. + $settings['content_permissions_error'] = stripslashes( wp_filter_post_kses( addslashes( $settings['content_permissions_error'] ) ) ); + $settings['private_feed_error'] = stripslashes( wp_filter_post_kses( addslashes( $settings['private_feed_error'] ) ) ); + + // Return the validated/sanitized settings. + return $settings; + } + + /** + * Role/Caps section callback. + * + * @since 1.2.0 + * @access public + * @return void + */ + public function section_roles_caps() { ?> + +

+ +

+ + + + + + + + + + + + + 'members_settings[content_permissions_error]', + 'drag_drop_upload' => true, + 'editor_height' => 250 + ) + ); + } + + /** + * Login widget field callback. + * + * @since 1.2.0 + * @access public + * @return void + */ + public function field_widget_login() { ?> + + + + + + + + + + + + 'members_settings[private_feed_error]', + 'drag_drop_upload' => true, + 'editor_height' => 250 + ) + ); + } + + /** + * Renders the settings page. + * + * @since 1.2.0 + * @access public + * @return void + */ + public function template() { ?> + +
+ + + + + + add_help_tab( + array( + 'id' => 'roles-caps', + 'title' => esc_html__( 'Role and Capabilities', 'members' ), + 'callback' => array( $this, 'help_tab_roles_caps' ) + ) + ); + + // Content Permissions help tab. + $screen->add_help_tab( + array( + 'id' => 'content-permissions', + 'title' => esc_html__( 'Content Permissions', 'members' ), + 'callback' => array( $this, 'help_tab_content_permissions' ) + ) + ); + + // Widgets help tab. + $screen->add_help_tab( + array( + 'id' => 'sidebar-widgets', + 'title' => esc_html__( 'Sidebar Widgets', 'members' ), + 'callback' => array( $this, 'help_tab_sidebar_widgets' ) + ) + ); + + // Private Site help tab. + $screen->add_help_tab( + array( + 'id' => 'private-site', + 'title' => esc_html__( 'Private Site', 'members' ), + 'callback' => array( $this, 'help_tab_private_site' ) + ) + ); + + // Get docs and help links. + $docs_link = sprintf( '
  • %s
  • ', esc_html__( 'Documentation', 'members' ) ); + $help_link = sprintf( '
  • %s
  • ', esc_html__( 'Support Forums', 'members' ) ); + $tut_link = sprintf( '
  • %s
  • ', esc_html__( 'Users, Roles, and Capabilities', 'members' ) ); + + // Set the help sidebar. + $screen->set_help_sidebar( members_get_help_sidebar_text() ); + } + + /** + * Displays the roles/caps help tab. + * + * @since 1.2.0 + * @access public + * @return void + */ + public function help_tab_roles_caps() { ?> + +

    + +

    + +

    + +

    + +

    + +

    + + +

    + restrict_content' ); ?> +

    + + +

    + +

    + + +

    + +

    + + * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @link http://themehybrid.com/plugins/members + * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + */ + +/** + * Settings view base class. + * + * @since 1.2.0 + * @access public + */ +class Members_Settings_View { + + /** + * Name/ID for the group. + * + * @since 1.2.0 + * @access protected + * @var string + */ + public $name = ''; + + /** + * Internationalized text label for the group. + * + * @since 1.2.0 + * @access protected + * @var string + */ + public $label = ''; + + /** + * Priority (order) the control should be output. + * + * @since 1.2.0 + * @access public + * @var int + */ + public $priority = 10; + + /** + * A user role capability required to show the control. + * + * @since 1.2.0 + * @access public + * @var string|array + */ + public $capability = 'manage_options'; + + /** + * Magic method to use in case someone tries to output the object as a string. + * We'll just return the name. + * + * @since 1.2.0 + * @access public + * @return string + */ + public function __toString() { + return $this->name; + } + + /** + * Register a new object. + * + * @since 1.2.0 + * @access public + * @param string $name + * @param array $args { + * @type string $label Internationalized text label. + * @type string $icon Dashicon icon in the form of `dashicons-icon-name`. + * @type string $callback Callback function for outputting the content for the view. + * } + * @return void + */ + public function __construct( $name, $args = array() ) { + + foreach ( array_keys( get_object_vars( $this ) ) as $key ) { + + if ( isset( $args[ $key ] ) ) + $this->$key = $args[ $key ]; + } + + $this->name = sanitize_key( $name ); + } + + /** + * Enqueue scripts/styles for the control. + * + * @since 1.2.0 + * @access public + * @return void + */ + public function enqueue() {} + + /** + * Register settings for the view. + * + * @since 1.2.0 + * @access public + * @return void + */ + public function register_settings() {} + + /** + * Add help tabs for the view. + * + * @since 1.2.0 + * @access public + * @return void + */ + public function add_help_tabs() {} + + /** + * Output the content for the view. + * + * @since 1.2.0 + * @access public + * @return void + */ + public function template() {} + + /** + * Checks if the control should be allowed at all. + * + * @since 1.2.0 + * @access public + * @return bool + */ + public function check_capabilities() { + + if ( $this->capability && ! call_user_func_array( 'current_user_can', (array) $this->capability ) ) + return false; + + return true; + } +} diff --git a/img/add-ons/icon-members-role-hierarchy.png b/img/add-ons/icon-members-role-hierarchy.png new file mode 100644 index 0000000000000000000000000000000000000000..3b31c16b9e66501383807b89c48f503e0e176e56 GIT binary patch literal 6006 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 literal 0 HcmV?d00001 diff --git a/img/add-ons/icon-members-role-levels.png b/img/add-ons/icon-members-role-levels.png new file mode 100644 index 0000000000000000000000000000000000000000..3b31c16b9e66501383807b89c48f503e0e176e56 GIT binary patch literal 6006 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 literal 0 HcmV?d00001 From f7816cc38af2287bb9fd974d1d259cde22658542 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 23 Jun 2017 08:55:54 -0500 Subject: [PATCH 019/157] Adds the `.wp-tab-panel` wrapper around the user roles checklist on the edit user screen. This is to prevent long lists of roles from taking up too much screen space. --- admin/class-user-edit.php | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/admin/class-user-edit.php b/admin/class-user-edit.php index 3c1bbc7..24fa85f 100644 --- a/admin/class-user-edit.php +++ b/admin/class-user-edit.php @@ -92,16 +92,18 @@ public function profile_fields( $user ) {
    From 5aa4d9e9f098ff26db17ff0d48372926a1779493 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 23 Jun 2017 08:56:37 -0500 Subject: [PATCH 020/157] Don't save content permissions on autosave or for post revisions. --- admin/class-meta-box-content-permissions.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/admin/class-meta-box-content-permissions.php b/admin/class-meta-box-content-permissions.php index 080e556..3bfb42f 100644 --- a/admin/class-meta-box-content-permissions.php +++ b/admin/class-meta-box-content-permissions.php @@ -191,6 +191,13 @@ public function meta_box( $post ) { */ public function update( $post_id, $post = '' ) { + $do_autosave = defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE; + $is_autosave = wp_is_post_autosave( $post_id ); + $is_revision = wp_is_post_revision( $post_id ); + + if ( $do_autosave || $is_autosave || $is_revision ) + return; + // Fix for attachment save issue in WordPress 3.5. // @link http://core.trac.wordpress.org/ticket/21963 if ( ! is_object( $post ) ) From 970442c8cdc5776eff0e87627cf8b0f7c3346e0e Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sat, 24 Jun 2017 13:13:37 -0500 Subject: [PATCH 021/157] First pass at a capability registration system. Primarily, this system does two things at the moment: 1) Allows plugins to register human-readable and translatable capability labels and 2) Allows capabilities to be added to a cap group when registered. However, the system would allow for us to build other things on top of it in the future. This change addresses https://github.com/justintadlock/members/issues/61 --- admin/class-cap-control.php | 1 + admin/class-cap-group.php | 8 +- admin/functions-cap-groups.php | 129 ++++----- admin/tmpl/cap-control.php | 2 +- admin/views/class-settings-view-general.php | 35 ++- inc/class-capability-factory.php | 114 ++++++++ inc/class-capability.php | 79 +++++ inc/functions-capabilities.php | 301 +++++++++++++------- inc/functions-deprecated.php | 93 ++++++ inc/functions-options.php | 14 + js/edit-role.js | 2 +- js/edit-role.min.js | 2 +- members.php | 10 +- 13 files changed, 599 insertions(+), 191 deletions(-) create mode 100644 inc/class-capability-factory.php create mode 100644 inc/class-capability.php diff --git a/admin/class-cap-control.php b/admin/class-cap-control.php index 028f0da..3205b21 100644 --- a/admin/class-cap-control.php +++ b/admin/class-cap-control.php @@ -112,6 +112,7 @@ public function to_json() { // Set up the input labels. $this->json['label'] = array( + 'cap' => members_show_human_caps() && members_cap_exists( $this->cap ) ? members_get_cap( $this->cap )->label : $this->cap, 'grant' => sprintf( esc_html__( 'Grant %s capability', 'members' ), "{$this->cap}" ), 'deny' => sprintf( esc_html__( 'Deny %s capability', 'members' ), "{$this->cap}" ) ); diff --git a/admin/class-cap-group.php b/admin/class-cap-group.php index d6def5e..b2101e0 100644 --- a/admin/class-cap-group.php +++ b/admin/class-cap-group.php @@ -52,10 +52,10 @@ final class Members_Cap_Group { * @access protected * @var array */ - public $caps = array( 'read' ); + public $caps = array(); /** - * Whether to merge this groups caps with the added caps array. + * Whether to merge this group's caps with the added caps array. * * @since 1.0.0 * @access protected @@ -109,6 +109,10 @@ public function __construct( $name, $args = array() ) { $this->name = sanitize_key( $name ); + $registered_caps = array_keys( wp_list_filter( members_get_caps(), array( 'group' => $this->name ) ) ); + + $this->caps = array_unique( array_merge( $this->caps, $registered_caps ) ); + $this->caps = members_remove_hidden_caps( $this->caps ); } } diff --git a/admin/functions-cap-groups.php b/admin/functions-cap-groups.php index edd9926..1b7b50c 100644 --- a/admin/functions-cap-groups.php +++ b/admin/functions-cap-groups.php @@ -11,7 +11,7 @@ */ # Registers default groups. -add_action( 'init', 'members_register_cap_groups', 15 ); +add_action( 'init', 'members_register_cap_groups', 95 ); /** * Returns the instance of the `Members_Cap_Group_Factory` object. Use this function to access the object. @@ -114,7 +114,6 @@ function members_register_cap_groups() { members_register_cap_group( 'general', array( 'label' => esc_html__( 'General', 'members' ), - 'caps' => members_get_general_group_caps(), 'icon' => 'dashicons-wordpress' ) ); @@ -173,7 +172,6 @@ function members_register_cap_groups() { members_register_cap_group( 'theme', array( 'label' => esc_html__( 'Appearance', 'members' ), - 'caps' => members_get_theme_group_caps(), 'icon' => 'dashicons-admin-appearance' ) ); @@ -182,7 +180,6 @@ function members_register_cap_groups() { members_register_cap_group( 'plugin', array( 'label' => esc_html__( 'Plugins', 'members' ), - 'caps' => members_get_plugin_group_caps(), 'icon' => 'dashicons-admin-plugins' ) ); @@ -191,7 +188,6 @@ function members_register_cap_groups() { members_register_cap_group( 'user', array( 'label' => esc_html__( 'Users', 'members' ), - 'caps' => members_get_user_group_caps(), 'icon' => 'dashicons-admin-users' ) ); @@ -253,29 +249,6 @@ function members_get_all_group_caps() { return members_get_capabilities(); } -/** - * Returns the caps for the general capability group. - * - * @since 1.0.0 - * @access public - * @return array - */ -function members_get_general_group_caps() { - - return array( - 'edit_dashboard', - 'edit_files', - 'export', - 'import', - 'manage_links', - 'manage_options', - 'moderate_comments', - 'read', - 'unfiltered_html', - 'update_core', - ); -} - /** * Returns the caps for a specific post type capability group. * @@ -311,6 +284,11 @@ function members_get_post_type_group_caps( $post_type = 'post' ) { if ( 'attachment' === $post_type ) $caps[] = 'unfiltered_upload'; + $registered_caps = array_keys( wp_list_filter( members_get_caps(), array( 'group' => "type-{$post_type}" ) ) ); + + if ( $registered_caps ) + array_merge( $caps, $registered_caps ); + // Make sure there are no duplicates and return. return array_unique( $caps ); } @@ -331,78 +309,81 @@ function members_get_taxonomy_group_caps() { foreach ( $taxi as $tax ) $caps = array_merge( $caps, array_values( (array) $tax->cap ) ); + $registered_caps = array_keys( wp_list_filter( members_get_caps(), array( 'group' => 'taxonomy' ) ) ); + + if ( $registered_caps ) + array_merge( $caps, $registered_caps ); + return array_unique( $caps ); } /** - * Returns the caps for the theme capability group. + * Returns the caps for the custom capability group. * * @since 1.0.0 * @access public * @return array */ -function members_get_theme_group_caps() { +function members_get_custom_group_caps() { - return array( - 'delete_themes', - 'edit_theme_options', - 'edit_themes', - 'install_themes', - 'switch_themes', - 'update_themes', - ); + $caps = members_get_capabilities(); + + $registered_caps = array_keys( wp_list_filter( members_get_caps(), array( 'group' => 'custom' ) ) ); + + if ( $registered_caps ) + array_merge( $caps, $registered_caps ); + + return array_unique( $caps ); } /** - * Returns the caps for the plugin capability group. + * Returns the caps for the general capability group. * - * @since 1.0.0 - * @access public - * @return array + * @since 1.0.0 + * @deprecated 1.2.0 + * @access public + * @return array */ -function members_get_plugin_group_caps() { +function members_get_general_group_caps() { - return array( - 'activate_plugins', - 'delete_plugins', - 'edit_plugins', - 'install_plugins', - 'update_plugins', - ); + return array_keys( wp_list_filter( members_get_caps(), array( 'group' => 'general' ) ) ); } /** - * Returns the caps for the user capability group. + * Returns the caps for the theme capability group. * - * @since 1.0.0 - * @access public - * @return array + * @since 1.0.0 + * @deprecated 1.2.0 + * @access public + * @return array */ -function members_get_user_group_caps() { +function members_get_theme_group_caps() { - return array( - 'add_users', - 'create_roles', - 'create_users', - 'delete_roles', - 'delete_users', - 'edit_roles', - 'edit_users', - 'list_roles', - 'list_users', - 'promote_users', - 'remove_users', - ); + return array_keys( wp_list_filter( members_get_caps(), array( 'group' => 'theme' ) ) ); } /** - * Returns the caps for the custom capability group. + * Returns the caps for the plugin capability group. * - * @since 1.0.0 - * @access public - * @return array + * @since 1.0.0 + * @deprecated 1.2.0 + * @access public + * @return array */ -function members_get_custom_group_caps() { +function members_get_plugin_group_caps() { - return members_get_capabilities(); + return array_keys( wp_list_filter( members_get_caps(), array( 'group' => 'plugin' ) ) ); +} + +/** + * Returns the caps for the user capability group. + * + * @since 1.0.0 + * @deprecated 1.2.0 + * @access public + * @return array + */ +function members_get_user_group_caps() { + + return array_keys( wp_list_filter( members_get_caps(), array( 'group' => 'user' ) ) ); } diff --git a/admin/tmpl/cap-control.php b/admin/tmpl/cap-control.php index 86d5278..c3ba19c 100644 --- a/admin/tmpl/cap-control.php +++ b/admin/tmpl/cap-control.php @@ -12,7 +12,7 @@ ?> diff --git a/admin/views/class-settings-view-general.php b/admin/views/class-settings-view-general.php index e1f9823..aa1de65 100644 --- a/admin/views/class-settings-view-general.php +++ b/admin/views/class-settings-view-general.php @@ -66,8 +66,9 @@ function register_settings() { // Role manager fields. add_settings_field( 'enable_role_manager', esc_html__( 'Role Manager', 'members' ), array( $this, 'field_enable_role_manager' ), 'members-settings', 'roles_caps' ); - add_settings_field( 'explicit_denied_caps', esc_html__( 'Capabilities', 'members' ), array( $this, 'field_explicit_denied_caps' ), 'members-settings', 'roles_caps' ); add_settings_field( 'enable_multi_roles', esc_html__( 'Multiple User Roles', 'members' ), array( $this, 'field_enable_multi_roles' ), 'members-settings', 'roles_caps' ); + add_settings_field( 'explicit_denied_caps', esc_html__( 'Capabilities', 'members' ), array( $this, 'field_explicit_denied_caps' ), 'members-settings', 'roles_caps' ); + // add_settings_field( 'show_human_caps', esc_html__( 'Human Capabilities', 'members' ), array( $this, 'field_show_human_caps' ), 'members-settings', 'roles_caps' ); // Content permissions fields. add_settings_field( 'enable_content_permissions', esc_html__( 'Enable Permissions', 'members' ), array( $this, 'field_enable_content_permissions' ), 'members-settings', 'content_permissions' ); @@ -149,10 +150,23 @@ public function field_enable_role_manager() { ?> */ public function field_explicit_denied_caps() { ?> - +
    + +

    + +

    + +

    + +

    + +
    + + + * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @link http://themehybrid.com/plugins/members + * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + */ + +/** + * Capability factory class. + * + * @since 1.2.0 + * @access public + */ +final class Members_Capability_Factory { + + /** + * Array of cap objects. + * + * @since 1.2.0 + * @access public + * @var array + */ + public $caps = array(); + + /** + * Constructor method. + * + * @since 1.2.0 + * @access private + * @return void + */ + private function __construct() {} + + /** + * Register a new cap object + * + * @since 1.2.0 + * @access public + * @param string $name + * @param array $args + * @return void + */ + public function register_cap( $name, $args = array() ) { + + if ( ! $this->cap_exists( $name ) ) { + + $cap = new Members_Capability( $name, $args ); + + $this->caps[ $cap->name ] = $cap; + } + } + + /** + * Unregisters a cap object. + * + * @since 1.2.0 + * @access public + * @param string $name + * @return void + */ + public function unregister_cap( $name ) { + + if ( $this->cap_exists( $name ) ) + unset( $this->caps[ $name ] ); + } + + /** + * Checks if a cap exists. + * + * @since 1.2.0 + * @access public + * @param string $name + * @return bool + */ + public function cap_exists( $name ) { + + return isset( $this->caps[ $name ] ); + } + + /** + * Gets a cap object. + * + * @since 1.2.0 + * @access public + * @param string $name + * @return object|bool + */ + public function get_cap( $name ) { + + return $this->cap_exists( $name ) ? $this->caps[ $name ] : false; + } + + /** + * Returns the instance. + * + * @since 1.2.0 + * @access public + * @return object + */ + public static function get_instance() { + + static $instance = null; + + if ( is_null( $instance ) ) + $instance = new self; + + return $instance; + } +} diff --git a/inc/class-capability.php b/inc/class-capability.php new file mode 100644 index 0000000..c5efc2c --- /dev/null +++ b/inc/class-capability.php @@ -0,0 +1,79 @@ + + * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @link http://themehybrid.com/plugins/members + * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + */ + +/** + * Capability class. + * + * @since 1.2.0 + * @access public + */ +class Members_Capability { + + /** + * The capability name. + * + * @since 1.2.0 + * @access public + * @var string + */ + public $name = ''; + + /** + * The capability label. + * + * @since 1.2.0 + * @access public + * @var string + */ + public $label = ''; + + /** + * The group the capability belongs to. + * + * @see Members_Cap_Group + * @since 1.2.0 + * @access public + * @var string + */ + public $group = ''; + + /** + * Return the role string in attempts to use the object as a string. + * + * @since 1.2.0 + * @access public + * @return string + */ + public function __toString() { + return $this->slug; + } + + /** + * Creates a new role object. + * + * @since 1.2.0 + * @access public + * @global object $wp_roles + * @param string $role + * @return void + */ + public function __construct( $name, $args = array() ) { + + foreach ( array_keys( get_object_vars( $this ) ) as $key ) { + + if ( isset( $args[ $key ] ) ) + $this->$key = $args[ $key ]; + } + + $this->name = sanitize_key( $name ); + } +} diff --git a/inc/functions-capabilities.php b/inc/functions-capabilities.php index 1d03da9..c64fcc4 100644 --- a/inc/functions-capabilities.php +++ b/inc/functions-capabilities.php @@ -10,32 +10,219 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +# Register capabilities. +add_action( 'init', 'members_register_caps', 95 ); +add_action( 'members_register_caps', 'members_register_default_caps', 5 ); + # Disables the old user levels from capabilities array. add_filter( 'members_get_capabilities', 'members_remove_old_levels' ); add_filter( 'members_get_capabilities', 'members_remove_hidden_caps' ); /** - * Function for sanitizing a capability. + * Fires the action hook for registering capabilities. + * + * @since 1.2.0 + * @access public + * @return void + */ +function members_register_caps() { + + do_action( 'members_register_caps' ); +} + +/** + * Registers all of our default caps. In particular, the plugin registers its own caps plus core + * WP's caps. * + * @since 1.2.0 + * @access public + * @return void + */ +function members_register_default_caps() { + + $caps = array(); + + // General caps. + $caps['edit_dashboard'] = array( 'label' => __( 'Edit Dashboard', 'members' ), 'group' => 'general' ); + $caps['edit_files'] = array( 'label' => __( 'Edit Files', 'members' ), 'group' => 'general' ); + $caps['export'] = array( 'label' => __( 'Export', 'members' ), 'group' => 'general' ); + $caps['import'] = array( 'label' => __( 'Import', 'members' ), 'group' => 'general' ); + $caps['manage_links'] = array( 'label' => __( 'Manage Links', 'members' ), 'group' => 'general' ); + $caps['manage_options'] = array( 'label' => __( 'Manage Options', 'members' ), 'group' => 'general' ); + $caps['moderate_comments'] = array( 'label' => __( 'Moderate Comments', 'members' ), 'group' => 'general' ); + $caps['read'] = array( 'label' => __( 'Read', 'members' ), 'group' => 'general' ); + $caps['unfiltered_html'] = array( 'label' => __( 'Unfiltered HTML', 'members' ), 'group' => 'general' ); + $caps['update_core'] = array( 'label' => __( 'Update Core', 'members' ), 'group' => 'general' ); + + // Post caps. + $caps['delete_others_posts'] = array( 'label' => __( "Delete Others' Posts", 'members' ), 'group' => 'type-post' ); + $caps['delete_posts'] = array( 'label' => __( 'Delete Posts', 'members' ), 'group' => 'type-post' ); + $caps['delete_private_posts'] = array( 'label' => __( 'Delete Private Posts', 'members' ), 'group' => 'type-post' ); + $caps['delete_published_posts'] = array( 'label' => __( 'Delete Published Posts', 'members' ), 'group' => 'type-post' ); + $caps['edit_others_posts'] = array( 'label' => __( "Edit Others' Posts", 'members' ), 'group' => 'type-post' ); + $caps['edit_posts'] = array( 'label' => __( 'Edit Posts', 'members' ), 'group' => 'type-post' ); + $caps['edit_private_posts'] = array( 'label' => __( 'Edit Private Posts', 'members' ), 'group' => 'type-post' ); + $caps['edit_published_posts'] = array( 'label' => __( 'Edit Published Posts', 'members' ), 'group' => 'type-post' ); + $caps['publish_posts'] = array( 'label' => __( 'Publish Posts', 'members' ), 'group' => 'type-post' ); + $caps['read_private_posts'] = array( 'label' => __( 'Read Private Posts', 'members' ), 'group' => 'type-post' ); + + // Page caps. + $caps['delete_others_pages'] = array( 'label' => __( "Delete Others' Pages", 'members' ), 'group' => 'type-page' ); + $caps['delete_pages'] = array( 'label' => __( 'Delete Pages', 'members' ), 'group' => 'type-page' ); + $caps['delete_private_pages'] = array( 'label' => __( 'Delete Private Pages', 'members' ), 'group' => 'type-page' ); + $caps['delete_published_pages'] = array( 'label' => __( 'Delete Published Pages', 'members' ), 'group' => 'type-page' ); + $caps['edit_others_pages'] = array( 'label' => __( "Edit Others' Pages", 'members' ), 'group' => 'type-page' ); + $caps['edit_pages'] = array( 'label' => __( 'Edit Pages', 'members' ), 'group' => 'type-page' ); + $caps['edit_private_pages'] = array( 'label' => __( 'Edit Private Pages', 'members' ), 'group' => 'type-page' ); + $caps['edit_published_pages'] = array( 'label' => __( 'Edit Published Pages', 'members' ), 'group' => 'type-page' ); + $caps['publish_pages'] = array( 'label' => __( 'Publish Pages', 'members' ), 'group' => 'type-page' ); + $caps['read_private_pages'] = array( 'label' => __( 'Read Private Pages', 'members' ), 'group' => 'type-page' ); + + // Attachment caps. + $caps['upload_files'] = array( 'label' => __( 'Upload Files', 'members' ), 'group' => 'type-attachment' ); + + // Taxonomy caps. + $caps['assign_categories'] = array( 'label' => __( 'Assign Categories', 'members' ), 'group' => 'taxonomy' ); + $caps['edit_categories'] = array( 'label' => __( 'Edit Categories', 'members' ), 'group' => 'taxonomy' ); + $caps['delete_categories'] = array( 'label' => __( 'Delete Categories', 'members' ), 'group' => 'taxonomy' ); + $caps['manage_categories'] = array( 'label' => __( 'Manage Categories', 'members' ), 'group' => 'taxonomy' ); + + $caps['assign_post_tags'] = array( 'label' => __( 'Assign Tags', 'members' ), 'group' => 'taxonomy' ); + $caps['edit_post_tags'] = array( 'label' => __( 'Edit Tags', 'members' ), 'group' => 'taxonomy' ); + $caps['delete_post_tags'] = array( 'label' => __( 'Delete Tags', 'members' ), 'group' => 'taxonomy' ); + $caps['manage_post_tags'] = array( 'label' => __( 'Manage Tags', 'members' ), 'group' => 'taxonomy' ); + + // Theme caps. + $caps['delete_themes'] = array( 'label' => __( 'Delete Themes', 'members' ), 'group' => 'theme' ); + $caps['edit_theme_options'] = array( 'label' => __( 'Edit Theme Options', 'members' ), 'group' => 'theme' ); + $caps['edit_themes'] = array( 'label' => __( 'Edit Themes', 'members' ), 'group' => 'theme' ); + $caps['install_themes'] = array( 'label' => __( 'Install Themes', 'members' ), 'group' => 'theme' ); + $caps['switch_themes'] = array( 'label' => __( 'Switch Themes', 'members' ), 'group' => 'theme' ); + $caps['update_themes'] = array( 'label' => __( 'Update Themes', 'members' ), 'group' => 'theme' ); + + // Plugin caps. + $caps['activate_plugins'] = array( 'label' => __( 'Activate Plugins', 'members' ), 'group' => 'plugin' ); + $caps['delete_plugins'] = array( 'label' => __( 'Delete Plugins', 'members' ), 'group' => 'plugin' ); + $caps['edit_plugins'] = array( 'label' => __( 'Edit Plugins', 'members' ), 'group' => 'plugin' ); + $caps['install_plugins'] = array( 'label' => __( 'Install Plugins', 'members' ), 'group' => 'plugin' ); + $caps['update_plugins'] = array( 'label' => __( 'Update Plugins', 'members' ), 'group' => 'plugin' ); + + // User caps. + $caps['add_users'] = array( 'label' => __( 'Add Users', 'members' ), 'group' => 'user' ); + $caps['create_roles'] = array( 'label' => __( 'Create Roles', 'members' ), 'group' => 'user' ); + $caps['create_users'] = array( 'label' => __( 'Create Users', 'members' ), 'group' => 'user' ); + $caps['delete_roles'] = array( 'label' => __( 'Delete Roles', 'members' ), 'group' => 'user' ); + $caps['delete_users'] = array( 'label' => __( 'Delete Users', 'members' ), 'group' => 'user' ); + $caps['edit_roles'] = array( 'label' => __( 'Edit Roles', 'members' ), 'group' => 'user' ); + $caps['edit_users'] = array( 'label' => __( 'Edit Users', 'members' ), 'group' => 'user' ); + $caps['list_roles'] = array( 'label' => __( 'List Roles', 'members' ), 'group' => 'user' ); + $caps['list_users'] = array( 'label' => __( 'List Users', 'members' ), 'group' => 'user' ); + $caps['promote_users'] = array( 'label' => __( 'Promote Users', 'members' ), 'group' => 'user' ); + $caps['remove_users'] = array( 'label' => __( 'Remove Users', 'members' ), 'group' => 'user' ); + + // Custom caps. + $caps['restrict_content'] = array( 'label' => __( 'Restrict Content', 'members' ), 'group' => 'custom' ); + + // Register each of the capabilities. + foreach ( $caps as $name => $args ) + members_register_cap( $name, $args ); +} + +/** + * Returns the instance of the capability factory. + * + * @see Members_Capability_Factory::get_instance() + * @since 1.2.0 + * @access public + * @return object + */ +function members_capability_factory() { + + return Members_Capability_Factory::get_instance(); +} + +/** + * Returns all registered caps. + * + * @see Members_Capability_Factory::caps + * @since 1.2.0 + * @access public + * @return array + */ +function members_get_caps() { + + return members_capability_factory()->caps; +} + +/** + * Registers a capability. + * + * @see Members_Capability_Factory::register_cap() + * @since 1.2.0 + * @access public + * @param string $name + * @param array $args + * @return void + */ +function members_register_cap( $name, $args = array() ) { + + members_capability_factory()->register_cap( $name, $args ); +} + +/** + * Unregisters a capability. + * + * @see Members_Capability_Factory::unregister_cap() + * @since 1.2.0 + * @access public + * @param string $name + * @return void + */ +function members_unregister_cap( $name ) { + + members_capability_factory()->unregister_cap( $name ); +} + +/** + * Returns a capability object. + * + * @see Members_Capability_Factory::get_cap() + * @since 1.2.0 + * @access public + * @param string $name + * @return object + */ +function members_get_cap( $name ) { + + return members_capability_factory()->get_cap( $name ); +} + +/** + * Checks if a capability object exists. + * + * @note In 1.2.0, the function was changed to only check from registered caps. + * + * @see Members_Capability_Factory::unregister_cap() * @since 1.0.0 * @access public - * @param string $cap - * @return string + * @param string $name + * @return bool */ -function members_sanitize_cap( $cap ) { - return apply_filters( 'members_sanitize_cap', sanitize_key( $cap ) ); +function members_cap_exists( $name ) { + + return members_capability_factory()->cap_exists( $name ); } /** - * Conditional tag for checking whether a capability exists. + * Function for sanitizing a capability. * * @since 1.0.0 * @access public * @param string $cap - * @return bool + * @return string */ -function members_cap_exists( $cap ) { - return in_array( $cap, members_get_capabilities() ); +function members_sanitize_cap( $cap ) { + return apply_filters( 'members_sanitize_cap', sanitize_key( $cap ) ); } /** @@ -90,9 +277,8 @@ function members_get_capabilities() { // Merge the default WP, role, and plugin caps together. $capabilities = array_merge( - members_get_wp_capabilities(), - members_get_role_capabilities(), - members_get_plugin_capabilities() + array_keys( members_get_caps() ), + members_get_role_capabilities() ); // Apply filters to the array of capabilities. @@ -139,97 +325,6 @@ function members_get_role_capabilities() { return array_unique( $capabilities ); } -/** - * Additional capabilities provided by the Members plugin that gives users permissions to handle - * certain features of the plugin. - * - * @since 1.0.0 - * @access public - * @return array - */ -function members_get_plugin_capabilities() { - - return array( - 'list_roles', // View roles list. - 'create_roles', // Create new roles. - 'delete_roles', // Delete roles. - 'edit_roles', // Edit a role's caps. - 'restrict_content' // Restrict content (content permissions component). - ); -} - -/** - * Make sure we keep the default capabilities in case users screw 'em up. A user could easily - * remove a useful WordPress capability from all roles. When this happens, the capability is no - * longer stored in any of the roles, so it basically doesn't exist. This function will house - * all of the default WordPress capabilities in case this scenario comes into play. - * - * For those reading this note, yes, I did "accidentally" remove all capabilities from my - * administrator account when developing this plugin. And yes, that was fun putting back - * together. ;) - * - * @link http://codex.wordpress.org/Roles_and_Capabilities#Capabilities - * @since 1.0.0 - * @access public - * @return array - */ -function members_get_wp_capabilities() { - - return array( - 'activate_plugins', - 'add_users', - 'create_users', - 'delete_others_pages', - 'delete_others_posts', - 'delete_pages', - 'delete_plugins', - 'delete_posts', - 'delete_private_pages', - 'delete_private_posts', - 'delete_published_pages', - 'delete_published_posts', - 'delete_themes', - 'delete_users', - 'edit_dashboard', - 'edit_files', - 'edit_others_pages', - 'edit_others_posts', - 'edit_pages', - 'edit_plugins', - 'edit_posts', - 'edit_private_pages', - 'edit_private_posts', - 'edit_published_pages', - 'edit_published_posts', - 'edit_theme_options', - 'edit_themes', - 'edit_users', - 'export', - 'import', - 'install_plugins', - 'install_themes', - 'list_users', - 'manage_categories', - 'manage_links', - 'manage_options', - 'moderate_comments', - 'promote_users', - 'publish_pages', - 'publish_posts', - 'read', - 'read_private_pages', - 'read_private_posts', - 'remove_users', - 'switch_themes', - 'unfiltered_html', - 'unfiltered_upload', - 'update_core', - 'update_plugins', - 'update_themes', - 'upload_files' - ); -} - /** * Checks if a specific capability has been given to at least one role. If it has, return true. * Else, return false. diff --git a/inc/functions-deprecated.php b/inc/functions-deprecated.php index 586af5b..7ed2012 100644 --- a/inc/functions-deprecated.php +++ b/inc/functions-deprecated.php @@ -10,6 +10,99 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +/** + * Additional capabilities provided by the Members plugin that gives users permissions to handle + * certain features of the plugin. + * + * @since 1.0.0 + * @deprecated 1.2.0 + * @access public + * @return array + */ +function members_get_plugin_capabilities() { + + return array( + 'list_roles', // View roles list. + 'create_roles', // Create new roles. + 'delete_roles', // Delete roles. + 'edit_roles', // Edit a role's caps. + 'restrict_content' // Restrict content (content permissions component). + ); +} + +/** + * Make sure we keep the default capabilities in case users screw 'em up. A user could easily + * remove a useful WordPress capability from all roles. When this happens, the capability is no + * longer stored in any of the roles, so it basically doesn't exist. This function will house + * all of the default WordPress capabilities in case this scenario comes into play. + * + * For those reading this note, yes, I did "accidentally" remove all capabilities from my + * administrator account when developing this plugin. And yes, that was fun putting back + * together. ;) + * + * @link http://codex.wordpress.org/Roles_and_Capabilities#Capabilities + * @since 1.0.0 + * @deprecated 1.2.0 + * @access public + * @return array + */ +function members_get_wp_capabilities() { + + return array( + 'activate_plugins', + 'add_users', + 'create_users', + 'delete_others_pages', + 'delete_others_posts', + 'delete_pages', + 'delete_plugins', + 'delete_posts', + 'delete_private_pages', + 'delete_private_posts', + 'delete_published_pages', + 'delete_published_posts', + 'delete_themes', + 'delete_users', + 'edit_dashboard', + 'edit_files', + 'edit_others_pages', + 'edit_others_posts', + 'edit_pages', + 'edit_plugins', + 'edit_posts', + 'edit_private_pages', + 'edit_private_posts', + 'edit_published_pages', + 'edit_published_posts', + 'edit_theme_options', + 'edit_themes', + 'edit_users', + 'export', + 'import', + 'install_plugins', + 'install_themes', + 'list_users', + 'manage_categories', + 'manage_links', + 'manage_options', + 'moderate_comments', + 'promote_users', + 'publish_pages', + 'publish_posts', + 'read', + 'read_private_pages', + 'read_private_posts', + 'remove_users', + 'switch_themes', + 'unfiltered_html', + 'unfiltered_upload', + 'update_core', + 'update_plugins', + 'update_themes', + 'upload_files' + ); +} + /** * @since 0.2.0 * @deprecated 1.0.0 diff --git a/inc/functions-options.php b/inc/functions-options.php index 16ef8f1..547168b 100644 --- a/inc/functions-options.php +++ b/inc/functions-options.php @@ -33,6 +33,17 @@ function members_explicitly_deny_caps() { return apply_filters( 'members_explicitly_deny_caps', members_get_setting( 'explicit_denied_caps' ) ); } +/** + * Whether to show human-readable caps. + * + * @since 1.2.0 + * @access public + * @return bool + */ +function members_show_human_caps() { + return apply_filters( 'members_show_human_caps', members_get_setting( 'show_human_caps' ) ); +} + /** * Conditional check to see if the role manager is enabled. * @@ -119,5 +130,8 @@ function members_get_default_settings() { // @since 1.0.0 'explicit_denied_caps' => true, 'multi_roles' => true, + + // @since 1.2.0 + 'show_human_caps' => true, ); } diff --git a/js/edit-role.js b/js/edit-role.js index dc62509..d2ebfee 100644 --- a/js/edit-role.js +++ b/js/edit-role.js @@ -377,7 +377,7 @@ jQuery( document ).ready( function() { name : { grant : 'grant-new-caps[]', deny : 'deny-new-caps[]' }, is_granted_cap : true, is_denied_cap : false, - label : { grant : members_i18n.label_grant_cap, deny : members_i18n.label_deny_cap } + label : { cap : new_cap, grant : members_i18n.label_grant_cap, deny : members_i18n.label_deny_cap } }; // Prepend our template to the "custom" edit caps tab content. diff --git a/js/edit-role.min.js b/js/edit-role.min.js index 3031c7c..b717d8c 100644 --- a/js/edit-role.min.js +++ b/js/edit-role.min.js @@ -1 +1 @@ -jQuery(document).ready(function(){function e(e){e=e.toLowerCase().trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,""),jQuery(".role-slug").text(e)}function r(){var e=jQuery("#members-tab-all input[data-grant-cap]:checked").length,r=jQuery("#members-tab-all input[data-deny-cap]:checked").length,t=jQuery('#members-tab-custom input[name="grant-new-caps[]"]:checked').length,a=jQuery('#members-tab-custom input[name="deny-new-caps[]"]:checked').length;jQuery("#submitdiv .granted-count").text(e+t),jQuery("#submitdiv .denied-count").text(r+a)}function t(e){var r="grant",t="deny";jQuery(e).attr("data-deny-cap")&&(r="deny",t="grant");var a=jQuery(e).attr("data-"+r+"-cap");jQuery(e).prop("checked")?(jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!0),jQuery("input[data-"+t+'-cap="'+a+'"]').prop("checked",!1)):jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!1)}jQuery(".members-delete-role-link").click(function(){return window.confirm(members_i18n.ays_delete_role)}),jQuery('input[name="role_name"]').keyup(function(){jQuery('input[name="role"]').val()||e(this.value)}),jQuery('input[name="role"], .role-ok-button').hide(),jQuery(document).on("click",".role-edit-button.closed",function(){jQuery(this).removeClass("closed").addClass("open").text(members_i18n.button_role_ok),jQuery('input[name="role"]').show(),jQuery('input[name="role"]').trigger("focus"),jQuery('input[name="role"]').attr("value",jQuery(".role-slug").text())}),jQuery(document).on("click",".role-edit-button.open",function(){jQuery(this).removeClass("open").addClass("closed").text(members_i18n.button_role_edit),jQuery('input[name="role"]').hide();var r=jQuery('input[name="role"]').val();r?e(r):e(jQuery('input[name="role_name"]').val())}),jQuery('input[name="role"]').keypress(function(e){return 13===e.keyCode?(jQuery(".role-edit-button").click().trigger("focus"),e.preventDefault(),!1):void 0}),jQuery('.users_page_role-new input[name="role_name"]').val()||jQuery(".users_page_role-new #publish").prop("disabled",!0),jQuery('.users_page_role-new input[name="role_name"]').on("input",function(){jQuery(this).val()?jQuery(".users_page_role-new #publish").prop("disabled",!1):jQuery(".users_page_role-new #publish").prop("disabled",!0)});var a=wp.template("members-cap-section"),n=wp.template("members-cap-control");"undefined"!=typeof members_sections&&"undefined"!=typeof members_controls&&(_.each(members_sections,function(e){jQuery(".members-tab-wrap").append(a(e))}),_.each(members_controls,function(e){jQuery("#members-tab-"+e.section+" tbody").append(n(e))})),jQuery(".members-cap-tabs .members-tab-content").hide(),jQuery(".members-cap-tabs .members-tab-content:first-child").show(),jQuery(".members-tab-nav :first-child").attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(".members-tab-nav :first-child a").text()),jQuery(".members-tab-nav li a").click(function(e){e.preventDefault();var r=jQuery(this).attr("href");jQuery(this).parents(".members-cap-tabs").find(".members-tab-content").hide(),jQuery(this).parents(".members-cap-tabs").find(r).show(),jQuery(this).parents(".members-cap-tabs").find(".members-tab-title").attr("aria-selected","false"),jQuery(this).parent().attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(this).text())}),r(),jQuery(document).on("change",".members-cap-checklist input[data-grant-cap], .members-cap-checklist input[data-deny-cap]",function(){t(this),r()}),jQuery(document).on("click",".editable-role .members-cap-checklist button",function(){var e=jQuery(this).closest(".members-cap-checklist"),r=jQuery(e).find("input[data-grant-cap]"),t=jQuery(e).find("input[data-deny-cap]");jQuery(r).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!0).change()):jQuery(t).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!1).change()):jQuery(r).prop("checked",!0).change()}),jQuery(document).on("hover",".editable-role .members-cap-checklist button",function(){jQuery(".members-cap-checklist button:focus").not(this).blur()}),postboxes.add_postbox_toggles(pagenow),jQuery("#newcapdiv button.handlediv").attr("type","button"),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery("#members-new-cap-field").on("input",function(){jQuery(this).val()?jQuery("#members-add-new-cap").prop("disabled",!1):jQuery("#members-add-new-cap").prop("disabled",!0)}),jQuery("#members-new-cap-field").keypress(function(e){return 13===e.keyCode?(jQuery("#members-add-new-cap").click(),e.preventDefault(),!1):void 0}),jQuery("#members-add-new-cap").click(function(){var e=jQuery("#members-new-cap-field").val();if(e=e.trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,"")){jQuery('a[href="#members-tab-custom"]').trigger("click"),members_i18n.label_grant_cap=members_i18n.label_grant_cap.replace(/%s/g,""+e+""),members_i18n.label_deny_cap=members_i18n.label_deny_cap.replace(/%s/g,""+e+"");var r={cap:e,readonly:"",name:{grant:"grant-new-caps[]",deny:"deny-new-caps[]"},is_granted_cap:!0,is_denied_cap:!1,label:{grant:members_i18n.label_grant_cap,deny:members_i18n.label_deny_cap}};jQuery("#members-tab-custom tbody").prepend(n(r));var t=jQuery('[data-grant-cap="'+e+'"]').parents(".members-cap-checklist");jQuery(t).addClass("members-highlight"),setTimeout(function(){jQuery(t).removeClass("members-highlight")},500),jQuery("#members-new-cap-field").val(""),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery('.members-cap-checklist input[data-grant-cap="'+e+'"]').trigger("change")}})}); \ No newline at end of file +jQuery(document).ready(function(){function e(e){e=e.toLowerCase().trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,""),jQuery(".role-slug").text(e)}function r(){var e=jQuery("#members-tab-all input[data-grant-cap]:checked").length,r=jQuery("#members-tab-all input[data-deny-cap]:checked").length,t=jQuery('#members-tab-custom input[name="grant-new-caps[]"]:checked').length,a=jQuery('#members-tab-custom input[name="deny-new-caps[]"]:checked').length;jQuery("#submitdiv .granted-count").text(e+t),jQuery("#submitdiv .denied-count").text(r+a)}function t(e){var r="grant",t="deny";jQuery(e).attr("data-deny-cap")&&(r="deny",t="grant");var a=jQuery(e).attr("data-"+r+"-cap");jQuery(e).prop("checked")?(jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!0),jQuery("input[data-"+t+'-cap="'+a+'"]').prop("checked",!1)):jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!1)}jQuery(".members-delete-role-link").click(function(){return window.confirm(members_i18n.ays_delete_role)}),jQuery('input[name="role_name"]').keyup(function(){jQuery('input[name="role"]').val()||e(this.value)}),jQuery('input[name="role"], .role-ok-button').hide(),jQuery(document).on("click",".role-edit-button.closed",function(){jQuery(this).removeClass("closed").addClass("open").text(members_i18n.button_role_ok),jQuery('input[name="role"]').show(),jQuery('input[name="role"]').trigger("focus"),jQuery('input[name="role"]').attr("value",jQuery(".role-slug").text())}),jQuery(document).on("click",".role-edit-button.open",function(){jQuery(this).removeClass("open").addClass("closed").text(members_i18n.button_role_edit),jQuery('input[name="role"]').hide();var r=jQuery('input[name="role"]').val();e(r?r:jQuery('input[name="role_name"]').val())}),jQuery('input[name="role"]').keypress(function(e){if(13===e.keyCode)return jQuery(".role-edit-button").click().trigger("focus"),e.preventDefault(),!1}),jQuery('.users_page_role-new input[name="role_name"]').val()||jQuery(".users_page_role-new #publish").prop("disabled",!0),jQuery('.users_page_role-new input[name="role_name"]').on("input",function(){jQuery(this).val()?jQuery(".users_page_role-new #publish").prop("disabled",!1):jQuery(".users_page_role-new #publish").prop("disabled",!0)});var a=wp.template("members-cap-section"),n=wp.template("members-cap-control");"undefined"!=typeof members_sections&&"undefined"!=typeof members_controls&&(_.each(members_sections,function(e){jQuery(".members-tab-wrap").append(a(e))}),_.each(members_controls,function(e){jQuery("#members-tab-"+e.section+" tbody").append(n(e))})),jQuery(".members-cap-tabs .members-tab-content").hide(),jQuery(".members-cap-tabs .members-tab-content:first-child").show(),jQuery(".members-tab-nav :first-child").attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(".members-tab-nav :first-child a").text()),jQuery(".members-tab-nav li a").click(function(e){e.preventDefault();var r=jQuery(this).attr("href");jQuery(this).parents(".members-cap-tabs").find(".members-tab-content").hide(),jQuery(this).parents(".members-cap-tabs").find(r).show(),jQuery(this).parents(".members-cap-tabs").find(".members-tab-title").attr("aria-selected","false"),jQuery(this).parent().attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(this).text())}),r(),jQuery(document).on("change",".members-cap-checklist input[data-grant-cap], .members-cap-checklist input[data-deny-cap]",function(){t(this),r()}),jQuery(document).on("click",".editable-role .members-cap-checklist button",function(){var e=jQuery(this).closest(".members-cap-checklist"),r=jQuery(e).find("input[data-grant-cap]"),t=jQuery(e).find("input[data-deny-cap]");jQuery(r).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!0).change()):jQuery(t).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!1).change()):jQuery(r).prop("checked",!0).change()}),jQuery(document).on("hover",".editable-role .members-cap-checklist button",function(){jQuery(".members-cap-checklist button:focus").not(this).blur()}),postboxes.add_postbox_toggles(pagenow),jQuery("#newcapdiv button.handlediv").attr("type","button"),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery("#members-new-cap-field").on("input",function(){jQuery(this).val()?jQuery("#members-add-new-cap").prop("disabled",!1):jQuery("#members-add-new-cap").prop("disabled",!0)}),jQuery("#members-new-cap-field").keypress(function(e){if(13===e.keyCode)return jQuery("#members-add-new-cap").click(),e.preventDefault(),!1}),jQuery("#members-add-new-cap").click(function(){var e=jQuery("#members-new-cap-field").val();if(e=e.trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,"")){jQuery('a[href="#members-tab-custom"]').trigger("click"),members_i18n.label_grant_cap=members_i18n.label_grant_cap.replace(/%s/g,""+e+""),members_i18n.label_deny_cap=members_i18n.label_deny_cap.replace(/%s/g,""+e+"");var r={cap:e,readonly:"",name:{grant:"grant-new-caps[]",deny:"deny-new-caps[]"},is_granted_cap:!0,is_denied_cap:!1,label:{cap:e,grant:members_i18n.label_grant_cap,deny:members_i18n.label_deny_cap}};jQuery("#members-tab-custom tbody").prepend(n(r));var t=jQuery('[data-grant-cap="'+e+'"]').parents(".members-cap-checklist");jQuery(t).addClass("members-highlight"),setTimeout(function(){jQuery(t).removeClass("members-highlight")},500),jQuery("#members-new-cap-field").val(""),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery('.members-cap-checklist input[data-grant-cap="'+e+'"]').trigger("change")}})}); \ No newline at end of file diff --git a/members.php b/members.php index f0d9cec..73d0e07 100644 --- a/members.php +++ b/members.php @@ -3,7 +3,7 @@ * Plugin Name: Members * Plugin URI: http://themehybrid.com/plugins/members * Description: A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private. - * Version: 1.1.3 + * Version: 1.2.0-dev * Author: Justin Tadlock * Author URI: http://themehybrid.com * Text Domain: members @@ -25,7 +25,7 @@ * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * @package Members - * @version 1.1.3 + * @version 1.2.0 * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2016, Justin Tadlock * @link http://themehybrid.com/plugins/members @@ -222,8 +222,10 @@ private function setup() { private function includes() { // Load class files. - require_once( $this->inc_dir . 'class-role.php' ); - require_once( $this->inc_dir . 'class-role-factory.php' ); + require_once( $this->inc_dir . 'class-capability.php' ); + require_once( $this->inc_dir . 'class-capability-factory.php' ); + require_once( $this->inc_dir . 'class-role.php' ); + require_once( $this->inc_dir . 'class-role-factory.php' ); // Load includes files. require_once( $this->inc_dir . 'functions.php' ); From c1c750aed803c36d3998d19db3a43b6c64d34927 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sat, 24 Jun 2017 15:33:42 -0500 Subject: [PATCH 022/157] Prevent users from adding the `do_not_allow` capability to roles. Fixes: https://github.com/justintadlock/members/issues/137 --- admin/class-role-edit.php | 4 ++-- admin/class-role-new.php | 4 ++-- inc/functions-capabilities.php | 3 +++ js/edit-role.js | 7 ++++++- js/edit-role.min.js | 2 +- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/admin/class-role-edit.php b/admin/class-role-edit.php index 34b063b..d632b8d 100644 --- a/admin/class-role-edit.php +++ b/admin/class-role-edit.php @@ -166,7 +166,7 @@ public function load() { $_cap = members_sanitize_cap( $grant_new_cap ); // If not an existing cap, add it. - if ( ! in_array( $_cap, $this->capabilities ) ) { + if ( 'do_not_allow' !== $_cap && ! in_array( $_cap, $this->capabilities ) ) { $this->role->add_cap( $_cap ); $push_caps[] = $_cap; @@ -179,7 +179,7 @@ public function load() { $_cap = members_sanitize_cap( $deny_new_cap ); // If not a granted cap and not an existing cap, add it. - if ( ! in_array( $_cap, $this->capabilities ) && ! in_array( $_cap, $grant_new_caps ) ) { + if ( 'do_not_allow' !== $_cap && ! in_array( $_cap, $this->capabilities ) && ! in_array( $_cap, $grant_new_caps ) ) { $this->role->add_cap( $_cap, false ); $push_caps[] = $_cap; diff --git a/admin/class-role-new.php b/admin/class-role-new.php index 115e3b1..c5a6434 100644 --- a/admin/class-role-new.php +++ b/admin/class-role-new.php @@ -179,7 +179,7 @@ public function load() { $_cap = members_sanitize_cap( $grant_new_cap ); - if ( ! in_array( $_cap, $_m_caps ) ) + if ( 'do_not_allow' !== $_cap && ! in_array( $_cap, $_m_caps ) ) $new_caps[ $_cap ] = true; } @@ -187,7 +187,7 @@ public function load() { $_cap = members_sanitize_cap( $deny_new_cap ); - if ( ! in_array( $_cap, $_m_caps ) ) + if ( 'do_not_allow' !== $_cap && ! in_array( $_cap, $_m_caps ) ) $new_caps[ $_cap ] = false; } diff --git a/inc/functions-capabilities.php b/inc/functions-capabilities.php index c64fcc4..95625c4 100644 --- a/inc/functions-capabilities.php +++ b/inc/functions-capabilities.php @@ -355,6 +355,9 @@ function members_get_hidden_caps() { $caps = array(); + // This is always a hidden cap and should never be added to the caps list. + $caps[] = 'do_not_allow'; + // Unfiltered uploads. if ( is_multisite() || ! defined( 'ALLOW_UNFILTERED_UPLOADS' ) || ! ALLOW_UNFILTERED_UPLOADS ) $caps[] = 'unfiltered_upload'; diff --git a/js/edit-role.js b/js/edit-role.js index d2ebfee..74d6855 100644 --- a/js/edit-role.js +++ b/js/edit-role.js @@ -325,7 +325,7 @@ jQuery( document ).ready( function() { function() { // If there's a value in the input, enable the add new button. - if ( jQuery( this ).val() ) { + if ( 'do_not_allow' !== jQuery( this ).val() ) { jQuery( '#members-add-new-cap' ).prop( 'disabled', false ); @@ -363,6 +363,11 @@ jQuery( document ).ready( function() { // If there's a new cap value. if ( new_cap ) { + // Don't allow the 'do_not_allow' cap. + if ( 'do_not_allow' === new_cap ) { + return; + } + // Trigger a click event on the "custom" tab in the edit caps box. jQuery( 'a[href="#members-tab-custom"]' ).trigger( 'click' ); diff --git a/js/edit-role.min.js b/js/edit-role.min.js index b717d8c..e1d1436 100644 --- a/js/edit-role.min.js +++ b/js/edit-role.min.js @@ -1 +1 @@ -jQuery(document).ready(function(){function e(e){e=e.toLowerCase().trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,""),jQuery(".role-slug").text(e)}function r(){var e=jQuery("#members-tab-all input[data-grant-cap]:checked").length,r=jQuery("#members-tab-all input[data-deny-cap]:checked").length,t=jQuery('#members-tab-custom input[name="grant-new-caps[]"]:checked').length,a=jQuery('#members-tab-custom input[name="deny-new-caps[]"]:checked').length;jQuery("#submitdiv .granted-count").text(e+t),jQuery("#submitdiv .denied-count").text(r+a)}function t(e){var r="grant",t="deny";jQuery(e).attr("data-deny-cap")&&(r="deny",t="grant");var a=jQuery(e).attr("data-"+r+"-cap");jQuery(e).prop("checked")?(jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!0),jQuery("input[data-"+t+'-cap="'+a+'"]').prop("checked",!1)):jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!1)}jQuery(".members-delete-role-link").click(function(){return window.confirm(members_i18n.ays_delete_role)}),jQuery('input[name="role_name"]').keyup(function(){jQuery('input[name="role"]').val()||e(this.value)}),jQuery('input[name="role"], .role-ok-button').hide(),jQuery(document).on("click",".role-edit-button.closed",function(){jQuery(this).removeClass("closed").addClass("open").text(members_i18n.button_role_ok),jQuery('input[name="role"]').show(),jQuery('input[name="role"]').trigger("focus"),jQuery('input[name="role"]').attr("value",jQuery(".role-slug").text())}),jQuery(document).on("click",".role-edit-button.open",function(){jQuery(this).removeClass("open").addClass("closed").text(members_i18n.button_role_edit),jQuery('input[name="role"]').hide();var r=jQuery('input[name="role"]').val();e(r?r:jQuery('input[name="role_name"]').val())}),jQuery('input[name="role"]').keypress(function(e){if(13===e.keyCode)return jQuery(".role-edit-button").click().trigger("focus"),e.preventDefault(),!1}),jQuery('.users_page_role-new input[name="role_name"]').val()||jQuery(".users_page_role-new #publish").prop("disabled",!0),jQuery('.users_page_role-new input[name="role_name"]').on("input",function(){jQuery(this).val()?jQuery(".users_page_role-new #publish").prop("disabled",!1):jQuery(".users_page_role-new #publish").prop("disabled",!0)});var a=wp.template("members-cap-section"),n=wp.template("members-cap-control");"undefined"!=typeof members_sections&&"undefined"!=typeof members_controls&&(_.each(members_sections,function(e){jQuery(".members-tab-wrap").append(a(e))}),_.each(members_controls,function(e){jQuery("#members-tab-"+e.section+" tbody").append(n(e))})),jQuery(".members-cap-tabs .members-tab-content").hide(),jQuery(".members-cap-tabs .members-tab-content:first-child").show(),jQuery(".members-tab-nav :first-child").attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(".members-tab-nav :first-child a").text()),jQuery(".members-tab-nav li a").click(function(e){e.preventDefault();var r=jQuery(this).attr("href");jQuery(this).parents(".members-cap-tabs").find(".members-tab-content").hide(),jQuery(this).parents(".members-cap-tabs").find(r).show(),jQuery(this).parents(".members-cap-tabs").find(".members-tab-title").attr("aria-selected","false"),jQuery(this).parent().attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(this).text())}),r(),jQuery(document).on("change",".members-cap-checklist input[data-grant-cap], .members-cap-checklist input[data-deny-cap]",function(){t(this),r()}),jQuery(document).on("click",".editable-role .members-cap-checklist button",function(){var e=jQuery(this).closest(".members-cap-checklist"),r=jQuery(e).find("input[data-grant-cap]"),t=jQuery(e).find("input[data-deny-cap]");jQuery(r).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!0).change()):jQuery(t).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!1).change()):jQuery(r).prop("checked",!0).change()}),jQuery(document).on("hover",".editable-role .members-cap-checklist button",function(){jQuery(".members-cap-checklist button:focus").not(this).blur()}),postboxes.add_postbox_toggles(pagenow),jQuery("#newcapdiv button.handlediv").attr("type","button"),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery("#members-new-cap-field").on("input",function(){jQuery(this).val()?jQuery("#members-add-new-cap").prop("disabled",!1):jQuery("#members-add-new-cap").prop("disabled",!0)}),jQuery("#members-new-cap-field").keypress(function(e){if(13===e.keyCode)return jQuery("#members-add-new-cap").click(),e.preventDefault(),!1}),jQuery("#members-add-new-cap").click(function(){var e=jQuery("#members-new-cap-field").val();if(e=e.trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,"")){jQuery('a[href="#members-tab-custom"]').trigger("click"),members_i18n.label_grant_cap=members_i18n.label_grant_cap.replace(/%s/g,""+e+""),members_i18n.label_deny_cap=members_i18n.label_deny_cap.replace(/%s/g,""+e+"");var r={cap:e,readonly:"",name:{grant:"grant-new-caps[]",deny:"deny-new-caps[]"},is_granted_cap:!0,is_denied_cap:!1,label:{cap:e,grant:members_i18n.label_grant_cap,deny:members_i18n.label_deny_cap}};jQuery("#members-tab-custom tbody").prepend(n(r));var t=jQuery('[data-grant-cap="'+e+'"]').parents(".members-cap-checklist");jQuery(t).addClass("members-highlight"),setTimeout(function(){jQuery(t).removeClass("members-highlight")},500),jQuery("#members-new-cap-field").val(""),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery('.members-cap-checklist input[data-grant-cap="'+e+'"]').trigger("change")}})}); \ No newline at end of file +jQuery(document).ready(function(){function e(e){e=e.toLowerCase().trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,""),jQuery(".role-slug").text(e)}function r(){var e=jQuery("#members-tab-all input[data-grant-cap]:checked").length,r=jQuery("#members-tab-all input[data-deny-cap]:checked").length,t=jQuery('#members-tab-custom input[name="grant-new-caps[]"]:checked').length,a=jQuery('#members-tab-custom input[name="deny-new-caps[]"]:checked').length;jQuery("#submitdiv .granted-count").text(e+t),jQuery("#submitdiv .denied-count").text(r+a)}function t(e){var r="grant",t="deny";jQuery(e).attr("data-deny-cap")&&(r="deny",t="grant");var a=jQuery(e).attr("data-"+r+"-cap");jQuery(e).prop("checked")?(jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!0),jQuery("input[data-"+t+'-cap="'+a+'"]').prop("checked",!1)):jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!1)}jQuery(".members-delete-role-link").click(function(){return window.confirm(members_i18n.ays_delete_role)}),jQuery('input[name="role_name"]').keyup(function(){jQuery('input[name="role"]').val()||e(this.value)}),jQuery('input[name="role"], .role-ok-button').hide(),jQuery(document).on("click",".role-edit-button.closed",function(){jQuery(this).removeClass("closed").addClass("open").text(members_i18n.button_role_ok),jQuery('input[name="role"]').show(),jQuery('input[name="role"]').trigger("focus"),jQuery('input[name="role"]').attr("value",jQuery(".role-slug").text())}),jQuery(document).on("click",".role-edit-button.open",function(){jQuery(this).removeClass("open").addClass("closed").text(members_i18n.button_role_edit),jQuery('input[name="role"]').hide();var r=jQuery('input[name="role"]').val();e(r?r:jQuery('input[name="role_name"]').val())}),jQuery('input[name="role"]').keypress(function(e){if(13===e.keyCode)return jQuery(".role-edit-button").click().trigger("focus"),e.preventDefault(),!1}),jQuery('.users_page_role-new input[name="role_name"]').val()||jQuery(".users_page_role-new #publish").prop("disabled",!0),jQuery('.users_page_role-new input[name="role_name"]').on("input",function(){jQuery(this).val()?jQuery(".users_page_role-new #publish").prop("disabled",!1):jQuery(".users_page_role-new #publish").prop("disabled",!0)});var a=wp.template("members-cap-section"),n=wp.template("members-cap-control");"undefined"!=typeof members_sections&&"undefined"!=typeof members_controls&&(_.each(members_sections,function(e){jQuery(".members-tab-wrap").append(a(e))}),_.each(members_controls,function(e){jQuery("#members-tab-"+e.section+" tbody").append(n(e))})),jQuery(".members-cap-tabs .members-tab-content").hide(),jQuery(".members-cap-tabs .members-tab-content:first-child").show(),jQuery(".members-tab-nav :first-child").attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(".members-tab-nav :first-child a").text()),jQuery(".members-tab-nav li a").click(function(e){e.preventDefault();var r=jQuery(this).attr("href");jQuery(this).parents(".members-cap-tabs").find(".members-tab-content").hide(),jQuery(this).parents(".members-cap-tabs").find(r).show(),jQuery(this).parents(".members-cap-tabs").find(".members-tab-title").attr("aria-selected","false"),jQuery(this).parent().attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(this).text())}),r(),jQuery(document).on("change",".members-cap-checklist input[data-grant-cap], .members-cap-checklist input[data-deny-cap]",function(){t(this),r()}),jQuery(document).on("click",".editable-role .members-cap-checklist button",function(){var e=jQuery(this).closest(".members-cap-checklist"),r=jQuery(e).find("input[data-grant-cap]"),t=jQuery(e).find("input[data-deny-cap]");jQuery(r).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!0).change()):jQuery(t).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!1).change()):jQuery(r).prop("checked",!0).change()}),jQuery(document).on("hover",".editable-role .members-cap-checklist button",function(){jQuery(".members-cap-checklist button:focus").not(this).blur()}),postboxes.add_postbox_toggles(pagenow),jQuery("#newcapdiv button.handlediv").attr("type","button"),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery("#members-new-cap-field").on("input",function(){"do_not_allow"!==jQuery(this).val()?jQuery("#members-add-new-cap").prop("disabled",!1):jQuery("#members-add-new-cap").prop("disabled",!0)}),jQuery("#members-new-cap-field").keypress(function(e){if(13===e.keyCode)return jQuery("#members-add-new-cap").click(),e.preventDefault(),!1}),jQuery("#members-add-new-cap").click(function(){var e=jQuery("#members-new-cap-field").val();if(e=e.trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,"")){if("do_not_allow"===e)return;jQuery('a[href="#members-tab-custom"]').trigger("click"),members_i18n.label_grant_cap=members_i18n.label_grant_cap.replace(/%s/g,""+e+""),members_i18n.label_deny_cap=members_i18n.label_deny_cap.replace(/%s/g,""+e+"");var r={cap:e,readonly:"",name:{grant:"grant-new-caps[]",deny:"deny-new-caps[]"},is_granted_cap:!0,is_denied_cap:!1,label:{cap:e,grant:members_i18n.label_grant_cap,deny:members_i18n.label_deny_cap}};jQuery("#members-tab-custom tbody").prepend(n(r));var t=jQuery('[data-grant-cap="'+e+'"]').parents(".members-cap-checklist");jQuery(t).addClass("members-highlight"),setTimeout(function(){jQuery(t).removeClass("members-highlight")},500),jQuery("#members-new-cap-field").val(""),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery('.members-cap-checklist input[data-grant-cap="'+e+'"]').trigger("change")}})}); \ No newline at end of file From c428b51dc8acc0050ff0e9cc16106d8380692c4a Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sat, 24 Jun 2017 15:44:47 -0500 Subject: [PATCH 023/157] Register the "all" cap group last. --- admin/functions-cap-groups.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/admin/functions-cap-groups.php b/admin/functions-cap-groups.php index 1b7b50c..0c8e353 100644 --- a/admin/functions-cap-groups.php +++ b/admin/functions-cap-groups.php @@ -100,16 +100,6 @@ function members_get_cap_group( $name ) { */ function members_register_cap_groups() { - // Register the all group. - members_register_cap_group( 'all', - array( - 'label' => esc_html__( 'All', 'members' ), - 'caps' => members_get_all_group_caps(), - 'icon' => 'dashicons-plus', - 'merge_added' => false - ) - ); - // Registers the general group. members_register_cap_group( 'general', array( @@ -202,6 +192,16 @@ function members_register_cap_groups() { ) ); + // Register the all group. + members_register_cap_group( 'all', + array( + 'label' => esc_html__( 'All', 'members' ), + 'caps' => members_get_all_group_caps(), + 'icon' => 'dashicons-plus', + 'merge_added' => false + ) + ); + // Hook for registering cap groups. Plugins should always register on this hook. do_action( 'members_register_cap_groups' ); From a3e992db032ff3f2aa8ee7b9cb7027c20d5f3743 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sat, 24 Jun 2017 16:09:21 -0500 Subject: [PATCH 024/157] Add a new `members_priority_sort()` function for sorting objects by priority. Use it to sort cap groups. --- admin/class-cap-group.php | 9 +++++++ admin/class-cap-tabs.php | 6 ++++- admin/functions-cap-groups.php | 49 +++++++++++++++------------------- inc/functions.php | 15 +++++++++++ 4 files changed, 51 insertions(+), 28 deletions(-) diff --git a/admin/class-cap-group.php b/admin/class-cap-group.php index b2101e0..3a48d14 100644 --- a/admin/class-cap-group.php +++ b/admin/class-cap-group.php @@ -54,6 +54,15 @@ final class Members_Cap_Group { */ public $caps = array(); + /** + * Sort order priority. + * + * @since 1.0.0 + * @access public + * @var int + */ + public $priority = 10; + /** * Whether to merge this group's caps with the added caps array. * diff --git a/admin/class-cap-tabs.php b/admin/class-cap-tabs.php index 3cad8f4..037b58e 100644 --- a/admin/class-cap-tabs.php +++ b/admin/class-cap-tabs.php @@ -127,8 +127,12 @@ public function register() { // Hook before registering. do_action( 'members_pre_edit_caps_manager_register' ); + $groups = members_get_cap_groups(); + + uasort( $groups, 'members_priority_sort' ); + // Get and loop through the available capability groups. - foreach ( members_get_cap_groups() as $group ) { + foreach ( $groups as $group ) { $caps = $group->caps; diff --git a/admin/functions-cap-groups.php b/admin/functions-cap-groups.php index 0c8e353..39c7484 100644 --- a/admin/functions-cap-groups.php +++ b/admin/functions-cap-groups.php @@ -103,8 +103,9 @@ function members_register_cap_groups() { // Registers the general group. members_register_cap_group( 'general', array( - 'label' => esc_html__( 'General', 'members' ), - 'icon' => 'dashicons-wordpress' + 'label' => esc_html__( 'General', 'members' ), + 'icon' => 'dashicons-wordpress', + 'priority' => 5 ) ); @@ -141,9 +142,10 @@ function members_register_cap_groups() { // Register the post type cap group. members_register_cap_group( "type-{$type->name}", array( - 'label' => $type->labels->name, - 'caps' => $has_caps, - 'icon' => $icon + 'label' => $type->labels->name, + 'caps' => $has_caps, + 'icon' => $icon, + 'priority' => 5 ) ); } @@ -154,31 +156,35 @@ function members_register_cap_groups() { 'label' => esc_html__( 'Taxonomies', 'members' ), 'caps' => members_get_taxonomy_group_caps(), 'icon' => 'dashicons-tag', - 'diff_added' => true + 'diff_added' => true, + 'priority' => 10 ) ); // Register the theme group. members_register_cap_group( 'theme', array( - 'label' => esc_html__( 'Appearance', 'members' ), - 'icon' => 'dashicons-admin-appearance' + 'label' => esc_html__( 'Appearance', 'members' ), + 'icon' => 'dashicons-admin-appearance', + 'priority' => 15 ) ); // Register the plugin group. members_register_cap_group( 'plugin', array( - 'label' => esc_html__( 'Plugins', 'members' ), - 'icon' => 'dashicons-admin-plugins' + 'label' => esc_html__( 'Plugins', 'members' ), + 'icon' => 'dashicons-admin-plugins', + 'priority' => 20 ) ); // Register the user group. members_register_cap_group( 'user', array( - 'label' => esc_html__( 'Users', 'members' ), - 'icon' => 'dashicons-admin-users' + 'label' => esc_html__( 'Users', 'members' ), + 'icon' => 'dashicons-admin-users', + 'priority' => 25 ) ); @@ -188,7 +194,8 @@ function members_register_cap_groups() { 'label' => esc_html__( 'Custom', 'members' ), 'caps' => members_get_capabilities(), 'icon' => 'dashicons-admin-generic', - 'diff_added' => true + 'diff_added' => true, + 'priority' => 90 ) ); @@ -198,7 +205,8 @@ function members_register_cap_groups() { 'label' => esc_html__( 'All', 'members' ), 'caps' => members_get_all_group_caps(), 'icon' => 'dashicons-plus', - 'merge_added' => false + 'merge_added' => false, + 'priority' => 95 ) ); @@ -222,19 +230,6 @@ function members_register_cap_groups() { // Assign all caps to the `all` group. $_group->caps = array_unique( $caps ); } - - // Check if the `custom` group is registered and there's possibly other non-default groups. - if ( has_action( 'members_register_cap_groups' ) && members_cap_group_exists( 'custom' ) ) { - - // Get the custom group object. - $custom = members_cap_group_factory()->groups[ 'custom' ]; - - // Unset the custom group object. - unset( members_cap_group_factory()->groups[ 'custom' ] ); - - // Move the custom group object to the end. - members_cap_group_factory()->groups[ 'custom' ] = $custom; - } } /** diff --git a/inc/functions.php b/inc/functions.php index 0d89927..59847bf 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -22,3 +22,18 @@ function members_validate_boolean( $val ) { return filter_var( $val, FILTER_VALIDATE_BOOLEAN ); } + + +/** + * Helper function for sorting objects by priority. + * + * @since 1.2.0 + * @access protected + * @param object $a + * @param object $b + * @return int + */ +function members_priority_sort( $a, $b ) { + + return $a->priority - $b->priority; +} From 9935fd1ef13833d99ab3926ab775e8132a1cbaf1 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sat, 24 Jun 2017 16:10:35 -0500 Subject: [PATCH 025/157] Use the `members_priority_sort()` function for sorting settings views. --- admin/class-settings.php | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/admin/class-settings.php b/admin/class-settings.php index e84ed87..bf43f71 100644 --- a/admin/class-settings.php +++ b/admin/class-settings.php @@ -171,7 +171,7 @@ public function admin_menu() { do_action( 'members_register_settings_views', $this ); - uasort( $this->views, array( $this, 'priority_sort' ) ); + uasort( $this->views, 'members_priority_sort' ); // Register setings. add_action( 'admin_init', array( $this, 'register_settings' ) ); @@ -301,23 +301,6 @@ private function filter_links() { ?> priority === $b->priority ) - return $a->instance_number - $b->instance_number; - - return $a->priority - $b->priority; - } - /** * Adds help tabs. * From 2d3ca47537349f91d653d350224bc32639ce9419 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 26 Jun 2017 14:35:02 -0500 Subject: [PATCH 026/157] Complete overhaul of the factory-registry patterned classes previously used to store collections of data. These were all basically rewrites of the same code. The new code introduces a single Registry class and does away with the factory aspect, which was unnecessary for our needs. Some code changes means a minimum of PHP 5.3 is now required. This commit also introduces the `Members` namespace since we're now committed to PHP 5.3+. Suffice it to say, there's some back-compatibility breakage here for any developers who were using various classes directly. This was always frowned upon, especially considering wrapper functions exist for everything. This should not break back-compat for anyone using those wrapper functions. The plugin should also be bumped to 2.0.0-dev from 1.2.0-dev to keep up with semantic versioning. --- admin/class-cap-group-factory.php | 115 ------------- admin/class-cap-group.php | 6 +- admin/class-role-edit.php | 10 +- admin/class-role-group-factory.php | 115 ------------- admin/class-role-group.php | 8 +- admin/class-role-list-table.php | 10 +- admin/class-role-new.php | 2 +- admin/class-roles.php | 2 +- admin/class-user-edit.php | 14 +- admin/functions-cap-groups.php | 31 ++-- admin/functions-role-groups.php | 39 +++-- inc/class-capability-factory.php | 114 ------------- inc/class-capability.php | 6 +- inc/class-registry.php | 149 +++++++++++++++++ inc/class-role-factory.php | 165 ------------------- inc/class-role.php | 117 ++++++------- inc/class-widget-users.php | 10 +- inc/functions-capabilities.php | 24 +-- inc/functions-deprecated.php | 225 ++++++++++++++++++++++++- inc/functions-roles.php | 255 +++++++++++++---------------- inc/functions-users.php | 2 +- members.php | 23 ++- 22 files changed, 624 insertions(+), 818 deletions(-) delete mode 100644 admin/class-cap-group-factory.php delete mode 100644 admin/class-role-group-factory.php delete mode 100644 inc/class-capability-factory.php create mode 100644 inc/class-registry.php delete mode 100644 inc/class-role-factory.php diff --git a/admin/class-cap-group-factory.php b/admin/class-cap-group-factory.php deleted file mode 100644 index d19d4be..0000000 --- a/admin/class-cap-group-factory.php +++ /dev/null @@ -1,115 +0,0 @@ - - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock - * @link http://themehybrid.com/plugins/members - * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - */ - -/** - * Capability group factory class. - * - * @since 1.0.0 - * @access public - */ -final class Members_Cap_Group_Factory { - - /** - * Array of group objects. - * - * @since 1.0.0 - * @access public - * @var array - */ - public $groups = array(); - - /** - * Constructor method. - * - * @since 1.0.0 - * @access private - * @return void - */ - private function __construct() {} - - /** - * Register a new group object - * - * @see Members_Cap_Group::__construct() - * @since 1.0.0 - * @access public - * @param string $name - * @param array $args - * @return void - */ - public function register_group( $name, $args = array() ) { - - if ( ! $this->group_exists( $name ) ) { - - $group = new Members_Cap_Group( $name, $args ); - - $this->groups[ $group->name ] = $group; - } - } - - /** - * Unregisters a group object. - * - * @since 1.0.0 - * @access public - * @param string $name - * @return void - */ - public function unregister_group( $name ) { - - if ( $this->group_exists( $name ) ) - unset( $this->groups[ $name ] ); - } - - /** - * Checks if a group exists. - * - * @since 1.0.0 - * @access public - * @param string $name - * @return bool - */ - public function group_exists( $name ) { - - return isset( $this->groups[ $name ] ); - } - - /** - * Gets a group object. - * - * @since 1.0.0 - * @access public - * @param string $name - * @return object|bool - */ - public function get_group( $name ) { - - return $this->group_exists( $name ) ? $this->groups[ $name ] : false; - } - - /** - * Returns the instance. - * - * @since 1.0.0 - * @access public - * @return object - */ - public static function get_instance() { - - static $instance = null; - - if ( is_null( $instance ) ) - $instance = new Members_Cap_Group_Factory; - - return $instance; - } -} diff --git a/admin/class-cap-group.php b/admin/class-cap-group.php index 3a48d14..4b24ec6 100644 --- a/admin/class-cap-group.php +++ b/admin/class-cap-group.php @@ -10,13 +10,15 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members; + /** * Capability group object class. * * @since 1.0.0 * @access public */ -final class Members_Cap_Group { +final class Cap_Group { /** * Name/ID for the group. @@ -108,7 +110,7 @@ public function __toString() { * } * @return void */ - public function __construct( $name, $args = array() ) { + public function __construct( string $name, array $args = array() ) { foreach ( array_keys( get_object_vars( $this ) ) as $key ) { diff --git a/admin/class-role-edit.php b/admin/class-role-edit.php index d632b8d..f4a5295 100644 --- a/admin/class-role-edit.php +++ b/admin/class-role-edit.php @@ -213,19 +213,19 @@ public function load() { // If successful update. if ( $this->role_updated ) - add_settings_error( 'members_edit_role', 'role_updated', sprintf( esc_html__( '%s role updated.', 'members' ), members_get_role_name( $this->role->name ) ), 'updated' ); + add_settings_error( 'members_edit_role', 'role_updated', sprintf( esc_html__( '%s role updated.', 'members' ), members_get_role( $this->role->name )->label ), 'updated' ); // If the role is not editable. if ( ! $this->is_editable ) - add_settings_error( 'members_edit_role', 'role_uneditable', sprintf( esc_html__( 'The %s role is not editable. This means that it is most likely added via another plugin for a special use or that you do not have permission to edit it.', 'members' ), members_get_role_name( $this->role->name ) ) ); + add_settings_error( 'members_edit_role', 'role_uneditable', sprintf( esc_html__( 'The %s role is not editable. This means that it is most likely added via another plugin for a special use or that you do not have permission to edit it.', 'members' ), members_get_role( $this->role->name )->label ) ); // If editing the core administrator role. if ( 'administrator' === $this->role->name ) - add_settings_error( 'members_edit_role', 'role_is_admin', sprintf( esc_html__( 'The %s role is typically the most important role on the site. Please take extreme caution that you do no inadvertently remove necessary capabilities.', 'members' ), members_get_role_name( $this->role->name ) ) ); + add_settings_error( 'members_edit_role', 'role_is_admin', sprintf( esc_html__( 'The %s role is typically the most important role on the site. Please take extreme caution that you do no inadvertently remove necessary capabilities.', 'members' ), members_get_role( $this->role->name )->label ) ); // If a new role was added (redirect from new role screen). if ( isset( $_GET['message'] ) && 'role_added' === $_GET['message'] ) - add_settings_error( 'members_edit_role', 'role_added', sprintf( esc_html__( 'The %s role has been created.', 'members' ), members_get_role_name( $this->role->name ) ), 'updated' ); + add_settings_error( 'members_edit_role', 'role_added', sprintf( esc_html__( 'The %s role has been created.', 'members' ), members_get_role( $this->role->name )->label ), 'updated' ); // Load page hook. do_action( 'members_load_role_edit' ); @@ -308,7 +308,7 @@ public function page() { ?>
    - +
    diff --git a/admin/class-role-group-factory.php b/admin/class-role-group-factory.php deleted file mode 100644 index 3870811..0000000 --- a/admin/class-role-group-factory.php +++ /dev/null @@ -1,115 +0,0 @@ - - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock - * @link http://themehybrid.com/plugins/members - * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - */ - -/** - * Roleability group factory class. - * - * @since 1.0.0 - * @access public - */ -final class Members_Role_Group_Factory { - - /** - * Array of group objects. - * - * @since 1.0.0 - * @access public - * @var array - */ - public $groups = array(); - - /** - * Constructor method. - * - * @since 1.0.0 - * @access private - * @return void - */ - private function __construct() {} - - /** - * Register a new group object - * - * @see Members_Role_Group::__construct() - * @since 1.0.0 - * @access public - * @param string $name - * @param array $args - * @return void - */ - public function register_group( $name, $args = array() ) { - - if ( ! $this->group_exists( $name ) ) { - - $group = new Members_Role_Group( $name, $args ); - - $this->groups[ $group->name ] = $group; - } - } - - /** - * Unregisters a group object. - * - * @since 1.0.0 - * @access public - * @param string $name - * @return void - */ - public function unregister_group( $name ) { - - if ( $this->group_exists( $name ) && false === $this->get( $name )->_internal ) - unset( $this->groups[ $name ] ); - } - - /** - * Checks if a group exists. - * - * @since 1.0.0 - * @access public - * @param string $name - * @return bool - */ - public function group_exists( $name ) { - - return isset( $this->groups[ $name ] ); - } - - /** - * Gets a group object. - * - * @since 1.0.0 - * @access public - * @param string $name - * @return object|bool - */ - public function get_group( $name ) { - - return $this->group_exists( $name ) ? $this->groups[ $name ] : false; - } - - /** - * Returns the instance. - * - * @since 1.0.0 - * @access public - * @return object - */ - public static function get_instance() { - - static $instance = null; - - if ( is_null( $instance ) ) - $instance = new Members_Role_Group_Factory; - - return $instance; - } -} diff --git a/admin/class-role-group.php b/admin/class-role-group.php index 521c2e0..58da06b 100644 --- a/admin/class-role-group.php +++ b/admin/class-role-group.php @@ -10,13 +10,15 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members; + /** * Role group object class. * * @since 1.0.0 * @access public */ -final class Members_Role_Group { +final class Role_Group { /** * Stores the properties for the object. @@ -103,7 +105,7 @@ public function __toString() { * } * @return void */ - public function __construct( $name, $args = array() ) { + public function __construct( string $name, array $args = array() ) { $name = sanitize_key( $name ); @@ -117,7 +119,7 @@ public function __construct( $name, $args = array() ) { $this->args = wp_parse_args( $args, $defaults ); // Get the roles that exist. - $existing_roles = array_keys( members_get_role_names() ); + $existing_roles = array_keys( members_get_roles() ); // Remove roles that don't exist. if ( $this->args['roles'] ) diff --git a/admin/class-role-list-table.php b/admin/class-role-list-table.php index 990e326..3a1c113 100644 --- a/admin/class-role-list-table.php +++ b/admin/class-role-list-table.php @@ -97,7 +97,7 @@ public function prepare_items() { // Get the roles for the default/All view. if ( 'all' === $this->role_view ) { - $roles = members_get_role_slugs(); + $roles = array_keys( members_get_roles() ); // If a custom view, get the roles. } else { @@ -245,7 +245,7 @@ protected function column_title( $role ) { } // Add the title and role states. - $title = sprintf( '%s%s', esc_url( members_get_edit_role_url( $role ) ), esc_html( members_get_role_name( $role ) ), $role_states ); + $title = sprintf( '%s%s', esc_url( members_get_edit_role_url( $role ) ), esc_html( members_get_role( $role )->label ), $role_states ); return apply_filters( 'members_manage_roles_column_role_name', $title, $role ); } @@ -391,14 +391,14 @@ protected function get_views() { $inactive = members_get_role_group( 'inactive' ); if ( $active ) - $active->roles = members_get_active_role_slugs(); + $active->roles = members_get_active_roles(); if ( $inactive ) - $inactive->roles = members_get_inactive_role_slugs(); + $inactive->roles = members_get_inactive_roles(); $views = array(); $current = ' class="current"'; - $all_count = count( members_get_role_slugs() ); + $all_count = count( members_get_roles() ); // Add the default/all view. $views['all'] = sprintf( diff --git a/admin/class-role-new.php b/admin/class-role-new.php index c5a6434..88f63fd 100644 --- a/admin/class-role-new.php +++ b/admin/class-role-new.php @@ -323,7 +323,7 @@ public function page() { ?>
    - +
    diff --git a/admin/class-roles.php b/admin/class-roles.php index 8b5fe3d..353023c 100644 --- a/admin/class-roles.php +++ b/admin/class-roles.php @@ -126,7 +126,7 @@ public function load() { if ( members_role_exists( $role ) ) { // Add role deleted message. - add_settings_error( 'members_roles', 'role_deleted', sprintf( esc_html__( '%s role deleted.', 'members' ), members_get_role_name( $role ) ), 'updated' ); + add_settings_error( 'members_roles', 'role_deleted', sprintf( esc_html__( '%s role deleted.', 'members' ), members_get_role( $role )->label ), 'updated' ); // Delete the role. members_delete_role( $role ); diff --git a/admin/class-user-edit.php b/admin/class-user-edit.php index 24fa85f..26b7c27 100644 --- a/admin/class-user-edit.php +++ b/admin/class-user-edit.php @@ -78,9 +78,9 @@ public function profile_fields( $user ) { $user_roles = (array) $user->roles; - $editable_roles = members_get_editable_role_names(); + $roles = members_get_roles(); - asort( $editable_roles ); + ksort( $roles ); wp_nonce_field( 'new_user_roles', 'members_new_user_roles_nonce' ); ?> @@ -94,13 +94,17 @@ public function profile_fields( $user ) {
    -
      - $name ) : ?> -
    • - -
    • - -
    +
    +
      + $name ) : ?> +
    • + +
    • + +
    +
    - +
      - $name ) : ?> + + + name ) ) :?>
    • + +
    diff --git a/admin/functions-cap-groups.php b/admin/functions-cap-groups.php index 39c7484..0f5b66b 100644 --- a/admin/functions-cap-groups.php +++ b/admin/functions-cap-groups.php @@ -14,21 +14,20 @@ add_action( 'init', 'members_register_cap_groups', 95 ); /** - * Returns the instance of the `Members_Cap_Group_Factory` object. Use this function to access the object. + * Returns the instance of cap group registry. * - * @see Members_Cap_Group_Factory - * @since 1.0.0 + * @since 1.2.0 * @access public * @return object */ -function members_cap_group_factory() { - return Members_Cap_Group_Factory::get_instance(); +function members_cap_group_registry() { + + return \Members\Registry::get_instance( 'cap_group' ); } /** * Function for registering a cap group. * - * @see Members_Cap_Group_Factory::register_group() * @since 1.0.0 * @access public * @param string $name @@ -36,59 +35,59 @@ function members_cap_group_factory() { * @return void */ function members_register_cap_group( $name, $args = array() ) { - members_cap_group_factory()->register_group( $name, $args ); + + members_cap_group_registry()->register( $name, new \Members\Cap_Group( $name, $args ) ); } /** * Unregisters a group. * - * @see Members_Cap_Group_Factory::unregister_group() * @since 1.0.0 * @access public * @param string $name * @return void */ function members_unregister_cap_group( $name ) { - members_cap_group_factory()->unregister_group( $name ); + + members_cap_group_registry()->unregister( $name ); } /** * Checks if a group exists. * - * @see Members_Cap_Group_Factory::group_exists() * @since 1.0.0 * @access public * @param string $name * @return bool */ function members_cap_group_exists( $name ) { - return members_cap_group_factory()->group_exists( $name ); + + return members_cap_group_registry()->exists( $name ); } /** * Returns an array of registered group objects. * - * @see Members_Cap_Group_Factory::group * @since 1.0.0 * @access public * @return array */ function members_get_cap_groups() { - return members_cap_group_factory()->groups; + + return members_cap_group_registry()->get_collection(); } /** * Returns a group object if it exists. Otherwise, `FALSE`. * - * @see Members_Cap_Group_Factory::get_group() - * @see Members_Cap_Group * @since 1.0.0 * @access public * @param string $name * @return object|bool */ function members_get_cap_group( $name ) { - return members_cap_group_factory()->get_group( $name ); + + return members_cap_group_registry()->get( $name ); } /** diff --git a/admin/functions-role-groups.php b/admin/functions-role-groups.php index 3a327d7..7065eb6 100644 --- a/admin/functions-role-groups.php +++ b/admin/functions-role-groups.php @@ -11,24 +11,23 @@ */ # Registers default groups. -add_action( 'init', 'members_register_role_groups', 15 ); +add_action( 'init', 'members_register_role_groups', 95 ); /** - * Returns the instance of the `Members_Role_Group_Factory` object. Use this function to access the object. + * Returns the instance of the role group registry. * - * @see Members_Role_Group_Factory - * @since 1.0.0 + * @since 1.2.0 * @access public * @return object */ -function members_role_group_factory() { - return Members_Role_Group_Factory::get_instance(); +function members_role_group_registry() { + + return \Members\Registry::get_instance( 'role_group' ); } /** * Function for registering a role group. * - * @see Members_Role_Group_Factory::register_group() * @since 1.0.0 * @access public * @param string $name @@ -36,59 +35,59 @@ function members_role_group_factory() { * @return void */ function members_register_role_group( $name, $args = array() ) { - members_role_group_factory()->register_group( $name, $args ); + + members_role_group_registry()->register( $name, new \Members\Role_Group( $name, $args ) ); } /** * Unregisters a group. * - * @see Members_Role_Group_Factory::unregister_group() * @since 1.0.0 * @access public * @param string $name * @return void */ function members_unregister_role_group( $name ) { - members_role_group_factory()->unregister_group( $name ); + + members_role_group_registry()->unregister( $name ); } /** * Checks if a group exists. * - * @see Members_Role_Group_Factory::group_exists() * @since 1.0.0 * @access public * @param string $name * @return bool */ function members_role_group_exists( $name ) { - return members_role_group_factory()->group_exists( $name ); + + return members_role_group_registry()->exists( $name ); } /** * Returns an array of registered group objects. * - * @see Members_Role_Group_Factory::group * @since 1.0.0 * @access public * @return array */ function members_get_role_groups() { - return members_role_group_factory()->groups; + + return members_role_group_registry()->get_collection(); } /** * Returns a group object if it exists. Otherwise, `FALSE`. * - * @see Members_Role_Group_Factory::get_group() - * @see Members_Role_Group * @since 1.0.0 * @access public * @param string $name * @return object|bool */ function members_get_role_group( $name ) { - return members_role_group_factory()->get_group( $name ); + + return members_role_group_registry()->get( $name ); } /** @@ -138,7 +137,7 @@ function members_register_role_groups() { array( 'label' => esc_html__( 'Editable', 'members' ), 'label_count' => _n_noop( 'Editable %s', 'Editable %s', 'members' ), - 'roles' => members_get_editable_role_slugs(), + 'roles' => members_get_editable_roles(), ) ); @@ -147,7 +146,7 @@ function members_register_role_groups() { array( 'label' => esc_html__( 'Uneditable', 'members' ), 'label_count' => _n_noop( 'Uneditable %s', 'Uneditable %s', 'members' ), - 'roles' => members_get_uneditable_role_slugs(), + 'roles' => members_get_uneditable_roles(), ) ); @@ -156,7 +155,7 @@ function members_register_role_groups() { array( 'label' => esc_html__( 'WordPress', 'members' ), 'label_count' => _n_noop( 'WordPress %s', 'WordPress %s', 'members' ), - 'roles' => members_get_wordpress_role_slugs(), + 'roles' => members_get_wordpress_roles(), ) ); diff --git a/inc/class-capability-factory.php b/inc/class-capability-factory.php deleted file mode 100644 index b95d162..0000000 --- a/inc/class-capability-factory.php +++ /dev/null @@ -1,114 +0,0 @@ - - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock - * @link http://themehybrid.com/plugins/members - * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - */ - -/** - * Capability factory class. - * - * @since 1.2.0 - * @access public - */ -final class Members_Capability_Factory { - - /** - * Array of cap objects. - * - * @since 1.2.0 - * @access public - * @var array - */ - public $caps = array(); - - /** - * Constructor method. - * - * @since 1.2.0 - * @access private - * @return void - */ - private function __construct() {} - - /** - * Register a new cap object - * - * @since 1.2.0 - * @access public - * @param string $name - * @param array $args - * @return void - */ - public function register_cap( $name, $args = array() ) { - - if ( ! $this->cap_exists( $name ) ) { - - $cap = new Members_Capability( $name, $args ); - - $this->caps[ $cap->name ] = $cap; - } - } - - /** - * Unregisters a cap object. - * - * @since 1.2.0 - * @access public - * @param string $name - * @return void - */ - public function unregister_cap( $name ) { - - if ( $this->cap_exists( $name ) ) - unset( $this->caps[ $name ] ); - } - - /** - * Checks if a cap exists. - * - * @since 1.2.0 - * @access public - * @param string $name - * @return bool - */ - public function cap_exists( $name ) { - - return isset( $this->caps[ $name ] ); - } - - /** - * Gets a cap object. - * - * @since 1.2.0 - * @access public - * @param string $name - * @return object|bool - */ - public function get_cap( $name ) { - - return $this->cap_exists( $name ) ? $this->caps[ $name ] : false; - } - - /** - * Returns the instance. - * - * @since 1.2.0 - * @access public - * @return object - */ - public static function get_instance() { - - static $instance = null; - - if ( is_null( $instance ) ) - $instance = new self; - - return $instance; - } -} diff --git a/inc/class-capability.php b/inc/class-capability.php index c5efc2c..783685a 100644 --- a/inc/class-capability.php +++ b/inc/class-capability.php @@ -10,13 +10,15 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members; + /** * Capability class. * * @since 1.2.0 * @access public */ -class Members_Capability { +class Capability { /** * The capability name. @@ -66,7 +68,7 @@ public function __toString() { * @param string $role * @return void */ - public function __construct( $name, $args = array() ) { + public function __construct( string $name, array $args = array() ) { foreach ( array_keys( get_object_vars( $this ) ) as $key ) { diff --git a/inc/class-registry.php b/inc/class-registry.php new file mode 100644 index 0000000..a55fe75 --- /dev/null +++ b/inc/class-registry.php @@ -0,0 +1,149 @@ + + * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @link http://themehybrid.com/plugins/members + * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + */ + +namespace Members; + +/** + * Base registry class. + * + * @since 1.2.0 + * @access public + */ +class Registry { + + /** + * Registry instances. + * + * @since 1.2.0 + * @access private + * @var array + */ + private static $instances = array(); + + /** + * Array of objects in the collection. + * + * @since 1.2.0 + * @access protected + * @var array + */ + protected $collection = array(); + + /** + * Constructor method. + * + * @since 1.2.0 + * @access protected + * @return void + */ + protected function __construct() {} + + /** + * Lock down `__clone()`. + * + * @since 1.2.0 + * @access private + * @return void + */ + private function __clone() {} + + /** + * Lock down `__wakeup()`. + * + * @since 1.2.0 + * @access private + * @return void + */ + private function __wakeup() {} + + /** + * Register a new cap object + * + * @since 1.2.0 + * @access public + * @param string $name + * @param object $value + * @return void + */ + public function register( string $name, $value ) { + + if ( ! $this->exists( $name ) ) + $this->collection[ $name ] = $value; + } + + /** + * Unregisters a cap object. + * + * @since 1.2.0 + * @access public + * @param string $name + * @return void + */ + public function unregister( string $name ) { + + if ( $this->exists( $name ) ) + unset( $this->collection[ $name ] ); + } + + /** + * Checks if a cap exists. + * + * @since 1.2.0 + * @access public + * @param string $name + * @return bool + */ + public function exists( string $name ) { + + return isset( $this->collection[ $name ] ); + } + + /** + * Gets a cap object. + * + * @since 1.2.0 + * @access public + * @param string $name + * @return object|bool + */ + public function get( string $name ) { + + return $this->exists( $name ) ? $this->collection[ $name ] : false; + } + + /** + * Returns the entire collection. + * + * @since 1.2.0 + * @access public + * @return array + */ + public function get_collection() { + + return $this->collection; + } + + /** + * Returns the instance. + * + * @since 1.2.0 + * @access public + * @return object + */ + final public static function get_instance( string $name = '' ) { + + if ( ! isset( self::$instances[ $name ] ) ) + self::$instances[ $name ] = new static(); + + return self::$instances[ $name ]; + } +} diff --git a/inc/class-role-factory.php b/inc/class-role-factory.php deleted file mode 100644 index 6757c3b..0000000 --- a/inc/class-role-factory.php +++ /dev/null @@ -1,165 +0,0 @@ - - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock - * @link http://themehybrid.com/plugins/members - * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - */ - -/** - * Role factory class. - * - * @since 1.0.0 - * @access public - */ -final class Members_Role_Factory { - - /** - * Array of roles added. - * - * @since 1.0.0 - * @access public - * @var array - */ - public $roles = array(); - - /** - * Array of editable roles. - * - * @since 1.0.0 - * @access public - * @var array - */ - public $editable = array(); - - /** - * Array of uneditable roles. - * - * @since 1.0.0 - * @access public - * @var array - */ - public $uneditable = array(); - - /** - * Array of core WordPress roles. - * - * @since 1.0.0 - * @access public - * @var array - */ - public $wordpress = array(); - - /** - * Private constructor method to prevent a new instance of the object. - * - * @since 1.0.0 - * @access public - * @return void - */ - private function __construct() {} - - /** - * Adds a role object. - * - * @since 1.0.0 - * @access public - * @param string $role - * @return object - */ - public function add_role( $role ) { - - // If the role exists with WP but hasn't been added. - if ( members_role_exists( $role ) ) { - - // Get the role object. - $this->roles[ $role ] = new Members_Role( $role ); - - // Check if role is editable. - if ( $this->roles[ $role ]->is_editable ) - $this->editable[ $role ] = $this->roles[ $role ]; - else - $this->uneditable[ $role ] = $this->roles[ $role ]; - - // Is WP role? - if ( members_is_wordpress_role( $role ) ) - $this->wordpress[ $role ] = $this->roles[ $role ]; - } - } - - /** - * Returns a single role object. - * - * @since 1.0.0 - * @access public - * @param string $role - * @return object - */ - public function get_role( $role ) { - - return isset( $this->roles[ $role ] ) ? $this->roles[ $role ] : false; - } - - /** - * Removes a role object (doesn't remove from DB). - * - * @since 1.1.0 - * @access public - * @param string $role - * @return void - */ - public function remove_role( $role ) { - - if ( isset( $this->roles[ $role ] ) ) - unset( $this->roles[ $role ] ); - } - - /** - * Returns an array of role objects. - * - * @since 1.0.0 - * @access public - * @return array - */ - public function get_roles() { - return $this->roles; - } - - /** - * Adds all the WP roles as role objects. Rather than running this elsewhere, we're just - * going to call this directly within the class when it is first constructed. - * - * @since 1.0.0 - * @access public - * @return void - */ - protected function setup_roles() { - - foreach ( $GLOBALS['wp_roles']->role_names as $role => $name ) - $this->add_role( $role ); - } - - /** - * Returns the instance. - * - * @since 3.0.0 - * @access public - * @return object - */ - public static function get_instance() { - - static $instance = null; - - if ( is_null( $instance ) ) { - $instance = new Members_Role_Factory; - $instance->setup_roles(); - } - - return $instance; - } -} diff --git a/inc/class-role.php b/inc/class-role.php index f689802..9e13f51 100644 --- a/inc/class-role.php +++ b/inc/class-role.php @@ -11,54 +11,48 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members; + /** * Role class. * - * @since 1.0.0 + * @since 1.2.0 * @access public */ -class Members_Role { - - /** - * The role/slug. - * - * @since 1.0.0 - * @access public - * @var string - */ - public $slug = ''; +class Role { /** * The role name. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @var string */ public $name = ''; /** - * Whether the role can be edited. + * The role label. * - * @since 1.0.0 + * @since 1.2.0 * @access public - * @var bool + * @var string */ - public $is_editable = false; + public $label = ''; /** - * Whether the role is a core WP role. + * The group the role belongs to. * - * @since 1.0.0 + * @see Members\Role_Group + * @since 1.2.0 * @access public - * @var bool + * @var string */ - public $is_wordpress_role = false; + public $group = ''; /** * Whether the role has caps (granted). * - * @since 1.0.0 + * @since 1.2.0 * @access public * @var bool */ @@ -67,7 +61,7 @@ class Members_Role { /** * Capability count for the role. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @var int */ @@ -76,7 +70,7 @@ class Members_Role { /** * Capability count for the role. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @var int */ @@ -85,7 +79,7 @@ class Members_Role { /** * Array of capabilities that the role has. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @var array */ @@ -94,7 +88,7 @@ class Members_Role { /** * Array of granted capabilities that the role has. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @var array */ @@ -103,7 +97,7 @@ class Members_Role { /** * Array of denied capabilities that the role has. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @var array */ @@ -112,71 +106,56 @@ class Members_Role { /** * Return the role string in attempts to use the object as a string. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @return string */ public function __toString() { - return $this->slug; + return $this->name; } /** * Creates a new role object. * - * @since 1.0.0 + * @since 1.2.0 * @access public - * @global object $wp_roles * @param string $role + * @param array $args * @return void */ - public function __construct( $role ) { - global $wp_roles; - - // Get the WP role object. - $_role = get_role( $role ); - - // Set the slug. - $this->slug = $_role->name; + public function __construct( string $name, array $args = array() ) { - // Set the role name. - if ( isset( $wp_roles->role_names[ $role ] ) ) - $this->name = members_translate_role( $role ); + foreach ( array_keys( get_object_vars( $this ) ) as $key ) { - // Check whether the role is editable. - $editable_roles = function_exists( 'get_editable_roles' ) ? get_editable_roles() : apply_filters( 'editable_roles', $wp_roles->roles ); - $this->is_editable = array_key_exists( $role, $editable_roles ); - - // Loop through the role's caps. - foreach ( (array) $_role->capabilities as $cap => $grant ) { + if ( isset( $args[ $key ] ) ) + $this->$key = $args[ $key ]; + } - // Validate any boolean grant/denied in case they are stored as strings. - $grant = members_validate_boolean( $grant ); + $this->name = members_sanitize_role( $name ); - // Add to all caps array. - $this->caps[ $cap ] = $grant; + if ( $this->caps ) { - // If a granted cap. - if ( true === $grant ) - $this->granted_caps[] = $cap; + // Validate cap values as booleans in case they are stored as strings. + $this->caps = array_map( 'members_validate_boolean', $this->caps ); - // If a denied cap. - elseif ( false === $grant ) - $this->denied_caps[] = $cap; - } + // Get granted and denied caps. + $this->granted_caps = array_keys( $this->caps, true ); + $this->denied_caps = array_keys( $this->caps, false ); - // Remove user levels from granted/denied caps. - $this->granted_caps = members_remove_old_levels( $this->granted_caps ); - $this->denied_caps = members_remove_old_levels( $this->denied_caps ); + // Remove user levels from granted/denied caps. + $this->granted_caps = members_remove_old_levels( $this->granted_caps ); + $this->denied_caps = members_remove_old_levels( $this->denied_caps ); - // Remove hidden caps from granted/denied caps. - $this->granted_caps = members_remove_hidden_caps( $this->granted_caps ); - $this->denied_caps = members_remove_hidden_caps( $this->denied_caps ); + // Remove hidden caps from granted/denied caps. + $this->granted_caps = members_remove_hidden_caps( $this->granted_caps ); + $this->denied_caps = members_remove_hidden_caps( $this->denied_caps ); - // Set the cap count. - $this->granted_cap_count = count( $this->granted_caps ); - $this->denied_cap_count = count( $this->denied_caps ); + // Set the cap count. + $this->granted_cap_count = count( $this->granted_caps ); + $this->denied_cap_count = count( $this->denied_caps ); - // Check if we have caps. - $this->has_caps = 0 < $this->granted_cap_count; + // Check if we have caps. + $this->has_caps = 0 < $this->granted_cap_count; + } } } diff --git a/inc/class-widget-users.php b/inc/class-widget-users.php index f90d6d5..403454d 100644 --- a/inc/class-widget-users.php +++ b/inc/class-widget-users.php @@ -197,9 +197,8 @@ function form( $instance ) { $meta_key = array_merge( array( '' ), (array) members_get_user_meta_keys() ); - $roles = members_get_role_names(); - asort( $roles ); - $roles = array_merge( array( '' => '' ), $roles ); ?> + $roles = members_get_roles(); + asort( $roles ); ?>
    @@ -226,8 +225,9 @@ function form( $instance ) {

    diff --git a/inc/functions-capabilities.php b/inc/functions-capabilities.php index 95625c4..c4f3657 100644 --- a/inc/functions-capabilities.php +++ b/inc/functions-capabilities.php @@ -129,35 +129,32 @@ function members_register_default_caps() { } /** - * Returns the instance of the capability factory. + * Returns the instance of the capability registry. * - * @see Members_Capability_Factory::get_instance() * @since 1.2.0 * @access public * @return object */ -function members_capability_factory() { +function members_capability_registry() { - return Members_Capability_Factory::get_instance(); + return \Members\Registry::get_instance( 'cap' ); } /** * Returns all registered caps. * - * @see Members_Capability_Factory::caps * @since 1.2.0 * @access public * @return array */ function members_get_caps() { - return members_capability_factory()->caps; + return members_capability_registry()->get_collection(); } /** * Registers a capability. * - * @see Members_Capability_Factory::register_cap() * @since 1.2.0 * @access public * @param string $name @@ -166,13 +163,12 @@ function members_get_caps() { */ function members_register_cap( $name, $args = array() ) { - members_capability_factory()->register_cap( $name, $args ); + members_capability_registry()->register( $name, new \Members\Capability( $name, $args ) ); } /** * Unregisters a capability. * - * @see Members_Capability_Factory::unregister_cap() * @since 1.2.0 * @access public * @param string $name @@ -180,13 +176,12 @@ function members_register_cap( $name, $args = array() ) { */ function members_unregister_cap( $name ) { - members_capability_factory()->unregister_cap( $name ); + members_capability_registry()->unregister( $name ); } /** * Returns a capability object. * - * @see Members_Capability_Factory::get_cap() * @since 1.2.0 * @access public * @param string $name @@ -194,7 +189,7 @@ function members_unregister_cap( $name ) { */ function members_get_cap( $name ) { - return members_capability_factory()->get_cap( $name ); + return members_capability_registry()->get( $name ); } /** @@ -202,7 +197,6 @@ function members_get_cap( $name ) { * * @note In 1.2.0, the function was changed to only check from registered caps. * - * @see Members_Capability_Factory::unregister_cap() * @since 1.0.0 * @access public * @param string $name @@ -210,7 +204,7 @@ function members_get_cap( $name ) { */ function members_cap_exists( $name ) { - return members_capability_factory()->cap_exists( $name ); + return members_capability_registry()->exists( $name ); } /** @@ -236,7 +230,7 @@ function members_sanitize_cap( $cap ) { */ function members_is_cap_editable( $cap ) { - $uneditable = array_keys( members_get_uneditable_role_names() ); + $uneditable = array_keys( members_get_uneditable_roles() ); return ! in_array( $cap, members_get_wp_capabilities() ) && ! array_intersect( $uneditable, members_get_cap_roles( $cap ) ); } diff --git a/inc/functions-deprecated.php b/inc/functions-deprecated.php index 7ed2012..4b6f44c 100644 --- a/inc/functions-deprecated.php +++ b/inc/functions-deprecated.php @@ -10,6 +10,209 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +/** + * Returns an array of role names. + * + * @since 1.0.0 + * @access public + * @return array + */ +function members_get_role_names() { + _deprecated_function( __FUNCTION__, '1.2.0', '' ); + + $roles = array(); + + foreach ( members_get_roles() as $role ) + $roles[ $role->name ] = $role->name; + + return $roles; +} + +/** + * Returns an array of the role names of roles that have users. + * + * @since 1.0.0 + * @access public + * @return array + */ +function members_get_active_role_names() { + _deprecated_function( __FUNCTION__, '1.2.0', '' ); + + $has_users = array(); + + foreach ( members_get_active_roles() as $role ) + $has_users[ $role ] = members_get_role( $role )->label; + + return $has_users; +} + +/** + * Returns an array of the role names of roles that do not have users. + * + * @since 1.0.0 + * @access public + * @return array + */ +function members_get_inactive_role_names() { + _deprecated_function( __FUNCTION__, '1.2.0', '' ); + + return array_diff( members_get_role_names(), members_get_active_role_names() ); +} + +/** + * Returns an array of editable role names. + * + * @since 1.0.0 + * @access public + * @return array + */ +function members_get_editable_role_names() { + _deprecated_function( __FUNCTION__, '1.2.0', '' ); + + $editable = array(); + + foreach ( members_role_registry()->editable as $role ) + $editable[ $role->slug ] = $role->name; + + return $editable; +} + +/** + * Returns an array of editable roles. + * + * @since 1.0.0 + * @access public + * @return array + */ +function members_get_editable_role_slugs() { + _deprecated_function( __FUNCTION__, '1.2.0', '' ); + + return array_keys( members_role_registry()->editable ); +} + +/** + * Returns an array of uneditable role names. + * + * @since 1.0.0 + * @access public + * @return array + */ +function members_get_uneditable_role_names() { + _deprecated_function( __FUNCTION__, '1.2.0', '' ); + + $uneditable = array(); + + foreach ( members_role_registry()->uneditable as $role ) + $uneditable[ $role->slug ] = $role->name; + + return $uneditable; +} + +/** + * Returns an array of uneditable roles. + * + * @since 1.0.0 + * @access public + * @return array + */ +function members_get_uneditable_role_slugs() { + _deprecated_function( __FUNCTION__, '1.2.0', '' ); + + return array_keys( members_role_registry()->uneditable ); +} + +/** + * Returns an array of core WordPress role names. + * + * @since 1.0.0 + * @access public + * @return array + */ +function members_get_wordpress_role_names() { + _deprecated_function( __FUNCTION__, '1.2.0', '' ); + + $names = array(); + + foreach ( members_role_registry()->wordpress as $role ) + $names[ $role->slug ] = $role->name; + + return $names; +} + +/** + * Returns an array of core WP roles. + * + * @since 1.0.0 + * @access public + * @return array + */ +function members_get_wordpress_role_slugs() { + _deprecated_function( __FUNCTION__, '1.2.0', '' ); + + return array_keys( members_role_registry()->wordpress ); +} + +/** + * Returns the human-readable role name. + * + * @since 1.0.0 + * @access public + * @param string $role + * @return string + */ +function members_get_role_name( $role ) { + _deprecated_function( __FUNCTION__, '1.2.0', '' ); + + return members_role_registry()->get( $role )->name; +} + +/** + * Returns an array of roles. + * + * @since 1.0.0 + * @access public + * @return array + */ +function members_get_role_slugs() { + _deprecated_function( __FUNCTION__, '1.2.0', '' ); + + return array_keys( members_get_roles() ); +} + +/** + * Returns an array of the roles that have users. + * + * @since 1.0.0 + * @access public + * @return array + */ +function members_get_active_role_slugs() { + _deprecated_function( __FUNCTION__, '1.2.0', '' ); + + $has_users = array(); + + foreach ( members_get_role_user_count() as $role => $count ) { + + if ( 0 < $count ) + $has_users[] = $role; + } + + return $has_users; +} + +/** + * Returns an array of the roles that have no users. + * + * @since 1.0.0 + * @access public + * @return array + */ +function members_get_inactive_role_slugs() { + _deprecated_function( __FUNCTION__, '1.2.0', '' ); + + return array_diff( array_keys( members_get_roles() ), members_get_active_roles() ); +} + /** * Additional capabilities provided by the Members plugin that gives users permissions to handle * certain features of the plugin. @@ -107,19 +310,19 @@ function members_get_wp_capabilities() { * @since 0.2.0 * @deprecated 1.0.0 */ -function members_get_active_roles() { - _deprecated_function( __FUNCTION__, '1.0.0', 'members_get_active_role_names' ); - return members_get_active_role_names(); -} +//function members_get_active_roles() { +// _deprecated_function( __FUNCTION__, '1.0.0', 'members_get_active_role_names' ); +// return members_get_active_role_names(); +//} /** * @since 0.2.0 * @deprecated 1.0.0 */ -function members_get_inactive_roles() { - _deprecated_function( __FUNCTION__, '1.0.0', 'members_get_inactive_role_names' ); - return members_get_inactive_role_names(); -} +//function members_get_inactive_roles() { +// _deprecated_function( __FUNCTION__, '1.0.0', 'members_get_inactive_role_names' ); +// return members_get_inactive_role_names(); +//} /** * @since 0.2.0 @@ -148,6 +351,12 @@ function members_get_additional_capabilities() { return members_get_plugin_capabilities(); } +/* ====== Functions removed in the 1.2 branch. ====== */ + +function members_role_factory() {} +function members_role_group_factory() {} +function members_cap_group_factory() {} + /* ====== Functions removed in the 1.0 branch. ====== */ if ( ! function_exists( 'has_role' ) ) { function has_role() {} } diff --git a/inc/functions-roles.php b/inc/functions-roles.php index eb2d4fb..1b525af 100644 --- a/inc/functions-roles.php +++ b/inc/functions-roles.php @@ -10,234 +10,219 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ -/** - * Returns the instance of the `Members_Role_Factory`. - * - * @since 1.0.0 - * @access public - * @param string - * @return bool - */ -function members_role_factory() { - return Members_Role_Factory::get_instance(); -} - -/* ====== Multiple Role Functions ====== */ +# Register roles. +add_action( 'init', 'members_register_roles', 95 ); +add_action( 'members_register_roles', 'members_register_default_roles', 5 ); /** - * Returns a count of all the available roles for the site. + * Fires the role registration action hook. * - * @since 1.0.0 + * @since 1.2.0 * @access public - * @return int + * @return void */ -function members_get_role_count() { - return count( $GLOBALS['wp_roles']->role_names ); -} +function members_register_roles() { -/** - * Returns an array of `Members_Role` objects. - * - * @since 1.0.0 - * @access public - * @return array - */ -function members_get_roles() { - return members_role_factory()->roles; + do_action( 'members_register_roles' ); } /** - * Returns an array of role names. + * Registers any roles stored globally with WordPress. * - * @since 1.0.0 + * @since 1.2.0 * @access public - * @return array + * @return void */ -function members_get_role_names() { - $roles = array(); +function members_register_default_roles() { - foreach ( members_role_factory()->roles as $role ) - $roles[ $role->slug ] = $role->name; + foreach ( $GLOBALS['wp_roles']->roles as $name => $object ) { - return $roles; + $args = array( + 'label' => $object['name'], + 'caps' => $object['capabilities'] + ); + + members_register_role( $name, $args ); + } } /** - * Returns an array of roles. + * Returns the instance of the role registry. * - * @since 1.0.0 + * @since 1.2.0 * @access public - * @return array + * @return object */ -function members_get_role_slugs() { - return array_keys( members_role_factory()->roles ); +function members_role_registry() { + + return \Members\Registry::get_instance( 'role' ); } /** - * Returns an array of the role names of roles that have users. + * Returns all registered roles. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @return array */ -function members_get_active_role_names() { - $has_users = array(); - - foreach ( members_get_active_role_slugs() as $role ) - $has_users[ $role ] = members_get_role_name( $role ); +function members_get_roles() { - return $has_users; + return members_role_registry()->get_collection(); } /** - * Returns an array of the roles that have users. + * Registers a role. * - * @since 1.0.0 + * @since 1.2.0 * @access public - * @return array + * @param string $name + * @param array $args + * @return void */ -function members_get_active_role_slugs() { - - $has_users = array(); - - foreach ( members_get_role_user_count() as $role => $count ) { +function members_register_role( $name, $args = array() ) { - if ( 0 < $count ) - $has_users[] = $role; - } - - return $has_users; + members_role_registry()->register( $name, new \Members\Role( $name, $args ) ); } /** - * Returns an array of the role names of roles that do not have users. + * Unregisters a role. * - * @since 1.0.0 + * @since 1.2.0 * @access public - * @return array + * @param string $name + * @return void */ -function members_get_inactive_role_names() { - return array_diff( members_get_role_names(), members_get_active_role_names() ); +function members_unregister_role( $name ) { + + members_role_registry()->unregister( $name ); } /** - * Returns an array of the roles that have no users. + * Returns a role object. * - * @since 1.0.0 + * @since 1.2.0 * @access public - * @return array + * @param string $name + * @return object */ -function members_get_inactive_role_slugs() { - return array_diff( members_get_role_slugs(), members_get_active_role_slugs() ); +function members_get_role( $name ) { + + return members_role_registry()->get( $name ); } /** - * Returns an array of editable role names. + * Checks if a role object exists. * - * @since 1.0.0 + * @since 1.2.0 * @access public - * @return array + * @param string $name + * @return bool */ -function members_get_editable_role_names() { - $editable = array(); +function members_role_exists( $name ) { - foreach ( members_role_factory()->editable as $role ) - $editable[ $role->slug ] = $role->name; - - return $editable; + return members_role_registry()->exists( $name ); } +/* ====== Multiple Role Functions ====== */ + /** * Returns an array of editable roles. * - * @since 1.0.0 + * @since 1.2.0 * @access public + * @global array $wp_roles * @return array */ -function members_get_editable_role_slugs() { - return array_keys( members_role_factory()->editable ); +function members_get_editable_roles() { + global $wp_roles; + + $editable = function_exists( 'get_editable_roles' ) ? get_editable_roles() : apply_filters( 'editable_roles', $wp_roles->roles ); + + return array_keys( $editable ); } /** - * Returns an array of uneditable role names. + * Returns an array of uneditable roles. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @return array */ -function members_get_uneditable_role_names() { - $uneditable = array(); - - foreach ( members_role_factory()->uneditable as $role ) - $uneditable[ $role->slug ] = $role->name; +function members_get_uneditable_roles() { - return $uneditable; + return array_diff( array_keys( members_get_roles() ), members_get_editable_roles() ); } /** - * Returns an array of uneditable roles. + * Returns an array of core WP roles. Note that we remove any that are not registered. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @return array */ -function members_get_uneditable_role_slugs() { - return array_keys( members_role_factory()->uneditable ); +function members_get_wordpress_roles() { + + $roles = array( 'administrator', 'editor', 'author', 'contributor', 'subscriber' ); + + return array_intersect( $roles, array_keys( members_get_roles() ) ); } /** - * Returns an array of core WordPress role names. + * Returns an array of the roles that have users. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @return array */ -function members_get_wordpress_role_names() { - $names = array(); +function members_get_active_roles() { + + $has_users = array(); + + foreach ( members_get_role_user_count() as $role => $count ) { - foreach ( members_role_factory()->wordpress as $role ) - $names[ $role->slug ] = $role->name; + if ( 0 < $count ) + $has_users[] = $role; + } - return $names; + return $has_users; } /** - * Returns an array of core WP roles. + * Returns an array of the roles that have no users. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @return array */ -function members_get_wordpress_role_slugs() { - return array_keys( members_role_factory()->wordpress ); -} +function members_get_inactive_roles() { -/* ====== Single Role Functions ====== */ + return array_diff( array_keys( members_get_roles() ), members_get_active_roles() ); +} /** - * Conditional tag to check if a role exists. + * Returns a count of all the available roles for the site. * * @since 1.0.0 * @access public - * @param string - * @return bool + * @return int */ -function members_role_exists( $role ) { - return $GLOBALS['wp_roles']->is_role( $role ); +function members_get_role_count() { + return count( $GLOBALS['wp_roles']->role_names ); } /** - * Gets a Members role object. + * Returns an array of `Members_Role` objects. * - * @see Members_Role * @since 1.0.0 * @access public - * @param string - * @return object + * @return array */ -function members_get_role( $role ) { - return members_role_factory()->get_role( $role ); -} +//function members_get_roles() { +// return members_role_registry()->roles; +//} + + +/* ====== Single Role Functions ====== */ /** * Sanitizes a role name. This is a wrapper for the `sanitize_key()` WordPress function. Only @@ -280,7 +265,8 @@ function members_translate_role( $role ) { * @return bool */ function members_role_has_users( $role ) { - return in_array( $role, members_get_active_role_slugs() ); + + return in_array( $role, members_get_active_roles() ); } /** @@ -291,7 +277,8 @@ function members_role_has_users( $role ) { * @return bool */ function members_role_has_caps( $role ) { - return members_role_factory()->get_role( $role )->has_caps; + + return members_get_role( $role )->has_caps; } /** @@ -333,7 +320,8 @@ function members_get_role_user_count( $role = '' ) { * @return int */ function members_get_role_granted_cap_count( $role ) { - return members_role_factory()->get_role( $role )->granted_cap_count; + + return members_get_role( $role )->granted_cap_count; } /** @@ -345,19 +333,8 @@ function members_get_role_granted_cap_count( $role ) { * @return int */ function members_get_role_denied_cap_count( $role ) { - return members_role_factory()->get_role( $role )->denied_cap_count; -} -/** - * Returns the human-readable role name. - * - * @since 1.0.0 - * @access public - * @param string $role - * @return string - */ -function members_get_role_name( $role ) { - return members_role_factory()->get_role( $role )->name; + return members_get_role( $role )->denied_cap_count; } /** @@ -369,11 +346,12 @@ function members_get_role_name( $role ) { * @return bool */ function members_is_role_editable( $role ) { - return members_role_factory()->get_role( $role )->is_editable; + + return in_array( $role, members_get_editable_roles() ); } /** - * Conditional tag to check whether a role is a core WordPress URL. + * Conditional tag to check whether a role is a core WordPress role. * * @since 1.0.0 * @access public @@ -381,6 +359,7 @@ function members_is_role_editable( $role ) { * @return bool */ function members_is_wordpress_role( $role ) { + return in_array( $role, array( 'administrator', 'editor', 'author', 'contributor', 'subscriber' ) ); } diff --git a/inc/functions-users.php b/inc/functions-users.php index cbf567a..fe255df 100644 --- a/inc/functions-users.php +++ b/inc/functions-users.php @@ -107,7 +107,7 @@ function members_get_user_role_names( $user_id ) { $names = array(); foreach ( $user->roles as $role ) - $names[ $role ] = members_get_role_name( $role ); + $names[ $role ] = members_get_role( $role )->label; return $names; } diff --git a/members.php b/members.php index 73d0e07..71d7e53 100644 --- a/members.php +++ b/members.php @@ -222,10 +222,9 @@ private function setup() { private function includes() { // Load class files. - require_once( $this->inc_dir . 'class-capability.php' ); - require_once( $this->inc_dir . 'class-capability-factory.php' ); - require_once( $this->inc_dir . 'class-role.php' ); - require_once( $this->inc_dir . 'class-role-factory.php' ); + require_once( $this->inc_dir . 'class-capability.php' ); + require_once( $this->inc_dir . 'class-registry.php' ); + require_once( $this->inc_dir . 'class-role.php' ); // Load includes files. require_once( $this->inc_dir . 'functions.php' ); @@ -268,17 +267,15 @@ private function includes() { require_once( $this->admin_dir . 'class-meta-box-custom-cap.php' ); // Role groups. - require_once( $this->admin_dir . 'class-role-group.php' ); - require_once( $this->admin_dir . 'class-role-group-factory.php' ); - require_once( $this->admin_dir . 'functions-role-groups.php' ); + require_once( $this->admin_dir . 'class-role-group.php' ); + require_once( $this->admin_dir . 'functions-role-groups.php' ); // Edit capabilities tabs and groups. - require_once( $this->admin_dir . 'class-cap-tabs.php' ); - require_once( $this->admin_dir . 'class-cap-section.php' ); - require_once( $this->admin_dir . 'class-cap-control.php' ); - require_once( $this->admin_dir . 'class-cap-group.php' ); - require_once( $this->admin_dir . 'class-cap-group-factory.php' ); - require_once( $this->admin_dir . 'functions-cap-groups.php' ); + require_once( $this->admin_dir . 'class-cap-tabs.php' ); + require_once( $this->admin_dir . 'class-cap-section.php' ); + require_once( $this->admin_dir . 'class-cap-control.php' ); + require_once( $this->admin_dir . 'class-cap-group.php' ); + require_once( $this->admin_dir . 'functions-cap-groups.php' ); } } From ad162b28e4798cf19f4969ff648d542f16d21fb4 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 26 Jun 2017 14:45:37 -0500 Subject: [PATCH 027/157] Bring the `Members\Role_Group` class up to date with similar classes. --- admin/class-role-group.php | 99 +++++++++++++------------------------- 1 file changed, 34 insertions(+), 65 deletions(-) diff --git a/admin/class-role-group.php b/admin/class-role-group.php index 58da06b..5ceb97c 100644 --- a/admin/class-role-group.php +++ b/admin/class-role-group.php @@ -15,76 +15,62 @@ /** * Role group object class. * - * @since 1.0.0 + * @since 1.2.0 * @access public */ final class Role_Group { /** - * Stores the properties for the object. + * Name/ID for the group. * - * @since 1.0.0 + * @since 1.2.0 * @access protected - * @var array + * @var string */ - protected $args = array(); + public $name = ''; /** - * Magic method for getting object properties. + * Internationalized text label for the group. * - * @since 1.0.0 - * @access public - * @param string $property - * @return mixed + * @since 1.2.0 + * @access protected + * @var string */ - public function __get( $property ) { - - return isset( $this->$property ) ? $this->args[ $property ] : null; - } + public $label = ''; /** - * Magic method for setting object properties. + * Internationalized text label for the group + the count in the form of + * `_n_noop( 'Singular Name %s', 'Pluran Name %s', $textdomain )` * - * @since 1.0.0 - * @access public - * @param string $property - * @param mixed $value - * @return void + * @since 1.2.0 + * @access protected + * @var string */ - public function __set( $property, $value ) { - - if ( isset( $this->$property ) ) - $this->args[ $property ] = $value; - } + public $label_count = ''; /** - * Magic method for checking if a property is set. + * Array of roles that belong to the group. * - * @since 1.0.0 - * @access public - * @param string $property - * @return bool + * @since 1.2.0 + * @access protected + * @var array */ - public function __isset( $property ) { - - return isset( $this->args[ $property ] ); - } + public $roles = array(); /** - * Don't allow properties to be unset. + * Whether to create a view for the group on the Manage Roles screen. * - * @since 3.0.0 - * @access public - * @param string $property - * @return void + * @since 1.2.0 + * @access protected + * @var bool */ - public function __unset( $property ) {} + public $show_in_view_list = true; /** * Magic method to use in case someone tries to output the object as a string. * We'll just return the name. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @return string */ @@ -95,37 +81,20 @@ public function __toString() { /** * Register a new object. * - * @since 1.0.0 + * @since 1.2.0 * @access public * @param string $name - * @param array $args { - * @type string $label Internationalized text label. - * @type string $icon Count label in admin. - * @type array $roles Array of roles in the group. - * } + * @param array $args * @return void */ public function __construct( string $name, array $args = array() ) { - $name = sanitize_key( $name ); - - $defaults = array( - 'label' => '', - 'label_count' => '', - 'roles' => array(), - 'show_in_view_list' => true - ); - - $this->args = wp_parse_args( $args, $defaults ); - - // Get the roles that exist. - $existing_roles = array_keys( members_get_roles() ); + foreach ( array_keys( get_object_vars( $this ) ) as $key ) { - // Remove roles that don't exist. - if ( $this->args['roles'] ) - $this->args['roles'] = array_intersect( $existing_roles, $this->args['roles'] ); + if ( isset( $args[ $key ] ) ) + $this->$key = $args[ $key ]; + } - // Set the name. - $this->args['name'] = $name; + $this->name = sanitize_key( $name ); } } From 143b5aa4f5305dff64d54003f15c25cdfc9dd2e1 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 26 Jun 2017 14:50:35 -0500 Subject: [PATCH 028/157] Update copyright date and email in all file headers. --- admin/class-cap-control.php | 4 ++-- admin/class-cap-group.php | 4 ++-- admin/class-cap-section.php | 4 ++-- admin/class-cap-tabs.php | 4 ++-- admin/class-manage-roles.php | 4 ++-- admin/class-meta-box-content-permissions.php | 4 ++-- admin/class-meta-box-custom-cap.php | 4 ++-- admin/class-meta-box-publish-role.php | 4 ++-- admin/class-role-edit.php | 4 ++-- admin/class-role-group.php | 4 ++-- admin/class-role-list-table.php | 4 ++-- admin/class-role-new.php | 4 ++-- admin/class-roles.php | 4 ++-- admin/class-settings.php | 4 ++-- admin/class-user-edit.php | 4 ++-- admin/functions-admin.php | 4 ++-- admin/functions-cap-groups.php | 4 ++-- admin/functions-help.php | 4 ++-- admin/functions-role-groups.php | 4 ++-- admin/functions-settings.php | 4 ++-- admin/tmpl/cap-control.php | 4 ++-- admin/tmpl/cap-section.php | 4 ++-- admin/views/class-settings-view-add-ons.php | 4 ++-- admin/views/class-settings-view-general.php | 4 ++-- admin/views/class-settings-view.php | 4 ++-- inc/class-capability.php | 4 ++-- inc/class-registry.php | 4 ++-- inc/class-role.php | 4 ++-- inc/class-widget-login.php | 4 ++-- inc/class-widget-users.php | 4 ++-- inc/functions-admin-bar.php | 4 ++-- inc/functions-capabilities.php | 4 ++-- inc/functions-deprecated.php | 4 ++-- inc/functions-options.php | 4 ++-- inc/functions-private-site.php | 4 ++-- inc/functions-roles.php | 4 ++-- inc/functions-shortcodes.php | 4 ++-- inc/functions-users.php | 4 ++-- inc/functions-widgets.php | 4 ++-- inc/functions.php | 4 ++-- inc/template.php | 4 ++-- members.php | 4 ++-- 42 files changed, 84 insertions(+), 84 deletions(-) diff --git a/admin/class-cap-control.php b/admin/class-cap-control.php index 3205b21..5cf65a6 100644 --- a/admin/class-cap-control.php +++ b/admin/class-cap-control.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-cap-group.php b/admin/class-cap-group.php index 4b24ec6..5eff4cb 100644 --- a/admin/class-cap-group.php +++ b/admin/class-cap-group.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-cap-section.php b/admin/class-cap-section.php index 06c9596..db2f6b4 100644 --- a/admin/class-cap-section.php +++ b/admin/class-cap-section.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-cap-tabs.php b/admin/class-cap-tabs.php index 037b58e..e5cf5ff 100644 --- a/admin/class-cap-tabs.php +++ b/admin/class-cap-tabs.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-manage-roles.php b/admin/class-manage-roles.php index dd2e42d..898763f 100644 --- a/admin/class-manage-roles.php +++ b/admin/class-manage-roles.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-meta-box-content-permissions.php b/admin/class-meta-box-content-permissions.php index 3bfb42f..07fa3a0 100644 --- a/admin/class-meta-box-content-permissions.php +++ b/admin/class-meta-box-content-permissions.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-meta-box-custom-cap.php b/admin/class-meta-box-custom-cap.php index 30a39c9..a602330 100644 --- a/admin/class-meta-box-custom-cap.php +++ b/admin/class-meta-box-custom-cap.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-meta-box-publish-role.php b/admin/class-meta-box-publish-role.php index be9a204..c48b5d7 100644 --- a/admin/class-meta-box-publish-role.php +++ b/admin/class-meta-box-publish-role.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-role-edit.php b/admin/class-role-edit.php index f4a5295..5d2b8f2 100644 --- a/admin/class-role-edit.php +++ b/admin/class-role-edit.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-role-group.php b/admin/class-role-group.php index 5ceb97c..cbf8b6c 100644 --- a/admin/class-role-group.php +++ b/admin/class-role-group.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-role-list-table.php b/admin/class-role-list-table.php index 3a1c113..ce66abd 100644 --- a/admin/class-role-list-table.php +++ b/admin/class-role-list-table.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-role-new.php b/admin/class-role-new.php index 88f63fd..e09d6ec 100644 --- a/admin/class-role-new.php +++ b/admin/class-role-new.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-roles.php b/admin/class-roles.php index 353023c..3becc7d 100644 --- a/admin/class-roles.php +++ b/admin/class-roles.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-settings.php b/admin/class-settings.php index bf43f71..801d410 100644 --- a/admin/class-settings.php +++ b/admin/class-settings.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-user-edit.php b/admin/class-user-edit.php index 26b7c27..37defe1 100644 --- a/admin/class-user-edit.php +++ b/admin/class-user-edit.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/functions-admin.php b/admin/functions-admin.php index 1c846c2..fef68a5 100644 --- a/admin/functions-admin.php +++ b/admin/functions-admin.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/functions-cap-groups.php b/admin/functions-cap-groups.php index 0f5b66b..52bd4e6 100644 --- a/admin/functions-cap-groups.php +++ b/admin/functions-cap-groups.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/functions-help.php b/admin/functions-help.php index 92d5009..cde5ad2 100644 --- a/admin/functions-help.php +++ b/admin/functions-help.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/functions-role-groups.php b/admin/functions-role-groups.php index 7065eb6..7cb93ab 100644 --- a/admin/functions-role-groups.php +++ b/admin/functions-role-groups.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/functions-settings.php b/admin/functions-settings.php index 15d31e9..fb38101 100644 --- a/admin/functions-settings.php +++ b/admin/functions-settings.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/tmpl/cap-control.php b/admin/tmpl/cap-control.php index c3ba19c..9e18428 100644 --- a/admin/tmpl/cap-control.php +++ b/admin/tmpl/cap-control.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/tmpl/cap-section.php b/admin/tmpl/cap-section.php index 6d7d1c5..c202edf 100644 --- a/admin/tmpl/cap-section.php +++ b/admin/tmpl/cap-section.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/views/class-settings-view-add-ons.php b/admin/views/class-settings-view-add-ons.php index 32ec922..fe8f268 100644 --- a/admin/views/class-settings-view-add-ons.php +++ b/admin/views/class-settings-view-add-ons.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/views/class-settings-view-general.php b/admin/views/class-settings-view-general.php index aa1de65..c413904 100644 --- a/admin/views/class-settings-view-general.php +++ b/admin/views/class-settings-view-general.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/views/class-settings-view.php b/admin/views/class-settings-view.php index 9374064..b59640a 100644 --- a/admin/views/class-settings-view.php +++ b/admin/views/class-settings-view.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-capability.php b/inc/class-capability.php index 783685a..ab11ed0 100644 --- a/inc/class-capability.php +++ b/inc/class-capability.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Includes - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-registry.php b/inc/class-registry.php index a55fe75..269864e 100644 --- a/inc/class-registry.php +++ b/inc/class-registry.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Admin - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-role.php b/inc/class-role.php index 9e13f51..d084e02 100644 --- a/inc/class-role.php +++ b/inc/class-role.php @@ -5,8 +5,8 @@ * * @package Members * @subpackage Includes - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-widget-login.php b/inc/class-widget-login.php index 654f9be..53b1312 100644 --- a/inc/class-widget-login.php +++ b/inc/class-widget-login.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Includes - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-widget-users.php b/inc/class-widget-users.php index 403454d..c4fec44 100644 --- a/inc/class-widget-users.php +++ b/inc/class-widget-users.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Includes - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-admin-bar.php b/inc/functions-admin-bar.php index f0769b7..2e3b7a3 100644 --- a/inc/functions-admin-bar.php +++ b/inc/functions-admin-bar.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Includes - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-capabilities.php b/inc/functions-capabilities.php index c4f3657..9dd3bb6 100644 --- a/inc/functions-capabilities.php +++ b/inc/functions-capabilities.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Includes - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-deprecated.php b/inc/functions-deprecated.php index 4b6f44c..6865e8c 100644 --- a/inc/functions-deprecated.php +++ b/inc/functions-deprecated.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Includes - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-options.php b/inc/functions-options.php index 547168b..3a59207 100644 --- a/inc/functions-options.php +++ b/inc/functions-options.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Includes - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-private-site.php b/inc/functions-private-site.php index 003b8ef..9739ad1 100644 --- a/inc/functions-private-site.php +++ b/inc/functions-private-site.php @@ -6,8 +6,8 @@ * * @package Members * @subpackage Includes - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-roles.php b/inc/functions-roles.php index 1b525af..cf5baee 100644 --- a/inc/functions-roles.php +++ b/inc/functions-roles.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Includes - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-shortcodes.php b/inc/functions-shortcodes.php index ba6d3f1..9275e8a 100644 --- a/inc/functions-shortcodes.php +++ b/inc/functions-shortcodes.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Includes - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-users.php b/inc/functions-users.php index fe255df..01e67ef 100644 --- a/inc/functions-users.php +++ b/inc/functions-users.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Includes - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-widgets.php b/inc/functions-widgets.php index 9cf0625..3dbf3f1 100644 --- a/inc/functions-widgets.php +++ b/inc/functions-widgets.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Includes - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions.php b/inc/functions.php index 59847bf..1c161ba 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Includes - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/template.php b/inc/template.php index b118eda..59cb271 100644 --- a/inc/template.php +++ b/inc/template.php @@ -4,8 +4,8 @@ * * @package Members * @subpackage Includes - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/members.php b/members.php index 71d7e53..111cc9f 100644 --- a/members.php +++ b/members.php @@ -26,8 +26,8 @@ * * @package Members * @version 1.2.0 - * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2016, Justin Tadlock + * @author Justin Tadlock + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ From 6179f2fa8a7d8eb2525ebf08cacf296cb2b93022 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 26 Jun 2017 14:52:00 -0500 Subject: [PATCH 029/157] Version bump to 2.0.0-dev. --- admin/class-meta-box-content-permissions.php | 2 +- admin/class-role-group.php | 16 +++---- admin/class-settings.php | 22 +++++----- admin/functions-cap-groups.php | 10 ++--- admin/functions-role-groups.php | 2 +- admin/functions-settings.php | 12 ++--- admin/views/class-settings-view-add-ons.php | 8 ++-- admin/views/class-settings-view-general.php | 46 ++++++++++---------- admin/views/class-settings-view.php | 24 +++++----- inc/class-capability.php | 12 ++--- inc/class-registry.php | 24 +++++----- inc/class-role.php | 24 +++++----- inc/functions-capabilities.php | 16 +++---- inc/functions-deprecated.php | 30 ++++++------- inc/functions-options.php | 4 +- inc/functions-private-site.php | 2 +- inc/functions-roles.php | 26 +++++------ inc/functions.php | 2 +- members.php | 4 +- 19 files changed, 143 insertions(+), 143 deletions(-) diff --git a/admin/class-meta-box-content-permissions.php b/admin/class-meta-box-content-permissions.php index 07fa3a0..3a1b12e 100644 --- a/admin/class-meta-box-content-permissions.php +++ b/admin/class-meta-box-content-permissions.php @@ -106,7 +106,7 @@ public function add_meta_boxes( $post_type ) { /** * Checks if Content Permissions should appear for the given post type. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return bool */ diff --git a/admin/class-role-group.php b/admin/class-role-group.php index cbf8b6c..bb598a7 100644 --- a/admin/class-role-group.php +++ b/admin/class-role-group.php @@ -15,7 +15,7 @@ /** * Role group object class. * - * @since 1.2.0 + * @since 2.0.0 * @access public */ final class Role_Group { @@ -23,7 +23,7 @@ final class Role_Group { /** * Name/ID for the group. * - * @since 1.2.0 + * @since 2.0.0 * @access protected * @var string */ @@ -32,7 +32,7 @@ final class Role_Group { /** * Internationalized text label for the group. * - * @since 1.2.0 + * @since 2.0.0 * @access protected * @var string */ @@ -42,7 +42,7 @@ final class Role_Group { * Internationalized text label for the group + the count in the form of * `_n_noop( 'Singular Name %s', 'Pluran Name %s', $textdomain )` * - * @since 1.2.0 + * @since 2.0.0 * @access protected * @var string */ @@ -51,7 +51,7 @@ final class Role_Group { /** * Array of roles that belong to the group. * - * @since 1.2.0 + * @since 2.0.0 * @access protected * @var array */ @@ -60,7 +60,7 @@ final class Role_Group { /** * Whether to create a view for the group on the Manage Roles screen. * - * @since 1.2.0 + * @since 2.0.0 * @access protected * @var bool */ @@ -70,7 +70,7 @@ final class Role_Group { * Magic method to use in case someone tries to output the object as a string. * We'll just return the name. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return string */ @@ -81,7 +81,7 @@ public function __toString() { /** * Register a new object. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @param array $args diff --git a/admin/class-settings.php b/admin/class-settings.php index 801d410..4f5c6a9 100644 --- a/admin/class-settings.php +++ b/admin/class-settings.php @@ -30,7 +30,7 @@ final class Members_Settings_Page { /** * Holds an array the settings page views. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @var array */ @@ -68,7 +68,7 @@ private function __construct() {} /** * Loads settings files. * - * @since 1.2.0 + * @since 2.0.0 * @access private * @return void */ @@ -86,7 +86,7 @@ private function includes() { /** * Sets up initial actions. * - * @since 1.2.0 + * @since 2.0.0 * @access private * @return void */ @@ -98,7 +98,7 @@ private function setup_actions() { /** * Register a view. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param object $view * @return void @@ -112,7 +112,7 @@ public function register_view( $view ) { /** * Unregister a view. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @return void @@ -126,7 +126,7 @@ public function unregister_view( $name ) { /** * Get a view object * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @return object @@ -139,7 +139,7 @@ public function get_view( $name ) { /** * Check if a view exists. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @return bool @@ -187,7 +187,7 @@ public function admin_menu() { /** * Runs on page load. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -206,7 +206,7 @@ public function load() { /** * Print styles to the header. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -273,7 +273,7 @@ public function settings_page() { ?> /** * Outputs the list of views. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -305,7 +305,7 @@ private function filter_links() { ?> * Adds help tabs. * * @since 1.0.0 - * @deprecated 1.2.0 + * @deprecated 2.0.0 * @access public * @return void */ diff --git a/admin/functions-cap-groups.php b/admin/functions-cap-groups.php index 52bd4e6..749116f 100644 --- a/admin/functions-cap-groups.php +++ b/admin/functions-cap-groups.php @@ -16,7 +16,7 @@ /** * Returns the instance of cap group registry. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return object */ @@ -334,7 +334,7 @@ function members_get_custom_group_caps() { * Returns the caps for the general capability group. * * @since 1.0.0 - * @deprecated 1.2.0 + * @deprecated 2.0.0 * @access public * @return array */ @@ -347,7 +347,7 @@ function members_get_general_group_caps() { * Returns the caps for the theme capability group. * * @since 1.0.0 - * @deprecated 1.2.0 + * @deprecated 2.0.0 * @access public * @return array */ @@ -360,7 +360,7 @@ function members_get_theme_group_caps() { * Returns the caps for the plugin capability group. * * @since 1.0.0 - * @deprecated 1.2.0 + * @deprecated 2.0.0 * @access public * @return array */ @@ -373,7 +373,7 @@ function members_get_plugin_group_caps() { * Returns the caps for the user capability group. * * @since 1.0.0 - * @deprecated 1.2.0 + * @deprecated 2.0.0 * @access public * @return array */ diff --git a/admin/functions-role-groups.php b/admin/functions-role-groups.php index 7cb93ab..03abc72 100644 --- a/admin/functions-role-groups.php +++ b/admin/functions-role-groups.php @@ -16,7 +16,7 @@ /** * Returns the instance of the role group registry. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return object */ diff --git a/admin/functions-settings.php b/admin/functions-settings.php index fb38101..d3d0ff5 100644 --- a/admin/functions-settings.php +++ b/admin/functions-settings.php @@ -16,7 +16,7 @@ /** * Registers the plugin's built-in settings views. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param object $manager * @return void @@ -49,7 +49,7 @@ function members_register_default_settings_views( $manager ) { /** * Conditional function to check if on the plugin's settings page. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return bool */ @@ -63,7 +63,7 @@ function members_is_settings_page() { /** * Returns the URL to the settings page. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return string */ @@ -75,7 +75,7 @@ function members_get_settings_page_url() { /** * Returns the URL to a settings view page. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $view * @return string @@ -88,7 +88,7 @@ function members_get_settings_view_url( $view ) { /** * Returns the current settings view name. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return string */ @@ -103,7 +103,7 @@ function members_get_current_settings_view() { /** * Conditional function to check if on a specific settings view page. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $view * @return bool diff --git a/admin/views/class-settings-view-add-ons.php b/admin/views/class-settings-view-add-ons.php index fe8f268..d91bebd 100644 --- a/admin/views/class-settings-view-add-ons.php +++ b/admin/views/class-settings-view-add-ons.php @@ -13,7 +13,7 @@ /** * Sets up and handles the add-ons settings view. * - * @since 1.2.0 + * @since 2.0.0 * @access public */ class Members_Settings_View_Add_Ons extends Members_Settings_View { @@ -21,7 +21,7 @@ class Members_Settings_View_Add_Ons extends Members_Settings_View { /** * Renders the settings page. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -79,7 +79,7 @@ public function template() { ?> /** * Adds help tabs. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -105,7 +105,7 @@ public function add_help_tabs() { * Returns a list of add-ons for the Members plugin. This function is temporary until * we can get a proper API set up on Theme Hybrid to allow this data to be sent over. * - * @since 1.2.0 + * @since 2.0.0 * @access private * @return array */ diff --git a/admin/views/class-settings-view-general.php b/admin/views/class-settings-view-general.php index c413904..fe7f80c 100644 --- a/admin/views/class-settings-view-general.php +++ b/admin/views/class-settings-view-general.php @@ -13,7 +13,7 @@ /** * Sets up and handles the general settings view. * - * @since 1.2.0 + * @since 2.0.0 * @access public */ class Members_Settings_View_General extends Members_Settings_View { @@ -21,7 +21,7 @@ class Members_Settings_View_General extends Members_Settings_View { /** * Holds an array the plugin settings. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @var array */ @@ -30,7 +30,7 @@ class Members_Settings_View_General extends Members_Settings_View { /** * Enqueue scripts/styles. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -42,7 +42,7 @@ public function enqueue() { /** * Registers the plugin settings. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -87,7 +87,7 @@ function register_settings() { /** * Validates the plugin settings. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param array $input * @return array @@ -115,7 +115,7 @@ function validate_settings( $settings ) { /** * Role/Caps section callback. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -129,7 +129,7 @@ public function section_roles_caps() { ?> /** * Role manager field callback. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -144,7 +144,7 @@ public function field_enable_role_manager() { ?> /** * Explicit denied caps field callback. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -172,7 +172,7 @@ public function field_explicit_denied_caps() { ?> /** * Multiple roles field callback. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -187,7 +187,7 @@ public function field_enable_multi_roles() { ?> /** * Enable content permissions field callback. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -202,7 +202,7 @@ public function field_enable_content_permissions() { ?> /** * Enable content permissions field callback. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -213,7 +213,7 @@ public function field_show_human_caps() { ?> /** * Content permissions error message field callback. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -233,7 +233,7 @@ public function field_content_permissions_error() { /** * Login widget field callback. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -248,7 +248,7 @@ public function field_widget_login() { ?> /** * Uers widget field callback. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -263,7 +263,7 @@ public function field_widget_users() { ?> /** * Enable private site field callback. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -278,7 +278,7 @@ public function field_enable_private_site() { ?> /** * Enable private feed field callback. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -293,7 +293,7 @@ public function field_enable_private_feed() { ?> /** * Private feed error message field callback. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -313,7 +313,7 @@ public function field_private_feed_error() { /** * Renders the settings page. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -330,7 +330,7 @@ public function template() { ?> /** * Adds help tabs. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -387,7 +387,7 @@ public function add_help_tabs() { /** * Displays the roles/caps help tab. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -409,7 +409,7 @@ public function help_tab_roles_caps() { ?> /** * Displays the content permissions help tab. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -423,7 +423,7 @@ public function help_tab_content_permissions() { ?> /** * Displays the sidebar widgets help tab. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -437,7 +437,7 @@ public function help_tab_sidebar_widgets() { ?> /** * Displays the private site help tab. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ diff --git a/admin/views/class-settings-view.php b/admin/views/class-settings-view.php index b59640a..442763f 100644 --- a/admin/views/class-settings-view.php +++ b/admin/views/class-settings-view.php @@ -13,7 +13,7 @@ /** * Settings view base class. * - * @since 1.2.0 + * @since 2.0.0 * @access public */ class Members_Settings_View { @@ -21,7 +21,7 @@ class Members_Settings_View { /** * Name/ID for the group. * - * @since 1.2.0 + * @since 2.0.0 * @access protected * @var string */ @@ -30,7 +30,7 @@ class Members_Settings_View { /** * Internationalized text label for the group. * - * @since 1.2.0 + * @since 2.0.0 * @access protected * @var string */ @@ -39,7 +39,7 @@ class Members_Settings_View { /** * Priority (order) the control should be output. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @var int */ @@ -48,7 +48,7 @@ class Members_Settings_View { /** * A user role capability required to show the control. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @var string|array */ @@ -58,7 +58,7 @@ class Members_Settings_View { * Magic method to use in case someone tries to output the object as a string. * We'll just return the name. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return string */ @@ -69,7 +69,7 @@ public function __toString() { /** * Register a new object. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @param array $args { @@ -93,7 +93,7 @@ public function __construct( $name, $args = array() ) { /** * Enqueue scripts/styles for the control. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -102,7 +102,7 @@ public function enqueue() {} /** * Register settings for the view. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -111,7 +111,7 @@ public function register_settings() {} /** * Add help tabs for the view. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -120,7 +120,7 @@ public function add_help_tabs() {} /** * Output the content for the view. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -129,7 +129,7 @@ public function template() {} /** * Checks if the control should be allowed at all. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return bool */ diff --git a/inc/class-capability.php b/inc/class-capability.php index ab11ed0..3125ffd 100644 --- a/inc/class-capability.php +++ b/inc/class-capability.php @@ -15,7 +15,7 @@ /** * Capability class. * - * @since 1.2.0 + * @since 2.0.0 * @access public */ class Capability { @@ -23,7 +23,7 @@ class Capability { /** * The capability name. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @var string */ @@ -32,7 +32,7 @@ class Capability { /** * The capability label. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @var string */ @@ -42,7 +42,7 @@ class Capability { * The group the capability belongs to. * * @see Members_Cap_Group - * @since 1.2.0 + * @since 2.0.0 * @access public * @var string */ @@ -51,7 +51,7 @@ class Capability { /** * Return the role string in attempts to use the object as a string. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return string */ @@ -62,7 +62,7 @@ public function __toString() { /** * Creates a new role object. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @global object $wp_roles * @param string $role diff --git a/inc/class-registry.php b/inc/class-registry.php index 269864e..99b047d 100644 --- a/inc/class-registry.php +++ b/inc/class-registry.php @@ -15,7 +15,7 @@ /** * Base registry class. * - * @since 1.2.0 + * @since 2.0.0 * @access public */ class Registry { @@ -23,7 +23,7 @@ class Registry { /** * Registry instances. * - * @since 1.2.0 + * @since 2.0.0 * @access private * @var array */ @@ -32,7 +32,7 @@ class Registry { /** * Array of objects in the collection. * - * @since 1.2.0 + * @since 2.0.0 * @access protected * @var array */ @@ -41,7 +41,7 @@ class Registry { /** * Constructor method. * - * @since 1.2.0 + * @since 2.0.0 * @access protected * @return void */ @@ -50,7 +50,7 @@ protected function __construct() {} /** * Lock down `__clone()`. * - * @since 1.2.0 + * @since 2.0.0 * @access private * @return void */ @@ -59,7 +59,7 @@ private function __clone() {} /** * Lock down `__wakeup()`. * - * @since 1.2.0 + * @since 2.0.0 * @access private * @return void */ @@ -68,7 +68,7 @@ private function __wakeup() {} /** * Register a new cap object * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @param object $value @@ -83,7 +83,7 @@ public function register( string $name, $value ) { /** * Unregisters a cap object. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @return void @@ -97,7 +97,7 @@ public function unregister( string $name ) { /** * Checks if a cap exists. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @return bool @@ -110,7 +110,7 @@ public function exists( string $name ) { /** * Gets a cap object. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @return object|bool @@ -123,7 +123,7 @@ public function get( string $name ) { /** * Returns the entire collection. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return array */ @@ -135,7 +135,7 @@ public function get_collection() { /** * Returns the instance. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return object */ diff --git a/inc/class-role.php b/inc/class-role.php index d084e02..42c31a5 100644 --- a/inc/class-role.php +++ b/inc/class-role.php @@ -16,7 +16,7 @@ /** * Role class. * - * @since 1.2.0 + * @since 2.0.0 * @access public */ class Role { @@ -24,7 +24,7 @@ class Role { /** * The role name. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @var string */ @@ -33,7 +33,7 @@ class Role { /** * The role label. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @var string */ @@ -43,7 +43,7 @@ class Role { * The group the role belongs to. * * @see Members\Role_Group - * @since 1.2.0 + * @since 2.0.0 * @access public * @var string */ @@ -52,7 +52,7 @@ class Role { /** * Whether the role has caps (granted). * - * @since 1.2.0 + * @since 2.0.0 * @access public * @var bool */ @@ -61,7 +61,7 @@ class Role { /** * Capability count for the role. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @var int */ @@ -70,7 +70,7 @@ class Role { /** * Capability count for the role. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @var int */ @@ -79,7 +79,7 @@ class Role { /** * Array of capabilities that the role has. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @var array */ @@ -88,7 +88,7 @@ class Role { /** * Array of granted capabilities that the role has. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @var array */ @@ -97,7 +97,7 @@ class Role { /** * Array of denied capabilities that the role has. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @var array */ @@ -106,7 +106,7 @@ class Role { /** * Return the role string in attempts to use the object as a string. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return string */ @@ -117,7 +117,7 @@ public function __toString() { /** * Creates a new role object. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $role * @param array $args diff --git a/inc/functions-capabilities.php b/inc/functions-capabilities.php index 9dd3bb6..d281cf3 100644 --- a/inc/functions-capabilities.php +++ b/inc/functions-capabilities.php @@ -21,7 +21,7 @@ /** * Fires the action hook for registering capabilities. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -34,7 +34,7 @@ function members_register_caps() { * Registers all of our default caps. In particular, the plugin registers its own caps plus core * WP's caps. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -131,7 +131,7 @@ function members_register_default_caps() { /** * Returns the instance of the capability registry. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return object */ @@ -143,7 +143,7 @@ function members_capability_registry() { /** * Returns all registered caps. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return array */ @@ -155,7 +155,7 @@ function members_get_caps() { /** * Registers a capability. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @param array $args @@ -169,7 +169,7 @@ function members_register_cap( $name, $args = array() ) { /** * Unregisters a capability. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @return void @@ -182,7 +182,7 @@ function members_unregister_cap( $name ) { /** * Returns a capability object. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @return object @@ -195,7 +195,7 @@ function members_get_cap( $name ) { /** * Checks if a capability object exists. * - * @note In 1.2.0, the function was changed to only check from registered caps. + * @note In 2.0.0, the function was changed to only check from registered caps. * * @since 1.0.0 * @access public diff --git a/inc/functions-deprecated.php b/inc/functions-deprecated.php index 6865e8c..9e93e71 100644 --- a/inc/functions-deprecated.php +++ b/inc/functions-deprecated.php @@ -18,7 +18,7 @@ * @return array */ function members_get_role_names() { - _deprecated_function( __FUNCTION__, '1.2.0', '' ); + _deprecated_function( __FUNCTION__, '2.0.0', '' ); $roles = array(); @@ -36,7 +36,7 @@ function members_get_role_names() { * @return array */ function members_get_active_role_names() { - _deprecated_function( __FUNCTION__, '1.2.0', '' ); + _deprecated_function( __FUNCTION__, '2.0.0', '' ); $has_users = array(); @@ -54,7 +54,7 @@ function members_get_active_role_names() { * @return array */ function members_get_inactive_role_names() { - _deprecated_function( __FUNCTION__, '1.2.0', '' ); + _deprecated_function( __FUNCTION__, '2.0.0', '' ); return array_diff( members_get_role_names(), members_get_active_role_names() ); } @@ -67,7 +67,7 @@ function members_get_inactive_role_names() { * @return array */ function members_get_editable_role_names() { - _deprecated_function( __FUNCTION__, '1.2.0', '' ); + _deprecated_function( __FUNCTION__, '2.0.0', '' ); $editable = array(); @@ -85,7 +85,7 @@ function members_get_editable_role_names() { * @return array */ function members_get_editable_role_slugs() { - _deprecated_function( __FUNCTION__, '1.2.0', '' ); + _deprecated_function( __FUNCTION__, '2.0.0', '' ); return array_keys( members_role_registry()->editable ); } @@ -98,7 +98,7 @@ function members_get_editable_role_slugs() { * @return array */ function members_get_uneditable_role_names() { - _deprecated_function( __FUNCTION__, '1.2.0', '' ); + _deprecated_function( __FUNCTION__, '2.0.0', '' ); $uneditable = array(); @@ -116,7 +116,7 @@ function members_get_uneditable_role_names() { * @return array */ function members_get_uneditable_role_slugs() { - _deprecated_function( __FUNCTION__, '1.2.0', '' ); + _deprecated_function( __FUNCTION__, '2.0.0', '' ); return array_keys( members_role_registry()->uneditable ); } @@ -129,7 +129,7 @@ function members_get_uneditable_role_slugs() { * @return array */ function members_get_wordpress_role_names() { - _deprecated_function( __FUNCTION__, '1.2.0', '' ); + _deprecated_function( __FUNCTION__, '2.0.0', '' ); $names = array(); @@ -147,7 +147,7 @@ function members_get_wordpress_role_names() { * @return array */ function members_get_wordpress_role_slugs() { - _deprecated_function( __FUNCTION__, '1.2.0', '' ); + _deprecated_function( __FUNCTION__, '2.0.0', '' ); return array_keys( members_role_registry()->wordpress ); } @@ -161,7 +161,7 @@ function members_get_wordpress_role_slugs() { * @return string */ function members_get_role_name( $role ) { - _deprecated_function( __FUNCTION__, '1.2.0', '' ); + _deprecated_function( __FUNCTION__, '2.0.0', '' ); return members_role_registry()->get( $role )->name; } @@ -174,7 +174,7 @@ function members_get_role_name( $role ) { * @return array */ function members_get_role_slugs() { - _deprecated_function( __FUNCTION__, '1.2.0', '' ); + _deprecated_function( __FUNCTION__, '2.0.0', '' ); return array_keys( members_get_roles() ); } @@ -187,7 +187,7 @@ function members_get_role_slugs() { * @return array */ function members_get_active_role_slugs() { - _deprecated_function( __FUNCTION__, '1.2.0', '' ); + _deprecated_function( __FUNCTION__, '2.0.0', '' ); $has_users = array(); @@ -208,7 +208,7 @@ function members_get_active_role_slugs() { * @return array */ function members_get_inactive_role_slugs() { - _deprecated_function( __FUNCTION__, '1.2.0', '' ); + _deprecated_function( __FUNCTION__, '2.0.0', '' ); return array_diff( array_keys( members_get_roles() ), members_get_active_roles() ); } @@ -218,7 +218,7 @@ function members_get_inactive_role_slugs() { * certain features of the plugin. * * @since 1.0.0 - * @deprecated 1.2.0 + * @deprecated 2.0.0 * @access public * @return array */ @@ -245,7 +245,7 @@ function members_get_plugin_capabilities() { * * @link http://codex.wordpress.org/Roles_and_Capabilities#Capabilities * @since 1.0.0 - * @deprecated 1.2.0 + * @deprecated 2.0.0 * @access public * @return array */ diff --git a/inc/functions-options.php b/inc/functions-options.php index 3a59207..79290c8 100644 --- a/inc/functions-options.php +++ b/inc/functions-options.php @@ -36,7 +36,7 @@ function members_explicitly_deny_caps() { /** * Whether to show human-readable caps. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return bool */ @@ -131,7 +131,7 @@ function members_get_default_settings() { 'explicit_denied_caps' => true, 'multi_roles' => true, - // @since 1.2.0 + // @since 2.0.0 'show_human_caps' => true, ); } diff --git a/inc/functions-private-site.php b/inc/functions-private-site.php index 9739ad1..9af98d4 100644 --- a/inc/functions-private-site.php +++ b/inc/functions-private-site.php @@ -73,7 +73,7 @@ function members_please_log_in() { * Function for determining whether a page should be public even though we're in private * site mode. Plugin devs can filter this to make specific pages public. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return bool */ diff --git a/inc/functions-roles.php b/inc/functions-roles.php index cf5baee..9c37880 100644 --- a/inc/functions-roles.php +++ b/inc/functions-roles.php @@ -17,7 +17,7 @@ /** * Fires the role registration action hook. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -29,7 +29,7 @@ function members_register_roles() { /** * Registers any roles stored globally with WordPress. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return void */ @@ -49,7 +49,7 @@ function members_register_default_roles() { /** * Returns the instance of the role registry. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return object */ @@ -61,7 +61,7 @@ function members_role_registry() { /** * Returns all registered roles. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return array */ @@ -73,7 +73,7 @@ function members_get_roles() { /** * Registers a role. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @param array $args @@ -87,7 +87,7 @@ function members_register_role( $name, $args = array() ) { /** * Unregisters a role. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @return void @@ -100,7 +100,7 @@ function members_unregister_role( $name ) { /** * Returns a role object. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @return object @@ -113,7 +113,7 @@ function members_get_role( $name ) { /** * Checks if a role object exists. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @param string $name * @return bool @@ -128,7 +128,7 @@ function members_role_exists( $name ) { /** * Returns an array of editable roles. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @global array $wp_roles * @return array @@ -144,7 +144,7 @@ function members_get_editable_roles() { /** * Returns an array of uneditable roles. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return array */ @@ -156,7 +156,7 @@ function members_get_uneditable_roles() { /** * Returns an array of core WP roles. Note that we remove any that are not registered. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return array */ @@ -170,7 +170,7 @@ function members_get_wordpress_roles() { /** * Returns an array of the roles that have users. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return array */ @@ -190,7 +190,7 @@ function members_get_active_roles() { /** * Returns an array of the roles that have no users. * - * @since 1.2.0 + * @since 2.0.0 * @access public * @return array */ diff --git a/inc/functions.php b/inc/functions.php index 1c161ba..cb42d5c 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -27,7 +27,7 @@ function members_validate_boolean( $val ) { /** * Helper function for sorting objects by priority. * - * @since 1.2.0 + * @since 2.0.0 * @access protected * @param object $a * @param object $b diff --git a/members.php b/members.php index 111cc9f..f41680f 100644 --- a/members.php +++ b/members.php @@ -3,7 +3,7 @@ * Plugin Name: Members * Plugin URI: http://themehybrid.com/plugins/members * Description: A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private. - * Version: 1.2.0-dev + * Version: 2.0.0-dev * Author: Justin Tadlock * Author URI: http://themehybrid.com * Text Domain: members @@ -25,7 +25,7 @@ * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * @package Members - * @version 1.2.0 + * @version 2.0.0 * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link http://themehybrid.com/plugins/members From edc4c8bd150f437c5acd4fe86942ac113c5231b1 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 26 Jun 2017 15:39:27 -0500 Subject: [PATCH 030/157] Improve some escaping and sanitizing based on https://github.com/justintadlock/members/pull/109. --- admin/class-meta-box-content-permissions.php | 4 ++-- inc/class-widget-login.php | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/admin/class-meta-box-content-permissions.php b/admin/class-meta-box-content-permissions.php index 3a1b12e..0e57e28 100644 --- a/admin/class-meta-box-content-permissions.php +++ b/admin/class-meta-box-content-permissions.php @@ -173,7 +173,7 @@ public function meta_box( $post ) {

    - +

    @@ -271,12 +271,12 @@ function form( $instance ) {

    - +

    - +

    From ad1f8775d6cae86d0e3deec47b2a7056e27134ea Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 26 Jun 2017 15:54:36 -0500 Subject: [PATCH 031/157] Move the post type "public" check and attachment check into the `maybe_enable()` method for the content permissions meta box. This allows developers full control over whether the meta box shows. Fixes: https://github.com/justintadlock/members/issues/120 --- admin/class-meta-box-content-permissions.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/admin/class-meta-box-content-permissions.php b/admin/class-meta-box-content-permissions.php index 0e57e28..987cef6 100644 --- a/admin/class-meta-box-content-permissions.php +++ b/admin/class-meta-box-content-permissions.php @@ -94,13 +94,8 @@ public function add_meta_boxes( $post_type ) { if ( ! current_user_can( 'restrict_content' ) ) return; - // Get the post type object. - $type = get_post_type_object( $post_type ); - - // If this is a public post type, add the meta box. - // Note that we're disabling for attachments b/c users get confused between "content" and "file". - if ( 'attachment' !== $type->name && $type->public ) - add_meta_box( 'members-cp', esc_html__( 'Content Permissions', 'members' ), array( $this, 'meta_box' ), $post_type, 'advanced', 'high' ); + // Add the meta box. + add_meta_box( 'members-cp', esc_html__( 'Content Permissions', 'members' ), array( $this, 'meta_box' ), $post_type, 'advanced', 'high' ); } /** @@ -112,9 +107,13 @@ public function add_meta_boxes( $post_type ) { */ public function maybe_enable() { - $post_type = get_current_screen()->post_type; + // Get the post type object. + $type = get_post_type_object( get_current_screen()->post_type ); + + // Only enable for public post types and non-attachments by default. + $enable = 'attachment' !== $type->name && $type->public; - return apply_filters( "members_enable_{$post_type}_content_permissions", true ); + return apply_filters( "members_enable_{$type->name}_content_permissions", $enable ); } /** From 3c90dcd255869b4ebfe534b04e2b71715697cddf Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 26 Jun 2017 16:02:17 -0500 Subject: [PATCH 032/157] Change the text in the content permissions meta box to use "content" rather than "post" so that it's a bit more post type agnostic. Fixes https://github.com/justintadlock/members/issues/96 --- admin/class-meta-box-content-permissions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/class-meta-box-content-permissions.php b/admin/class-meta-box-content-permissions.php index 987cef6..b409c5a 100644 --- a/admin/class-meta-box-content-permissions.php +++ b/admin/class-meta-box-content-permissions.php @@ -146,7 +146,7 @@ public function meta_box( $post ) { do_action( 'members_cp_meta_box_before', $post ); ?>

    - +

    @@ -166,7 +166,7 @@ public function meta_box( $post ) {

    - restrict_content' ); ?> + restrict_content' ); ?>

    From 60b43976a315bd376b76f05999dca89bde6186f2 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 26 Jun 2017 16:18:30 -0500 Subject: [PATCH 033/157] Use the `$old_user_data` parameter (user object) to update the user roles on the edit user screen. This fixes and issue where the `remove_user_role` action hook never fires. Fixes: https://github.com/justintadlock/members/issues/129 --- admin/class-user-edit.php | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/admin/class-user-edit.php b/admin/class-user-edit.php index 37defe1..6e250a7 100644 --- a/admin/class-user-edit.php +++ b/admin/class-user-edit.php @@ -59,7 +59,7 @@ public function load_user_edit() { add_action( 'edit_user_profile', array( $this, 'profile_fields' ) ); // Must use `profile_update` to change role. Otherwise, WP will wipe it out. - add_action( 'profile_update', array( $this, 'role_update' ) ); + add_action( 'profile_update', array( $this, 'role_update' ), 10, 2 ); } /** @@ -122,9 +122,10 @@ public function profile_fields( $user ) { * @since 1.0.0 * @access public * @param int $user_id + * @param object $old_user_data * @return void */ - public function role_update( $user_id ) { + public function role_update( $user_id, $old_user_data ) { // If the current user can't promote users or edit this particular user, bail. if ( ! current_user_can( 'promote_users' ) || ! current_user_can( 'edit_user', $user_id ) ) @@ -135,13 +136,13 @@ public function role_update( $user_id ) { return; // Create a new user object. - $user = new WP_User( $user_id ); + //$user = new WP_User( $user_id ); // If we have an array of roles. if ( ! empty( $_POST['members_user_roles'] ) ) { // Get the current user roles. - $old_roles = (array) $user->roles; + $old_roles = (array) $old_user_data->roles; // Sanitize the posted roles. $new_roles = array_map( 'members_sanitize_role', $_POST['members_user_roles'] ); @@ -150,8 +151,8 @@ public function role_update( $user_id ) { foreach ( $new_roles as $new_role ) { // If the user doesn't already have the role, add it. - if ( members_is_role_editable( $new_role ) && ! in_array( $new_role, (array) $user->roles ) ) - $user->add_role( $new_role ); + if ( members_is_role_editable( $new_role ) && ! in_array( $new_role, (array) $old_user_data->roles ) ) + $old_user_data->add_role( $new_role ); } // Loop through the current user roles. @@ -159,7 +160,7 @@ public function role_update( $user_id ) { // If the role is editable and not in the new roles array, remove it. if ( members_is_role_editable( $old_role ) && ! in_array( $old_role, $new_roles ) ) - $user->remove_role( $old_role ); + $old_user_data->remove_role( $old_role ); } // If the posted roles are empty. @@ -170,7 +171,7 @@ public function role_update( $user_id ) { // Remove the role if it is editable. if ( members_is_role_editable( $old_role ) ) - $user->remove_role( $old_role ); + $old_user_data->remove_role( $old_role ); } } } From 9c1875931a4b1da76c60b4138d025dc292fa6315 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 26 Jun 2017 16:19:30 -0500 Subject: [PATCH 034/157] Correct year in change log. Fixes: https://github.com/justintadlock/members/issues/125 --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index f33cb55..bd74e09 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,6 @@ # Change Log -## [1.1.3] - 2016-02-06 +## [1.1.3] - 2017-02-06 ### Fixed From 4fbd1acad16aabae079be92d114ed9305c05714f Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 27 Jun 2017 16:27:21 -0500 Subject: [PATCH 035/157] First pass at a new manage users class. This commit's primary purpose is to introduce the ability to handle adding/removing roles from users in bulk. By default, core WP has a "change role to" option on the manage users screen. However, using it means that it will literally change the users' roles to that one role, wiping out all other roles for users with multiple. This change removes the core "change role to" select and replaces it with both a "add role" and "remove role" select when the multiple roles per user option is enabled. This makes for much easier bulk management of multi-roles. Fixes: https://github.com/justintadlock/members/issues/103 --- admin/class-manage-users.php | 378 +++++++++++++++++++++++++++++++++++ members.php | 5 +- 2 files changed, 381 insertions(+), 2 deletions(-) create mode 100644 admin/class-manage-users.php diff --git a/admin/class-manage-users.php b/admin/class-manage-users.php new file mode 100644 index 0000000..9e66ed0 --- /dev/null +++ b/admin/class-manage-users.php @@ -0,0 +1,378 @@ + + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @link http://themehybrid.com/plugins/members + * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + */ + +namespace Members\Admin; + +/** + * Manager users screen class. + * + * @since 2.0.0 + * @access public + */ +final class Manage_Users { + + /** + * Holds the instances of this class. + * + * @since 2.0.0 + * @access private + * @var object + */ + private static $instance = null; + + /** + * Custom admin notices. + * + * @since 2.0.0 + * @access public + * @var array + */ + public $notices = array(); + + /** + * Constructore method. + * + * @since 2.0.0 + * @access private + * @return void + */ + private function __construct() {} + + /** + * Sets up needed actions/filters. + * + * @since 2.0.0 + * @access private + * @return void + */ + private function setup_actions() { + + // If multiple roles per user is not enabled, bail. + if ( ! members_multiple_user_roles_enabled() ) + return; + + // Add our primary actions to the load hook. + add_action( 'load-users.php', array( $this, 'load' ) ); + add_action( 'load-users.php', array( $this, 'role_bulk_add' ) ); + add_action( 'load-users.php', array( $this, 'role_bulk_remove' ) ); + } + + /** + * Adds actions/filters on load. + * + * @since 2.0.0 + * @access public + * @return void + */ + public function load() { + + // Add custom bulk fields. + add_action( 'restrict_manage_users', array( $this, 'bulk_fields' ), 5 ); + + // Print custom styles. + add_action( 'admin_head', array( $this, 'print_styles' ) ); + + // If there was an update, add notices if they're from our plugin. + if ( isset( $_GET['update'] ) ) { + + $action = sanitize_key( $_GET['update'] ); + + // If a role was added. + if ( 'members-role-added' === $action ) { + + $this->notices['role_added'] = array( 'message' => esc_html__( 'Role added to selected users.', 'members' ), 'type' => 'success' ); + + // If a role was removed. + } elseif ( 'members-role-removed' === $action ) { + + $this->notices['role_removed'] = array( 'message' => esc_html__( 'Role removed from selected users.', 'members' ), 'type' => 'success' ); + + } elseif ( 'members-error-remove-admin' === $action ) { + + $this->notices['error_remove_admin'] = array( 'message' => esc_html__( 'The current user’s role must have user editing capabilities.', 'members' ), 'type' => 'error' ); + $this->notices['role_removed'] = array( 'message' => esc_html__( 'Role removed from other selected users.', 'members' ), 'type' => 'success' ); + } + + // If we have notices, hook them in. + if ( $this->notices ) + add_action( 'admin_notices', array( $this, 'notices' ) ); + } + } + + /** + * Adds a single role to users in bulk. + * + * @since 2.0.0 + * @access public + * @return void + */ + public function role_bulk_add() { + + // Bail if we ain't got users. + if ( empty( $_REQUEST['users'] ) ) + return; + + // Figure out if we have a role selected. + if ( ! empty( $_REQUEST['members-add-role-top'] ) && ! empty( $_REQUEST['members-add-role-submit-top'] ) ) + $role = members_sanitize_role( $_REQUEST['members-add-role-top'] ); + + elseif ( ! empty( $_REQUEST['members-add-role-bottom'] ) && ! empty( $_REQUEST['members-add-role-submit-bottom'] ) ) + $role = members_sanitize_role( $_REQUEST['members-add-role-bottom'] ); + + // Get only editable roles. + $editable_roles = members_get_editable_roles(); + + // If we don't have a role or the role is not editable, bail. + if ( empty( $role ) || ! in_array( $role, $editable_roles ) ) + return; + + // Validate our nonce. + check_admin_referer( 'members-bulk-users', 'members-bulk-users-nonce' ); + + // If the current user cannot promote users, bail. + if ( ! current_user_can( 'promote_users' ) ) + return; + + // Loop through the users and add the role if possible. + foreach ( (array) $_REQUEST['users'] as $user_id ) { + + $user_id = absint( $user_id ); + + // If the user doesn't already belong to the blog, bail. + if ( is_multisite() && ! is_user_member_of_blog( $user_id ) ) { + + wp_die( + sprintf( + '

    %s

    %s

    ', + esc_html__( 'Whoah, partner!', 'members' ), + esc_html__( 'One of the selected users is not a member of this site.', 'members' ) + ), + 403 + ); + } + + // Check that the current user can promote this specific user. + if ( ! current_user_can( 'promote_user', $user_id ) ) + continue; + + // Get the user object. + $user = new \WP_User( $user_id ); + + // If the user doesn't have the role, add it. + if ( ! in_array( $role, $user->roles ) ) + $user->add_role( $role ); + } + + // Redirect to the users screen. + wp_redirect( add_query_arg( 'update', 'members-role-added', 'users.php' ) ); + } + + /** + * Removes a single role from users in bulk. + * + * @since 2.0.0 + * @access public + * @return void + */ + public function role_bulk_remove() { + + // Bail if we ain't got users. + if ( empty( $_REQUEST['users'] ) ) + return; + + // Figure out if we have a role selected. + if ( ! empty( $_REQUEST['members-remove-role-top'] ) && ! empty( $_REQUEST['members-remove-role-submit-top'] ) ) + $role = members_sanitize_role( $_REQUEST['members-remove-role-top'] ); + + elseif ( ! empty( $_REQUEST['members-remove-role-bottom'] ) && ! empty( $_REQUEST['members-remove-role-submit-bottom'] ) ) + $role = members_sanitize_role( $_REQUEST['members-remove-role-bottom'] ); + + // Get only editable roles. + $editable_roles = members_get_editable_roles(); + + // If we don't have a role or the role is not editable, bail. + if ( empty( $role ) || ! in_array( $role, $editable_roles ) ) + return; + + // Validate our nonce. + check_admin_referer( 'members-bulk-users', 'members-bulk-users-nonce' ); + + // If the current user cannot promote users, bail. + if ( ! current_user_can( 'promote_users' ) ) + return; + + // Get the current user. + $current_user = wp_get_current_user(); + + $m_role = members_get_role( $role ); + + $update = 'members-role-removed'; + + // Loop through the users and remove the role if possible. + foreach ( (array) $_REQUEST['users'] as $user_id ) { + + $user_id = absint( $user_id ); + + // If the user doesn't already belong to the blog, bail. + if ( is_multisite() && ! is_user_member_of_blog( $user_id ) ) { + + wp_die( + sprintf( + '

    %s

    %s

    ', + esc_html__( 'Whoah, partner!', 'members' ), + esc_html__( 'One of the selected users is not a member of this site.', 'members' ) + ), + 403 + ); + } + + // Check that the current user can promote this specific user. + if ( ! current_user_can( 'promote_user', $user_id ) ) + continue; + + $is_current_user = $user_id == $current_user->ID; + $role_can_promote = in_array( 'promote_users', $m_role->granted_caps ); + $can_manage_network = is_multisite() && current_user_can( 'manage_network_users' ); + + // If the removed role has the `promote_users` cap and user is removing it from themselves. + if ( $is_current_user && $role_can_promote && ! $can_manage_network ) { + + $can_remove = false; + + // Loop through the current user's roles. + foreach ( $current_user->roles as $_r ) { + + // If the current user has another role that can promote users, it's + // safe to remove the role. Else, the current user needs to keep + // the role. + if ( $role !== $_r && in_array( 'promote_users', members_get_role( $_r )->granted_caps ) ) { + + $can_remove = true; + break; + } + } + + if ( ! $can_remove ) { + $update = 'members-error-remove-admin'; + continue; + } + } + + // Get the user object. + $user = new \WP_User( $user_id ); + + // If the user has the role, remove it. + if ( in_array( $role, $user->roles ) ) + $user->remove_role( $role ); + } + + // Redirect to the users screen. + wp_redirect( add_query_arg( 'update', $update, 'users.php' ) ); + } + + /** + * Print admin notices. + * + * @since 2.0.0 + * @access public + * @param string $which + * @return void + */ + public function notices() { + + if ( $this->notices ) : ?> + + notices as $notice ) : ?> + +
    + ' . $notice['message'] . '' ); ?> +
    + + + + + + + + + + + + + + + + + + setup_actions(); + } + + return self::$instance; + } +} + +Manage_Users::get_instance(); diff --git a/members.php b/members.php index f41680f..3f615f1 100644 --- a/members.php +++ b/members.php @@ -252,8 +252,9 @@ private function includes() { // Plugin settings. require_once( $this->admin_dir . 'class-settings.php' ); - // Edit users. - require_once( $this->admin_dir . 'class-user-edit.php' ); + // User management. + require_once( $this->admin_dir . 'class-manage-users.php' ); + require_once( $this->admin_dir . 'class-user-edit.php' ); // Edit posts. require_once( $this->admin_dir . 'class-meta-box-content-permissions.php' ); From 71cc0773dba65c0e6d509e60af5b2c3cd33a8b0e Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 27 Jun 2017 16:43:01 -0500 Subject: [PATCH 036/157] Move the users column management functionality to the manage users class. Deprecate old functionality for showing all roles in the users list table since core WP now handles this. --- admin/class-manage-users.php | 58 ++++++++++++++++++++++++++++-- admin/functions-admin.php | 68 ------------------------------------ inc/functions-deprecated.php | 4 ++- 3 files changed, 59 insertions(+), 71 deletions(-) diff --git a/admin/class-manage-users.php b/admin/class-manage-users.php index 9e66ed0..33bb732 100644 --- a/admin/class-manage-users.php +++ b/admin/class-manage-users.php @@ -78,6 +78,9 @@ public function load() { // Add custom bulk fields. add_action( 'restrict_manage_users', array( $this, 'bulk_fields' ), 5 ); + // Custom manage users columns. + add_filter( 'manage_users_columns', array( $this, 'manage_users_columns' ) ); + // Print custom styles. add_action( 'admin_head', array( $this, 'print_styles' ) ); @@ -151,7 +154,7 @@ public function role_bulk_add() { if ( is_multisite() && ! is_user_member_of_blog( $user_id ) ) { wp_die( - sprintf( + sprintf( '

    %s

    %s

    ', esc_html__( 'Whoah, partner!', 'members' ), esc_html__( 'One of the selected users is not a member of this site.', 'members' ) @@ -226,7 +229,7 @@ public function role_bulk_remove() { if ( is_multisite() && ! is_user_member_of_blog( $user_id ) ) { wp_die( - sprintf( + sprintf( '

    %s

    %s

    ', esc_html__( 'Whoah, partner!', 'members' ), esc_html__( 'One of the selected users is not a member of this site.', 'members' ) @@ -340,6 +343,57 @@ public function bulk_fields( $which ) { roles ) ) { + + foreach ( $user->roles as $role ) { + + if ( members_role_exists( $role ) ) + $user_roles[] = members_translate_role( $role ); + } + + $output = join( ', ', $user_roles ); + } + } + + return $output; + } + /** * Hides the core WP change role form fields because these are hardcoded in. * diff --git a/admin/functions-admin.php b/admin/functions-admin.php index fef68a5..add528a 100644 --- a/admin/functions-admin.php +++ b/admin/functions-admin.php @@ -14,9 +14,6 @@ add_action( 'admin_enqueue_scripts', 'members_admin_register_scripts', 0 ); add_action( 'admin_enqueue_scripts', 'members_admin_register_styles', 0 ); -# Custom manage users columns. -add_filter( 'manage_users_columns', 'members_manage_users_columns' ); -add_filter( 'manage_users_custom_column', 'members_manage_users_custom_column', 10, 3 ); /** * Get an Underscore JS template. @@ -128,68 +125,3 @@ function members_get_user_meta_keys() { return $wpdb->get_col( "SELECT meta_key FROM $wpdb->usermeta GROUP BY meta_key ORDER BY meta_key" ); } - -/** - * Adds custom columns to the `users.php` screen. - * - * @since 1.0.0 - * @access public - * @param array $columns - * @return array - */ -function members_manage_users_columns( $columns ) { - - // If multiple roles per user is not enabled, bail. - if ( ! members_multiple_user_roles_enabled() ) - return $columns; - - // Unset the core WP `role` column. - if ( isset( $columns['role'] ) ) - unset( $columns['role'] ); - - // Add our new roles column. - $columns['roles'] = esc_html__( 'Roles', 'members' ); - - // Move the core WP `posts` column to the end. - if ( isset( $columns['posts'] ) ) { - $p = $columns['posts']; - unset( $columns['posts'] ); - $columns['posts'] = $p; - } - - return $columns; -} - -/** - * Handles the output of the roles column on the `users.php` screen. - * - * @since 1.0.0 - * @access public - * @param string $output - * @param string $column - * @param int $user_id - * @return string - */ -function members_manage_users_custom_column( $output, $column, $user_id ) { - - if ( 'roles' === $column && members_multiple_user_roles_enabled() ) { - - $user = new WP_User( $user_id ); - - $user_roles = array(); - $output = esc_html__( 'None', 'members' ); - - if ( is_array( $user->roles ) ) { - - foreach ( $user->roles as $role ) { - - if ( members_role_exists( $role ) ) - $user_roles[] = members_translate_role( $role ); - } - - $output = join( ', ', $user_roles ); - } - } - - return $output; -} diff --git a/inc/functions-deprecated.php b/inc/functions-deprecated.php index 9e93e71..9bd0205 100644 --- a/inc/functions-deprecated.php +++ b/inc/functions-deprecated.php @@ -351,11 +351,13 @@ function members_get_additional_capabilities() { return members_get_plugin_capabilities(); } -/* ====== Functions removed in the 1.2 branch. ====== */ +/* ====== Functions removed in the 2.0 branch. ====== */ function members_role_factory() {} function members_role_group_factory() {} function members_cap_group_factory() {} +function members_manage_users_columns() {} +function members_manage_users_custom_column() {} /* ====== Functions removed in the 1.0 branch. ====== */ From bafe62df75650909cc9908ea1d0dd4260731d243 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 27 Jun 2017 17:06:14 -0500 Subject: [PATCH 037/157] Use `members_unregister_role()`. --- admin/functions-admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/functions-admin.php b/admin/functions-admin.php index add528a..1cc9fcd 100644 --- a/admin/functions-admin.php +++ b/admin/functions-admin.php @@ -109,7 +109,7 @@ function members_delete_role( $role ) { remove_role( $role ); // Remove the role from the role factory. - members_role_factory()->remove_role( $role ); + members_unregister_role( $role ); } /** From d95567ebdb8f31e60024a67f3d01254eb9afff3d Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 28 Jun 2017 09:49:31 -0500 Subject: [PATCH 038/157] When multiple roles are enabled, add a multi-role checkbox to the Add New User screen in the admin. This allows for multiple roles on user registration. Fixes: https://github.com/justintadlock/members/issues/97 Props: @mhull --- admin/class-user-new.php | 240 +++++++++++++++++++++++++++++++++++++++ members.php | 1 + 2 files changed, 241 insertions(+) create mode 100644 admin/class-user-new.php diff --git a/admin/class-user-new.php b/admin/class-user-new.php new file mode 100644 index 0000000..e98ae8f --- /dev/null +++ b/admin/class-user-new.php @@ -0,0 +1,240 @@ + + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @link http://themehybrid.com/plugins/members + * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + */ + +namespace Members\Admin; + +/** + * Edit user screen class. + * + * @since 2.0.0 + * @access public + */ +final class User_New { + + /** + * Holds the instances of this class. + * + * @since 2.0.0 + * @access private + * @var object + */ + private static $instance; + + /** + * Constructor method. + * + * @since 2.0.0 + * @access private + * @return void + */ + private function __construct() {} + + /** + * Sets up needed actions/filters for the admin to initialize. + * + * @since 2.0.0 + * @access private + * @return void + */ + private function setup_actions() { + + // If multiple roles per user is not enabled, bail. + if ( ! members_multiple_user_roles_enabled() ) + return; + + // Only run our customization on the 'user-edit.php' page in the admin. + add_action( 'load-user-new.php', array( $this, 'load' ) ); + } + + /** + * Adds actions/filters on load. + * + * @since 2.0.0 + * @access public + * @return void + */ + public function load() { + + // Adds the profile fields. + add_action( 'user_new_form', array( $this, 'profile_fields' ) ); + + // Sets the new user's roles. + add_action( 'user_register', array( $this, 'user_register' ) ); + + // Handle scripts. + add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) ); + add_action( 'admin_footer', array( $this, 'print_scripts' ), 25 ); + } + + /** + * Adds custom profile fields. + * + * @since 2.0.0 + * @access public + * @return void + */ + public function profile_fields() { + + if ( ! current_user_can( 'promote_users' ) ) + return; + + // Get the default user roles. + $new_user_roles = apply_filters( 'members_default_user_roles', array( get_option( 'default_role' ) ) ); + + // If the form was submitted but didn't go through, get the posted roles. + if ( isset( $_POST['createuser'] ) && ! empty( $_POST['members_user_roles'] ) ) + $new_user_roles = array_map( 'members_sanitize_role', $_POST['members_user_roles'] ); + + $roles = members_get_roles(); + + ksort( $roles ); + + wp_nonce_field( 'new_user_roles', 'members_new_user_roles_nonce' ); ?> + + + + + + + + + +
    +
    +
      + + + name ) ) :?> +
    • + +
    • + + + +
    +
    +
    + roles; + + // Sanitize the posted roles. + $new_roles = array_map( 'members_sanitize_role', $_POST['members_user_roles'] ); + + // Loop through the posted roles. + foreach ( $new_roles as $new_role ) { + + // If the user doesn't already have the role, add it. + if ( members_is_role_editable( $new_role ) && ! in_array( $new_role, (array) $user->roles ) ) + $user->add_role( $new_role ); + } + + // Loop through the current user roles. + foreach ( $old_roles as $old_role ) { + + // If the role is editable and not in the new roles array, remove it. + if ( members_is_role_editable( $old_role ) && ! in_array( $old_role, $new_roles ) ) + $user->remove_role( $old_role ); + } + + // If the posted roles are empty. + } else { + + // Loop through the current user roles. + foreach ( (array) $user->roles as $old_role ) { + + // Remove the role if it is editable. + if ( members_is_role_editable( $old_role ) ) + $user->remove_role( $old_role ); + } + } + } + + /** + * Enqueue scripts. + * + * @since 2.0.0 + * @access public + * @return void + */ + public function enqueue() { + + wp_enqueue_script( 'jquery' ); + } + + /** + * Enqueue the plugin admin CSS. + * + * @since 2.0.0 + * @access public + * @return void + */ + public function print_scripts() { ?> + + + + setup_actions(); + } + + return self::$instance; + } +} + +User_New::get_instance(); diff --git a/members.php b/members.php index 3f615f1..e9707ab 100644 --- a/members.php +++ b/members.php @@ -255,6 +255,7 @@ private function includes() { // User management. require_once( $this->admin_dir . 'class-manage-users.php' ); require_once( $this->admin_dir . 'class-user-edit.php' ); + require_once( $this->admin_dir . 'class-user-new.php' ); // Edit posts. require_once( $this->admin_dir . 'class-meta-box-content-permissions.php' ); From d51a42eceffe21219ed6a1dc53bcfe3623660e00 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 28 Jun 2017 13:37:51 -0500 Subject: [PATCH 039/157] Use the newer `members_unregister_role()` and `members_register_role()` to reset the role after it's been edited. --- admin/class-role-edit.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/admin/class-role-edit.php b/admin/class-role-edit.php index 5d2b8f2..4142211 100644 --- a/admin/class-role-edit.php +++ b/admin/class-role-edit.php @@ -200,8 +200,16 @@ public function load() { } } - // Add the updated role to the role factory. - members_role_factory()->add_role( $this->role->name ); + // Add the updated role to the role registry. + members_unregister_role( $this->role->name ); + + members_register_role( + $this->role->name, + array( + 'label' => $this->members_role->label, + 'caps' => $this->role->capabilities + ) + ); // Reset the Members role object. $this->members_role = members_get_role( $this->role->name ); From 0c1a3ece2a09d6c2ba0d0632b11e65ab9196f73d Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 28 Jun 2017 14:12:00 -0500 Subject: [PATCH 040/157] Move the widget classes to the `Members` namespace. --- inc/class-widget-login.php | 16 +++++++++------- inc/class-widget-users.php | 16 +++++++++------- inc/functions-widgets.php | 4 ++-- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/inc/class-widget-login.php b/inc/class-widget-login.php index 7c49548..c9f1d86 100644 --- a/inc/class-widget-login.php +++ b/inc/class-widget-login.php @@ -10,18 +10,20 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members; + /** * Login form widget class. * - * @since 0.1.0 + * @since 2.0.0 * @access public */ -class Members_Widget_Login extends WP_Widget { +class Widget_Login extends \WP_Widget { /** * Default arguments for the widget settings. * - * @since 1.0.3 + * @since 2.0.0 * @access public * @var array */ @@ -30,7 +32,7 @@ class Members_Widget_Login extends WP_Widget { /** * Set up the widget's unique name, ID, class, description, and other options. * - * @since 0.2.5 + * @since 2.0.0 * @access public * @return void */ @@ -76,7 +78,7 @@ public function __construct() { /** * Outputs the widget based on the arguments input through the widget controls. * - * @since 0.1.0 + * @since 2.0.0 * @access public * @param array $sidebar * @param array $instance @@ -154,7 +156,7 @@ function widget( $sidebar, $instance ) { /** * Sanitizes/Validates widget options before being saved. * - * @since 0.1.0 + * @since 2.0.0 * @access public * @param array $new_instance * @param array $old_instance @@ -191,7 +193,7 @@ function update( $new_instance, $old_instance ) { /** * Displays the widget control options in the Widgets admin screen. * - * @since 0.1.0 + * @since 2.0.0 * @access public * @param array $instance * @return void diff --git a/inc/class-widget-users.php b/inc/class-widget-users.php index c4fec44..4343b3b 100644 --- a/inc/class-widget-users.php +++ b/inc/class-widget-users.php @@ -10,18 +10,20 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members; + /** * Users widget archive class. * - * @since 0.1.0 + * @since 2.0.0 * @access public */ -class Members_Widget_Users extends WP_Widget { +class Widget_Users extends \WP_Widget { /** * Default arguments for the widget settings. * - * @since 1.0.3 + * @since 2.0.0 * @access public * @var array */ @@ -30,7 +32,7 @@ class Members_Widget_Users extends WP_Widget { /** * Set up the widget's unique name, ID, class, description, and other options. * - * @since 0.2.5 + * @since 2.0.0 * @access public * @return void */ @@ -71,7 +73,7 @@ public function __construct() { /** * Outputs the widget based on the arguments input through the widget controls. * - * @since 0.1.0 + * @since 2.0.0 * @access public * @param array $sidebar * @param array $instance @@ -136,7 +138,7 @@ function widget( $sidebar, $instance ) { /** * Sanitizes/Validates widget options before being saved. * - * @since 0.1.0 + * @since 2.0.0 * @access public * @param array $new_instance * @param array $old_instance @@ -169,7 +171,7 @@ function update( $new_instance, $old_instance ) { /** * Displays the widget control options in the Widgets admin screen. * - * @since 0.1.0 + * @since 2.0.0 * @access public * @param array $instance * @return void diff --git a/inc/functions-widgets.php b/inc/functions-widgets.php index 3dbf3f1..d5c7e11 100644 --- a/inc/functions-widgets.php +++ b/inc/functions-widgets.php @@ -27,7 +27,7 @@ function members_register_widgets() { require_once( members_plugin()->inc_dir . 'class-widget-login.php' ); - register_widget( 'Members_Widget_Login' ); + register_widget( '\Members\Widget_Login' ); } // If the users widget is enabled. @@ -35,6 +35,6 @@ function members_register_widgets() { require_once( members_plugin()->inc_dir . 'class-widget-users.php' ); - register_widget( 'Members_Widget_users' ); + register_widget( '\Members\Widget_Users' ); } } From b6c58cb44ae56e4d3a8e35ab25026b2d6e2b3f4e Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 29 Jun 2017 11:15:02 -0500 Subject: [PATCH 041/157] Bump 'custom' and 'all' cap groups up really high in priority. --- admin/functions-cap-groups.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/functions-cap-groups.php b/admin/functions-cap-groups.php index 749116f..34216c8 100644 --- a/admin/functions-cap-groups.php +++ b/admin/functions-cap-groups.php @@ -194,7 +194,7 @@ function members_register_cap_groups() { 'caps' => members_get_capabilities(), 'icon' => 'dashicons-admin-generic', 'diff_added' => true, - 'priority' => 90 + 'priority' => 995 ) ); @@ -205,7 +205,7 @@ function members_register_cap_groups() { 'caps' => members_get_all_group_caps(), 'icon' => 'dashicons-plus', 'merge_added' => false, - 'priority' => 95 + 'priority' => 995 ) ); From baf73a647daa2e1924a072762061563c1f2467d5 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 29 Jun 2017 12:44:11 -0500 Subject: [PATCH 042/157] Add core taxonomy caps to the WP caps array. --- inc/functions-deprecated.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/inc/functions-deprecated.php b/inc/functions-deprecated.php index 9bd0205..697fea8 100644 --- a/inc/functions-deprecated.php +++ b/inc/functions-deprecated.php @@ -254,18 +254,23 @@ function members_get_wp_capabilities() { return array( 'activate_plugins', 'add_users', + 'assign_categories', + 'assign_post_tags', 'create_users', + 'delete_categories', 'delete_others_pages', 'delete_others_posts', 'delete_pages', 'delete_plugins', 'delete_posts', + 'delete_post_tags', 'delete_private_pages', 'delete_private_posts', 'delete_published_pages', 'delete_published_posts', 'delete_themes', 'delete_users', + 'edit_categories', 'edit_dashboard', 'edit_files', 'edit_others_pages', @@ -273,6 +278,7 @@ function members_get_wp_capabilities() { 'edit_pages', 'edit_plugins', 'edit_posts', + 'edit_post_tags', 'edit_private_pages', 'edit_private_posts', 'edit_published_pages', @@ -288,6 +294,7 @@ function members_get_wp_capabilities() { 'manage_categories', 'manage_links', 'manage_options', + 'manage_post_tags', 'moderate_comments', 'promote_users', 'publish_pages', From b7ca5d0894fe29a3e77032b697200e78cbd46a2b Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 29 Jun 2017 12:46:57 -0500 Subject: [PATCH 043/157] Temporarily comment out taxonomy caps until we best figure out how to handle these. --- inc/functions-capabilities.php | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/inc/functions-capabilities.php b/inc/functions-capabilities.php index d281cf3..73d997d 100644 --- a/inc/functions-capabilities.php +++ b/inc/functions-capabilities.php @@ -82,15 +82,15 @@ function members_register_default_caps() { $caps['upload_files'] = array( 'label' => __( 'Upload Files', 'members' ), 'group' => 'type-attachment' ); // Taxonomy caps. - $caps['assign_categories'] = array( 'label' => __( 'Assign Categories', 'members' ), 'group' => 'taxonomy' ); - $caps['edit_categories'] = array( 'label' => __( 'Edit Categories', 'members' ), 'group' => 'taxonomy' ); - $caps['delete_categories'] = array( 'label' => __( 'Delete Categories', 'members' ), 'group' => 'taxonomy' ); + //$caps['assign_categories'] = array( 'label' => __( 'Assign Categories', 'members' ), 'group' => 'taxonomy' ); + //$caps['edit_categories'] = array( 'label' => __( 'Edit Categories', 'members' ), 'group' => 'taxonomy' ); + //$caps['delete_categories'] = array( 'label' => __( 'Delete Categories', 'members' ), 'group' => 'taxonomy' ); $caps['manage_categories'] = array( 'label' => __( 'Manage Categories', 'members' ), 'group' => 'taxonomy' ); - $caps['assign_post_tags'] = array( 'label' => __( 'Assign Tags', 'members' ), 'group' => 'taxonomy' ); - $caps['edit_post_tags'] = array( 'label' => __( 'Edit Tags', 'members' ), 'group' => 'taxonomy' ); - $caps['delete_post_tags'] = array( 'label' => __( 'Delete Tags', 'members' ), 'group' => 'taxonomy' ); - $caps['manage_post_tags'] = array( 'label' => __( 'Manage Tags', 'members' ), 'group' => 'taxonomy' ); + //$caps['assign_post_tags'] = array( 'label' => __( 'Assign Tags', 'members' ), 'group' => 'taxonomy' ); + //$caps['edit_post_tags'] = array( 'label' => __( 'Edit Tags', 'members' ), 'group' => 'taxonomy' ); + //$caps['delete_post_tags'] = array( 'label' => __( 'Delete Tags', 'members' ), 'group' => 'taxonomy' ); + //$caps['manage_post_tags'] = array( 'label' => __( 'Manage Tags', 'members' ), 'group' => 'taxonomy' ); // Theme caps. $caps['delete_themes'] = array( 'label' => __( 'Delete Themes', 'members' ), 'group' => 'theme' ); @@ -108,7 +108,6 @@ function members_register_default_caps() { $caps['update_plugins'] = array( 'label' => __( 'Update Plugins', 'members' ), 'group' => 'plugin' ); // User caps. - $caps['add_users'] = array( 'label' => __( 'Add Users', 'members' ), 'group' => 'user' ); $caps['create_roles'] = array( 'label' => __( 'Create Roles', 'members' ), 'group' => 'user' ); $caps['create_users'] = array( 'label' => __( 'Create Users', 'members' ), 'group' => 'user' ); $caps['delete_roles'] = array( 'label' => __( 'Delete Roles', 'members' ), 'group' => 'user' ); From 3bab2d129c6101e61080d8e5632a2044267d0597 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 29 Jun 2017 13:05:44 -0500 Subject: [PATCH 044/157] Use `wp_editor()` to output the WP Editor instead of a plain textarea for the per-post permissions error. Fixes: https://github.com/justintadlock/members/issues/74 --- admin/class-meta-box-content-permissions.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/admin/class-meta-box-content-permissions.php b/admin/class-meta-box-content-permissions.php index b409c5a..621233d 100644 --- a/admin/class-meta-box-content-permissions.php +++ b/admin/class-meta-box-content-permissions.php @@ -171,7 +171,18 @@ public function meta_box( $post ) {

    - +

    + + ID, '_members_access_error', true ), + 'members_access_error', + array( + 'drag_drop_upload' => true, + 'editor_height' => 200 + ) + ); ?> + +

    Date: Thu, 29 Jun 2017 13:15:20 -0500 Subject: [PATCH 045/157] Adds the `[members_not_logged_in]` shortcode for showing content to users who are not logged in. Fixes: https://github.com/justintadlock/members/issues/91 --- inc/functions-shortcodes.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/inc/functions-shortcodes.php b/inc/functions-shortcodes.php index 9275e8a..7558d3e 100644 --- a/inc/functions-shortcodes.php +++ b/inc/functions-shortcodes.php @@ -38,6 +38,9 @@ function members_register_shortcodes() { add_shortcode( 'members_logged_in', 'members_is_user_logged_in_shortcode' ); add_shortcode( 'is_user_logged_in', 'members_is_user_logged_in_shortcode' ); // @deprecated 1.0.0 + // Add the `[members_not_logged_in]` shortcode. + add_shortcode( 'members_not_logged_in', 'members_not_logged_in_shortcode' ); + // @deprecated 0.2.0. add_shortcode( 'get_avatar', 'members_get_avatar_shortcode' ); add_shortcode( 'avatar', 'members_get_avatar_shortcode' ); @@ -58,6 +61,20 @@ function members_is_user_logged_in_shortcode( $attr, $content = null ) { return is_feed() || ! is_user_logged_in() || is_null( $content ) ? '' : do_shortcode( $content ); } +/** + * Displays content if the user viewing it is not currently logged in. + * + * @since 2.0.0 + * @access public + * @param array $attr + * @param string $content + * @return string + */ +function members_not_logged_in_shortcode( $attr, $content = null ) { + + return is_user_logged_in() || is_null( $content ) ? '' : do_shortcode( $content ); +} + /** * Content that should only be shown in feed readers. Can be useful for displaying * feed-specific items. From cc2fa5e2d2d5af77d487c005ab87fc7f7889e50b Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 29 Jun 2017 13:57:41 -0500 Subject: [PATCH 046/157] Adds the `members_default_post_roles` filter hook. This hook allows developers to set some default roles as checked in the content permissions meta box. Fixes: https://github.com/justintadlock/members/issues/33 --- admin/class-meta-box-content-permissions.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/admin/class-meta-box-content-permissions.php b/admin/class-meta-box-content-permissions.php index 621233d..e57c80a 100644 --- a/admin/class-meta-box-content-permissions.php +++ b/admin/class-meta-box-content-permissions.php @@ -27,6 +27,17 @@ final class Members_Meta_Box_Content_Permissions { */ private static $instance; + /** + * Whether this is a new post. Once the post is saved and we're + * no longer on the `post-new.php` screen, this is going to be + * `false`. + * + * @since 2.0.0 + * @access public + * @var bool + */ + public $is_new_post = false; + /** * Sets up the appropriate actions. * @@ -58,6 +69,9 @@ public function load() { if ( ! $this->maybe_enable() ) return; + // Is this a new post? + $this->is_new_post = 'load-post-new.php' === current_action(); + // Enqueue scripts/styles. add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) ); @@ -135,6 +149,9 @@ public function meta_box( $post ) { // Get the roles saved for the post. $roles = get_post_meta( $post->ID, '_members_access_role', false ); + if ( ! $roles && $this->is_new_post ) + $roles = apply_filters( 'members_default_post_roles', array(), $post->ID ); + // Convert old post meta to the new system if no roles were found. if ( empty( $roles ) ) $roles = members_convert_old_post_meta( $post->ID ); From 14b8c6fb408ba131dc40d0b658b5149dd1c2ea0d Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 29 Jun 2017 15:29:15 -0500 Subject: [PATCH 047/157] Use the `wp_roles_init` hook added in WP 4.7 to to register our roles. --- inc/functions-roles.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/inc/functions-roles.php b/inc/functions-roles.php index 9c37880..0c89f16 100644 --- a/inc/functions-roles.php +++ b/inc/functions-roles.php @@ -11,7 +11,7 @@ */ # Register roles. -add_action( 'init', 'members_register_roles', 95 ); +add_action( 'wp_roles_init', 'members_register_roles', 95 ); add_action( 'members_register_roles', 'members_register_default_roles', 5 ); /** @@ -19,11 +19,12 @@ * * @since 2.0.0 * @access public + * @param object $wp_roles * @return void */ -function members_register_roles() { +function members_register_roles( $wp_roles ) { - do_action( 'members_register_roles' ); + do_action( 'members_register_roles', $wp_roles ); } /** @@ -31,11 +32,12 @@ function members_register_roles() { * * @since 2.0.0 * @access public + * @param object $wp_roles * @return void */ -function members_register_default_roles() { +function members_register_default_roles( $wp_roles ) { - foreach ( $GLOBALS['wp_roles']->roles as $name => $object ) { + foreach ( $wp_roles->roles as $name => $object ) { $args = array( 'label' => $object['name'], From 176cc4e2c8b2111f6fc0d36fad0b4ff1eb874db9 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 29 Jun 2017 18:26:12 -0500 Subject: [PATCH 048/157] Add a private REST API option to disable for users who are not logged in. Fixes: https://github.com/justintadlock/members/issues/114 --- admin/views/class-settings-view-general.php | 17 +++++++++++ inc/functions-options.php | 1 + inc/functions-private-site.php | 31 +++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/admin/views/class-settings-view-general.php b/admin/views/class-settings-view-general.php index fe7f80c..8fadce1 100644 --- a/admin/views/class-settings-view-general.php +++ b/admin/views/class-settings-view-general.php @@ -80,6 +80,7 @@ function register_settings() { // Private site fields. add_settings_field( 'enable_private_site', esc_html__( 'Enable Private Site', 'members' ), array( $this, 'field_enable_private_site' ), 'members-settings', 'private_site' ); + add_settings_field( 'private_rest_api', esc_html__( 'REST API', 'members' ), array( $this, 'field_private_rest_api' ), 'members-settings', 'private_site' ); add_settings_field( 'enable_private_feed', esc_html__( 'Disable Feed', 'members' ), array( $this, 'field_enable_private_feed' ), 'members-settings', 'private_site' ); add_settings_field( 'private_feed_error', esc_html__( 'Feed Error Message', 'members' ), array( $this, 'field_private_feed_error' ), 'members-settings', 'private_site' ); } @@ -102,6 +103,7 @@ function validate_settings( $settings ) { $settings['login_form_widget'] = ! empty( $settings['login_form_widget'] ) ? true : false; $settings['users_widget'] = ! empty( $settings['users_widget'] ) ? true : false; $settings['private_blog'] = ! empty( $settings['private_blog'] ) ? true : false; + $settings['private_rest_api'] = ! empty( $settings['private_rest_api'] ) ? true : false; $settings['private_feed'] = ! empty( $settings['private_feed'] ) ? true : false; // Kill evil scripts. @@ -275,6 +277,21 @@ public function field_enable_private_site() { ?> + + + true, + 'private_rest_api' => false, ); } diff --git a/inc/functions-private-site.php b/inc/functions-private-site.php index 9af98d4..80a1cb9 100644 --- a/inc/functions-private-site.php +++ b/inc/functions-private-site.php @@ -30,6 +30,8 @@ add_filter( 'members_feed_error_message', 'do_shortcode', 30 ); add_filter( 'members_feed_error_message', 'shortcode_unautop', 35 ); +add_filter( 'rest_authentication_errors', 'members_private_rest_api', 95 ); + /** * Conditional tag to see if we have a private blog. * @@ -52,6 +54,18 @@ function members_is_private_feed() { return members_get_setting( 'private_feed' ); } +/** + * Conditional tag to see if we have a private REST API + * + * @since 2.0.0 + * @access public + * @return bool + */ +function members_is_private_rest_api() { + + return members_get_setting( 'private_rest_api' ); +} + /** * Redirects users that are not logged in to the 'wp-login.php' page. * @@ -119,3 +133,20 @@ function members_get_private_feed_message() { return apply_filters( 'members_feed_error_message', members_get_setting( 'private_feed_error' ) ); } + +/** + * Returns an error if the REST API is accessed by an unauthenticated user. + * + * @link https://developer.wordpress.org/rest-api/using-the-rest-api/frequently-asked-questions/#require-authentication-for-all-requests + * @since 2.0.0 + * @access public + * @param object $result + * @return object + */ +function members_private_rest_api( $result ) { + + if ( empty( $result ) && members_is_private_rest_api() && ! is_user_logged_in() ) + return new WP_Error( 'rest_not_logged_in', esc_html__( 'You are not currently logged in.', 'members' ), array( 'status' => 401 ) ); + + return $result; +} From 3e5875ceab2dc1486bca39226b50757a7aea4a54 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 30 Jun 2017 07:01:27 -0500 Subject: [PATCH 049/157] Drop parameter type hinting for now. --- admin/class-cap-group.php | 2 +- admin/class-role-group.php | 2 +- inc/class-capability.php | 2 +- inc/class-registry.php | 10 +++++----- inc/class-role.php | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/admin/class-cap-group.php b/admin/class-cap-group.php index 5eff4cb..ab36760 100644 --- a/admin/class-cap-group.php +++ b/admin/class-cap-group.php @@ -110,7 +110,7 @@ public function __toString() { * } * @return void */ - public function __construct( string $name, array $args = array() ) { + public function __construct( $name, $args = array() ) { foreach ( array_keys( get_object_vars( $this ) ) as $key ) { diff --git a/admin/class-role-group.php b/admin/class-role-group.php index bb598a7..45518fd 100644 --- a/admin/class-role-group.php +++ b/admin/class-role-group.php @@ -87,7 +87,7 @@ public function __toString() { * @param array $args * @return void */ - public function __construct( string $name, array $args = array() ) { + public function __construct( $name, $args = array() ) { foreach ( array_keys( get_object_vars( $this ) ) as $key ) { diff --git a/inc/class-capability.php b/inc/class-capability.php index 3125ffd..b0e6962 100644 --- a/inc/class-capability.php +++ b/inc/class-capability.php @@ -68,7 +68,7 @@ public function __toString() { * @param string $role * @return void */ - public function __construct( string $name, array $args = array() ) { + public function __construct( $name, $args = array() ) { foreach ( array_keys( get_object_vars( $this ) ) as $key ) { diff --git a/inc/class-registry.php b/inc/class-registry.php index 99b047d..d835e04 100644 --- a/inc/class-registry.php +++ b/inc/class-registry.php @@ -74,7 +74,7 @@ private function __wakeup() {} * @param object $value * @return void */ - public function register( string $name, $value ) { + public function register( $name, $value ) { if ( ! $this->exists( $name ) ) $this->collection[ $name ] = $value; @@ -88,7 +88,7 @@ public function register( string $name, $value ) { * @param string $name * @return void */ - public function unregister( string $name ) { + public function unregister( $name ) { if ( $this->exists( $name ) ) unset( $this->collection[ $name ] ); @@ -102,7 +102,7 @@ public function unregister( string $name ) { * @param string $name * @return bool */ - public function exists( string $name ) { + public function exists( $name ) { return isset( $this->collection[ $name ] ); } @@ -115,7 +115,7 @@ public function exists( string $name ) { * @param string $name * @return object|bool */ - public function get( string $name ) { + public function get( $name ) { return $this->exists( $name ) ? $this->collection[ $name ] : false; } @@ -139,7 +139,7 @@ public function get_collection() { * @access public * @return object */ - final public static function get_instance( string $name = '' ) { + final public static function get_instance( $name = '' ) { if ( ! isset( self::$instances[ $name ] ) ) self::$instances[ $name ] = new static(); diff --git a/inc/class-role.php b/inc/class-role.php index 42c31a5..524eaa4 100644 --- a/inc/class-role.php +++ b/inc/class-role.php @@ -123,7 +123,7 @@ public function __toString() { * @param array $args * @return void */ - public function __construct( string $name, array $args = array() ) { + public function __construct( $name, $args = array() ) { foreach ( array_keys( get_object_vars( $this ) ) as $key ) { From 948d34214c9945459bc32e16762735e64d5b7087 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sat, 1 Jul 2017 17:46:20 -0500 Subject: [PATCH 050/157] Disables access to private blogs in multisite where the user is logged into the network but isn't a user of the blog itself. Fixes: https://github.com/justintadlock/members/issues/87 --- inc/functions-private-site.php | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/inc/functions-private-site.php b/inc/functions-private-site.php index 80a1cb9..49787ca 100644 --- a/inc/functions-private-site.php +++ b/inc/functions-private-site.php @@ -75,6 +75,11 @@ function members_is_private_rest_api() { */ function members_please_log_in() { + // If this is a multisite instance and the user is logged into the network. + if ( members_is_private_blog() && is_multisite() && is_user_logged_in() && ! is_user_member_of_blog() ) { + members_ms_private_blog_die(); + } + // Check if the private blog feature is active and if the user is not logged in. if ( members_is_private_blog() && ! is_user_logged_in() && members_is_private_page() ) { @@ -150,3 +155,36 @@ function members_private_rest_api( $result ) { return $result; } + +/** + * Outputs an error message if a user attempts to access a site that they do not have + * access to on multisite. + * + * @since 2.0.0 + * @access public + * @return void + */ +function members_ms_private_blog_die() { + + $blogs = get_blogs_of_user( get_current_user_id() ); + + $blogname = get_bloginfo( 'name' ); + + $message = __( 'You do not currently have access to the "%s" site. If you believe you should have access, please contact your network administrator.', 'members' ); + + if ( empty( $blogs ) ) + wp_die( sprintf( $message, $blogname ), 403 ); + + $output = '

    ' . sprintf( $message, $blogname ) . '

    '; + + $output .= sprintf( '

    %s

    ', __( 'If you reached this page by accident and meant to visit one of your own sites, try one of the following links.', 'members' ) ); + + $output .= '
      '; + + foreach ( $blogs as $blog ) + $output .= sprintf( '
    • %s
    • ', esc_url( get_home_url( $blog->userblog_id ) ), esc_html( $blog->blogname ) ); + + $output .= '
    '; + + wp_die( $output, 403 ); +} From b00dc0b38c36955243d92265b7ca8b187d7d9c5b Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sun, 2 Jul 2017 12:10:10 -0500 Subject: [PATCH 051/157] Adds a `members_has_post_roles()` conditional tag. Partial fix for https://github.com/justintadlock/members/issues/135 --- inc/functions-content-permissions.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/inc/functions-content-permissions.php b/inc/functions-content-permissions.php index 13d5f43..1b76981 100644 --- a/inc/functions-content-permissions.php +++ b/inc/functions-content-permissions.php @@ -22,6 +22,21 @@ function members_get_post_roles( $post_id ) { return get_post_meta( $post_id, '_members_access_role', false ); } +/** + * Conditional check to determine if a post has roles assigned to it. + * + * @since 2.0.0 + * @access public + * @param int $post_id + * @return bool + */ +function members_has_post_roles( $post_id ) { + + $roles = members_get_post_roles( $post_id ); + + return ! empty( $roles ); +} + /** * Adds a single role to a post's access roles. * From 0d9a0285380826c5a38f2c569a27b50ac2483861 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sun, 2 Jul 2017 12:36:48 -0500 Subject: [PATCH 052/157] Filter `get_comment_text` instead of just `comment_text_rss` to make sure we're covering all our bases with Content Permissions. Fixes: https://github.com/justintadlock/members/issues/123 --- inc/functions-content-permissions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/functions-content-permissions.php b/inc/functions-content-permissions.php index 1b76981..10ee427 100644 --- a/inc/functions-content-permissions.php +++ b/inc/functions-content-permissions.php @@ -127,7 +127,7 @@ function members_enable_content_permissions() { add_filter( 'get_the_excerpt', 'members_content_permissions_protect', 95 ); add_filter( 'the_excerpt', 'members_content_permissions_protect', 95 ); add_filter( 'the_content_feed', 'members_content_permissions_protect', 95 ); - add_filter( 'comment_text_rss', 'members_content_permissions_protect', 95 ); + add_filter( 'get_comment_text', 'members_content_permissions_protect', 95 ); // Filter the comments template to make sure comments aren't shown to users without access. add_filter( 'comments_template', 'members_content_permissions_comments', 95 ); From d170ba10d89b1011345565c89e2d2190bc7afa07 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 3 Jul 2017 18:17:57 -0500 Subject: [PATCH 053/157] Create a tabbed interface for the Content Permissions meta box. --- admin/class-meta-box-content-permissions.php | 96 ++++++++++------ admin/functions-admin.php | 1 + css/admin.css | 112 +++++++++++++++++-- css/admin.min.css | 2 +- js/edit-post.js | 38 +++++++ js/edit-post.min.js | 1 + 6 files changed, 201 insertions(+), 49 deletions(-) create mode 100644 js/edit-post.js create mode 100644 js/edit-post.min.js diff --git a/admin/class-meta-box-content-permissions.php b/admin/class-meta-box-content-permissions.php index e57c80a..facd8b7 100644 --- a/admin/class-meta-box-content-permissions.php +++ b/admin/class-meta-box-content-permissions.php @@ -91,6 +91,7 @@ public function load() { */ public function enqueue() { + wp_enqueue_script( 'members-edit-post' ); wp_enqueue_style( 'members-admin' ); } @@ -162,46 +163,69 @@ public function meta_box( $post ) { // Hook for firing at the top of the meta box. do_action( 'members_cp_meta_box_before', $post ); ?> -

    - -

    +
    -
    + -
      +
      - $name ) : ?> -
    • - -
    • - +
      -
    -
    - -

    - restrict_content' ); ?> -

    - -

    - -

    - - ID, '_members_access_error', true ), - 'members_access_error', - array( - 'drag_drop_upload' => true, - 'editor_height' => 200 - ) - ); ?> - -

    - -

    + + + +
    + +
      + + $name ) : ?> +
    • + +
    • + + +
    +
    + + + restrict_content' ); ?> + + +
    + +
    + + ID, '_members_access_error', true ), + 'members_access_error', + array( + 'drag_drop_upload' => true, + 'editor_height' => 200 + ) + ); ?> + +
    + +
    + + js_uri . "settings{$min}.js", array( 'jquery' ), '', true ); + wp_register_script( 'members-edit-post', members_plugin()->js_uri . "edit-post{$min}.js", array( 'jquery' ), '', true ); wp_register_script( 'members-edit-role', members_plugin()->js_uri . "edit-role{$min}.js", array( 'postbox', 'wp-util' ), '', true ); // Localize our script with some text we want to pass in. diff --git a/css/admin.css b/css/admin.css index 707a7c8..9422162 100644 --- a/css/admin.css +++ b/css/admin.css @@ -43,14 +43,16 @@ border-bottom: 1px solid #eee; } - #tabcapsdiv .inside { + #tabcapsdiv .inside, + #members-cp .inside { margin: 0; padding: 0; } /* Tabs wrapper. */ -.members-cap-tabs { +.members-cap-tabs, +.members-tabs { overflow: hidden; background: #fff; background: linear-gradient( 90deg, #fafafa 0%, #fafafa 20%, #fff 20%, #fff 100% ); @@ -58,14 +60,16 @@ @media only screen and ( max-width: 782px ) { - .members-cap-tabs { + .members-cap-tabs, + .members-tabs { background: linear-gradient( 90deg, #fafafa 0%, #fafafa 48px, #fff 48px, #fff 100% ); } } /* Tab nav. */ - .members-cap-tabs .members-tab-nav { + .members-cap-tabs .members-tab-nav, + .members-tabs .members-tab-nav { position: relative; float: left; list-style: none; @@ -78,7 +82,8 @@ box-sizing: border-box; } - .members-cap-tabs .members-tab-nav li { + .members-cap-tabs .members-tab-nav li, + .members-tabs .members-tab-nav li { display: block; position: relative; margin: 0; @@ -86,7 +91,8 @@ line-height: 20px; } - .members-cap-tabs .members-tab-nav li a { + .members-cap-tabs .members-tab-nav li a, + .members-tabs .members-tab-nav li a { display: block; margin: 0; padding: 10px; @@ -96,12 +102,14 @@ box-shadow: none; } - .members-cap-tabs .members-tab-nav li a .dashicons { + .members-cap-tabs .members-tab-nav li a .dashicons, + .members-tabs .members-tab-nav li a .dashicons { line-height: 20px; margin-right: 3px; } - .members-cap-tabs .members-tab-nav li[aria-selected="true"] a { + .members-cap-tabs .members-tab-nav li[aria-selected="true"] a, + .members-tabs .members-tab-nav li[aria-selected="true"] a { position: relative; font-weight: bold; color: #555; @@ -110,15 +118,18 @@ @media only screen and ( max-width: 782px ) { - .members-cap-tabs .members-tab-nav { width: 48px; } + .members-cap-tabs .members-tab-nav, + .members-tabs .members-tab-nav { width: 48px; } - .members-cap-tabs .members-tab-nav li a .dashicons { + .members-cap-tabs .members-tab-nav li a .dashicons, + .members-tabs .members-tab-nav li a .dashicons { width: 24px; height: 24px; font-size: 24px; line-height: 24px; } + .members-tab-nav li .dashicons::before, .members-tab-nav li .dashicons::before { width: 24px; height: 24px; @@ -136,7 +147,8 @@ /* Tab content wrapper */ - .members-cap-tabs .members-tab-wrap { + .members-cap-tabs .members-tab-wrap, + .members-tabs .members-tab-wrap { float: left; width: 80%; margin-left: -1px; @@ -144,11 +156,87 @@ @media only screen and ( max-width: 782px ) { - .members-cap-tabs .members-tab-wrap { + .members-cap-tabs .members-tab-wrap, + .members-tabs .members-tab-wrap { width: calc( 100% - 48px ); } } +#members-cp .members-tab-content { + padding: 10px; + border-left: 1px solid #e5e5e5; +} + +/* === Manager when in the side meta box. === */ + +@media only screen and ( min-width: 850px ) { + + #side-sortables .members-tabs { background: #fff; } + + #side-sortables .members-tabs .members-tab-wrap { width: 100%; } + + #side-sortables .members-tabs .members-tab-nav { + display: table; + width: 100%; + } + + #side-sortables .members-tabs .members-tab-nav li { + display: table-cell; + text-align: center; + border-right: 1px solid #eee; + } + + #side-sortables .members-tabs .members-tab-nav li:last-of-type { border-right: none; } + + #side-sortables .members-tabs .members-tab-nav li a { + padding: 10px 0; + } + + #side-sortables .members-tabs .members-tab-nav .dashicons { + width: 24px; + height: 24px; + font-size: 24px; + line-height: 24px; + } + + #side-sortables .members-tabs .members-tab-nav .dashicons::before { + width: 24px; + height: 24px; + } + + #side-sortables .members-tabs .members-tab-nav .label { + overflow: hidden; + position: absolute; + top: -1000em; + left: -1000em; + width: 1px; + height: 1px; + } + } + + + .members-tabs .members-tabs-label { + display : block !important; + font-weight : bold; + display : inline-block; + margin-bottom : 4px; + } + + .members-tabs .butterbean-control-checkbox .members-tabs-label { + display: inline !important; + } + + .members-tabs .members-tabs-description { + display : block; + font-style : italic; + margin-top : 4px; + } + + .members-tabs .members-tabs-label + .members-tabs-description { + margin-top : 0; + margin-bottom : 4px; + } + /* Tab tables. */ #tabcapsdiv table { diff --git a/css/admin.min.css b/css/admin.min.css index 4ce7ec6..5133c16 100644 --- a/css/admin.min.css +++ b/css/admin.min.css @@ -1 +1 @@ -@media only screen and (min-width:783px){.users_page_roles .column-users,.users_page_roles .column-granted_caps,.users_page_roles .column-denied_caps{width:100px;text-align:center}}.members-title-div #titlewrap input{padding:0 8px;font-size:1.7em;line-height:normal;height:1.7em;width:100%;outline:0;margin:0 0 3px;background-color:#fff}.members-title-div input[name=role]{font-size:13px;height:22px;margin:0;width:16em}#tabcapsdiv{margin-top:1em}#tabcapsdiv>.hndle{padding:10px;border-bottom:1px solid #eee}#tabcapsdiv .inside{margin:0;padding:0}.members-cap-tabs{overflow:hidden;background:#fff;background:linear-gradient(90deg,#fafafa 0,#fafafa 20%,#fff 20%,#fff 100%)}@media only screen and (max-width:782px){.members-cap-tabs{background:linear-gradient(90deg,#fafafa 0,#fafafa 48px,#fff 48px,#fff 100%)}}.members-cap-tabs .members-tab-nav{position:relative;float:left;list-style:none;width:20%;line-height:1em;margin:0 0 -1px 0;padding:0;background-color:#fafafa;border-right:1px solid #eee;box-sizing:border-box}.members-cap-tabs .members-tab-nav li{display:block;position:relative;margin:0;padding:0;line-height:20px}.members-cap-tabs .members-tab-nav li a{display:block;margin:0;padding:10px;line-height:20px!important;text-decoration:none;border-bottom:1px solid #eee;box-shadow:none}.members-cap-tabs .members-tab-nav li a .dashicons{line-height:20px;margin-right:3px}.members-cap-tabs .members-tab-nav li[aria-selected=true] a{position:relative;font-weight:700;color:#555;background-color:#e0e0e0}@media only screen and (max-width:782px){.members-cap-tabs .members-tab-nav{width:48px}.members-cap-tabs .members-tab-nav li a .dashicons{width:24px;height:24px;font-size:24px;line-height:24px}.members-tab-nav li .dashicons::before{width:24px;height:24px}.members-tab-nav li .label{overflow:hidden;position:absolute;top:-1000em;left:-1000em;width:1px;height:1px}}.members-cap-tabs .members-tab-wrap{float:left;width:80%;margin-left:-1px}@media only screen and (max-width:782px){.members-cap-tabs .members-tab-wrap{width:calc(100% - 48px)}}#tabcapsdiv table{border-right:0;border-top:0;border-bottom:0}#tabcapsdiv table td,#tabcapsdiv table th{padding:10px;padding-bottom:10px;border-bottom:1px solid #eee;font-size:13px;line-height:20px}#tabcapsdiv table td{padding:9px}#tabcapsdiv tbody tr:last-of-type td{border-bottom:0}#tabcapsdiv tfoot th{border-color:#eee}@media only screen and (max-width:782px){#tabcapsdiv table td,#tabcapsdiv table th{line-height:24px}}.members-roles-select .column-grant,.members-roles-select .column-deny{width:70px!important;text-align:center;display:table-cell!important;clear:none!important}.members-cap-tabs button{display:inline;margin:-4px;line-height:inherit;padding:4px 8px;border:1px solid transparent;background:transparent;border-radius:0;outline:0;-webkit-transition:all .25s ease-out;-moz-transition:all .25s ease-out;-o-transition:all .25s ease-out;transition:all .25s ease-out}.members-cap-tabs button:hover,.members-cap-tabs button:focus{border-color:#eee;background:#fafafa;cursor:pointer}.members-cap-tabs button:active{color:#0073aa;border-color:#0073aa}.members-cap-tabs button+.dashicons{display:none;margin-top:1px;margin-bottom:-1px;line-height:inherit}.members-cap-tabs button:hover+.dashicons,.members-cap-tabs button:focus+.dashicons{display:inline-block}.members-tab-content .members-highlight{background-color:rgba(0,115,170,.05)}.members-tab-content tbody{-webkit-transition:all 2s ease-in-out;-moz-transition:all 2s ease-in-out;-o-transition:all 2s ease-in-out;transition:all 2s ease-in-out}.members-cp-role-list-wrap{overflow:auto;min-height:42px;max-height:200px;padding:0 .9em;border:solid 1px #dfdfdf;background-color:#fdfdfd} \ No newline at end of file +@media only screen and (min-width:783px){.users_page_roles .column-denied_caps,.users_page_roles .column-granted_caps,.users_page_roles .column-users{width:100px;text-align:center}}.members-title-div #titlewrap input{padding:0 8px;font-size:1.7em;line-height:normal;height:1.7em;width:100%;outline:0;margin:0 0 3px;background-color:#fff}.members-title-div input[name=role]{font-size:13px;height:22px;margin:0;width:16em}#tabcapsdiv{margin-top:1em}#tabcapsdiv>.hndle{padding:10px;border-bottom:1px solid #eee}#members-cp .inside,#tabcapsdiv .inside{margin:0;padding:0}.members-cap-tabs,.members-tabs{overflow:hidden;background:#fff;background:linear-gradient(90deg,#fafafa 0,#fafafa 20%,#fff 20%,#fff 100%)}@media only screen and (max-width:782px){.members-cap-tabs,.members-tabs{background:linear-gradient(90deg,#fafafa 0,#fafafa 48px,#fff 48px,#fff 100%)}}.members-cap-tabs .members-tab-nav,.members-tabs .members-tab-nav{position:relative;float:left;list-style:none;width:20%;line-height:1em;margin:0 0 -1px 0;padding:0;background-color:#fafafa;border-right:1px solid #eee;box-sizing:border-box}.members-cap-tabs .members-tab-nav li,.members-tabs .members-tab-nav li{display:block;position:relative;margin:0;padding:0;line-height:20px}.members-cap-tabs .members-tab-nav li a,.members-tabs .members-tab-nav li a{display:block;margin:0;padding:10px;line-height:20px!important;text-decoration:none;border-bottom:1px solid #eee;box-shadow:none}.members-cap-tabs .members-tab-nav li a .dashicons,.members-tabs .members-tab-nav li a .dashicons{line-height:20px;margin-right:3px}.members-cap-tabs .members-tab-nav li[aria-selected=true] a,.members-tabs .members-tab-nav li[aria-selected=true] a{position:relative;font-weight:700;color:#555;background-color:#e0e0e0}@media only screen and (max-width:782px){.members-cap-tabs .members-tab-nav,.members-tabs .members-tab-nav{width:48px}.members-cap-tabs .members-tab-nav li a .dashicons,.members-tabs .members-tab-nav li a .dashicons{width:24px;height:24px;font-size:24px;line-height:24px}.members-tab-nav li .dashicons::before{width:24px;height:24px}.members-tab-nav li .label{overflow:hidden;position:absolute;top:-1000em;left:-1000em;width:1px;height:1px}}.members-cap-tabs .members-tab-wrap,.members-tabs .members-tab-wrap{float:left;width:80%;margin-left:-1px}@media only screen and (max-width:782px){.members-cap-tabs .members-tab-wrap,.members-tabs .members-tab-wrap{width:calc(100% - 48px)}}#members-cp .members-tab-content{padding:10px;border-left:1px solid #e5e5e5}@media only screen and (min-width:850px){#side-sortables .members-tabs{background:#fff}#side-sortables .members-tabs .members-tab-wrap{width:100%}#side-sortables .members-tabs .members-tab-nav{display:table;width:100%}#side-sortables .members-tabs .members-tab-nav li{display:table-cell;text-align:center;border-right:1px solid #eee}#side-sortables .members-tabs .members-tab-nav li:last-of-type{border-right:none}#side-sortables .members-tabs .members-tab-nav li a{padding:10px 0}#side-sortables .members-tabs .members-tab-nav .dashicons{width:24px;height:24px;font-size:24px;line-height:24px}#side-sortables .members-tabs .members-tab-nav .dashicons::before{width:24px;height:24px}#side-sortables .members-tabs .members-tab-nav .label{overflow:hidden;position:absolute;top:-1000em;left:-1000em;width:1px;height:1px}}.members-tabs .members-tabs-label{display:block!important;font-weight:700;display:inline-block;margin-bottom:4px}.members-tabs .butterbean-control-checkbox .members-tabs-label{display:inline!important}.members-tabs .members-tabs-description{display:block;font-style:italic;margin-top:4px}.members-tabs .members-tabs-label+.members-tabs-description{margin-top:0;margin-bottom:4px}#tabcapsdiv table{border-right:none;border-top:none;border-bottom:none}#tabcapsdiv table td,#tabcapsdiv table th{padding:10px;padding-bottom:10px;border-bottom:1px solid #eee;font-size:13px;line-height:20px}#tabcapsdiv table td{padding:9px}#tabcapsdiv tbody tr:last-of-type td{border-bottom:none}#tabcapsdiv tfoot th{border-color:#eee}@media only screen and (max-width:782px){#tabcapsdiv table td,#tabcapsdiv table th{line-height:24px}}.members-roles-select .column-deny,.members-roles-select .column-grant{width:70px!important;text-align:center;display:table-cell!important;clear:none!important}.members-cap-tabs button{display:inline;margin:-4px;line-height:inherit;padding:4px 8px;border:1px solid transparent;background:0 0;border-radius:0;outline:0;-webkit-transition:all .25s ease-out;-moz-transition:all .25s ease-out;-o-transition:all .25s ease-out;transition:all .25s ease-out}.members-cap-tabs button:focus,.members-cap-tabs button:hover{border-color:#eee;background:#fafafa;cursor:pointer}.members-cap-tabs button:active{color:#0073aa;border-color:#0073aa}.members-cap-tabs button+.dashicons{display:none;margin-top:1px;margin-bottom:-1px;line-height:inherit}.members-cap-tabs button:focus+.dashicons,.members-cap-tabs button:hover+.dashicons{display:inline-block}.members-tab-content .members-highlight{background-color:rgba(0,115,170,.05)}.members-tab-content tbody{-webkit-transition:all 2s ease-in-out;-moz-transition:all 2s ease-in-out;-o-transition:all 2s ease-in-out;transition:all 2s ease-in-out}.members-cp-role-list-wrap{overflow:auto;min-height:42px;max-height:200px;padding:0 .9em;border:solid 1px #dfdfdf;background-color:#fdfdfd} \ No newline at end of file diff --git a/js/edit-post.js b/js/edit-post.js new file mode 100644 index 0000000..d80606f --- /dev/null +++ b/js/edit-post.js @@ -0,0 +1,38 @@ +( function() { + + /* ====== Tabs ====== */ + + // Hides the tab content. + jQuery( '.members-tabs .members-tab-content' ).hide(); + + // Shows the first tab's content. + jQuery( '.members-tabs .members-tab-content:first-child' ).show(); + + // Makes the 'aria-selected' attribute true for the first tab nav item. + jQuery( '.members-tab-nav :first-child' ).attr( 'aria-selected', 'true' ); + + // When a tab nav item is clicked. + jQuery( '.members-tab-nav li a' ).click( + function( j ) { + + // Prevent the default browser action when a link is clicked. + j.preventDefault(); + + // Get the `href` attribute of the item. + var href = jQuery( this ).attr( 'href' ); + + // Hide all tab content. + jQuery( this ).parents( '.members-tabs' ).find( '.members-tab-content' ).hide(); + + // Find the tab content that matches the tab nav item and show it. + jQuery( this ).parents( '.members-tabs' ).find( href ).show(); + + // Set the `aria-selected` attribute to false for all tab nav items. + jQuery( this ).parents( '.members-tabs' ).find( '.members-tab-title' ).attr( 'aria-selected', 'false' ); + + // Set the `aria-selected` attribute to true for this tab nav item. + jQuery( this ).parent().attr( 'aria-selected', 'true' ); + } + ); // click() + +}() ); diff --git a/js/edit-post.min.js b/js/edit-post.min.js new file mode 100644 index 0000000..8a192a9 --- /dev/null +++ b/js/edit-post.min.js @@ -0,0 +1 @@ +!function(){jQuery(".members-tabs .members-tab-content").hide(),jQuery(".members-tabs .members-tab-content:first-child").show(),jQuery(".members-tab-nav :first-child").attr("aria-selected","true"),jQuery(".members-tab-nav li a").click(function(e){e.preventDefault();var t=jQuery(this).attr("href");jQuery(this).parents(".members-tabs").find(".members-tab-content").hide(),jQuery(this).parents(".members-tabs").find(t).show(),jQuery(this).parents(".members-tabs").find(".members-tab-title").attr("aria-selected","false"),jQuery(this).parent().attr("aria-selected","true")})}(); \ No newline at end of file From 5e578746a4b2ad2510963b430a8cd513ecfb7445 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 4 Jul 2017 09:46:34 -0500 Subject: [PATCH 054/157] Adds the `members_has_post_permissions()` function. Currently, this is just a wrapper for `members_has_post_roles()`. However, there are plans to allow users to set post permissions based on capability too. So, we're creating a wrapper function for any type of permission. --- inc/functions-content-permissions.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/inc/functions-content-permissions.php b/inc/functions-content-permissions.php index 10ee427..48eb946 100644 --- a/inc/functions-content-permissions.php +++ b/inc/functions-content-permissions.php @@ -10,6 +10,20 @@ # Enable the content permissions features. add_action( 'after_setup_theme', 'members_enable_content_permissions', 0 ); +/** + * Conditional check to determine if a post any permissions rules assigned + * to it. + * + * @since 2.0.0 + * @access public + * @param $post_id + * @return bool + */ +function members_has_post_permissions( $post_id = '' ) { + + return members_has_post_roles( $post_id ); +} + /** * Returns an array of the roles for a given post. * @@ -30,7 +44,10 @@ function members_get_post_roles( $post_id ) { * @param int $post_id * @return bool */ -function members_has_post_roles( $post_id ) { +function members_has_post_roles( $post_id = '' ) { + + if ( ! $post_id ) + $post_id = get_the_ID(); $roles = members_get_post_roles( $post_id ); From b0a03ee0525e14c4c82e3dc319229dfee50a3fb5 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 4 Jul 2017 09:59:04 -0500 Subject: [PATCH 055/157] Use jQuery to hide role-related fields that WP outputs on the manage users screen and edit user screen. We're already hiding them with CSS, but we're not removing them from the DOM with jQuery. --- admin/class-manage-users.php | 38 ++++++++++++++++++++++++++++++++++-- admin/class-user-edit.php | 35 ++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/admin/class-manage-users.php b/admin/class-manage-users.php index 33bb732..5665020 100644 --- a/admin/class-manage-users.php +++ b/admin/class-manage-users.php @@ -81,8 +81,10 @@ public function load() { // Custom manage users columns. add_filter( 'manage_users_columns', array( $this, 'manage_users_columns' ) ); - // Print custom styles. - add_action( 'admin_head', array( $this, 'print_styles' ) ); + // Handle scripts and styles. + add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) ); + add_action( 'admin_footer', array( $this, 'print_scripts' ), 25 ); + add_action( 'admin_head', array( $this, 'print_styles' ) ); // If there was an update, add notices if they're from our plugin. if ( isset( $_GET['update'] ) ) { @@ -394,6 +396,38 @@ public function manage_users_custom_column( $output, $column, $user_id ) { return $output; } + /** + * Enqueue scripts. + * + * @since 2.0.0 + * @access public + * @return void + */ + public function enqueue() { + + wp_enqueue_script( 'jquery' ); + } + + /** + * Enqueue the plugin admin CSS. + * + * @since 2.0.0 + * @access public + * @return void + */ + public function print_scripts() { ?> + + + + + + + + Date: Wed, 5 Jul 2017 12:54:31 -0500 Subject: [PATCH 056/157] Adds the `operator` parameter to the `[members_access]` shortcode. Currently, the only accepted value is `!` for negating the role or capability. Fixes: https://github.com/justintadlock/members/issues/93 `[members_access capability="read" operator="!"]` is more complex than something like `[members_access capability="!read"]`. However, we don't have to do any weird string manipulation with this method. Additionally, it opens us up to do other types of operations if we choose to do so in the future. --- inc/functions-shortcodes.php | 24 +++++++-------- inc/functions-users.php | 60 +++++++++++++++++++++++++++++++----- readme.md | 7 ++++- 3 files changed, 71 insertions(+), 20 deletions(-) diff --git a/inc/functions-shortcodes.php b/inc/functions-shortcodes.php index 7558d3e..eea849d 100644 --- a/inc/functions-shortcodes.php +++ b/inc/functions-shortcodes.php @@ -108,28 +108,31 @@ function members_access_check_shortcode( $attr, $content = null ) { if ( is_null( $content ) || is_feed() ) return ''; + $user_can = false; + // Set up the default attributes. $defaults = array( 'capability' => '', // Single capability or comma-separated multiple capabilities. 'role' => '', // Single role or comma-separated multiple roles. + 'operator' => 'or' // Only the `!` operator is supported for now. Everything else falls back to `or`. ); // Merge the input attributes and the defaults. $attr = shortcode_atts( $defaults, $attr, 'members_access' ); + // Get the operator. + $operator = strtolower( $attr['operator'] ); + // If the current user has the capability, show the content. if ( $attr['capability'] ) { // Get the capabilities. $caps = explode( ',', $attr['capability'] ); - // Loop through each capability. - foreach ( $caps as $cap ) { + if ( '!' === $operator ) + return members_current_user_can_any( $caps ) ? '' : do_shortcode( $content ); - // If the current user can perform the capability, return the content. - if ( current_user_can( trim( $cap ) ) ) - return do_shortcode( $content ); - } + return members_current_user_can_any( $caps ) ? do_shortcode( $content ) : ''; } // If the current user has the role, show the content. @@ -138,13 +141,10 @@ function members_access_check_shortcode( $attr, $content = null ) { // Get the roles. $roles = explode( ',', $attr['role'] ); - // Loop through each of the roles. - foreach ( $roles as $role ) { + if ( '!' === $operator ) + return members_current_user_has_role( $roles ) ? '' : do_shortcode( $content ); - // If the current user has the role, return the content. - if ( members_current_user_has_role( trim( $role ) ) ) - return do_shortcode( $content ); - } + return members_current_user_has_role( $roles ) ? do_shortcode( $content ) : ''; } // Return an empty string if we've made it to this point. diff --git a/inc/functions-users.php b/inc/functions-users.php index 01e67ef..d1913b3 100644 --- a/inc/functions-users.php +++ b/inc/functions-users.php @@ -68,15 +68,21 @@ function members_user_has_cap_filter( $allcaps, $caps, $args, $user ) { * * @since 1.0.0 * @access public - * @param int $user_id - * @param string $role + * @param int $user_id + * @param string|array $roles * @return bool */ -function members_user_has_role( $user_id, $role ) { +function members_user_has_role( $user_id, $roles ) { $user = new WP_User( $user_id ); - return in_array( $role, (array) $user->roles ); + foreach ( (array) $roles as $role ) { + + if ( in_array( $role, (array) $user->roles ) ) + return true; + } + + return false; } /** @@ -84,12 +90,52 @@ function members_user_has_role( $user_id, $role ) { * * @since 1.0.0 * @access public - * @param string $role + * @param string|array $roles * @return bool */ -function members_current_user_has_role( $role ) { +function members_current_user_has_role( $roles ) { + + return is_user_logged_in() ? members_user_has_role( get_current_user_id(), $roles ) : false; +} + +/** + * Wrapper for `current_user_can()` that checks if the user can perform any action. + * Accepts an array of caps instead of a single cap. + * + * @since 2.0.0 + * @access public + * @param array $caps + * @return bool + */ +function members_current_user_can_any( $caps = array() ) { + + foreach ( $caps as $cap ) { + + if ( current_user_can( $cap ) ) + return true; + } + + return false; +} + +/** + * Wrapper for `current_user_can()` that checks if the user can perform all actions. + * Accepts an array of caps instead of a single cap. + * + * @since 2.0.0 + * @access public + * @param array $caps + * @return bool + */ +function members_current_user_can_all( $caps = array() ) { + + foreach ( $caps as $cap ) { + + if ( ! current_user_can( $cap ) ) + return false; + } - return is_user_logged_in() ? members_user_has_role( get_current_user_id(), $role ) : false; + return true; } /** diff --git a/readme.md b/readme.md index e5388ce..67b9b52 100644 --- a/readme.md +++ b/readme.md @@ -101,12 +101,17 @@ The `[members_access]` shortcode is for hiding content from particular roles and * `capability`: A capability that has been assigned to a role. * `role`: A user role from WordPress or one that you've created. +* `operator`: Accepts `!` to negate the role or capability. Note that `capability` and `role` parameters aren't used in conjunction. The code first checks for the capability (if input) then checks for the role (if input). To check for multiple capabilities or multiple roles, simply add a comma between each capability/role. For example, the following code checks for an editor or administrator: - [members_access role="administrator,editor"]Hide this content from everyone but administrators and editors.[/members_access] + [members_access role="administrator,editor"]Show this content to administrators or editors only.[/members_access] + +To check that the user does not have a role: + + [members_access role="administrator" operator="!"]Show this content to anyone who is not an administrator.[/members_access] #### [members_logged_in] From 25201caad65d19671ea9f0cd8ec3a3891bca2afa Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 5 Jul 2017 13:16:05 -0500 Subject: [PATCH 057/157] Adds a `composer.json` file. Props @jlambe Fixes: https://github.com/justintadlock/members/issues/116 --- composer.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 composer.json diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..ddd2622 --- /dev/null +++ b/composer.json @@ -0,0 +1,22 @@ +{ + "name" : "justintadlock/members", + "description" : "A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private.", + "keywords" : ["wordpress"], + "homepage" : "https://themehybrid.com/plugins/members", + "license" : "GPL-2.0+", + "type" : "wordpress-plugin", + "authors" : [ + { + "name" : "Justin Tadlock", + "email" : "justintadlock@gmail.com", + "homepage" : "http://justintadlock.com" + } + ], + "require" : { + "php" : ">=5.3.0" + }, + "support" : { + "issues": "https://github.com/justintadlock/members/issues", + "forum" : "https://themehybrid.com/board/topics" + } +} From 92808cfbb1955ba948c0a29531cfbc718713cfe9 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 5 Jul 2017 13:41:20 -0500 Subject: [PATCH 058/157] Add `composer/installers` requirement to `composer.json`. Hopefully fixes https://github.com/justintadlock/members/issues/116 for good. --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ddd2622..2b1c001 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,8 @@ } ], "require" : { - "php" : ">=5.3.0" + "composer/installers" : "^1.0", + "php" : ">=5.3.0" }, "support" : { "issues": "https://github.com/justintadlock/members/issues", From 0edbc53a5042b59a7564ad524e25f8c4625fbdb5 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 5 Jul 2017 14:37:52 -0500 Subject: [PATCH 059/157] Adds a link to the Roles and Capabilities page in the WordPress Codex in the Overview help tab while editing a role. Fixes: https://github.com/justintadlock/members/issues/62 --- admin/functions-help.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/admin/functions-help.php b/admin/functions-help.php index cde5ad2..d0bb481 100644 --- a/admin/functions-help.php +++ b/admin/functions-help.php @@ -108,6 +108,13 @@ function members_edit_role_help_overview_cb() { ?>

    + +

    + ' . esc_html__( 'Roles and Capabilities', 'members' ) . '' + ); ?> +

    Date: Wed, 5 Jul 2017 14:40:54 -0500 Subject: [PATCH 060/157] Typo fix: "no" should be "not". --- admin/class-role-edit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/class-role-edit.php b/admin/class-role-edit.php index 4142211..0dedaa7 100644 --- a/admin/class-role-edit.php +++ b/admin/class-role-edit.php @@ -229,7 +229,7 @@ public function load() { // If editing the core administrator role. if ( 'administrator' === $this->role->name ) - add_settings_error( 'members_edit_role', 'role_is_admin', sprintf( esc_html__( 'The %s role is typically the most important role on the site. Please take extreme caution that you do no inadvertently remove necessary capabilities.', 'members' ), members_get_role( $this->role->name )->label ) ); + add_settings_error( 'members_edit_role', 'role_is_admin', sprintf( esc_html__( 'The %s role is typically the most important role on the site. Please take extreme caution that you do not inadvertently remove necessary capabilities.', 'members' ), members_get_role( $this->role->name )->label ) ); // If a new role was added (redirect from new role screen). if ( isset( $_GET['message'] ) && 'role_added' === $_GET['message'] ) From 85a4b47f3f5858068b768461f726f7c58612c2e9 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 5 Jul 2017 16:10:06 -0500 Subject: [PATCH 061/157] Better handling of the taxonomy caps that are mapped to `manage_categories`. We're only going to register these if they've already been added to a role. That way, they don't show up on the edit role screen. Additionally, this commit registers all capabilities that are added to roles but have not been registered by the time the `members_register_caps` hook has fired. --- admin/functions-cap-groups.php | 12 +++++++- inc/functions-capabilities.php | 50 ++++++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/admin/functions-cap-groups.php b/admin/functions-cap-groups.php index 34216c8..7f51170 100644 --- a/admin/functions-cap-groups.php +++ b/admin/functions-cap-groups.php @@ -296,6 +296,16 @@ function members_get_post_type_group_caps( $post_type = 'post' ) { */ function members_get_taxonomy_group_caps() { + $do_not_add = array( + 'assign_categories', + 'edit_categories', + 'delete_categories', + 'assign_post_tags', + 'edit_post_tags', + 'delete_post_tags', + 'manage_post_tags' + ); + $taxi = get_taxonomies( array(), 'objects' ); $caps = array(); @@ -308,7 +318,7 @@ function members_get_taxonomy_group_caps() { if ( $registered_caps ) array_merge( $caps, $registered_caps ); - return array_unique( $caps ); + return array_diff( array_unique( $caps ), $do_not_add ); } /** diff --git a/inc/functions-capabilities.php b/inc/functions-capabilities.php index 73d997d..a5f3c9c 100644 --- a/inc/functions-capabilities.php +++ b/inc/functions-capabilities.php @@ -28,6 +28,17 @@ function members_register_caps() { do_action( 'members_register_caps' ); + + // The following is a quick way to register capabilities that technically + // exist (i.e., caps that have been added to a role). These are caps that + // we don't know about because they haven't been registered. + + $role_caps = array_values( members_get_role_capabilities() ); + $unregistered = array_diff( $role_caps, array_keys( members_get_caps() ) ); + + foreach ( $unregistered as $cap ) + members_register_cap( $cap, array( 'label' => $cap ) ); + } /** @@ -82,16 +93,8 @@ function members_register_default_caps() { $caps['upload_files'] = array( 'label' => __( 'Upload Files', 'members' ), 'group' => 'type-attachment' ); // Taxonomy caps. - //$caps['assign_categories'] = array( 'label' => __( 'Assign Categories', 'members' ), 'group' => 'taxonomy' ); - //$caps['edit_categories'] = array( 'label' => __( 'Edit Categories', 'members' ), 'group' => 'taxonomy' ); - //$caps['delete_categories'] = array( 'label' => __( 'Delete Categories', 'members' ), 'group' => 'taxonomy' ); $caps['manage_categories'] = array( 'label' => __( 'Manage Categories', 'members' ), 'group' => 'taxonomy' ); - //$caps['assign_post_tags'] = array( 'label' => __( 'Assign Tags', 'members' ), 'group' => 'taxonomy' ); - //$caps['edit_post_tags'] = array( 'label' => __( 'Edit Tags', 'members' ), 'group' => 'taxonomy' ); - //$caps['delete_post_tags'] = array( 'label' => __( 'Delete Tags', 'members' ), 'group' => 'taxonomy' ); - //$caps['manage_post_tags'] = array( 'label' => __( 'Manage Tags', 'members' ), 'group' => 'taxonomy' ); - // Theme caps. $caps['delete_themes'] = array( 'label' => __( 'Delete Themes', 'members' ), 'group' => 'theme' ); $caps['edit_theme_options'] = array( 'label' => __( 'Edit Theme Options', 'members' ), 'group' => 'theme' ); @@ -125,6 +128,29 @@ function members_register_default_caps() { // Register each of the capabilities. foreach ( $caps as $name => $args ) members_register_cap( $name, $args ); + + // === Category and Tag caps. === + // These are mapped to `manage_categories` in a default WP install. However, it's possible + // for another plugin to map these differently and handle them correctly. So, we're only + // going to register the caps if they've been assigned to a role. There's no other way + // to reliably detect if they've been mapped. + + $role_caps = array_values( members_get_role_capabilities() ); + $tax_caps = array(); + + $tax_caps['assign_categories'] = array( 'label' => __( 'Assign Categories', 'members' ), 'group' => 'taxonomy' ); + $tax_caps['edit_categories'] = array( 'label' => __( 'Edit Categories', 'members' ), 'group' => 'taxonomy' ); + $tax_caps['delete_categories'] = array( 'label' => __( 'Delete Categories', 'members' ), 'group' => 'taxonomy' ); + $tax_caps['assign_post_tags'] = array( 'label' => __( 'Assign Post Tags', 'members' ), 'group' => 'taxonomy' ); + $tax_caps['edit_post_tags'] = array( 'label' => __( 'Edit Post Tags', 'members' ), 'group' => 'taxonomy' ); + $tax_caps['delete_post_tags'] = array( 'label' => __( 'Delete Post Tags', 'members' ), 'group' => 'taxonomy' ); + $tax_caps['manage_post_tags'] = array( 'label' => __( 'Manage Post Tags', 'members' ), 'group' => 'taxonomy' ); + + foreach ( $tax_caps as $tax_cap => $args ) { + + if ( in_array( $tax_cap, $role_caps ) ) + members_register_cap( $tax_cap, $args ); + } } /** @@ -268,14 +294,8 @@ function members_get_cap_roles( $cap ) { */ function members_get_capabilities() { - // Merge the default WP, role, and plugin caps together. - $capabilities = array_merge( - array_keys( members_get_caps() ), - members_get_role_capabilities() - ); - // Apply filters to the array of capabilities. - $capabilities = apply_filters( 'members_get_capabilities', $capabilities ); + $capabilities = apply_filters( 'members_get_capabilities', array_keys( members_get_caps() ) ); // Sort the capabilities alphabetically. sort( $capabilities ); From a7e9b89d1bf53b4ac07471eb38f157b7acdfea79 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 5 Jul 2017 16:22:06 -0500 Subject: [PATCH 062/157] Update all references to `http` to `https` for `themehybrid.com`. --- admin/class-cap-control.php | 2 +- admin/class-cap-group.php | 2 +- admin/class-cap-section.php | 2 +- admin/class-cap-tabs.php | 2 +- admin/class-manage-roles.php | 2 +- admin/class-manage-users.php | 2 +- admin/class-meta-box-content-permissions.php | 2 +- admin/class-meta-box-custom-cap.php | 2 +- admin/class-meta-box-publish-role.php | 2 +- admin/class-role-edit.php | 2 +- admin/class-role-group.php | 2 +- admin/class-role-list-table.php | 2 +- admin/class-role-new.php | 2 +- admin/class-roles.php | 2 +- admin/class-settings.php | 2 +- admin/class-user-edit.php | 2 +- admin/class-user-new.php | 2 +- admin/functions-admin.php | 2 +- admin/functions-cap-groups.php | 2 +- admin/functions-help.php | 4 ++-- admin/functions-role-groups.php | 2 +- admin/functions-settings.php | 2 +- admin/tmpl/cap-control.php | 2 +- admin/tmpl/cap-section.php | 2 +- admin/views/class-settings-view-add-ons.php | 2 +- admin/views/class-settings-view-general.php | 4 ++-- admin/views/class-settings-view.php | 2 +- inc/class-capability.php | 2 +- inc/class-registry.php | 2 +- inc/class-role.php | 2 +- inc/class-widget-login.php | 2 +- inc/class-widget-users.php | 2 +- inc/functions-admin-bar.php | 2 +- inc/functions-capabilities.php | 2 +- inc/functions-deprecated.php | 2 +- inc/functions-options.php | 2 +- inc/functions-private-site.php | 2 +- inc/functions-roles.php | 2 +- inc/functions-shortcodes.php | 2 +- inc/functions-users.php | 2 +- inc/functions-widgets.php | 2 +- inc/functions.php | 2 +- inc/template.php | 2 +- members.php | 6 +++--- readme.md | 2 +- readme.txt | 12 ++++++------ 46 files changed, 55 insertions(+), 55 deletions(-) diff --git a/admin/class-cap-control.php b/admin/class-cap-control.php index 5cf65a6..17de4df 100644 --- a/admin/class-cap-control.php +++ b/admin/class-cap-control.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-cap-group.php b/admin/class-cap-group.php index ab36760..d39d72b 100644 --- a/admin/class-cap-group.php +++ b/admin/class-cap-group.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-cap-section.php b/admin/class-cap-section.php index db2f6b4..2556133 100644 --- a/admin/class-cap-section.php +++ b/admin/class-cap-section.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-cap-tabs.php b/admin/class-cap-tabs.php index e5cf5ff..6597eae 100644 --- a/admin/class-cap-tabs.php +++ b/admin/class-cap-tabs.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-manage-roles.php b/admin/class-manage-roles.php index 898763f..440c290 100644 --- a/admin/class-manage-roles.php +++ b/admin/class-manage-roles.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-manage-users.php b/admin/class-manage-users.php index 5665020..033dabb 100644 --- a/admin/class-manage-users.php +++ b/admin/class-manage-users.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-meta-box-content-permissions.php b/admin/class-meta-box-content-permissions.php index facd8b7..9288e8f 100644 --- a/admin/class-meta-box-content-permissions.php +++ b/admin/class-meta-box-content-permissions.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-meta-box-custom-cap.php b/admin/class-meta-box-custom-cap.php index a602330..453819f 100644 --- a/admin/class-meta-box-custom-cap.php +++ b/admin/class-meta-box-custom-cap.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-meta-box-publish-role.php b/admin/class-meta-box-publish-role.php index c48b5d7..39c8b4f 100644 --- a/admin/class-meta-box-publish-role.php +++ b/admin/class-meta-box-publish-role.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-role-edit.php b/admin/class-role-edit.php index 0dedaa7..63ec605 100644 --- a/admin/class-role-edit.php +++ b/admin/class-role-edit.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-role-group.php b/admin/class-role-group.php index 45518fd..68bd95c 100644 --- a/admin/class-role-group.php +++ b/admin/class-role-group.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-role-list-table.php b/admin/class-role-list-table.php index ce66abd..58a8dc0 100644 --- a/admin/class-role-list-table.php +++ b/admin/class-role-list-table.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-role-new.php b/admin/class-role-new.php index e09d6ec..2461f89 100644 --- a/admin/class-role-new.php +++ b/admin/class-role-new.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-roles.php b/admin/class-roles.php index 3becc7d..4cbc87d 100644 --- a/admin/class-roles.php +++ b/admin/class-roles.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-settings.php b/admin/class-settings.php index 4f5c6a9..e0ad9ec 100644 --- a/admin/class-settings.php +++ b/admin/class-settings.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-user-edit.php b/admin/class-user-edit.php index 5f67763..b43be6a 100644 --- a/admin/class-user-edit.php +++ b/admin/class-user-edit.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-user-new.php b/admin/class-user-new.php index e98ae8f..8ebb0e5 100644 --- a/admin/class-user-new.php +++ b/admin/class-user-new.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/functions-admin.php b/admin/functions-admin.php index 8f6444d..9b8e16a 100644 --- a/admin/functions-admin.php +++ b/admin/functions-admin.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/functions-cap-groups.php b/admin/functions-cap-groups.php index 7f51170..d89027d 100644 --- a/admin/functions-cap-groups.php +++ b/admin/functions-cap-groups.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/functions-help.php b/admin/functions-help.php index d0bb481..1af6b66 100644 --- a/admin/functions-help.php +++ b/admin/functions-help.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ @@ -21,7 +21,7 @@ function members_get_help_sidebar_text() { // Get docs and help links. $docs_link = sprintf( '
  • %s
  • ', esc_html__( 'Documentation', 'members' ) ); - $help_link = sprintf( '
  • %s
  • ', esc_html__( 'Support Forums', 'members' ) ); + $help_link = sprintf( '
  • %s
  • ', esc_html__( 'Support Forums', 'members' ) ); // Return the text. return sprintf( diff --git a/admin/functions-role-groups.php b/admin/functions-role-groups.php index 03abc72..ba96b91 100644 --- a/admin/functions-role-groups.php +++ b/admin/functions-role-groups.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/functions-settings.php b/admin/functions-settings.php index d3d0ff5..4c01147 100644 --- a/admin/functions-settings.php +++ b/admin/functions-settings.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/tmpl/cap-control.php b/admin/tmpl/cap-control.php index 9e18428..4bdf729 100644 --- a/admin/tmpl/cap-control.php +++ b/admin/tmpl/cap-control.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ ?> diff --git a/admin/tmpl/cap-section.php b/admin/tmpl/cap-section.php index c202edf..0fe0a06 100644 --- a/admin/tmpl/cap-section.php +++ b/admin/tmpl/cap-section.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ ?> diff --git a/admin/views/class-settings-view-add-ons.php b/admin/views/class-settings-view-add-ons.php index d91bebd..97f2abd 100644 --- a/admin/views/class-settings-view-add-ons.php +++ b/admin/views/class-settings-view-add-ons.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/views/class-settings-view-general.php b/admin/views/class-settings-view-general.php index 8fadce1..882e918 100644 --- a/admin/views/class-settings-view-general.php +++ b/admin/views/class-settings-view-general.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ @@ -394,7 +394,7 @@ public function add_help_tabs() { // Get docs and help links. $docs_link = sprintf( '
  • %s
  • ', esc_html__( 'Documentation', 'members' ) ); - $help_link = sprintf( '
  • %s
  • ', esc_html__( 'Support Forums', 'members' ) ); + $help_link = sprintf( '
  • %s
  • ', esc_html__( 'Support Forums', 'members' ) ); $tut_link = sprintf( '
  • %s
  • ', esc_html__( 'Users, Roles, and Capabilities', 'members' ) ); // Set the help sidebar. diff --git a/admin/views/class-settings-view.php b/admin/views/class-settings-view.php index 442763f..906758a 100644 --- a/admin/views/class-settings-view.php +++ b/admin/views/class-settings-view.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-capability.php b/inc/class-capability.php index b0e6962..669142e 100644 --- a/inc/class-capability.php +++ b/inc/class-capability.php @@ -6,7 +6,7 @@ * @subpackage Includes * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-registry.php b/inc/class-registry.php index d835e04..8f9827d 100644 --- a/inc/class-registry.php +++ b/inc/class-registry.php @@ -6,7 +6,7 @@ * @subpackage Admin * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-role.php b/inc/class-role.php index 524eaa4..4d8d5ca 100644 --- a/inc/class-role.php +++ b/inc/class-role.php @@ -7,7 +7,7 @@ * @subpackage Includes * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-widget-login.php b/inc/class-widget-login.php index c9f1d86..dae4d47 100644 --- a/inc/class-widget-login.php +++ b/inc/class-widget-login.php @@ -6,7 +6,7 @@ * @subpackage Includes * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-widget-users.php b/inc/class-widget-users.php index 4343b3b..74c217d 100644 --- a/inc/class-widget-users.php +++ b/inc/class-widget-users.php @@ -6,7 +6,7 @@ * @subpackage Includes * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-admin-bar.php b/inc/functions-admin-bar.php index 2e3b7a3..7a4d43c 100644 --- a/inc/functions-admin-bar.php +++ b/inc/functions-admin-bar.php @@ -6,7 +6,7 @@ * @subpackage Includes * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-capabilities.php b/inc/functions-capabilities.php index a5f3c9c..8735d10 100644 --- a/inc/functions-capabilities.php +++ b/inc/functions-capabilities.php @@ -6,7 +6,7 @@ * @subpackage Includes * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-deprecated.php b/inc/functions-deprecated.php index 697fea8..f32f6a2 100644 --- a/inc/functions-deprecated.php +++ b/inc/functions-deprecated.php @@ -6,7 +6,7 @@ * @subpackage Includes * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-options.php b/inc/functions-options.php index 1fc68be..e9f59a8 100644 --- a/inc/functions-options.php +++ b/inc/functions-options.php @@ -6,7 +6,7 @@ * @subpackage Includes * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-private-site.php b/inc/functions-private-site.php index 49787ca..eb62bce 100644 --- a/inc/functions-private-site.php +++ b/inc/functions-private-site.php @@ -8,7 +8,7 @@ * @subpackage Includes * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-roles.php b/inc/functions-roles.php index 0c89f16..0c47bc1 100644 --- a/inc/functions-roles.php +++ b/inc/functions-roles.php @@ -6,7 +6,7 @@ * @subpackage Includes * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-shortcodes.php b/inc/functions-shortcodes.php index eea849d..7d2d16c 100644 --- a/inc/functions-shortcodes.php +++ b/inc/functions-shortcodes.php @@ -6,7 +6,7 @@ * @subpackage Includes * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-users.php b/inc/functions-users.php index d1913b3..67423e8 100644 --- a/inc/functions-users.php +++ b/inc/functions-users.php @@ -6,7 +6,7 @@ * @subpackage Includes * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-widgets.php b/inc/functions-widgets.php index d5c7e11..10dee80 100644 --- a/inc/functions-widgets.php +++ b/inc/functions-widgets.php @@ -6,7 +6,7 @@ * @subpackage Includes * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions.php b/inc/functions.php index cb42d5c..8857e44 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -6,7 +6,7 @@ * @subpackage Includes * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/template.php b/inc/template.php index 59cb271..4e688c1 100644 --- a/inc/template.php +++ b/inc/template.php @@ -6,7 +6,7 @@ * @subpackage Includes * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/members.php b/members.php index e9707ab..66f9195 100644 --- a/members.php +++ b/members.php @@ -1,11 +1,11 @@ * @copyright Copyright (c) 2009 - 2017, Justin Tadlock - * @link http://themehybrid.com/plugins/members + * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/readme.md b/readme.md index 67b9b52..d1fcdc8 100644 --- a/readme.md +++ b/readme.md @@ -17,7 +17,7 @@ It puts you in control over permissions on your site by providing a user interfa ## Professional Support -If you need professional plugin support from me, the plugin author, you can access the support forums at [Theme Hybrid](http://themehybrid.com/board/topics), which is a professional WordPress help/support site where I handle support for all my plugins and themes for a community of 60,000+ users (and growing). +If you need professional plugin support from me, the plugin author, you can access the support forums at [Theme Hybrid](https://themehybrid.com/board/topics), which is a professional WordPress help/support site where I handle support for all my plugins and themes for a community of 60,000+ users (and growing). ## Copyright and License diff --git a/readme.txt b/readme.txt index 8cc8a48..d0f5f0d 100644 --- a/readme.txt +++ b/readme.txt @@ -1,7 +1,7 @@ === Members === Contributors: greenshady -Donate link: http://themehybrid.com/donate +Donate link: https://themehybrid.com/donate Tags: admin, role, roles, member, members, profile, shortcode, user, users, widget, widgets Requires at least: 4.3 Tested up to: 4.7.2 @@ -27,19 +27,19 @@ It puts you in control over permissions on your site by providing a user interfa * **Private Site:** You can make your site and its feed completely private if you want. * **Plugin Integration:** Members is highly recommended by other WordPress developers. Many existing plugins integrate their custom roles and caps directly into it. -For more info, vist the [Members plugin home page](http://themehybrid.com/plugins/members). +For more info, vist the [Members plugin home page](https://themehybrid.com/plugins/members). ### Like this plugin? The Members plugin is a massive project with 1,000s of lines of code to maintain. A major update can take weeks or months of work. I don't make any money directly from this plugin while other, similar plugins charge substantial fees to even download them or get updates. Please consider helping the cause by: -* [Making a donation](http://themehybrid.com/donate). -* [Signing up at my site](http://themehybrid.com/club). +* [Making a donation](https://themehybrid.com/donate). +* [Signing up at my site](https://themehybrid.com/club). * [Rating the plugin](https://wordpress.org/support/view/plugin-reviews/members?rate=5#postform). ### Professional Support -If you need professional plugin support from me, the plugin author, you can access the support forums at [Theme Hybrid](http://themehybrid.com/board/topics), which is a professional WordPress help/support site where I handle support for all my plugins and themes for a community of 60,000+ users (and growing). +If you need professional plugin support from me, the plugin author, you can access the support forums at [Theme Hybrid](https://themehybrid.com/board/topics), which is a professional WordPress help/support site where I handle support for all my plugins and themes for a community of 60,000+ users (and growing). ### Plugin Development @@ -77,7 +77,7 @@ If, for some reason, you do have the administrator role and the role manager is Please read the documentation for the plugin before actually using it, especially a plugin that controls permissions for your site. I cannot stress this enough. This is a powerful plugin that allows you to make direct changes to roles and capabilities in the database. -You'll need to stop by my [support forums](http://themehybrid.com/board/topics) to see if we can get your site fixed if you managed to lock yourself out. I know that this can be a bit can be a bit scary, but it's not that tough to fix with a little custom code. +You'll need to stop by my [support forums](https://themehybrid.com/board/topics) to see if we can get your site fixed if you managed to lock yourself out. I know that this can be a bit can be a bit scary, but it's not that tough to fix with a little custom code. == Screenshots == From 03bc42ca368413b3f663d9f5a725b0bddcb9542c Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sat, 8 Jul 2017 17:49:55 -0500 Subject: [PATCH 063/157] First pass at integrating with an external API for handling add-ons. Note that the API is not yet live, so we're just outputting an error message for the time being. This commit also introduces a Members add-on API for registering add-ons. Third-party plugins can hook in and recommend their own add-ons. --- admin/class-addon.php | 173 +++++++++++++++++ admin/functions-addons.php | 144 ++++++++++++++ admin/views/class-settings-view-add-ons.php | 179 ++++++++++-------- img/add-ons/icon-members-role-levels.png | Bin 6006 -> 0 bytes ...n-members-role-hierarchy.png => addon.png} | Bin 5 files changed, 412 insertions(+), 84 deletions(-) create mode 100644 admin/class-addon.php create mode 100644 admin/functions-addons.php delete mode 100644 img/add-ons/icon-members-role-levels.png rename img/{add-ons/icon-members-role-hierarchy.png => addon.png} (100%) diff --git a/admin/class-addon.php b/admin/class-addon.php new file mode 100644 index 0000000..2ccc1c1 --- /dev/null +++ b/admin/class-addon.php @@ -0,0 +1,173 @@ + + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @link https://themehybrid.com/plugins/members + * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + */ + +namespace Members; + +/** + * Add-on object class. + * + * @since 2.0.0 + * @access public + */ +final class Addon { + + /** + * Name/ID for the addon. + * + * @since 2.0.0 + * @access protected + * @var string + */ + public $name = ''; + + /** + * Title of the add-on. + * + * @since 2.0.0 + * @access protected + * @var string + */ + public $title = ''; + + /** + * Short description of the add-on. + * + * @since 2.0.0 + * @access protected + * @var string + */ + public $excerpt = ''; + + /** + * URL where the add-on can be found. + * + * @since 2.0.0 + * @access protected + * @var string + */ + public $url = 'https://themehybrid.com/plugins/members'; + + /** + * Add-on ZIP file URL. + * + * @since 2.0.0 + * @access protected + * @var string + */ + public $download_url = ''; + + /** + * Alternate purchase URL. + * + * @since 2.0.0 + * @access protected + * @var string + */ + public $purchase_url = ''; + + /** + * URL for a 128x128 (size used by WordPress.org) icon image. + * + * @since 2.0.0 + * @access protected + * @var string + */ + public $icon_url = ''; + + /** + * Add-on plugin's author URL. + * + * @since 2.0.0 + * @access protected + * @var string + */ + public $author_url = ''; + + /** + * Add-on plugin's author display name. + * + * @since 2.0.0 + * @access protected + * @var string + */ + public $author_name = ''; + + /** + * Rating for the add-on. This is the total rating based on a 5-star rating system. + * It will be divided by the rating count, so both must be supplied. + * + * @since 2.0.0 + * @access protected + * @var int + */ + public $rating = ''; + + /** + * Number of ratings. + * + * @since 2.0.0 + * @access protected + * @var int + */ + public $rating_count = 0; + + /** + * Number of active installs. Note that this will be displayed with a `+` at + * the end, such as `100,000+`. Exact counts are necessary. Just a round number. + * + * @since 2.0.0 + * @access protected + * @var string + */ + public $install_count = 0; + + /** + * Magic method to use in case someone tries to output the object as a string. + * We'll just return the name. + * + * @since 2.0.0 + * @access public + * @return string + */ + public function __toString() { + return $this->name; + } + + /** + * Register a new object. + * + * @since 2.0.0 + * @access public + * @param string $name + * @param array $args { + * @type string $label Internationalized text label. + * @type string $icon Dashicon icon in the form of `dashicons-icon-name`. + * @type array $caps Array of capabilities in the addon. + * @type bool $merge_added Whether to merge this caps into the added caps array. + * @type bool $diff_added Whether to remove previously-added caps from this addon. + * } + * @return void + */ + public function __construct( $name, $args = array() ) { + + foreach ( array_keys( get_object_vars( $this ) ) as $key ) { + + if ( isset( $args[ $key ] ) ) + $this->$key = $args[ $key ]; + } + + $this->name = sanitize_key( $name ); + + if ( ! $this->icon_url ) + $this->icon_url = members_plugin()->dir_uri . 'img/addon.png'; + } +} diff --git a/admin/functions-addons.php b/admin/functions-addons.php new file mode 100644 index 0000000..996e66a --- /dev/null +++ b/admin/functions-addons.php @@ -0,0 +1,144 @@ + + * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @link https://themehybrid.com/plugins/members + * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + */ + +# Register addons. +add_action( 'members_register_addons', 'members_register_default_addons', 5 ); + +/** + * Registers any addons stored globally with WordPress. + * + * @since 2.0.0 + * @access public + * @param object $wp_addons + * @return void + */ +function members_register_default_addons() { + + /**/ + // Comment out for local testing. + return; + /**/ + + // Sandbox URL for the time being. + $url = 'http://localhost/api/th/v1/plugins?addons=members'; + + // Get data from the remote URL. + $response = wp_remote_get( $url ); + + // Bail if we get no response. + if ( is_wp_error( $response ) ) + return; + + // Decode the data that we got. + $data = json_decode( wp_remote_retrieve_body( $response ) ); + + // If we have an array of data, let's roll. + if ( ! empty( $data ) && is_array( $data ) ) { + + foreach ( $data as $addon ) { + + $args = array( + 'title' => $addon->title, + 'excerpt' => $addon->excerpt, + 'url' => $addon->url, + 'purchase_url' => $addon->meta->purchase_url, + 'download_url' => $addon->meta->download_url, + 'rating' => $addon->meta->rating, + 'rating_count' => $addon->meta->rating_count, + 'install_count' => $addon->meta->install_count, + 'icon_url' => $addon->media->icon->url, + 'author_url' => $addon->author->url, + 'author_name' => $addon->author->name + ); + + members_register_addon( $addon->slug, $args ); + } + } +} + +/** + * Returns the instance of the addon registry. + * + * @since 2.0.0 + * @access public + * @return object + */ +function members_addon_registry() { + + return \Members\Registry::get_instance( 'addon' ); +} + +/** + * Returns all registered addons. + * + * @since 2.0.0 + * @access public + * @return array + */ +function members_get_addons() { + + return members_addon_registry()->get_collection(); +} + +/** + * Registers a addon. + * + * @since 2.0.0 + * @access public + * @param string $name + * @param array $args + * @return void + */ +function members_register_addon( $name, $args = array() ) { + + members_addon_registry()->register( $name, new \Members\Addon( $name, $args ) ); +} + +/** + * Unregisters a addon. + * + * @since 2.0.0 + * @access public + * @param string $name + * @return void + */ +function members_unregister_addon( $name ) { + + members_addon_registry()->unregister( $name ); +} + +/** + * Returns a addon object. + * + * @since 2.0.0 + * @access public + * @param string $name + * @return object + */ +function members_get_addon( $name ) { + + return members_addon_registry()->get( $name ); +} + +/** + * Checks if a addon object exists. + * + * @since 2.0.0 + * @access public + * @param string $name + * @return bool + */ +function members_addon_exists( $name ) { + + return members_addon_registry()->exists( $name ); +} diff --git a/admin/views/class-settings-view-add-ons.php b/admin/views/class-settings-view-add-ons.php index 97f2abd..cbb05d3 100644 --- a/admin/views/class-settings-view-add-ons.php +++ b/admin/views/class-settings-view-add-ons.php @@ -25,54 +25,123 @@ class Members_Settings_View_Add_Ons extends Members_Settings_View { * @access public * @return void */ - public function template() { ?> + public function template() { + + require_once( members_plugin()->admin_dir . 'class-addon.php' ); + require_once( members_plugin()->admin_dir . 'functions-addons.php' ); + + do_action( 'members_register_addons' ); + + $addons = members_get_addons(); ?>
    - get_add_ons() as $addon ) : ?> + + + + + addon_card( $addon ); ?> + + + + + +
    +

    + +

    +
    + + + +
    + + +
    -
    +
    -
    + - + +
    + + rating && $addon->rating_count ) : ?> - - +
    + 'rating', 'rating' => floatval( $addon->rating ), 'number' => absint( $addon->rating_count ) ) ); ?> +
    -
    - excerpt ) ); ?> + -

    - %s', esc_url( $addon->author_url ), esc_html( $addon->author ) ); ?> + install_count ) : ?> - -

    +
    + install_count ) ) + ); ?>
    -
    -
    - + + +
    -
    +
    set_help_sidebar( members_get_help_sidebar_text() ); } - - /** - * Returns a list of add-ons for the Members plugin. This function is temporary until - * we can get a proper API set up on Theme Hybrid to allow this data to be sent over. - * - * @since 2.0.0 - * @access private - * @return array - */ - private function get_add_ons() { - - $addons = array(); - - $defaults = array( - 'title' => '', - 'excerpt' => '', - 'url' => '', - 'author' => '', - 'author_url' => '', - 'purchase_url' => '', - 'wporg_slug' => '', - 'download_count' => '', - 'install_count' => '', - 'icon_url' => '', - 'slug' => '' - ); - - $_addons = array( - - 'members-role-hierarchy' => array( - 'title' => 'Members - Role Hierarchy', - 'url' => 'https://themehybrid.com/plugins/members-role-hierarchy', - 'excerpt' => 'Add-on plugin for Members for hierarchical user roles.', - 'icon_url' => members_plugin()->dir_uri . 'img/add-ons/icon-members-role-hierarchy.png', - 'author' => 'Justin Tadlock', - 'author_url' => 'https://themehybrid.com' - ), - - 'members-role-levels' => array( - 'title' => 'Members - Role Levels', - 'url' => 'https://themehybrid.com/plugins/members-role-levels', - 'purchase_url' => 'https://themehybrid.com/plugins/members-role-levels', - 'excerpt' => "Exposes the old user levels system, which fixes the WordPress author drop-down bug.", - 'icon_url' => members_plugin()->dir_uri . 'img/add-ons/icon-members-role-levels.png', - 'author' => 'Justin Tadlock', - 'author_url' => 'https://themehybrid.com' - ) - ); - - foreach ( $_addons as $slug => $args ) { - - $addons[ $slug ] = (object) wp_parse_args( $args, $defaults ); - - $addons[ $slug ]->slug = $slug; - } - - return $addons; - } } diff --git a/img/add-ons/icon-members-role-levels.png b/img/add-ons/icon-members-role-levels.png deleted file mode 100644 index 3b31c16b9e66501383807b89c48f503e0e176e56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6006 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 diff --git a/img/add-ons/icon-members-role-hierarchy.png b/img/addon.png similarity index 100% rename from img/add-ons/icon-members-role-hierarchy.png rename to img/addon.png From 22ae6cd98caf2d9e40a33b965d8d174704f4ae18 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 10 Jul 2017 10:07:29 -0500 Subject: [PATCH 064/157] Adds a temporary `addons.json` file for testing the add-ons page. --- admin/addons.json | 43 ++++++++++++++++++++++++++++++++++++++ admin/functions-addons.php | 8 ++----- 2 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 admin/addons.json diff --git a/admin/addons.json b/admin/addons.json new file mode 100644 index 0000000..1aa0a2e --- /dev/null +++ b/admin/addons.json @@ -0,0 +1,43 @@ +[ + { + "title" : "Members - Role Levels", + "url" : "https:\/\/themehybrid.com\/plugins\/members-role-levels", + "slug" : "members-role-levels", + "excerpt" : "

    Exposes the old user levels system, which fixes the WordPress author drop-down bug when users don’t have a role with one of the assigned levels.<\/p>\n", + "author" : { + "name" : "Justin Tadlock", + "url" : "https:\/\/themehybrid.com\/plugins\/authors\/admin" + }, + "meta" : { + "purchase_url" : "https:\/\/themehybrid.com\/plugins\/members-role-levels", + "download_url" : "", + "rating" : 0, + "rating_count" : 0, + "install_count" : 0 + },"media" : { + "banner" : {"url" : ""}, + "icon" : {"url" : ""} + } + }, + { + "title" : "Members - Role Hierarchy", + "url" : "https:\/\/themehybrid.com\/plugins\/members-role-hierarchy", + "slug" : "members-role-hierarchy", + "excerpt" : "

    Add-on plugin for Members for hierarchical user roles.<\/p>\n", + "author" : { + "name" : "Justin Tadlock", + "url" : "https:\/\/themehybrid.com\/plugins\/authors\/admin" + }, + "meta" : { + "purchase_url" : "", + "download_url" : "https:\/\/themehybrid.com\/plugins\/members-role-hierarchy", + "rating" : 0, + "rating_count" : 0, + "install_count" : 100 + },"media" : { + "banner" : { "url" : "" }, + "icon" : { "url" : "" } + } + } +] + diff --git a/admin/functions-addons.php b/admin/functions-addons.php index 996e66a..3075bbe 100644 --- a/admin/functions-addons.php +++ b/admin/functions-addons.php @@ -24,13 +24,9 @@ */ function members_register_default_addons() { - /**/ - // Comment out for local testing. - return; - /**/ - // Sandbox URL for the time being. - $url = 'http://localhost/api/th/v1/plugins?addons=members'; + // $url = 'http://localhost/api/th/v1/plugins?addons=members'; + $url = members_plugin()->dir_uri . 'admin/addons.json'; // Get data from the remote URL. $response = wp_remote_get( $url ); From 63c01c5bbce2a149f0b2ef565a421c45a7b314a9 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 10 Jul 2017 14:41:36 -0500 Subject: [PATCH 065/157] Use the `Members\Admin` namespace for settings classes. --- admin/class-settings.php | 6 ++++-- admin/functions-settings.php | 4 ++-- admin/views/class-settings-view-add-ons.php | 4 +++- admin/views/class-settings-view-general.php | 4 +++- admin/views/class-settings-view.php | 4 +++- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/admin/class-settings.php b/admin/class-settings.php index e0ad9ec..def4742 100644 --- a/admin/class-settings.php +++ b/admin/class-settings.php @@ -10,13 +10,15 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Sets up and handles the plugin settings screen. * * @since 1.0.0 * @access public */ -final class Members_Settings_Page { +final class Settings_Page { /** * Settings page name. @@ -312,4 +314,4 @@ private function filter_links() { ?> public function add_help_tabs() {} } -Members_Settings_Page::get_instance(); +Settings_Page::get_instance(); diff --git a/admin/functions-settings.php b/admin/functions-settings.php index 4c01147..289f224 100644 --- a/admin/functions-settings.php +++ b/admin/functions-settings.php @@ -25,7 +25,7 @@ function members_register_default_settings_views( $manager ) { // Register general settings view (default view). $manager->register_view( - new Members_Settings_View_General( + new \Members\Admin\View_General( 'general', array( 'label' => esc_html__( 'General', 'members' ), @@ -36,7 +36,7 @@ function members_register_default_settings_views( $manager ) { // Register add-ons view. $manager->register_view( - new Members_Settings_View_Add_Ons( + new \Members\Admin\View_Addons( 'add-ons', array( 'label' => esc_html__( 'Add-Ons', 'members' ), diff --git a/admin/views/class-settings-view-add-ons.php b/admin/views/class-settings-view-add-ons.php index cbb05d3..2de60f7 100644 --- a/admin/views/class-settings-view-add-ons.php +++ b/admin/views/class-settings-view-add-ons.php @@ -10,13 +10,15 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Sets up and handles the add-ons settings view. * * @since 2.0.0 * @access public */ -class Members_Settings_View_Add_Ons extends Members_Settings_View { +class View_Addons extends View { /** * Renders the settings page. diff --git a/admin/views/class-settings-view-general.php b/admin/views/class-settings-view-general.php index 882e918..1e5a8fb 100644 --- a/admin/views/class-settings-view-general.php +++ b/admin/views/class-settings-view-general.php @@ -10,13 +10,15 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Sets up and handles the general settings view. * * @since 2.0.0 * @access public */ -class Members_Settings_View_General extends Members_Settings_View { +class View_General extends View { /** * Holds an array the plugin settings. diff --git a/admin/views/class-settings-view.php b/admin/views/class-settings-view.php index 906758a..baaed3f 100644 --- a/admin/views/class-settings-view.php +++ b/admin/views/class-settings-view.php @@ -10,13 +10,15 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Settings view base class. * * @since 2.0.0 * @access public */ -class Members_Settings_View { +class View { /** * Name/ID for the group. From 9c7668c3684ea748ffa72a5f5359e741c970cfc3 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 10 Jul 2017 14:45:11 -0500 Subject: [PATCH 066/157] Rename view class files. --- admin/class-settings.php | 6 +++--- ...lass-settings-view-add-ons.php => class-view-addons.php} | 0 ...ass-settings-view-general.php => class-view-general.php} | 0 admin/views/{class-settings-view.php => class-view.php} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename admin/views/{class-settings-view-add-ons.php => class-view-addons.php} (100%) rename admin/views/{class-settings-view-general.php => class-view-general.php} (100%) rename admin/views/{class-settings-view.php => class-view.php} (100%) diff --git a/admin/class-settings.php b/admin/class-settings.php index def4742..1b70184 100644 --- a/admin/class-settings.php +++ b/admin/class-settings.php @@ -80,9 +80,9 @@ private function includes() { require_once( members_plugin()->admin_dir . 'functions-settings.php' ); // Load settings view classes. - require_once( members_plugin()->admin_dir . 'views/class-settings-view.php' ); - require_once( members_plugin()->admin_dir . 'views/class-settings-view-general.php' ); - require_once( members_plugin()->admin_dir . 'views/class-settings-view-add-ons.php' ); + require_once( members_plugin()->admin_dir . 'views/class-view.php' ); + require_once( members_plugin()->admin_dir . 'views/class-view-general.php' ); + require_once( members_plugin()->admin_dir . 'views/class-view-addons.php' ); } /** diff --git a/admin/views/class-settings-view-add-ons.php b/admin/views/class-view-addons.php similarity index 100% rename from admin/views/class-settings-view-add-ons.php rename to admin/views/class-view-addons.php diff --git a/admin/views/class-settings-view-general.php b/admin/views/class-view-general.php similarity index 100% rename from admin/views/class-settings-view-general.php rename to admin/views/class-view-general.php diff --git a/admin/views/class-settings-view.php b/admin/views/class-view.php similarity index 100% rename from admin/views/class-settings-view.php rename to admin/views/class-view.php From e9e8087c5d381928181929376542c7e81d199da2 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 10 Jul 2017 14:56:03 -0500 Subject: [PATCH 067/157] Move cap and role group classes and functions files to the `inc` directory. --- {admin => inc}/class-cap-group.php | 0 {admin => inc}/class-role-group.php | 0 {admin => inc}/functions-cap-groups.php | 0 {admin => inc}/functions-role-groups.php | 0 members.php | 10 ++++------ 5 files changed, 4 insertions(+), 6 deletions(-) rename {admin => inc}/class-cap-group.php (100%) rename {admin => inc}/class-role-group.php (100%) rename {admin => inc}/functions-cap-groups.php (100%) rename {admin => inc}/functions-role-groups.php (100%) diff --git a/admin/class-cap-group.php b/inc/class-cap-group.php similarity index 100% rename from admin/class-cap-group.php rename to inc/class-cap-group.php diff --git a/admin/class-role-group.php b/inc/class-role-group.php similarity index 100% rename from admin/class-role-group.php rename to inc/class-role-group.php diff --git a/admin/functions-cap-groups.php b/inc/functions-cap-groups.php similarity index 100% rename from admin/functions-cap-groups.php rename to inc/functions-cap-groups.php diff --git a/admin/functions-role-groups.php b/inc/functions-role-groups.php similarity index 100% rename from admin/functions-role-groups.php rename to inc/functions-role-groups.php diff --git a/members.php b/members.php index 66f9195..d7623e7 100644 --- a/members.php +++ b/members.php @@ -223,18 +223,22 @@ private function includes() { // Load class files. require_once( $this->inc_dir . 'class-capability.php' ); + require_once( $this->inc_dir . 'class-cap-group.php' ); require_once( $this->inc_dir . 'class-registry.php' ); + require_once( $this->inc_dir . 'class-role-group.php' ); require_once( $this->inc_dir . 'class-role.php' ); // Load includes files. require_once( $this->inc_dir . 'functions.php' ); require_once( $this->inc_dir . 'functions-admin-bar.php' ); require_once( $this->inc_dir . 'functions-capabilities.php' ); + require_once( $this->inc_dir . 'functions-cap-groups.php' ); require_once( $this->inc_dir . 'functions-content-permissions.php' ); require_once( $this->inc_dir . 'functions-deprecated.php' ); require_once( $this->inc_dir . 'functions-options.php' ); require_once( $this->inc_dir . 'functions-private-site.php' ); require_once( $this->inc_dir . 'functions-roles.php' ); + require_once( $this->inc_dir . 'functions-role-groups.php' ); require_once( $this->inc_dir . 'functions-shortcodes.php' ); require_once( $this->inc_dir . 'functions-users.php' ); require_once( $this->inc_dir . 'functions-widgets.php' ); @@ -268,16 +272,10 @@ private function includes() { require_once( $this->admin_dir . 'class-meta-box-publish-role.php' ); require_once( $this->admin_dir . 'class-meta-box-custom-cap.php' ); - // Role groups. - require_once( $this->admin_dir . 'class-role-group.php' ); - require_once( $this->admin_dir . 'functions-role-groups.php' ); - // Edit capabilities tabs and groups. require_once( $this->admin_dir . 'class-cap-tabs.php' ); require_once( $this->admin_dir . 'class-cap-section.php' ); require_once( $this->admin_dir . 'class-cap-control.php' ); - require_once( $this->admin_dir . 'class-cap-group.php' ); - require_once( $this->admin_dir . 'functions-cap-groups.php' ); } } From e55ef6dceeaa5e2296c031adc49d4dd010484fd2 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 10 Jul 2017 17:23:20 -0500 Subject: [PATCH 068/157] Update admin classes to use the `Members\Admin` namespace. --- admin/class-cap-control.php | 20 +++++---- admin/class-cap-section.php | 22 +++++----- admin/class-cap-tabs.php | 36 +++++++-------- admin/class-manage-roles.php | 30 +++++++------ admin/class-meta-box-content-permissions.php | 24 +++++----- admin/class-meta-box-custom-cap.php | 20 +++++---- admin/class-meta-box-publish-role.php | 20 +++++---- admin/class-role-edit.php | 28 ++++++------ admin/class-role-list-table.php | 46 ++++++++++---------- admin/class-role-new.php | 40 +++++++++-------- admin/class-roles.php | 30 +++++++------ admin/class-user-edit.php | 22 +++++----- 12 files changed, 181 insertions(+), 157 deletions(-) diff --git a/admin/class-cap-control.php b/admin/class-cap-control.php index 17de4df..58615d6 100644 --- a/admin/class-cap-control.php +++ b/admin/class-cap-control.php @@ -10,19 +10,21 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Cap control class. * - * @since 1.0.0 + * @since 2.0.0 * @access public */ -final class Members_Cap_Control { +final class Cap_Control { /** * Stores the cap tabs object. * * @see Members_Cap_Tabs - * @since 1.0.0 + * @since 2.0.0 * @access public * @var object */ @@ -31,7 +33,7 @@ final class Members_Cap_Control { /** * Name of the capability the control is for. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var string */ @@ -40,7 +42,7 @@ final class Members_Cap_Control { /** * ID of the section the control is for. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var string */ @@ -49,7 +51,7 @@ final class Members_Cap_Control { /** * Array of data to pass as a json object to the Underscore template. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var array */ @@ -58,7 +60,7 @@ final class Members_Cap_Control { /** * Creates a new control object. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @param object $manager * @param string $cap @@ -80,7 +82,7 @@ public function __construct( $manager, $cap, $args = array() ) { /** * Returns the json array. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return array */ @@ -92,7 +94,7 @@ public function json() { /** * Adds custom data to the json array. This data is passed to the Underscore template. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ diff --git a/admin/class-cap-section.php b/admin/class-cap-section.php index 2556133..12ef8ce 100644 --- a/admin/class-cap-section.php +++ b/admin/class-cap-section.php @@ -10,19 +10,21 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Cap section class. * - * @since 1.0.0 + * @since 2.0.0 * @access public */ -final class Members_Cap_Section { +final class Cap_Section { /** * Stores the cap tabs object. * * @see Members_Cap_Tabs - * @since 1.0.0 + * @since 2.0.0 * @access public * @var object */ @@ -31,7 +33,7 @@ final class Members_Cap_Section { /** * ID of the section. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var string */ @@ -40,7 +42,7 @@ final class Members_Cap_Section { /** * Dashicons icon for the section. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var string */ @@ -49,7 +51,7 @@ final class Members_Cap_Section { /** * Label for the section. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var string */ @@ -58,7 +60,7 @@ final class Members_Cap_Section { /** * Array of data to pass as a json object to the Underscore template. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var array */ @@ -67,7 +69,7 @@ final class Members_Cap_Section { /** * Creates a new section object. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @param object $manager * @param string $section @@ -89,7 +91,7 @@ public function __construct( $manager, $section, $args = array() ) { /** * Returns the json array. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return array */ @@ -101,7 +103,7 @@ public function json() { /** * Adds custom data to the json array. This data is passed to the Underscore template. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ diff --git a/admin/class-cap-tabs.php b/admin/class-cap-tabs.php index 6597eae..22b3bd1 100644 --- a/admin/class-cap-tabs.php +++ b/admin/class-cap-tabs.php @@ -10,18 +10,20 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Handles building the edit caps tabs. * - * @since 1.0.0 + * @since 2.0.0 * @access public */ -final class Members_Cap_Tabs { +final class Cap_Tabs { /** * The role object that we're creating tabs for. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var object */ @@ -30,7 +32,7 @@ final class Members_Cap_Tabs { /** * Array of caps shown by the cap tabs. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var array */ @@ -40,7 +42,7 @@ final class Members_Cap_Tabs { * The caps the role has. Note that if this is a new role (new role screen), the default * new role caps will be passed in. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var array */ @@ -49,7 +51,7 @@ final class Members_Cap_Tabs { /** * Array of tab sections. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var array */ @@ -58,7 +60,7 @@ final class Members_Cap_Tabs { /** * Array of single cap controls. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var array */ @@ -67,7 +69,7 @@ final class Members_Cap_Tabs { /** * Array of section json data. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var array */ @@ -76,7 +78,7 @@ final class Members_Cap_Tabs { /** * Array of control json data. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var array */ @@ -85,7 +87,7 @@ final class Members_Cap_Tabs { /** * Sets up the cap tabs. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @param string $role * @param array $has_caps @@ -118,7 +120,7 @@ public function __construct( $role = '', $has_caps = array() ) { * Registers the sections (and each section's controls) that will be used for * the tab content. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -145,7 +147,7 @@ public function register() { $this->added_caps = array_unique( array_merge( $this->added_caps, $caps ) ); // Create a new section. - $this->sections[] = $section = new Members_Cap_Section( $this, $group->name, array( 'icon' => $group->icon, 'label' => $group->label ) ); + $this->sections[] = $section = new Cap_Section( $this, $group->name, array( 'icon' => $group->icon, 'label' => $group->label ) ); // Get the section json data. $this->sections_json[] = $section->json(); @@ -153,7 +155,7 @@ public function register() { // Create new controls for each cap. foreach ( $caps as $cap ) { - $this->controls[] = $control = new Members_Cap_Control( $this, $cap, array( 'section' => $group->name ) ); + $this->controls[] = $control = new Cap_Control( $this, $cap, array( 'section' => $group->name ) ); // Get the control json data. $this->controls_json[] = $control->json(); @@ -167,7 +169,7 @@ public function register() { /** * Displays the cap tabs. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -192,7 +194,7 @@ public function display() { ?> /** * Outputs the tab nav. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -216,7 +218,7 @@ public function tab_nav() { ?> /** * Passes our sections and controls data as json to the `edit-role.js` file. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -229,7 +231,7 @@ public function localize_scripts() { /** * Outputs the Underscore JS templates. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ diff --git a/admin/class-manage-roles.php b/admin/class-manage-roles.php index 440c290..5a46043 100644 --- a/admin/class-manage-roles.php +++ b/admin/class-manage-roles.php @@ -10,18 +10,20 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Role management class. * - * @since 1.0.0 + * @since 2.0.0 * @access public */ -final class Members_Admin_Manage_Roles { +final class Manage_Roles { /** * Holds the instances of this class. * - * @since 1.0.0 + * @since 2.0.0 * @access private * @var object */ @@ -30,7 +32,7 @@ final class Members_Admin_Manage_Roles { /** * Name of the page we've created. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var string */ @@ -39,7 +41,7 @@ final class Members_Admin_Manage_Roles { /** * The page object to show. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var object */ @@ -48,7 +50,7 @@ final class Members_Admin_Manage_Roles { /** * Sets up our initial actions. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -62,7 +64,7 @@ public function __construct() { /** * Adds the roles page to the admin. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -94,11 +96,11 @@ public function add_admin_page() { // If viewing the edit role page. if ( isset( $_REQUEST['action'] ) && 'edit' === $_REQUEST['action'] && current_user_can( 'edit_roles' ) ) - $this->page_obj = new Members_Admin_Role_Edit(); + $this->page_obj = new Role_Edit(); // If viewing the role list page. else - $this->page_obj = new Members_Admin_Roles(); + $this->page_obj = new Roles(); // Load actions. add_action( "load-{$this->page}", array( $this, 'load' ) ); @@ -111,7 +113,7 @@ public function add_admin_page() { /** * Checks posted data on load and performs actions if needed. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -124,7 +126,7 @@ public function load() { /** * Loads necessary scripts/styles. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @param string $hook_suffix * @return void @@ -138,7 +140,7 @@ public function enqueue( $hook_suffix ) { /** * Outputs the page. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -151,7 +153,7 @@ public function page() { /** * Returns the instance. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return object */ @@ -164,4 +166,4 @@ public static function get_instance() { } } -Members_Admin_Manage_Roles::get_instance(); +Manage_Roles::get_instance(); diff --git a/admin/class-meta-box-content-permissions.php b/admin/class-meta-box-content-permissions.php index 9288e8f..3e1b68a 100644 --- a/admin/class-meta-box-content-permissions.php +++ b/admin/class-meta-box-content-permissions.php @@ -10,18 +10,20 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Class to handle the content permissios meta box and saving the meta. * - * @since 1.0.0 + * @since 2.0.0 * @access public */ -final class Members_Meta_Box_Content_Permissions { +final class Meta_Box_Content_Permissions { /** * Holds the instances of this class. * - * @since 1.0.0 + * @since 2.0.0 * @access private * @var object */ @@ -41,7 +43,7 @@ final class Members_Meta_Box_Content_Permissions { /** * Sets up the appropriate actions. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @return void */ @@ -59,7 +61,7 @@ protected function __construct() { * Fires on the page load hook to add actions specifically for the post and * new post screens. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -85,7 +87,7 @@ public function load() { /** * Enqueues scripts styles. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -98,7 +100,7 @@ public function enqueue() { /** * Adds the meta box. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @param string $post_type * @return void @@ -134,7 +136,7 @@ public function maybe_enable() { /** * Outputs the meta box HTML. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @param object $post * @global object $wp_roles @@ -234,7 +236,7 @@ public function meta_box( $post ) { /** * Saves the post meta. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @param int $post_id * @param object $post @@ -294,7 +296,7 @@ public function update( $post_id, $post = '' ) { /** * Returns the instance. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return object */ @@ -307,4 +309,4 @@ public static function get_instance() { } } -Members_Meta_Box_Content_Permissions::get_instance(); +Meta_Box_Content_Permissions::get_instance(); diff --git a/admin/class-meta-box-custom-cap.php b/admin/class-meta-box-custom-cap.php index 453819f..727378a 100644 --- a/admin/class-meta-box-custom-cap.php +++ b/admin/class-meta-box-custom-cap.php @@ -10,18 +10,20 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Class to handle the new cap meta box on the edit/new role screen. * - * @since 1.0.0 + * @since 2.0.0 * @access public */ -final class Members_Meta_Box_Custom_Cap { +final class Meta_Box_Custom_Cap { /** * Holds the instances of this class. * - * @since 1.0.0 + * @since 2.0.0 * @access private * @var object */ @@ -30,7 +32,7 @@ final class Members_Meta_Box_Custom_Cap { /** * Adds our methods to the proper hooks. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -43,7 +45,7 @@ protected function __construct() { /** * Runs on the page load hook to hook in the meta boxes. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -55,7 +57,7 @@ public function load() { /** * Adds the meta box. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @param string $screen_id * @param string $role @@ -74,7 +76,7 @@ public function add_meta_boxes( $screen_id, $role = '' ) { /** * Outputs the meta box HTML. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -92,7 +94,7 @@ public function meta_box() { ?> /** * Returns the instance. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return object */ @@ -105,4 +107,4 @@ public static function get_instance() { } } -Members_Meta_Box_Custom_Cap::get_instance(); +Meta_Box_Custom_Cap::get_instance(); diff --git a/admin/class-meta-box-publish-role.php b/admin/class-meta-box-publish-role.php index 39c8b4f..080807b 100644 --- a/admin/class-meta-box-publish-role.php +++ b/admin/class-meta-box-publish-role.php @@ -10,18 +10,20 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Class to handle the role meta box edit/new role screen. * - * @since 1.0.0 + * @since 2.0.0 * @access public */ -final class Members_Meta_Box_Publish_Role { +final class Meta_Box_Publish_Role { /** * Holds the instances of this class. * - * @since 1.0.0 + * @since 2.0.0 * @access private * @var object */ @@ -30,7 +32,7 @@ final class Members_Meta_Box_Publish_Role { /** * Adds our methods to the proper hooks. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -43,7 +45,7 @@ protected function __construct() { /** * Runs on the page load hook to hook in the meta boxes. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -55,7 +57,7 @@ public function load() { /** * Adds the meta box. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @param string $screen_id * @return void @@ -68,7 +70,7 @@ public function add_meta_boxes( $screen_id ) { /** * Outputs the meta box HTML. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @param object $role * @return void @@ -140,7 +142,7 @@ public function meta_box( $role ) { /** * Returns the instance. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return object */ @@ -153,4 +155,4 @@ public static function get_instance() { } } -Members_Meta_Box_Publish_Role::get_instance(); +Meta_Box_Publish_Role::get_instance(); diff --git a/admin/class-role-edit.php b/admin/class-role-edit.php index 63ec605..ffb6337 100644 --- a/admin/class-role-edit.php +++ b/admin/class-role-edit.php @@ -10,18 +10,20 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Class that displays the edit role screen and handles the form submissions for that page. * - * @since 1.0.0 + * @since 2.0.0 * @access public */ -final class Members_Admin_Role_Edit { +final class Role_Edit { /** * Current role object to be edited/viewed. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @var object */ @@ -30,7 +32,7 @@ final class Members_Admin_Role_Edit { /** * Current Members role object to be edited/viewed. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @var object */ @@ -39,7 +41,7 @@ final class Members_Admin_Role_Edit { /** * Whether the current role can be edited. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @var bool */ @@ -48,7 +50,7 @@ final class Members_Admin_Role_Edit { /** * Available capabilities. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @var array */ @@ -57,7 +59,7 @@ final class Members_Admin_Role_Edit { /** * Whether the page was updated. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @var bool */ @@ -66,7 +68,7 @@ final class Members_Admin_Role_Edit { /** * Sets up some necessary actions/filters. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -79,7 +81,7 @@ public function __construct() { /** * Runs on the `load-{$page}` hook. This is the handler for form submissions. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -249,7 +251,7 @@ public function load() { /** * Adds help tabs. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -271,7 +273,7 @@ public function add_help_tabs() { /** * Enqueue scripts/styles. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -284,7 +286,7 @@ public function enqueue() { /** * Displays the page content. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -327,7 +329,7 @@ public function page() { ?>

    - role->name ); ?> + role->name ); ?> display(); ?> diff --git a/admin/class-role-list-table.php b/admin/class-role-list-table.php index 58a8dc0..10268fb 100644 --- a/admin/class-role-list-table.php +++ b/admin/class-role-list-table.php @@ -10,19 +10,21 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Role list table for the roles management page in the admin. Extends the core `WP_List_Table` * class in the admin. * - * @since 1.0.0 + * @since 2.0.0 * @access public */ -class Members_Role_List_Table extends WP_List_Table { +class Role_List_Table extends \WP_List_Table { /** * The current view. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var string */ @@ -31,7 +33,7 @@ class Members_Role_List_Table extends WP_List_Table { /** * Allowed role views. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var array */ @@ -40,7 +42,7 @@ class Members_Role_List_Table extends WP_List_Table { /** * The default role. This will be assigned the value of `get_option( 'default_role' )`. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var string */ @@ -49,7 +51,7 @@ class Members_Role_List_Table extends WP_List_Table { /** * The current user object. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var object */ @@ -58,7 +60,7 @@ class Members_Role_List_Table extends WP_List_Table { /** * Sets up the list table. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -72,7 +74,7 @@ public function __construct() { parent::__construct( $args ); // Get the current user object. - $this->current_user = new WP_User( get_current_user_id() ); + $this->current_user = new \WP_User( get_current_user_id() ); // Get the defined default role. $this->default_role = get_option( 'default_role', $this->default_role ); @@ -88,7 +90,7 @@ public function __construct() { /** * Sets up the items (roles) to list. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -168,7 +170,7 @@ public function prepare_items() { * Returns an array of columns to show. * * @see members_manage_roles_columns() - * @since 1.0.0 + * @since 2.0.0 * @access public * @return array */ @@ -195,7 +197,7 @@ protected function column_default( $role, $column_name ) { /** * The checkbox column callback. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @param string $role * @return string @@ -214,7 +216,7 @@ protected function column_cb( $role ) { /** * The role name column callback. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @param string $role * @return string @@ -253,7 +255,7 @@ protected function column_title( $role ) { /** * The role column callback. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @param string $role * @return string @@ -265,7 +267,7 @@ protected function column_role( $role ) { /** * The users column callback. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @param string $role * @return string @@ -277,7 +279,7 @@ protected function column_users( $role ) { /** * The caps column callback. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @param string $role * @return string @@ -289,7 +291,7 @@ protected function column_granted_caps( $role ) { /** * The caps column callback. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @param string $role * @return string @@ -301,7 +303,7 @@ protected function column_denied_caps( $role ) { /** * Returns the name of the primary column. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @return string */ @@ -312,7 +314,7 @@ protected function get_default_primary_column_name() { /** * Handles the row actions. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @param string $role * @param string $column_name @@ -366,7 +368,7 @@ protected function handle_row_actions( $role, $column_name, $primary ) { /** * Returns an array of sortable columns. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @return array */ @@ -381,7 +383,7 @@ protected function get_sortable_columns() { /** * Returns an array of views for the list table. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @return array */ @@ -438,7 +440,7 @@ protected function get_views() { /** * Displays the list table. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -452,7 +454,7 @@ public function display() { /** * Returns an array of bulk actions available. * - * @since 1.0.0 + * @since 2.0.0 * @access protected * @return array */ diff --git a/admin/class-role-new.php b/admin/class-role-new.php index 2461f89..c366fba 100644 --- a/admin/class-role-new.php +++ b/admin/class-role-new.php @@ -10,18 +10,20 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Class that displays the new role screen and handles the form submissions for that page. * - * @since 1.0.0 + * @since 2.0.0 * @access public */ -final class Members_Admin_Role_New { +final class Role_New { /** * Holds the instances of this class. * - * @since 1.0.0 + * @since 2.0.0 * @access private * @var object */ @@ -30,7 +32,7 @@ final class Members_Admin_Role_New { /** * Name of the page we've created. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var string */ @@ -39,7 +41,7 @@ final class Members_Admin_Role_New { /** * Role that's being created. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var string */ @@ -48,7 +50,7 @@ final class Members_Admin_Role_New { /** * Name of the role that's being created. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var string */ @@ -57,7 +59,7 @@ final class Members_Admin_Role_New { /** * Array of the role's capabilities. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var array */ @@ -66,7 +68,7 @@ final class Members_Admin_Role_New { /** * Conditional to see if we're cloning a role. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var bool */ @@ -75,7 +77,7 @@ final class Members_Admin_Role_New { /** * Role that is being cloned. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var string */ @@ -84,7 +86,7 @@ final class Members_Admin_Role_New { /** * Sets up our initial actions. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -98,7 +100,7 @@ public function __construct() { /** * Adds the roles page to the admin. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -117,7 +119,7 @@ public function add_admin_page() { /** * Checks posted data on load and performs actions if needed. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -262,7 +264,7 @@ public function load() { /** * Adds help tabs. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -284,7 +286,7 @@ public function add_help_tabs() { /** * Enqueue scripts/styles. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -297,7 +299,7 @@ public function enqueue() { /** * Outputs the page. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -336,7 +338,7 @@ public function page() { ?> - capabilities ); ?> + capabilities ); ?> display(); ?> @@ -362,7 +364,7 @@ public function page() { ?> /** * Filters the new role default caps in the case that we're cloning a role. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @param array $capabilities * @param array @@ -383,7 +385,7 @@ public function clone_default_caps( $capabilities ) { /** * Returns the instance. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return object */ @@ -396,4 +398,4 @@ public static function get_instance() { } } -Members_Admin_Role_New::get_instance(); +Role_New::get_instance(); diff --git a/admin/class-roles.php b/admin/class-roles.php index 4cbc87d..e761824 100644 --- a/admin/class-roles.php +++ b/admin/class-roles.php @@ -10,18 +10,20 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Class that displays the roles admin screen and handles requests for that page. * - * @since 1.0.0 + * @since 2.0.0 * @access public */ -final class Members_Admin_Roles { +final class Roles { /** * Sets up some necessary actions/filters. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -40,7 +42,7 @@ public function __construct() { /** * Modifies the current screen object. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -53,7 +55,7 @@ public function current_screen( $screen ) { /** * Sets up the roles column headers. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @param array $columns * @return array @@ -75,7 +77,7 @@ public function manage_roles_columns( $columns ) { /** * Runs on the `load-{$page}` hook. This is the handler for form submissions and requests. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -141,7 +143,7 @@ public function load() { /** * Enqueue scripts/styles. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -154,7 +156,7 @@ public function enqueue() { /** * Displays the page content. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -178,7 +180,7 @@ public function page() {
    - + prepare_items(); ?> display(); ?> @@ -192,7 +194,7 @@ public function page() { /** * Adds help tabs. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -244,7 +246,7 @@ public function add_help_tabs() { /** * Overview help tab callback function. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -258,7 +260,7 @@ public function help_tab_overview() { ?> /** * Screen content help tab callback function. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -277,7 +279,7 @@ public function help_tab_screen_content() { ?> /** * Row actions help tab callback function. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -298,7 +300,7 @@ public function help_tab_row_actions() { ?> /** * Bulk actions help tab callback function. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ diff --git a/admin/class-user-edit.php b/admin/class-user-edit.php index b43be6a..b9eacdf 100644 --- a/admin/class-user-edit.php +++ b/admin/class-user-edit.php @@ -10,18 +10,20 @@ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ +namespace Members\Admin; + /** * Edit user screen class. * - * @since 1.0.0 + * @since 2.0.0 * @access public */ -final class Members_Admin_User_Edit { +final class User_Edit { /** * Holds the instances of this class. * - * @since 1.0.0 + * @since 2.0.0 * @access private * @var object */ @@ -30,7 +32,7 @@ final class Members_Admin_User_Edit { /** * Sets up needed actions/filters for the admin to initialize. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -47,7 +49,7 @@ public function __construct() { /** * Adds actions/filters on load. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -68,7 +70,7 @@ public function load_user_edit() { /** * Adds custom profile fields. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @param object $user * @return void @@ -122,7 +124,7 @@ public function profile_fields( $user ) { * on a different hook, `profile_update`. Using the normal hooks on the edit user screen won't work * because WP will wipe out the role. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @param int $user_id * @param object $old_user_data @@ -212,7 +214,7 @@ public function print_scripts() { ?> /** * Enqueue the plugin admin CSS. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ @@ -225,7 +227,7 @@ public function print_styles() { ?> /** * Returns the instance. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return object */ @@ -238,4 +240,4 @@ public static function get_instance() { } } -Members_Admin_User_Edit::get_instance(); +User_Edit::get_instance(); From e81cfe170875d3a121b47bcb86f8b8a7d7571d4f Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 10 Jul 2017 17:44:34 -0500 Subject: [PATCH 069/157] Separate registering default role and cap groups into their own functions. --- inc/functions-cap-groups.php | 173 ++++++++++++++++++---------------- inc/functions-role-groups.php | 155 ++++++++++++++++-------------- 2 files changed, 175 insertions(+), 153 deletions(-) diff --git a/inc/functions-cap-groups.php b/inc/functions-cap-groups.php index d89027d..64090bc 100644 --- a/inc/functions-cap-groups.php +++ b/inc/functions-cap-groups.php @@ -11,93 +11,48 @@ */ # Registers default groups. -add_action( 'init', 'members_register_cap_groups', 95 ); +add_action( 'init', 'members_register_cap_groups', 95 ); +add_action( 'members_register_cap_groups', 'members_register_default_cap_groups', 5 ); /** - * Returns the instance of cap group registry. - * - * @since 2.0.0 - * @access public - * @return object - */ -function members_cap_group_registry() { - - return \Members\Registry::get_instance( 'cap_group' ); -} - -/** - * Function for registering a cap group. - * - * @since 1.0.0 - * @access public - * @param string $name - * @param array $args - * @return void - */ -function members_register_cap_group( $name, $args = array() ) { - - members_cap_group_registry()->register( $name, new \Members\Cap_Group( $name, $args ) ); -} - -/** - * Unregisters a group. + * Fires the cap group registration action hook. * * @since 1.0.0 * @access public - * @param string $name * @return void */ -function members_unregister_cap_group( $name ) { - - members_cap_group_registry()->unregister( $name ); -} +function members_register_cap_groups() { -/** - * Checks if a group exists. - * - * @since 1.0.0 - * @access public - * @param string $name - * @return bool - */ -function members_cap_group_exists( $name ) { + // Hook for registering cap groups. Plugins should always register on this hook. + do_action( 'members_register_cap_groups' ); - return members_cap_group_registry()->exists( $name ); -} + // Check if the `all` group is registered. + if ( members_cap_group_exists( 'all' ) ) { -/** - * Returns an array of registered group objects. - * - * @since 1.0.0 - * @access public - * @return array - */ -function members_get_cap_groups() { + // Set up an empty caps array and get the `all` group object. + $caps = array(); + $_group = members_get_cap_group( 'all' ); - return members_cap_group_registry()->get_collection(); -} + // Get the caps from every registered group. + foreach ( members_get_cap_groups() as $group ) + $caps = array_merge( $caps, $group->caps ); -/** - * Returns a group object if it exists. Otherwise, `FALSE`. - * - * @since 1.0.0 - * @access public - * @param string $name - * @return object|bool - */ -function members_get_cap_group( $name ) { + // Sort the caps alphabetically. + asort( $caps ); - return members_cap_group_registry()->get( $name ); + // Assign all caps to the `all` group. + $_group->caps = array_unique( $caps ); + } } /** * Registers the default cap groups. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ -function members_register_cap_groups() { +function members_register_default_cap_groups() { // Registers the general group. members_register_cap_group( 'general', @@ -208,27 +163,83 @@ function members_register_cap_groups() { 'priority' => 995 ) ); +} - // Hook for registering cap groups. Plugins should always register on this hook. - do_action( 'members_register_cap_groups' ); +/** + * Returns the instance of cap group registry. + * + * @since 2.0.0 + * @access public + * @return object + */ +function members_cap_group_registry() { - // Check if the `all` group is registered. - if ( members_cap_group_exists( 'all' ) ) { + return \Members\Registry::get_instance( 'cap_group' ); +} - // Set up an empty caps array and get the `all` group object. - $caps = array(); - $_group = members_get_cap_group( 'all' ); +/** + * Function for registering a cap group. + * + * @since 1.0.0 + * @access public + * @param string $name + * @param array $args + * @return void + */ +function members_register_cap_group( $name, $args = array() ) { - // Get the caps from every registered group. - foreach ( members_get_cap_groups() as $group ) - $caps = array_merge( $caps, $group->caps ); + members_cap_group_registry()->register( $name, new \Members\Cap_Group( $name, $args ) ); +} - // Sort the caps alphabetically. - asort( $caps ); +/** + * Unregisters a group. + * + * @since 1.0.0 + * @access public + * @param string $name + * @return void + */ +function members_unregister_cap_group( $name ) { - // Assign all caps to the `all` group. - $_group->caps = array_unique( $caps ); - } + members_cap_group_registry()->unregister( $name ); +} + +/** + * Checks if a group exists. + * + * @since 1.0.0 + * @access public + * @param string $name + * @return bool + */ +function members_cap_group_exists( $name ) { + + return members_cap_group_registry()->exists( $name ); +} + +/** + * Returns an array of registered group objects. + * + * @since 1.0.0 + * @access public + * @return array + */ +function members_get_cap_groups() { + + return members_cap_group_registry()->get_collection(); +} + +/** + * Returns a group object if it exists. Otherwise, `FALSE`. + * + * @since 1.0.0 + * @access public + * @param string $name + * @return object|bool + */ +function members_get_cap_group( $name ) { + + return members_cap_group_registry()->get( $name ); } /** diff --git a/inc/functions-role-groups.php b/inc/functions-role-groups.php index ba96b91..2234e3d 100644 --- a/inc/functions-role-groups.php +++ b/inc/functions-role-groups.php @@ -11,93 +11,30 @@ */ # Registers default groups. -add_action( 'init', 'members_register_role_groups', 95 ); +add_action( 'init', 'members_register_role_groups', 95 ); +add_action( 'members_register_role_groups', 'members_register_default_role_groups', 5 ); /** - * Returns the instance of the role group registry. - * - * @since 2.0.0 - * @access public - * @return object - */ -function members_role_group_registry() { - - return \Members\Registry::get_instance( 'role_group' ); -} - -/** - * Function for registering a role group. - * - * @since 1.0.0 - * @access public - * @param string $name - * @param array $args - * @return void - */ -function members_register_role_group( $name, $args = array() ) { - - members_role_group_registry()->register( $name, new \Members\Role_Group( $name, $args ) ); -} - -/** - * Unregisters a group. + * Fires the role group registration action hook. * * @since 1.0.0 * @access public - * @param string $name * @return void */ -function members_unregister_role_group( $name ) { - - members_role_group_registry()->unregister( $name ); -} - -/** - * Checks if a group exists. - * - * @since 1.0.0 - * @access public - * @param string $name - * @return bool - */ -function members_role_group_exists( $name ) { +function members_register_role_groups() { - return members_role_group_registry()->exists( $name ); + do_action( 'members_register_role_groups' ); } -/** - * Returns an array of registered group objects. - * - * @since 1.0.0 - * @access public - * @return array - */ -function members_get_role_groups() { - - return members_role_group_registry()->get_collection(); -} - -/** - * Returns a group object if it exists. Otherwise, `FALSE`. - * - * @since 1.0.0 - * @access public - * @param string $name - * @return object|bool - */ -function members_get_role_group( $name ) { - - return members_role_group_registry()->get( $name ); -} /** * Registers the default role groups. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return void */ -function members_register_role_groups() { +function members_register_default_role_groups() { // Get the current user. $current_user = wp_get_current_user(); @@ -158,7 +95,81 @@ function members_register_role_groups() { 'roles' => members_get_wordpress_roles(), ) ); +} - // Hook for registering role groups. Plugins should always register on this hook. - do_action( 'members_register_role_groups' ); +/** + * Returns the instance of the role group registry. + * + * @since 2.0.0 + * @access public + * @return object + */ +function members_role_group_registry() { + + return \Members\Registry::get_instance( 'role_group' ); +} + +/** + * Function for registering a role group. + * + * @since 1.0.0 + * @access public + * @param string $name + * @param array $args + * @return void + */ +function members_register_role_group( $name, $args = array() ) { + + members_role_group_registry()->register( $name, new \Members\Role_Group( $name, $args ) ); +} + +/** + * Unregisters a group. + * + * @since 1.0.0 + * @access public + * @param string $name + * @return void + */ +function members_unregister_role_group( $name ) { + + members_role_group_registry()->unregister( $name ); +} + +/** + * Checks if a group exists. + * + * @since 1.0.0 + * @access public + * @param string $name + * @return bool + */ +function members_role_group_exists( $name ) { + + return members_role_group_registry()->exists( $name ); +} + +/** + * Returns an array of registered group objects. + * + * @since 1.0.0 + * @access public + * @return array + */ +function members_get_role_groups() { + + return members_role_group_registry()->get_collection(); +} + +/** + * Returns a group object if it exists. Otherwise, `FALSE`. + * + * @since 1.0.0 + * @access public + * @param string $name + * @return object|bool + */ +function members_get_role_group( $name ) { + + return members_role_group_registry()->get( $name ); } From 18eee79f2699caf71e8a4688e26ef4d90e0193e5 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 11 Jul 2017 17:57:19 -0500 Subject: [PATCH 070/157] Put the add-on icons into the `img` folder. This will allow us to save some resources on Theme Hybrid but still allow us to add new add-ons without updating the plugin (falls back to the icon passed through the API). --- admin/views/class-view-addons.php | 8 +++++++- img/{addon.png => icon-addon.png} | Bin img/icon-members-role-hierarchy.png | Bin 0 -> 6006 bytes img/icon-members-role-levels.png | Bin 0 -> 6245 bytes 4 files changed, 7 insertions(+), 1 deletion(-) rename img/{addon.png => icon-addon.png} (100%) create mode 100644 img/icon-members-role-hierarchy.png create mode 100644 img/icon-members-role-levels.png diff --git a/admin/views/class-view-addons.php b/admin/views/class-view-addons.php index 2de60f7..7d3ae09 100644 --- a/admin/views/class-view-addons.php +++ b/admin/views/class-view-addons.php @@ -77,8 +77,14 @@ public function addon_card( $addon ) { ?> title ); ?> - icon_url ) : ?> + dir_path . "img/icon-{$addon->name}.png" ) ) : ?> + + name}.png" ); ?>" alt="" /> + + icon_url ) : ?> + + diff --git a/img/addon.png b/img/icon-addon.png similarity index 100% rename from img/addon.png rename to img/icon-addon.png diff --git a/img/icon-members-role-hierarchy.png b/img/icon-members-role-hierarchy.png new file mode 100644 index 0000000000000000000000000000000000000000..3b31c16b9e66501383807b89c48f503e0e176e56 GIT binary patch literal 6006 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 literal 0 HcmV?d00001 diff --git a/img/icon-members-role-levels.png b/img/icon-members-role-levels.png new file mode 100644 index 0000000000000000000000000000000000000000..47b6897ef199dbd24def4ffb4fda5f80ac4b5bb9 GIT binary patch literal 6245 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 Date: Wed, 12 Jul 2017 10:01:22 -0500 Subject: [PATCH 071/157] Only show add-on card footer if there's a rating or install count. --- admin/views/class-view-addons.php | 36 +++++++++++++++++-------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/admin/views/class-view-addons.php b/admin/views/class-view-addons.php index 7d3ae09..91bdb06 100644 --- a/admin/views/class-view-addons.php +++ b/admin/views/class-view-addons.php @@ -125,29 +125,33 @@ public function addon_card( $addon ) { ?> -
    + rating && $addon->rating_count ) || $addon->install_count ) : ?> - rating && $addon->rating_count ) : ?> +
    -
    - 'rating', 'rating' => floatval( $addon->rating ), 'number' => absint( $addon->rating_count ) ) ); ?> - -
    + rating && $addon->rating_count ) : ?> - +
    + 'rating', 'rating' => floatval( $addon->rating ), 'number' => absint( $addon->rating_count ) ) ); ?> + +
    - install_count ) : ?> + -
    - install_count ) ) - ); ?> -
    + install_count ) : ?> - +
    + install_count ) ) + ); ?> +
    -
    + + +
    + + From 0e0762d3fb381fedad62382d3dd0bb3eafdb9869 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 12 Jul 2017 10:39:15 -0500 Subject: [PATCH 072/157] Officially start using the API from ThemeHybrid.com for handling the add-ons admin screen. --- admin/functions-addons.php | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/admin/functions-addons.php b/admin/functions-addons.php index 3075bbe..111d463 100644 --- a/admin/functions-addons.php +++ b/admin/functions-addons.php @@ -24,23 +24,32 @@ */ function members_register_default_addons() { - // Sandbox URL for the time being. - // $url = 'http://localhost/api/th/v1/plugins?addons=members'; - $url = members_plugin()->dir_uri . 'admin/addons.json'; + // Get the transient where the Members addons are stored on-site. + $data = get_transient( 'members_addons' ); - // Get data from the remote URL. - $response = wp_remote_get( $url ); + if ( ! $data || ! is_array( $data ) ) { - // Bail if we get no response. - if ( is_wp_error( $response ) ) - return; + // `localhost` is the sandbox URL. + // $url = 'http://localhost/api/th/v1/plugins?addons=members'; + $url = 'https://themehybrid.com/api/th/v1/plugins?addons=members'; - // Decode the data that we got. - $data = json_decode( wp_remote_retrieve_body( $response ) ); + // Get data from the remote URL. + $response = wp_remote_get( $url ); + + // Bail if we get no response. + if ( is_wp_error( $response ) ) + return; + + // Decode the data that we got. + $data = json_decode( wp_remote_retrieve_body( $response ) ); + } // If we have an array of data, let's roll. if ( ! empty( $data ) && is_array( $data ) ) { + // Set the transient with the new data. + set_transient( 'members_addons', $data, 7 * DAY_IN_SECONDS ); + foreach ( $data as $addon ) { $args = array( From 4343cbad0b23b6d8097c58f0fee96007957df587 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 12 Jul 2017 12:47:04 -0500 Subject: [PATCH 073/157] Update screenshots. --- screenshot-1.png | Bin 60561 -> 71778 bytes screenshot-2.png | Bin 65371 -> 86020 bytes screenshot-3.png | Bin 28028 -> 25427 bytes screenshot-4.png | Bin 74478 -> 76361 bytes screenshot-5.png | Bin 16039 -> 64281 bytes 5 files changed, 0 insertions(+), 0 deletions(-) diff --git a/screenshot-1.png b/screenshot-1.png index 217dab54d47f334a7a8e31fe5ab51ae77d8d1411..17b1b35c1aeb867d19dfb45c363e4a24d4835201 100644 GIT binary patch literal 71778 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 literal 60561 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 Ixwjwx3me)iod5s; diff --git a/screenshot-2.png b/screenshot-2.png index dcbc1747bce127a9d0f3f388e2082599dcd3b85f..d47ee56805bf6d2993fc42af9e84f556746ce663 100644 GIT binary patch literal 86020 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,?FUXrd1%S2|&BnNWS@HA_ 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 M&hRYmjBVJz0i^%^RsaA1 literal 65371 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 diff --git a/screenshot-3.png b/screenshot-3.png index cf7600ddce00488667fca62223a4dfe047caf4d9..5b7b4bcb6f6d01ea2cf9ec44ad48d734f74f9c67 100644 GIT binary patch literal 25427 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 literal 28028 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

    Gee%GA!Ti5U{TQPOh2Dm8k81+Pd869 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 E4?o`yr~m)} literal 74478 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
    diff --git a/admin/class-settings.php b/admin/class-settings.php index 1b70184..009e7b3 100644 --- a/admin/class-settings.php +++ b/admin/class-settings.php @@ -77,12 +77,12 @@ private function __construct() {} private function includes() { // Include the settings functions. - require_once( members_plugin()->admin_dir . 'functions-settings.php' ); + require_once( members_plugin()->dir . 'admin/functions-settings.php' ); // Load settings view classes. - require_once( members_plugin()->admin_dir . 'views/class-view.php' ); - require_once( members_plugin()->admin_dir . 'views/class-view-general.php' ); - require_once( members_plugin()->admin_dir . 'views/class-view-addons.php' ); + require_once( members_plugin()->dir . 'admin/views/class-view.php' ); + require_once( members_plugin()->dir . 'admin/views/class-view-general.php' ); + require_once( members_plugin()->dir . 'admin/views/class-view-addons.php' ); } /** diff --git a/admin/functions-admin.php b/admin/functions-admin.php index 9b8e16a..b25a644 100644 --- a/admin/functions-admin.php +++ b/admin/functions-admin.php @@ -24,7 +24,7 @@ * @return bool */ function members_get_underscore_template( $name ) { - require_once( members_plugin()->admin_dir . "tmpl/{$name}.php" ); + require_once( members_plugin()->dir . "admin/tmpl/{$name}.php" ); } /** @@ -38,9 +38,9 @@ function members_admin_register_scripts() { $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; - wp_register_script( 'members-settings', members_plugin()->js_uri . "settings{$min}.js", array( 'jquery' ), '', true ); - wp_register_script( 'members-edit-post', members_plugin()->js_uri . "edit-post{$min}.js", array( 'jquery' ), '', true ); - wp_register_script( 'members-edit-role', members_plugin()->js_uri . "edit-role{$min}.js", array( 'postbox', 'wp-util' ), '', true ); + wp_register_script( 'members-settings', members_plugin()->uri . "js/settings{$min}.js", array( 'jquery' ), '', true ); + wp_register_script( 'members-edit-post', members_plugin()->uri . "js/edit-post{$min}.js", array( 'jquery' ), '', true ); + wp_register_script( 'members-edit-role', members_plugin()->uri . "js/edit-role{$min}.js", array( 'postbox', 'wp-util' ), '', true ); // Localize our script with some text we want to pass in. $i18n = array( @@ -65,7 +65,7 @@ function members_admin_register_styles() { $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; - wp_register_style( 'members-admin', members_plugin()->css_uri . "admin{$min}.css" ); + wp_register_style( 'members-admin', members_plugin()->uri . "css/admin{$min}.css" ); } /** diff --git a/admin/views/class-view-addons.php b/admin/views/class-view-addons.php index 91bdb06..18ca35c 100644 --- a/admin/views/class-view-addons.php +++ b/admin/views/class-view-addons.php @@ -29,8 +29,8 @@ class View_Addons extends View { */ public function template() { - require_once( members_plugin()->admin_dir . 'class-addon.php' ); - require_once( members_plugin()->admin_dir . 'functions-addons.php' ); + require_once( members_plugin()->dir . 'admin/class-addon.php' ); + require_once( members_plugin()->dir . 'admin/functions-addons.php' ); do_action( 'members_register_addons' ); @@ -77,9 +77,9 @@ public function addon_card( $addon ) { ?> title ); ?> - dir_path . "img/icon-{$addon->name}.png" ) ) : ?> + dir . "img/icon-{$addon->name}.png" ) ) : ?> - name}.png" ); ?>" alt="" /> + name}.png" ); ?>" alt="" /> icon_url ) : ?> diff --git a/inc/functions-widgets.php b/inc/functions-widgets.php index 10dee80..1fd43d4 100644 --- a/inc/functions-widgets.php +++ b/inc/functions-widgets.php @@ -25,7 +25,7 @@ function members_register_widgets() { // If the login form widget is enabled. if ( members_login_widget_enabled() ) { - require_once( members_plugin()->inc_dir . 'class-widget-login.php' ); + require_once( members_plugin()->dir . 'inc/class-widget-login.php' ); register_widget( '\Members\Widget_Login' ); } @@ -33,7 +33,7 @@ function members_register_widgets() { // If the users widget is enabled. if ( members_users_widget_enabled() ) { - require_once( members_plugin()->inc_dir . 'class-widget-users.php' ); + require_once( members_plugin()->dir . 'inc/class-widget-users.php' ); register_widget( '\Members\Widget_Users' ); } diff --git a/members.php b/members.php index d7623e7..82ed7a9 100644 --- a/members.php +++ b/members.php @@ -43,65 +43,20 @@ final class Members_Plugin { /** * Plugin directory path. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var string */ - public $dir_path = ''; + public $dir = ''; /** * Plugin directory URI. * - * @since 1.0.0 - * @access public - * @var string - */ - public $dir_uri = ''; - - /** - * Plugin admin directory path. - * - * @since 1.0.0 - * @access public - * @var string - */ - public $admin_dir = ''; - - /** - * Plugin includes directory path. - * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var string */ - public $inc_dir = ''; - - /** - * Plugin templates directory path. - * - * @since 1.0.0 - * @access public - * @var string - */ - public $templates_dir = ''; - - /** - * Plugin CSS directory URI. - * - * @since 1.0.0 - * @access public - * @var string - */ - public $css_uri = ''; - - /** - * Plugin JS directory URI. - * - * @since 1.0.0 - * @access public - * @var string - */ - public $js_uri = ''; + public $uri = ''; /** * User count of all roles. @@ -125,7 +80,7 @@ public static function get_instance() { static $instance = null; if ( is_null( $instance ) ) { - $instance = new Members_Plugin; + $instance = new self; $instance->setup(); $instance->includes(); $instance->setup_actions(); @@ -199,17 +154,8 @@ public function __call( $method = '', $args = array() ) { private function setup() { // Main plugin directory path and URI. - $this->dir_path = trailingslashit( plugin_dir_path( __FILE__ ) ); - $this->dir_uri = trailingslashit( plugin_dir_url( __FILE__ ) ); - - // Plugin directory paths. - $this->inc_dir = trailingslashit( $this->dir_path . 'inc' ); - $this->admin_dir = trailingslashit( $this->dir_path . 'admin' ); - $this->templates_dir = trailingslashit( $this->dir_path . 'templates' ); - - // Plugin directory URIs. - $this->css_uri = trailingslashit( $this->dir_uri . 'css' ); - $this->js_uri = trailingslashit( $this->dir_uri . 'js' ); + $this->dir = trailingslashit( plugin_dir_path( __FILE__ ) ); + $this->uri = trailingslashit( plugin_dir_url( __FILE__ ) ); } /** @@ -222,60 +168,60 @@ private function setup() { private function includes() { // Load class files. - require_once( $this->inc_dir . 'class-capability.php' ); - require_once( $this->inc_dir . 'class-cap-group.php' ); - require_once( $this->inc_dir . 'class-registry.php' ); - require_once( $this->inc_dir . 'class-role-group.php' ); - require_once( $this->inc_dir . 'class-role.php' ); + require_once( $this->dir . 'inc/class-capability.php' ); + require_once( $this->dir . 'inc/class-cap-group.php' ); + require_once( $this->dir . 'inc/class-registry.php' ); + require_once( $this->dir . 'inc/class-role-group.php' ); + require_once( $this->dir . 'inc/class-role.php' ); // Load includes files. - require_once( $this->inc_dir . 'functions.php' ); - require_once( $this->inc_dir . 'functions-admin-bar.php' ); - require_once( $this->inc_dir . 'functions-capabilities.php' ); - require_once( $this->inc_dir . 'functions-cap-groups.php' ); - require_once( $this->inc_dir . 'functions-content-permissions.php' ); - require_once( $this->inc_dir . 'functions-deprecated.php' ); - require_once( $this->inc_dir . 'functions-options.php' ); - require_once( $this->inc_dir . 'functions-private-site.php' ); - require_once( $this->inc_dir . 'functions-roles.php' ); - require_once( $this->inc_dir . 'functions-role-groups.php' ); - require_once( $this->inc_dir . 'functions-shortcodes.php' ); - require_once( $this->inc_dir . 'functions-users.php' ); - require_once( $this->inc_dir . 'functions-widgets.php' ); + require_once( $this->dir . 'inc/functions.php' ); + require_once( $this->dir . 'inc/functions-admin-bar.php' ); + require_once( $this->dir . 'inc/functions-capabilities.php' ); + require_once( $this->dir . 'inc/functions-cap-groups.php' ); + require_once( $this->dir . 'inc/functions-content-permissions.php' ); + require_once( $this->dir . 'inc/functions-deprecated.php' ); + require_once( $this->dir . 'inc/functions-options.php' ); + require_once( $this->dir . 'inc/functions-private-site.php' ); + require_once( $this->dir . 'inc/functions-roles.php' ); + require_once( $this->dir . 'inc/functions-role-groups.php' ); + require_once( $this->dir . 'inc/functions-shortcodes.php' ); + require_once( $this->dir . 'inc/functions-users.php' ); + require_once( $this->dir . 'inc/functions-widgets.php' ); // Load template files. - require_once( $this->inc_dir . 'template.php' ); + require_once( $this->dir . 'inc/template.php' ); // Load admin files. if ( is_admin() ) { // General admin functions. - require_once( $this->admin_dir . 'functions-admin.php' ); - require_once( $this->admin_dir . 'functions-help.php' ); + require_once( $this->dir . 'admin/functions-admin.php' ); + require_once( $this->dir . 'admin/functions-help.php' ); // Plugin settings. - require_once( $this->admin_dir . 'class-settings.php' ); + require_once( $this->dir . 'admin/class-settings.php' ); // User management. - require_once( $this->admin_dir . 'class-manage-users.php' ); - require_once( $this->admin_dir . 'class-user-edit.php' ); - require_once( $this->admin_dir . 'class-user-new.php' ); + require_once( $this->dir . 'admin/class-manage-users.php' ); + require_once( $this->dir . 'admin/class-user-edit.php' ); + require_once( $this->dir . 'admin/class-user-new.php' ); // Edit posts. - require_once( $this->admin_dir . 'class-meta-box-content-permissions.php' ); + require_once( $this->dir . 'admin/class-meta-box-content-permissions.php' ); // Role management. - require_once( $this->admin_dir . 'class-manage-roles.php' ); - require_once( $this->admin_dir . 'class-roles.php' ); - require_once( $this->admin_dir . 'class-role-edit.php' ); - require_once( $this->admin_dir . 'class-role-new.php' ); - require_once( $this->admin_dir . 'class-meta-box-publish-role.php' ); - require_once( $this->admin_dir . 'class-meta-box-custom-cap.php' ); + require_once( $this->dir . 'admin/class-manage-roles.php' ); + require_once( $this->dir . 'admin/class-roles.php' ); + require_once( $this->dir . 'admin/class-role-edit.php' ); + require_once( $this->dir . 'admin/class-role-new.php' ); + require_once( $this->dir . 'admin/class-meta-box-publish-role.php' ); + require_once( $this->dir . 'admin/class-meta-box-custom-cap.php' ); // Edit capabilities tabs and groups. - require_once( $this->admin_dir . 'class-cap-tabs.php' ); - require_once( $this->admin_dir . 'class-cap-section.php' ); - require_once( $this->admin_dir . 'class-cap-control.php' ); + require_once( $this->dir . 'admin/class-cap-tabs.php' ); + require_once( $this->dir . 'admin/class-cap-section.php' ); + require_once( $this->dir . 'admin/class-cap-control.php' ); } } From ca3653991356e4dde980c261165785cf9ae7bf32 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 12 Jul 2017 13:20:56 -0500 Subject: [PATCH 075/157] Change `/languages` folder to `/lang` for consistency with other plugins and themes I work with. --- {languages => lang}/members.pot | 0 members.php | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) rename {languages => lang}/members.pot (100%) diff --git a/languages/members.pot b/lang/members.pot similarity index 100% rename from languages/members.pot rename to lang/members.pot diff --git a/members.php b/members.php index 82ed7a9..55a8d4c 100644 --- a/members.php +++ b/members.php @@ -249,7 +249,8 @@ private function setup_actions() { * @return void */ public function i18n() { - load_plugin_textdomain( 'members', false, trailingslashit( dirname( plugin_basename( __FILE__ ) ) ). 'languages' ); + + load_plugin_textdomain( 'members', false, trailingslashit( dirname( plugin_basename( __FILE__ ) ) ). 'lang' ); } /** From 4b033877db96dae49bb3ccba175706eb4cb54d39 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 12 Jul 2017 14:21:49 -0500 Subject: [PATCH 076/157] Add help tabs for the add-ons view. --- admin/views/class-view-addons.php | 70 ++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/admin/views/class-view-addons.php b/admin/views/class-view-addons.php index 18ca35c..002899f 100644 --- a/admin/views/class-view-addons.php +++ b/admin/views/class-view-addons.php @@ -170,15 +170,75 @@ public function add_help_tabs() { $screen = get_current_screen(); // Roles/Caps help tab. - /* $screen->add_help_tab( + $screen->add_help_tab( array( - 'id' => 'roles-caps', - 'title' => esc_html__( 'Role and Capabilities', 'members' ), - 'callback' => array( $this, 'help_tab_roles_caps' ) + 'id' => 'overview', + 'title' => esc_html__( 'Overview', 'members' ), + 'callback' => array( $this, 'help_tab_overview' ) ) ); - */ + + // Roles/Caps help tab. + $screen->add_help_tab( + array( + 'id' => 'download', + 'title' => esc_html__( 'Download', 'members' ), + 'callback' => array( $this, 'help_tab_download' ) + ) + ); + + // Roles/Caps help tab. + $screen->add_help_tab( + array( + 'id' => 'purchase', + 'title' => esc_html__( 'Purchase', 'members' ), + 'callback' => array( $this, 'help_tab_purchase' ) + ) + ); + // Set the help sidebar. $screen->set_help_sidebar( members_get_help_sidebar_text() ); } + + /** + * Displays the overview help tab. + * + * @since 2.0.0 + * @access public + * @return void + */ + public function help_tab_overview() { ?> + +

    + +

    + + +

    + +

    + + +

    + +

    + Date: Wed, 12 Jul 2017 14:24:51 -0500 Subject: [PATCH 077/157] Add a unique name to the settings page. This way, the info is passed when registering custom views. This is just for future-proofing in case we add more admin pages and need to register views for different pages. --- admin/class-settings.php | 9 +++++++++ admin/functions-settings.php | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/admin/class-settings.php b/admin/class-settings.php index 009e7b3..2724e04 100644 --- a/admin/class-settings.php +++ b/admin/class-settings.php @@ -20,6 +20,15 @@ */ final class Settings_Page { + /** + * Admin page name/ID. + * + * @since 2.0.0 + * @access public + * @var string + */ + public $name = 'members-settings'; + /** * Settings page name. * diff --git a/admin/functions-settings.php b/admin/functions-settings.php index 289f224..1b800c8 100644 --- a/admin/functions-settings.php +++ b/admin/functions-settings.php @@ -23,6 +23,10 @@ */ function members_register_default_settings_views( $manager ) { + // Bail if not on the settings screen. + if ( 'members-settings' !== $manager->name ) + return; + // Register general settings view (default view). $manager->register_view( new \Members\Admin\View_General( From b4e2f3bdc54a51837a7aa4b22b3eb4e4281433ec Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 12 Jul 2017 17:51:21 -0500 Subject: [PATCH 078/157] Remove unused settings field code. --- admin/views/class-view-general.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/admin/views/class-view-general.php b/admin/views/class-view-general.php index 1e5a8fb..5521cdd 100644 --- a/admin/views/class-view-general.php +++ b/admin/views/class-view-general.php @@ -70,7 +70,6 @@ function register_settings() { add_settings_field( 'enable_role_manager', esc_html__( 'Role Manager', 'members' ), array( $this, 'field_enable_role_manager' ), 'members-settings', 'roles_caps' ); add_settings_field( 'enable_multi_roles', esc_html__( 'Multiple User Roles', 'members' ), array( $this, 'field_enable_multi_roles' ), 'members-settings', 'roles_caps' ); add_settings_field( 'explicit_denied_caps', esc_html__( 'Capabilities', 'members' ), array( $this, 'field_explicit_denied_caps' ), 'members-settings', 'roles_caps' ); - // add_settings_field( 'show_human_caps', esc_html__( 'Human Capabilities', 'members' ), array( $this, 'field_show_human_caps' ), 'members-settings', 'roles_caps' ); // Content permissions fields. add_settings_field( 'enable_content_permissions', esc_html__( 'Enable Permissions', 'members' ), array( $this, 'field_enable_content_permissions' ), 'members-settings', 'content_permissions' ); @@ -203,17 +202,6 @@ public function field_enable_content_permissions() { ?> - - Date: Thu, 13 Jul 2017 08:09:43 -0500 Subject: [PATCH 079/157] Use the `$name` property when registering the settings page. --- admin/class-settings.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/admin/class-settings.php b/admin/class-settings.php index 2724e04..fed3133 100644 --- a/admin/class-settings.php +++ b/admin/class-settings.php @@ -174,7 +174,7 @@ public function admin_menu() { esc_html_x( 'Members', 'admin screen', 'members' ), esc_html_x( 'Members', 'admin screen', 'members' ), apply_filters( 'members_settings_capability', 'manage_options' ), - 'members-settings', + $this->name, array( $this, 'settings_page' ) ); @@ -210,8 +210,10 @@ public function load() { // Add help tabs for the current view. $view = $this->get_view( members_get_current_settings_view() ); - if ( $view ) + if ( $view ) { + $view->load(); $view->add_help_tabs(); + } } /** From 2cd3452fd113c027563d04717d739ccc2752295f Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 13 Jul 2017 08:10:05 -0500 Subject: [PATCH 080/157] Remove unused variables. --- admin/views/class-view-general.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/admin/views/class-view-general.php b/admin/views/class-view-general.php index 5521cdd..5a90a4a 100644 --- a/admin/views/class-view-general.php +++ b/admin/views/class-view-general.php @@ -382,11 +382,6 @@ public function add_help_tabs() { ) ); - // Get docs and help links. - $docs_link = sprintf( '
  • %s
  • ', esc_html__( 'Documentation', 'members' ) ); - $help_link = sprintf( '
  • %s
  • ', esc_html__( 'Support Forums', 'members' ) ); - $tut_link = sprintf( '
  • %s
  • ', esc_html__( 'Users, Roles, and Capabilities', 'members' ) ); - // Set the help sidebar. $screen->set_help_sidebar( members_get_help_sidebar_text() ); } From ec409b86749209bea104e8a591cdaeaca6290bf2 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 13 Jul 2017 08:11:11 -0500 Subject: [PATCH 081/157] Adds a `load()` method for admin/setting views that executes on the `load-{$page}` hook. --- admin/views/class-view.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/admin/views/class-view.php b/admin/views/class-view.php index baaed3f..e26dbba 100644 --- a/admin/views/class-view.php +++ b/admin/views/class-view.php @@ -92,6 +92,15 @@ public function __construct( $name, $args = array() ) { $this->name = sanitize_key( $name ); } + /** + * Runs on the `load-{$page}` hook + * + * @since 2.0.0 + * @access public + * @return void + */ + public function load() {} + /** * Enqueue scripts/styles for the control. * From 319e331b68c11f78d9cef6b2fc4c053989525db8 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 13 Jul 2017 08:13:09 -0500 Subject: [PATCH 082/157] The base `View` class should be abstract. --- admin/views/class-view.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/views/class-view.php b/admin/views/class-view.php index e26dbba..5a8c330 100644 --- a/admin/views/class-view.php +++ b/admin/views/class-view.php @@ -18,7 +18,7 @@ * @since 2.0.0 * @access public */ -class View { +abstract class View { /** * Name/ID for the group. From 751c7c72ef3400d518f73b591b794419655976c8 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 13 Jul 2017 08:14:03 -0500 Subject: [PATCH 083/157] Typo fix: "downloads" should be "add-ons". --- admin/views/class-view-addons.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/views/class-view-addons.php b/admin/views/class-view-addons.php index 002899f..936fc1e 100644 --- a/admin/views/class-view-addons.php +++ b/admin/views/class-view-addons.php @@ -238,7 +238,7 @@ public function help_tab_download() { ?> public function help_tab_purchase() { ?>

    - +

    Date: Thu, 13 Jul 2017 10:43:42 -0500 Subject: [PATCH 084/157] Deactivate the plugin and die if not running PHP 5.3.0+. Fixes: https://github.com/justintadlock/members/issues/139 --- members.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/members.php b/members.php index 55a8d4c..b77164a 100644 --- a/members.php +++ b/members.php @@ -40,6 +40,15 @@ */ final class Members_Plugin { + /** + * Minimum required PHP version. + * + * @since 2.0.0 + * @access public + * @var string + */ + private $php_version = '5.3.0'; + /** * Plugin directory path. * @@ -250,6 +259,9 @@ private function setup_actions() { */ public function i18n() { +//if ( version_compare( PHP_VERSION, '7.1.7', '<' ) ) +// wp_die( PHP_VERSION . 'hello' ); + load_plugin_textdomain( 'members', false, trailingslashit( dirname( plugin_basename( __FILE__ ) ) ). 'lang' ); } @@ -262,6 +274,20 @@ public function i18n() { */ public function activation() { + // Check PHP version requirements. + if ( version_compare( PHP_VERSION, $this->php_version, '<' ) ) { + + // Make sure the plugin is deactivated. + deactivate_plugins( plugin_basename( __FILE__ ) ); + + // Add an error message and die. + wp_die( sprintf( + __( 'Members requires PHP version %1$s. You are running version %2$s. Please upgrade and try again.', 'members' ), + $this->php_version, + PHP_VERSION + ) ); + } + // Get the administrator role. $role = get_role( 'administrator' ); From 88a075e6a4ab9cdc4a2f9fc1f5eaa1ab72e50749 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 13 Jul 2017 12:00:36 -0500 Subject: [PATCH 085/157] Bring the documentation in the `readme.md` file more up to date. --- readme.md | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index d1fcdc8..515a3aa 100644 --- a/readme.md +++ b/readme.md @@ -75,7 +75,9 @@ Every capability can have one of three "states" for a role. The role can be *gr You can assign a user more than one role by going to that edit user screen in the admin and locating the "Roles" section. There will be a checkbox for every role. -Note that the roles dropdown on the "Users" screen in the admin will overwrite all roles with a single role. So, you'll need to edit the individual users to give them multiple roles. +You can also multiple roles to a user from the add new user screen. + +On the "Users" screen in the admin, you can bulk add or remove single roles from multiple users. ### Content permissions feature @@ -121,6 +123,12 @@ The `[members_logged_in]` shortcode should be used to check if a user is current This shortcode has no parameters. +##### [members_not_logged_in] + +The `[members_not_logged_in]` shortcode should be used to show content to users who are not logged into the site. If the user is logged in, the content will be hidden. + + [members_not_logged_in]This content is only shown to logged-out visitors.[/members_not_logged_in] + #### [members_login_form] The `[members_login_form]` shortcode is used to show a login form on the page. @@ -178,3 +186,52 @@ Some plugins and themes might rely on the old user level system in WordPress. T By default, the levels aren't shown. They still exist, but are tucked away behind the scenes. While not recommended, if you need to control who has what level (levels are just capabilities), add this to your plugin or your theme's `functions.php`: add_filter( 'members_remove_old_levels', '__return_false' ); + +### Registering capabilities + +If you're a plugin developer with custom capabilities, beginning with version 2.0.0 of Members, you can register your capabilities with Members. Essentially, this allows users to see your capabilities in a nicely-formatted, human-readable form (e.g., `Publish Posts` instead of `publish_posts`). This also means that it can be translated so that it's easier to understand for users who do not read English. + + add_action( 'members_register_caps', 'th_register_caps' ); + + function th_register_caps() { + + members_register_cap( + 'your_cap_name', + array( + 'label' => __( 'Your Capability Label', 'example-textdomain' ), + 'group' => 'example' + ) + ); + } + +The `group` argument is not required, but will allow you to assign the capability to a cap group. + +### Registering cap groups + +Members groups capabilities so that users can more easily find them when editing roles. If your plugin has multiple capabilities, you should consider creating a custom cap group. + + add_action( 'members_register_cap_groups', 'th_register_cap_groups' ); + + function th_register_cap_groups() { + + members_register_cap_group( + 'your_group_name', + array( + 'label' => __( 'Your Group Label', 'example-textdomain' ), + 'caps' => array(), + 'icon' => 'dashicons-admin-generic', + 'priority' => 10 + ) + ); + } + +The arguments for the array are: + +* `label` - An internationalized text label for your group. +* `caps` - An array of initial capabilities to add to your group. +* `icon` - The name of one of core WP's [dashicons](https://developer.wordpress.org/resource/dashicons/) or a custom class (would need to be styled by your plugin in this case). +* `priority` - The priority of your group compared to other groups. `10` is the default. + +_Note that custom post types are automatically registered as groups with Members. So, if you want to do something custom with that, you simply need to unregister the group before registering your own._ + + members_unregister_cap_group( "type-{$post_type}" ); From ce3eeb548a132f88a1b5805d0a38e36552119cd2 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 13 Jul 2017 12:47:46 -0500 Subject: [PATCH 086/157] Remove all role groups except for the `wordpress` group. The other groups were merely views on the manage roles screen. This opens us up more to doing true role groups in the future since we're not shoehorning views into the groups system. --- admin/class-role-list-table.php | 84 +++++++++++++++++++++------------ inc/functions-role-groups.php | 51 -------------------- inc/functions-roles.php | 2 +- 3 files changed, 56 insertions(+), 81 deletions(-) diff --git a/admin/class-role-list-table.php b/admin/class-role-list-table.php index 10268fb..85df1c7 100644 --- a/admin/class-role-list-table.php +++ b/admin/class-role-list-table.php @@ -30,6 +30,8 @@ class Role_List_Table extends \WP_List_Table { */ public $role_view = 'all'; + public $role_views = array(); + /** * Allowed role views. * @@ -83,8 +85,8 @@ public function __construct() { $this->allowed_role_views = array_keys( $this->get_views() ); // Get the current view. - if ( isset( $_GET['role_view'] ) && in_array( $_GET['role_view'], $this->allowed_role_views ) ) - $this->role_view = $_GET['role_view']; + if ( isset( $_GET['view'] ) && in_array( $_GET['view'], $this->allowed_role_views ) ) + $this->role_view = $_GET['view']; } /** @@ -97,18 +99,18 @@ public function __construct() { public function prepare_items() { // Get the roles for the default/All view. - if ( 'all' === $this->role_view ) { + //if ( 'all' === $this->role_view ) { - $roles = array_keys( members_get_roles() ); + // $roles = array_keys( members_get_roles() ); // If a custom view, get the roles. - } else { + //} else { // Get the current group being viewed. - $group = members_get_role_group( $this->role_view ); + //$group = members_get_role_group( $this->role_view ); // Set the roles array. - $roles = $group ? $group->roles : array(); - } + $roles = $this->role_views[ $this->role_view ]['roles'];//$group ? $group->roles : array(); + //} // Allow devs to filter the items. $roles = apply_filters( 'members_manage_roles_items', $roles, $this->role_view ); @@ -389,25 +391,40 @@ protected function get_sortable_columns() { */ protected function get_views() { - $active = members_get_role_group( 'active' ); - $inactive = members_get_role_group( 'inactive' ); - - if ( $active ) - $active->roles = members_get_active_roles(); - - if ( $inactive ) - $inactive->roles = members_get_inactive_roles(); + // Get the current user. + $current_user = wp_get_current_user(); $views = array(); $current = ' class="current"'; - $all_count = count( members_get_roles() ); - - // Add the default/all view. - $views['all'] = sprintf( - '%s', - 'all' === $this->role_view ? $current : '', - esc_url( members_get_edit_roles_url() ), - sprintf( _n( 'All %s', 'All %s', $all_count, 'members' ), sprintf( '(%s)', number_format_i18n( $all_count ) ) ) + + $this->role_views['all'] = array( + 'label_count' => _n_noop( 'All %s', 'All %s', 'members' ), + 'roles' => array_keys( members_get_roles() ) + ); + + $this->role_views['mine'] = array( + 'label_count' => _n_noop( 'Mine %s', 'Mine %s', 'members' ), + 'roles' => $current_user->roles + ); + + $this->role_views['active'] = array( + 'label_count' => _n_noop( 'Has Users %s', 'Has Users %s', 'members' ), + 'roles' => members_get_active_roles() + ); + + $this->role_views['inactive'] = array( + 'label_count' => _n_noop( 'No Users %s', 'No Users %s', 'members' ), + 'roles' =>members_get_inactive_roles() + ); + + $this->role_views['editable'] = array( + 'label_count' => _n_noop( 'Editable %s', 'Editable %s', 'members' ), + 'roles' => members_get_editable_roles() + ); + + $this->role_views['uneditable'] = array( + 'label_count' => _n_noop( 'Uneditable %s', 'Uneditable %s', 'members' ), + 'roles' => members_get_uneditable_roles() ); // Loop through the role groups and put them into the view list. @@ -417,19 +434,28 @@ protected function get_views() { if ( ! $group->show_in_view_list ) continue; - $count = count( $group->roles ); + $this->role_views[ "group-{$group->name}" ] = array( + 'label_count' => $group->label_count, + 'roles' => $group->roles + ); + } + + // Loop through the default views and put them into the view list. + foreach ( $this->role_views as $view => $args ) { + + $count = count( $args['roles'] ); // Skip any views with 0 roles. if ( 0 >= $count ) continue; - $noop = $group->label_count; + $noop = $args['label_count']; // Add the view link. - $views[ $group->name ] = sprintf( + $views[ $view ] = sprintf( '%s', - $group->name === $this->role_view ? $current : '', - 'all' === $group->name ? esc_url( members_get_edit_roles_url() ) : esc_url( members_get_role_view_url( $group->name ) ), + $view === $this->role_view ? $current : '', + 'all' === $view ? esc_url( members_get_edit_roles_url() ) : esc_url( members_get_role_view_url( $view ) ), sprintf( translate_nooped_plural( $noop, $count, $noop['domain'] ), sprintf( '(%s)', number_format_i18n( $count ) ) ) ); } diff --git a/inc/functions-role-groups.php b/inc/functions-role-groups.php index 2234e3d..bc4a022 100644 --- a/inc/functions-role-groups.php +++ b/inc/functions-role-groups.php @@ -36,57 +36,6 @@ function members_register_role_groups() { */ function members_register_default_role_groups() { - // Get the current user. - $current_user = wp_get_current_user(); - - if ( is_object( $current_user ) ) { - - // Register the mine group. - members_register_role_group( 'mine', - array( - 'label' => esc_html__( 'Mine', 'members' ), - 'label_count' => _n_noop( 'Mine %s', 'Mine %s', 'members' ), - 'roles' => $current_user->roles, - ) - ); - } - - // Register the active group. - members_register_role_group( 'active', - array( - 'label' => esc_html__( 'Has Users', 'members' ), - 'label_count' => _n_noop( 'Has Users %s', 'Has Users %s', 'members' ), - 'roles' => array(), // These will be updated on the fly b/c it requires counting users. - ) - ); - - // Register the inactive group. - members_register_role_group( 'inactive', - array( - 'label' => esc_html__( 'No Users', 'members' ), - 'label_count' => _n_noop( 'No Users %s', 'No Users %s', 'members' ), - 'roles' => array(), // These will be updated on the fly b/c it requires counting users. - ) - ); - - // Register the editable group. - members_register_role_group( 'editable', - array( - 'label' => esc_html__( 'Editable', 'members' ), - 'label_count' => _n_noop( 'Editable %s', 'Editable %s', 'members' ), - 'roles' => members_get_editable_roles(), - ) - ); - - // Register the uneditable group. - members_register_role_group( 'uneditable', - array( - 'label' => esc_html__( 'Uneditable', 'members' ), - 'label_count' => _n_noop( 'Uneditable %s', 'Uneditable %s', 'members' ), - 'roles' => members_get_uneditable_roles(), - ) - ); - // Register the WordPress group. members_register_role_group( 'wordpress', array( diff --git a/inc/functions-roles.php b/inc/functions-roles.php index 0c47bc1..0e0e63b 100644 --- a/inc/functions-roles.php +++ b/inc/functions-roles.php @@ -410,7 +410,7 @@ function members_get_edit_roles_url() { * @return string */ function members_get_role_view_url( $view ) { - return add_query_arg( 'role_view', $view, members_get_edit_roles_url() ); + return add_query_arg( 'view', $view, members_get_edit_roles_url() ); } /** From 0137225443a1f39a71f7eacfb861cb61f5688b6a Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 13 Jul 2017 13:54:23 -0500 Subject: [PATCH 087/157] More role views cleanup. --- admin/class-role-list-table.php | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/admin/class-role-list-table.php b/admin/class-role-list-table.php index 85df1c7..1265d9c 100644 --- a/admin/class-role-list-table.php +++ b/admin/class-role-list-table.php @@ -30,6 +30,13 @@ class Role_List_Table extends \WP_List_Table { */ public $role_view = 'all'; + /** + * Array of role views. + * + * @since 2.0.0 + * @access public + * @var array + */ public $role_views = array(); /** @@ -98,19 +105,11 @@ public function __construct() { */ public function prepare_items() { - // Get the roles for the default/All view. - //if ( 'all' === $this->role_view ) { - - // $roles = array_keys( members_get_roles() ); - - // If a custom view, get the roles. - //} else { - // Get the current group being viewed. - //$group = members_get_role_group( $this->role_view ); + $roles = array(); - // Set the roles array. - $roles = $this->role_views[ $this->role_view ]['roles'];//$group ? $group->roles : array(); - //} + // Get the roles for the view. + if ( ! empty( $this->role_views[ $this->role_view ]['roles'] ) ) + $roles = $this->role_views[ $this->role_view ]['roles']; // Allow devs to filter the items. $roles = apply_filters( 'members_manage_roles_items', $roles, $this->role_view ); From 489ce547242451e17dec37ccfee5643ac2217ebc Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 13 Jul 2017 14:22:55 -0500 Subject: [PATCH 088/157] Remove the "All" cap group. While this is a capability tab on the edit role screen, it's not an actual group of defined capabilities. Instead, simply add the tab. --- admin/class-cap-tabs.php | 18 ++++++++++++++-- inc/class-cap-group.php | 9 -------- inc/functions-cap-groups.php | 41 ------------------------------------ inc/functions-deprecated.php | 13 ++++++++++++ 4 files changed, 29 insertions(+), 52 deletions(-) diff --git a/admin/class-cap-tabs.php b/admin/class-cap-tabs.php index 22b3bd1..165adb2 100644 --- a/admin/class-cap-tabs.php +++ b/admin/class-cap-tabs.php @@ -143,8 +143,7 @@ public function register() { $caps = array_diff( $group->caps, $this->added_caps ); // Add group's caps to the added caps array. - if ( $group->merge_added ) - $this->added_caps = array_unique( array_merge( $this->added_caps, $caps ) ); + $this->added_caps = array_unique( array_merge( $this->added_caps, $caps ) ); // Create a new section. $this->sections[] = $section = new Cap_Section( $this, $group->name, array( 'icon' => $group->icon, 'label' => $group->label ) ); @@ -162,6 +161,21 @@ public function register() { } } + // Create a new "All" section. + $this->sections[] = $section = new Cap_Section( $this, 'all', array( 'icon' => 'dashicons-plus', 'label' => esc_html__( 'All', 'members' ) ) ); + + // Get the section json data. + $this->sections_json[] = $section->json(); + + // Create new controls for each cap. + foreach ( $this->added_caps as $cap ) { + + $this->controls[] = $control = new Cap_Control( $this, $cap, array( 'section' => 'all' ) ); + + // Get the control json data. + $this->controls_json[] = $control->json(); + } + // Hook after registering. do_action( 'members_edit_caps_manager_register' ); } diff --git a/inc/class-cap-group.php b/inc/class-cap-group.php index d39d72b..f2242e9 100644 --- a/inc/class-cap-group.php +++ b/inc/class-cap-group.php @@ -65,15 +65,6 @@ final class Cap_Group { */ public $priority = 10; - /** - * Whether to merge this group's caps with the added caps array. - * - * @since 1.0.0 - * @access protected - * @var bool - */ - public $merge_added = true; - /** * Whether to remove previously-added caps from this group's caps. * diff --git a/inc/functions-cap-groups.php b/inc/functions-cap-groups.php index 64090bc..5c0d4a5 100644 --- a/inc/functions-cap-groups.php +++ b/inc/functions-cap-groups.php @@ -25,24 +25,6 @@ function members_register_cap_groups() { // Hook for registering cap groups. Plugins should always register on this hook. do_action( 'members_register_cap_groups' ); - - // Check if the `all` group is registered. - if ( members_cap_group_exists( 'all' ) ) { - - // Set up an empty caps array and get the `all` group object. - $caps = array(); - $_group = members_get_cap_group( 'all' ); - - // Get the caps from every registered group. - foreach ( members_get_cap_groups() as $group ) - $caps = array_merge( $caps, $group->caps ); - - // Sort the caps alphabetically. - asort( $caps ); - - // Assign all caps to the `all` group. - $_group->caps = array_unique( $caps ); - } } /** @@ -152,17 +134,6 @@ function members_register_default_cap_groups() { 'priority' => 995 ) ); - - // Register the all group. - members_register_cap_group( 'all', - array( - 'label' => esc_html__( 'All', 'members' ), - 'caps' => members_get_all_group_caps(), - 'icon' => 'dashicons-plus', - 'merge_added' => false, - 'priority' => 995 - ) - ); } /** @@ -242,18 +213,6 @@ function members_get_cap_group( $name ) { return members_cap_group_registry()->get( $name ); } -/** - * Returns the caps for the all capability group. - * - * @since 1.0.0 - * @access public - * @return array - */ -function members_get_all_group_caps() { - - return members_get_capabilities(); -} - /** * Returns the caps for a specific post type capability group. * diff --git a/inc/functions-deprecated.php b/inc/functions-deprecated.php index f32f6a2..8fa9ce7 100644 --- a/inc/functions-deprecated.php +++ b/inc/functions-deprecated.php @@ -213,6 +213,19 @@ function members_get_inactive_role_slugs() { return array_diff( array_keys( members_get_roles() ), members_get_active_roles() ); } +/** + * Returns the caps for the all capability group. + * + * @since 1.0.0 + * @access public + * @return array + */ +function members_get_all_group_caps() { + _deprecated_function( __FUNCTION__, '2.0.0', '' ); + + return members_get_capabilities(); +} + /** * Additional capabilities provided by the Members plugin that gives users permissions to handle * certain features of the plugin. From 25e007317eea2abcfdae8707d7ced9b26da7d6f1 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 13 Jul 2017 14:38:57 -0500 Subject: [PATCH 089/157] Update registry class info. --- inc/class-registry.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/inc/class-registry.php b/inc/class-registry.php index 8f9827d..c935277 100644 --- a/inc/class-registry.php +++ b/inc/class-registry.php @@ -30,7 +30,7 @@ class Registry { private static $instances = array(); /** - * Array of objects in the collection. + * Array of items in the collection. * * @since 2.0.0 * @access protected @@ -66,12 +66,12 @@ private function __clone() {} private function __wakeup() {} /** - * Register a new cap object + * Register an item. * * @since 2.0.0 * @access public * @param string $name - * @param object $value + * @param mixed $value * @return void */ public function register( $name, $value ) { @@ -81,7 +81,7 @@ public function register( $name, $value ) { } /** - * Unregisters a cap object. + * Unregisters an item. * * @since 2.0.0 * @access public @@ -95,7 +95,7 @@ public function unregister( $name ) { } /** - * Checks if a cap exists. + * Checks if an item exists. * * @since 2.0.0 * @access public @@ -108,12 +108,12 @@ public function exists( $name ) { } /** - * Gets a cap object. + * Returns an item. * * @since 2.0.0 * @access public * @param string $name - * @return object|bool + * @return mixed */ public function get( $name ) { From 62a0cdd8b50ca76bb37e5d1ec17b3e7be9335f39 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sun, 16 Jul 2017 11:31:32 -0500 Subject: [PATCH 090/157] General code and file cleanup. --- inc/class-cap-group.php | 28 +++++++++++++-------------- inc/class-capability.php | 2 +- inc/class-role-group.php | 12 ++++++------ inc/class-role.php | 2 +- inc/functions-capabilities.php | 3 +++ inc/functions-content-permissions.php | 8 +++++++- inc/functions-options.php | 7 +++++++ inc/functions-private-site.php | 5 ++++- inc/functions-roles.php | 24 +++++++++++------------ inc/functions-shortcodes.php | 1 + inc/functions.php | 1 + 11 files changed, 56 insertions(+), 37 deletions(-) diff --git a/inc/class-cap-group.php b/inc/class-cap-group.php index f2242e9..d37e816 100644 --- a/inc/class-cap-group.php +++ b/inc/class-cap-group.php @@ -15,7 +15,7 @@ /** * Capability group object class. * - * @since 1.0.0 + * @since 2.0.0 * @access public */ final class Cap_Group { @@ -23,8 +23,8 @@ final class Cap_Group { /** * Name/ID for the group. * - * @since 1.0.0 - * @access protected + * @since 2.0.0 + * @access public * @var string */ public $name = ''; @@ -32,8 +32,8 @@ final class Cap_Group { /** * Internationalized text label for the group. * - * @since 1.0.0 - * @access protected + * @since 2.0.0 + * @access public * @var string */ public $label = ''; @@ -41,8 +41,8 @@ final class Cap_Group { /** * Icon for the group. This can be a dashicons class or a custom class. * - * @since 1.0.0 - * @access protected + * @since 2.0.0 + * @access public * @var string */ public $icon = 'dashicons-admin-generic'; @@ -50,8 +50,8 @@ final class Cap_Group { /** * Capabilities for the group. * - * @since 1.0.0 - * @access protected + * @since 2.0.0 + * @access public * @var array */ public $caps = array(); @@ -59,7 +59,7 @@ final class Cap_Group { /** * Sort order priority. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @var int */ @@ -68,8 +68,8 @@ final class Cap_Group { /** * Whether to remove previously-added caps from this group's caps. * - * @since 1.0.0 - * @access protected + * @since 2.0.0 + * @access public * @var bool */ public $diff_added = false; @@ -78,7 +78,7 @@ final class Cap_Group { * Magic method to use in case someone tries to output the object as a string. * We'll just return the name. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @return string */ @@ -89,7 +89,7 @@ public function __toString() { /** * Register a new object. * - * @since 1.0.0 + * @since 2.0.0 * @access public * @param string $name * @param array $args { diff --git a/inc/class-capability.php b/inc/class-capability.php index 669142e..652606c 100644 --- a/inc/class-capability.php +++ b/inc/class-capability.php @@ -56,7 +56,7 @@ class Capability { * @return string */ public function __toString() { - return $this->slug; + return $this->name; } /** diff --git a/inc/class-role-group.php b/inc/class-role-group.php index 68bd95c..52dfd20 100644 --- a/inc/class-role-group.php +++ b/inc/class-role-group.php @@ -24,7 +24,7 @@ final class Role_Group { * Name/ID for the group. * * @since 2.0.0 - * @access protected + * @access public * @var string */ public $name = ''; @@ -33,17 +33,17 @@ final class Role_Group { * Internationalized text label for the group. * * @since 2.0.0 - * @access protected + * @access public * @var string */ public $label = ''; /** * Internationalized text label for the group + the count in the form of - * `_n_noop( 'Singular Name %s', 'Pluran Name %s', $textdomain )` + * `_n_noop( 'Singular Name %s', 'Plural Name %s', $textdomain )` * * @since 2.0.0 - * @access protected + * @access public * @var string */ public $label_count = ''; @@ -52,7 +52,7 @@ final class Role_Group { * Array of roles that belong to the group. * * @since 2.0.0 - * @access protected + * @access public * @var array */ public $roles = array(); @@ -61,7 +61,7 @@ final class Role_Group { * Whether to create a view for the group on the Manage Roles screen. * * @since 2.0.0 - * @access protected + * @access public * @var bool */ public $show_in_view_list = true; diff --git a/inc/class-role.php b/inc/class-role.php index 4d8d5ca..c093481 100644 --- a/inc/class-role.php +++ b/inc/class-role.php @@ -77,7 +77,7 @@ class Role { public $denied_cap_count = 0; /** - * Array of capabilities that the role has. + * Array of capabilities that the role has in the form of `array( $cap => $bool )`. * * @since 2.0.0 * @access public diff --git a/inc/functions-capabilities.php b/inc/functions-capabilities.php index 8735d10..8b12bba 100644 --- a/inc/functions-capabilities.php +++ b/inc/functions-capabilities.php @@ -241,6 +241,7 @@ function members_cap_exists( $name ) { * @return string */ function members_sanitize_cap( $cap ) { + return apply_filters( 'members_sanitize_cap', sanitize_key( $cap ) ); } @@ -414,6 +415,7 @@ function members_get_hidden_caps() { * @return array */ function members_remove_hidden_caps( $caps ) { + return apply_filters( 'members_remove_hidden_caps', true ) ? array_diff( $caps, members_get_hidden_caps() ) : $caps; } @@ -453,6 +455,7 @@ function members_get_old_levels() { * @return array */ function members_remove_old_levels( $caps ) { + return apply_filters( 'members_remove_old_levels', true ) ? array_diff( $caps, members_get_old_levels() ) : $caps; } diff --git a/inc/functions-content-permissions.php b/inc/functions-content-permissions.php index 48eb946..6fb3739 100644 --- a/inc/functions-content-permissions.php +++ b/inc/functions-content-permissions.php @@ -64,6 +64,7 @@ function members_has_post_roles( $post_id = '' ) { * @return int|false */ function members_add_post_role( $post_id, $role ) { + return add_post_meta( $post_id, '_members_access_role', $role, false ); } @@ -77,6 +78,7 @@ function members_add_post_role( $post_id, $role ) { * @return bool */ function members_remove_post_role( $post_id, $role ) { + return delete_post_meta( $post_id, '_members_access_role', $role ); } @@ -122,6 +124,7 @@ function members_set_post_roles( $post_id, $roles ) { * @return bool */ function members_delete_post_roles( $post_id ) { + return delete_post_meta( $post_id, '_members_access_role' ); } @@ -194,7 +197,7 @@ function members_content_permissions_comments( $template ) { $has_template = locate_template( array( 'comments-no-access.php' ) ); // If the template was found, use it. Otherwise, fall back to the Members comments.php template. - $template = $has_template ? $has_template : members_plugin()->templates_dir . 'comments.php'; + $template = $has_template ? $has_template : members_plugin()->dir . 'templates/comments.php'; // Allow devs to overwrite the comments template. $template = apply_filters( 'members_comments_template', $template ); @@ -236,6 +239,7 @@ function members_get_post_error_message( $post_id ) { * @return string */ function members_get_post_access_message( $post_id ) { + return get_post_meta( $post_id, '_members_access_error', true ); } @@ -249,6 +253,7 @@ function members_get_post_access_message( $post_id ) { * @return bool */ function members_set_post_access_message( $post_id, $message ) { + return update_post_meta( $post_id, '_members_access_error', $message ); } @@ -261,6 +266,7 @@ function members_set_post_access_message( $post_id, $message ) { * @return bool */ function members_delete_post_access_message( $post_id ) { + return delete_post_meta( $post_id, '_members_access_error' ); } diff --git a/inc/functions-options.php b/inc/functions-options.php index e9f59a8..1c349d0 100644 --- a/inc/functions-options.php +++ b/inc/functions-options.php @@ -18,6 +18,7 @@ * @return bool */ function members_role_manager_enabled() { + return apply_filters( 'members_role_manager_enabled', members_get_setting( 'role_manager' ) ); } @@ -30,6 +31,7 @@ function members_role_manager_enabled() { * @return bool */ function members_explicitly_deny_caps() { + return apply_filters( 'members_explicitly_deny_caps', members_get_setting( 'explicit_denied_caps' ) ); } @@ -41,6 +43,7 @@ function members_explicitly_deny_caps() { * @return bool */ function members_show_human_caps() { + return apply_filters( 'members_show_human_caps', members_get_setting( 'show_human_caps' ) ); } @@ -52,6 +55,7 @@ function members_show_human_caps() { * @return bool */ function members_multiple_user_roles_enabled() { + return apply_filters( 'members_multiple_roles_enabled', members_get_setting( 'multi_roles' ) ); } @@ -63,6 +67,7 @@ function members_multiple_user_roles_enabled() { * @return bool */ function members_content_permissions_enabled() { + return apply_filters( 'members_content_permissions_enabled', members_get_setting( 'content_permissions' ) ); } @@ -74,6 +79,7 @@ function members_content_permissions_enabled() { * @return bool */ function members_login_widget_enabled() { + return apply_filters( 'members_login_widget_enabled', members_get_setting( 'login_form_widget' ) ); } @@ -85,6 +91,7 @@ function members_login_widget_enabled() { * @return bool */ function members_users_widget_enabled() { + return apply_filters( 'members_users_widget_enabled', members_get_setting( 'users_widget' ) ); } diff --git a/inc/functions-private-site.php b/inc/functions-private-site.php index eb62bce..7ec81f8 100644 --- a/inc/functions-private-site.php +++ b/inc/functions-private-site.php @@ -30,6 +30,7 @@ add_filter( 'members_feed_error_message', 'do_shortcode', 30 ); add_filter( 'members_feed_error_message', 'shortcode_unautop', 35 ); +# Authenticate when accessing the REST API. add_filter( 'rest_authentication_errors', 'members_private_rest_api', 95 ); /** @@ -40,6 +41,7 @@ * @return bool */ function members_is_private_blog() { + return members_get_setting( 'private_blog' ); } @@ -51,6 +53,7 @@ function members_is_private_blog() { * @return bool */ function members_is_private_feed() { + return members_get_setting( 'private_feed' ); } @@ -157,7 +160,7 @@ function members_private_rest_api( $result ) { } /** - * Outputs an error message if a user attempts to access a site that they do not have + * Outputs an error message if a user attempts to access a site that they do not have * access to on multisite. * * @since 2.0.0 diff --git a/inc/functions-roles.php b/inc/functions-roles.php index 0e0e63b..322355c 100644 --- a/inc/functions-roles.php +++ b/inc/functions-roles.php @@ -63,7 +63,7 @@ function members_role_registry() { /** * Returns all registered roles. * - * @since 2.0.0 + * @since 1.0.0 * @access public * @return array */ @@ -209,21 +209,10 @@ function members_get_inactive_roles() { * @return int */ function members_get_role_count() { + return count( $GLOBALS['wp_roles']->role_names ); } -/** - * Returns an array of `Members_Role` objects. - * - * @since 1.0.0 - * @access public - * @return array - */ -//function members_get_roles() { -// return members_role_registry()->roles; -//} - - /* ====== Single Role Functions ====== */ /** @@ -235,8 +224,10 @@ function members_get_role_count() { * @return int */ function members_sanitize_role( $role ) { + $_role = strtolower( $role ); $_role = preg_replace( '/[^a-z0-9_\-\s]/', '', $_role ); + return apply_filters( 'members_sanitize_role', str_replace( ' ', '_', $_role ), $role ); } @@ -375,6 +366,7 @@ function members_is_wordpress_role( $role ) { * @return string */ function members_get_new_role_url() { + return add_query_arg( 'page', 'role-new', admin_url( 'users.php' ) ); } @@ -387,6 +379,7 @@ function members_get_new_role_url() { * @return string */ function members_get_clone_role_url( $role ) { + return add_query_arg( 'clone', $role, members_get_new_role_url() ); } @@ -398,6 +391,7 @@ function members_get_clone_role_url( $role ) { * @return string */ function members_get_edit_roles_url() { + return add_query_arg( 'page', 'roles', admin_url( 'users.php' ) ); } @@ -410,6 +404,7 @@ function members_get_edit_roles_url() { * @return string */ function members_get_role_view_url( $view ) { + return add_query_arg( 'view', $view, members_get_edit_roles_url() ); } @@ -422,6 +417,7 @@ function members_get_role_view_url( $view ) { * @return string */ function members_get_edit_role_url( $role ) { + return add_query_arg( array( 'action' => 'edit', 'role' => $role ), members_get_edit_roles_url() ); } @@ -434,6 +430,7 @@ function members_get_edit_role_url( $role ) { * @return string */ function members_get_delete_role_url( $role ) { + $url = add_query_arg( array( 'action' => 'delete', 'role' => $role ), members_get_edit_roles_url() ); return wp_nonce_url( $url, 'delete_role', 'members_delete_role_nonce' ); @@ -448,5 +445,6 @@ function members_get_delete_role_url( $role ) { * @return string */ function members_get_role_users_url( $role ) { + return admin_url( add_query_arg( 'role', $role, 'users.php' ) ); } diff --git a/inc/functions-shortcodes.php b/inc/functions-shortcodes.php index 7d2d16c..3697724 100644 --- a/inc/functions-shortcodes.php +++ b/inc/functions-shortcodes.php @@ -159,5 +159,6 @@ function members_access_check_shortcode( $attr, $content = null ) { * @return string */ function members_login_form_shortcode() { + return wp_login_form( array( 'echo' => false ) ); } diff --git a/inc/functions.php b/inc/functions.php index 8857e44..d365143 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -20,6 +20,7 @@ * @return bool */ function members_validate_boolean( $val ) { + return filter_var( $val, FILTER_VALIDATE_BOOLEAN ); } From ed0bbac54419210484587e8a0942d0af419c429c Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sun, 16 Jul 2017 12:23:43 -0500 Subject: [PATCH 091/157] Role group object should check if any roles were already registered to it when it's created. --- inc/class-role-group.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/inc/class-role-group.php b/inc/class-role-group.php index 52dfd20..3adbd97 100644 --- a/inc/class-role-group.php +++ b/inc/class-role-group.php @@ -96,5 +96,9 @@ public function __construct( $name, $args = array() ) { } $this->name = sanitize_key( $name ); + + $registered_roles = array_keys( wp_list_filter( members_get_roles(), array( 'group' => $this->name ) ) ); + + $this->roles = array_unique( array_merge( $this->roles, $registered_roles ) ); } } From 35763924c84cda2db977b2f9f6b4f0575ff53849 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sun, 16 Jul 2017 12:28:12 -0500 Subject: [PATCH 092/157] Move unused cap group functions to `functions-deprecated.php`. --- inc/functions-cap-groups.php | 52 ------------------------------------ inc/functions-deprecated.php | 52 ++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/inc/functions-cap-groups.php b/inc/functions-cap-groups.php index 5c0d4a5..ea9f4ec 100644 --- a/inc/functions-cap-groups.php +++ b/inc/functions-cap-groups.php @@ -309,55 +309,3 @@ function members_get_custom_group_caps() { return array_unique( $caps ); } - -/** - * Returns the caps for the general capability group. - * - * @since 1.0.0 - * @deprecated 2.0.0 - * @access public - * @return array - */ -function members_get_general_group_caps() { - - return array_keys( wp_list_filter( members_get_caps(), array( 'group' => 'general' ) ) ); -} - -/** - * Returns the caps for the theme capability group. - * - * @since 1.0.0 - * @deprecated 2.0.0 - * @access public - * @return array - */ -function members_get_theme_group_caps() { - - return array_keys( wp_list_filter( members_get_caps(), array( 'group' => 'theme' ) ) ); -} - -/** - * Returns the caps for the plugin capability group. - * - * @since 1.0.0 - * @deprecated 2.0.0 - * @access public - * @return array - */ -function members_get_plugin_group_caps() { - - return array_keys( wp_list_filter( members_get_caps(), array( 'group' => 'plugin' ) ) ); -} - -/** - * Returns the caps for the user capability group. - * - * @since 1.0.0 - * @deprecated 2.0.0 - * @access public - * @return array - */ -function members_get_user_group_caps() { - - return array_keys( wp_list_filter( members_get_caps(), array( 'group' => 'user' ) ) ); -} diff --git a/inc/functions-deprecated.php b/inc/functions-deprecated.php index 8fa9ce7..53703e9 100644 --- a/inc/functions-deprecated.php +++ b/inc/functions-deprecated.php @@ -226,6 +226,58 @@ function members_get_all_group_caps() { return members_get_capabilities(); } +/** + * Returns the caps for the general capability group. + * + * @since 1.0.0 + * @deprecated 2.0.0 + * @access public + * @return array + */ +function members_get_general_group_caps() { + + return array_keys( wp_list_filter( members_get_caps(), array( 'group' => 'general' ) ) ); +} + +/** + * Returns the caps for the theme capability group. + * + * @since 1.0.0 + * @deprecated 2.0.0 + * @access public + * @return array + */ +function members_get_theme_group_caps() { + + return array_keys( wp_list_filter( members_get_caps(), array( 'group' => 'theme' ) ) ); +} + +/** + * Returns the caps for the plugin capability group. + * + * @since 1.0.0 + * @deprecated 2.0.0 + * @access public + * @return array + */ +function members_get_plugin_group_caps() { + + return array_keys( wp_list_filter( members_get_caps(), array( 'group' => 'plugin' ) ) ); +} + +/** + * Returns the caps for the user capability group. + * + * @since 1.0.0 + * @deprecated 2.0.0 + * @access public + * @return array + */ +function members_get_user_group_caps() { + + return array_keys( wp_list_filter( members_get_caps(), array( 'group' => 'user' ) ) ); +} + /** * Additional capabilities provided by the Members plugin that gives users permissions to handle * certain features of the plugin. From dd5661851aca25ec84549751d7e22f91d98b0ab9 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sun, 16 Jul 2017 13:06:37 -0500 Subject: [PATCH 093/157] Introduce the following filter hooks for the private site feature: * `members_is_private_blog` * `members_is_private_feed` * `members_is_private_rest_api` * `members_rest_api_error_message` --- inc/functions-private-site.php | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/inc/functions-private-site.php b/inc/functions-private-site.php index 7ec81f8..11c7204 100644 --- a/inc/functions-private-site.php +++ b/inc/functions-private-site.php @@ -42,7 +42,7 @@ */ function members_is_private_blog() { - return members_get_setting( 'private_blog' ); + return apply_filters( 'members_is_private_blog', members_get_setting( 'private_blog' ) ); } /** @@ -54,7 +54,7 @@ function members_is_private_blog() { */ function members_is_private_feed() { - return members_get_setting( 'private_feed' ); + return apply_filters( 'members_is_private_feed', members_get_setting( 'private_feed' ) ); } /** @@ -66,7 +66,7 @@ function members_is_private_feed() { */ function members_is_private_rest_api() { - return members_get_setting( 'private_rest_api' ); + return apply_filters( 'members_is_private_rest_api', members_get_setting( 'private_rest_api' ) ); } /** @@ -153,8 +153,19 @@ function members_get_private_feed_message() { */ function members_private_rest_api( $result ) { - if ( empty( $result ) && members_is_private_rest_api() && ! is_user_logged_in() ) - return new WP_Error( 'rest_not_logged_in', esc_html__( 'You are not currently logged in.', 'members' ), array( 'status' => 401 ) ); + if ( empty( $result ) && members_is_private_rest_api() && ! is_user_logged_in() ) { + + return new WP_Error( + 'rest_not_logged_in', + esc_html( + apply_filters( + 'members_rest_api_error_message', + __( 'You are not currently logged in.', 'members' ) + ) + ), + array( 'status' => 401 ) + ); + } return $result; } From 6214294076e96203c697d67647b78ab345b81cf0 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 17 Jul 2017 13:54:20 -0500 Subject: [PATCH 094/157] Add note that PHP 5.3.0+ is required in the `readme.txt`. --- readme.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/readme.txt b/readme.txt index d0f5f0d..9d458df 100644 --- a/readme.txt +++ b/readme.txt @@ -67,6 +67,10 @@ Most things should be fairly straightforward, but I've included an in-depth guid You can also [view the readme](https://github.com/justintadlock/members/blob/master/readme.md) online. +### Minimum PHP requirements. + +Since version 2.0.0 of Members, PHP 5.3.0+ is required to use the plugin. The plugin will not allow itself to be activated and will output an error message if an earlier version of PHP is detected. + ### I can't access the "Role Manager" features. When the plugin is first activated, it runs a script that sets specific capabilities to the "Administrator" role on your site that grants you access to this feature. So, you must be logged in with the administrator account to access the role manager. @@ -87,6 +91,10 @@ You'll need to stop by my [support forums](https://themehybrid.com/board/topics) 4. Plugin settings screen 5. Select multiple roles per user (edit user screen) +== Upgrade Notice == + +If upgrading from a version prior to 2.0.0, please note that the plugin now requires PHP 5.3.0 or later. + == Changelog == The change log is located in the `changelog.md` file in the plugin folder. You may also [view the change log](https://github.com/justintadlock/members/blob/master/changelog.md) online. \ No newline at end of file From 6d6996f2a8a95eaa2aa03c609c32ba8e766a936b Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 18 Jul 2017 12:11:51 -0500 Subject: [PATCH 095/157] Update help tabs text for the general settings screen. --- admin/views/class-view-general.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/admin/views/class-view-general.php b/admin/views/class-view-general.php index 5a90a4a..cf80255 100644 --- a/admin/views/class-view-general.php +++ b/admin/views/class-view-general.php @@ -399,12 +399,16 @@ public function help_tab_roles_caps() { ?>

    +

    + +

    +

    - +

    Date: Tue, 18 Jul 2017 14:38:56 -0500 Subject: [PATCH 096/157] Remove the unused `addons.json` file. --- admin/addons.json | 43 ------------------------------------------- 1 file changed, 43 deletions(-) delete mode 100644 admin/addons.json diff --git a/admin/addons.json b/admin/addons.json deleted file mode 100644 index 1aa0a2e..0000000 --- a/admin/addons.json +++ /dev/null @@ -1,43 +0,0 @@ -[ - { - "title" : "Members - Role Levels", - "url" : "https:\/\/themehybrid.com\/plugins\/members-role-levels", - "slug" : "members-role-levels", - "excerpt" : "

    Exposes the old user levels system, which fixes the WordPress author drop-down bug when users don’t have a role with one of the assigned levels.<\/p>\n", - "author" : { - "name" : "Justin Tadlock", - "url" : "https:\/\/themehybrid.com\/plugins\/authors\/admin" - }, - "meta" : { - "purchase_url" : "https:\/\/themehybrid.com\/plugins\/members-role-levels", - "download_url" : "", - "rating" : 0, - "rating_count" : 0, - "install_count" : 0 - },"media" : { - "banner" : {"url" : ""}, - "icon" : {"url" : ""} - } - }, - { - "title" : "Members - Role Hierarchy", - "url" : "https:\/\/themehybrid.com\/plugins\/members-role-hierarchy", - "slug" : "members-role-hierarchy", - "excerpt" : "

    Add-on plugin for Members for hierarchical user roles.<\/p>\n", - "author" : { - "name" : "Justin Tadlock", - "url" : "https:\/\/themehybrid.com\/plugins\/authors\/admin" - }, - "meta" : { - "purchase_url" : "", - "download_url" : "https:\/\/themehybrid.com\/plugins\/members-role-hierarchy", - "rating" : 0, - "rating_count" : 0, - "install_count" : 100 - },"media" : { - "banner" : { "url" : "" }, - "icon" : { "url" : "" } - } - } -] - From d4110387e0a3a06fc6d179654ebf3a74f99bb162 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 18 Jul 2017 16:45:25 -0500 Subject: [PATCH 097/157] General file and code cleanup. --- admin/functions-admin.php | 1 - members.php | 11 ++++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/admin/functions-admin.php b/admin/functions-admin.php index b25a644..378c99a 100644 --- a/admin/functions-admin.php +++ b/admin/functions-admin.php @@ -14,7 +14,6 @@ add_action( 'admin_enqueue_scripts', 'members_admin_register_scripts', 0 ); add_action( 'admin_enqueue_scripts', 'members_admin_register_styles', 0 ); - /** * Get an Underscore JS template. * diff --git a/members.php b/members.php index b77164a..04268e9 100644 --- a/members.php +++ b/members.php @@ -157,7 +157,7 @@ public function __call( $method = '', $args = array() ) { * Sets up globals. * * @since 1.0.0 - * @access public + * @access private * @return void */ private function setup() { @@ -171,7 +171,7 @@ private function setup() { * Loads files needed by the plugin. * * @since 1.0.0 - * @access public + * @access private * @return void */ private function includes() { @@ -238,7 +238,7 @@ private function includes() { * Sets up main plugin actions and filters. * * @since 1.0.0 - * @access public + * @access private * @return void */ private function setup_actions() { @@ -259,10 +259,7 @@ private function setup_actions() { */ public function i18n() { -//if ( version_compare( PHP_VERSION, '7.1.7', '<' ) ) -// wp_die( PHP_VERSION . 'hello' ); - - load_plugin_textdomain( 'members', false, trailingslashit( dirname( plugin_basename( __FILE__ ) ) ). 'lang' ); + load_plugin_textdomain( 'members', false, trailingslashit( dirname( plugin_basename( __FILE__ ) ) ) . 'lang' ); } /** From 8dcf68095c76b67830c0f14e251711dc605794bc Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 18 Jul 2017 17:36:30 -0500 Subject: [PATCH 098/157] Update the `members.pot` file. --- lang/members.pot | 1099 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 768 insertions(+), 331 deletions(-) diff --git a/lang/members.pot b/lang/members.pot index b360673..3420939 100644 --- a/lang/members.pot +++ b/lang/members.pot @@ -1,82 +1,159 @@ -# Copyright (C) 2016 Members +# Copyright (C) 2017 Members # This file is distributed under the same license as the Members package. msgid "" msgstr "" -"Project-Id-Version: Members 1.1.1-dev\n" +"Project-Id-Version: Members 2.0.0-dev\n" "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/members\n" -"POT-Creation-Date: 2016-01-09 19:58:30+00:00\n" +"POT-Creation-Date: 2017-07-18 22:34:50+00:00\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: 2017-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" -#: _assets/class-cap-new.php:64 _assets/class-cap-new.php:158 -msgid "Add New Capability" +#: _assets/class-cap-edit.php:92 admin/class-manage-users.php:161 +#: admin/class-manage-users.php:236 admin/class-role-edit.php:92 +#: members.php:129 members.php:140 +msgid "Whoah, partner!" msgstr "" -#: _assets/class-cap-new.php:102 -msgid "Please input a valid capability." +#: _assets/class-cap-edit.php:99 +msgid "The requested cap to edit does not exist." msgstr "" -#: _assets/class-cap-new.php:106 -msgid "The %s capability already exists." +#: _assets/class-cap-edit.php:235 +msgid "%s cap updated." msgstr "" -#: _assets/class-cap-new.php:110 -msgid "Please select at least one role." +#: _assets/class-cap-edit.php:239 +msgid "The %s cap is not editable. This means that it is most likely added via another plugin for a special use or that you do not have permission to edit it." msgstr "" -#: _assets/class-cap-new.php:123 -msgid "The %s capability has been created." +#: _assets/class-cap-edit.php:247 +msgid "The %s cap has been created." msgstr "" -#: _assets/class-cap-new.php:172 admin/tmpl/cap-section.php:19 -#: admin/tmpl/cap-section.php:27 -msgid "Capability" +#: _assets/class-cap-edit.php:309 +msgid "Edit Cap" msgstr "" -#: _assets/class-cap-new.php:178 -msgid "The capability should be unique and contain only alphanumeric characters and underscores." +#: _assets/class-cap-edit.php:312 _assets/class-caps.php:175 +msgctxt "cap" +msgid "Add New" +msgstr "" + +#: _assets/class-cap-edit.php:331 +msgid "Capability Label" +msgstr "" + +#: _assets/class-cap-edit.php:337 +msgid "Capability:" msgstr "" -#: _assets/class-cap-new.php:185 admin/class-manage-roles.php:84 -#: admin/class-manage-roles.php:90 admin/class-roles.php:168 -#: admin/class-user-edit.php:87 admin/functions-admin.php:151 +#: _assets/class-cap-edit.php:344 _assets/class-cap-new.php:185 +#: _assets/class-caps.php:70 admin/class-manage-roles.php:86 +#: admin/class-manage-roles.php:92 admin/class-manage-users.php:360 +#: admin/class-meta-box-content-permissions.php:174 admin/class-roles.php:170 +#: admin/class-user-edit.php:92 msgid "Roles" msgstr "" -#: _assets/class-cap-new.php:189 -msgid "Select at least one role. Because of the way capabilities work in WordPress, they can only exist if assigned to a role." +#: _assets/class-cap-edit.php:351 _assets/class-cap-edit.php:358 +#: admin/class-meta-box-publish-role.php:67 admin/class-roles.php:68 +#: inc/functions-admin-bar.php:35 +msgid "Role" msgstr "" -#: _assets/class-cap-new.php:209 -msgid "Add Capability" +#: _assets/class-cap-edit.php:352 _assets/class-cap-edit.php:359 +#: admin/tmpl/cap-section.php:20 admin/tmpl/cap-section.php:28 +msgid "Grant" +msgstr "" + +#: _assets/class-cap-edit.php:353 _assets/class-cap-edit.php:360 +#: admin/tmpl/cap-section.php:21 admin/tmpl/cap-section.php:29 +msgid "Deny" msgstr "" +#: _assets/class-cap-list-table.php:377 admin/class-role-list-table.php:337 +#: admin/class-role-new.php:335 admin/functions-admin.php:46 +msgid "Edit" +msgstr "" + +#: _assets/class-cap-list-table.php:381 _assets/class-cap-list-table.php:520 #: _assets/class-capability-list-table.php:264 #: _assets/class-capability-list-table.php:387 -#: admin/class-role-list-table.php:338 admin/class-role-list-table.php:463 +#: admin/class-role-list-table.php:341 admin/class-role-list-table.php:490 msgid "Delete" msgstr "" +#: _assets/class-cap-list-table.php:387 admin/class-role-list-table.php:347 +msgid "View" +msgstr "" + +#: _assets/class-cap-list-table.php:452 #: _assets/class-capability-list-table.php:319 -#: admin/class-role-list-table.php:408 +#: admin/class-role-list-table.php:400 msgid "All %s" msgid_plural "All %s" msgstr[0] "" msgstr[1] "" +#: _assets/class-cap-list-table.php:464 #: _assets/class-capability-list-table.php:320 -#: admin/functions-role-groups.php:112 +#: admin/class-role-list-table.php:405 msgid "Mine %s" msgid_plural "Mine %s" msgstr[0] "" msgstr[1] "" -#: _assets/class-capability-list-table.php:321 -#: admin/functions-role-groups.php:158 +#: _assets/class-cap-list-table.php:538 +msgid "All Groups" +msgstr "" + +#: _assets/class-cap-list-table.php:547 +#: _assets/class-capability-list-table.php:359 +msgid "Filter" +msgstr "" + +#: _assets/class-cap-new.php:64 _assets/class-cap-new.php:158 +msgid "Add New Capability" +msgstr "" + +#: _assets/class-cap-new.php:102 +msgid "Please input a valid capability." +msgstr "" + +#: _assets/class-cap-new.php:106 +msgid "The %s capability already exists." +msgstr "" + +#: _assets/class-cap-new.php:110 +msgid "Please select at least one role." +msgstr "" + +#: _assets/class-cap-new.php:123 +msgid "The %s capability has been created." +msgstr "" + +#: _assets/class-cap-new.php:172 _assets/class-caps.php:68 +#: admin/tmpl/cap-section.php:19 admin/tmpl/cap-section.php:27 +msgid "Capability" +msgstr "" + +#: _assets/class-cap-new.php:178 +msgid "The capability should be unique and contain only alphanumeric characters and underscores." +msgstr "" + +#: _assets/class-cap-new.php:189 +msgid "Select at least one role. Because of the way capabilities work in WordPress, they can only exist if assigned to a role." +msgstr "" + +#: _assets/class-cap-new.php:209 +msgid "Add Capability" +msgstr "" + +#: _assets/class-capability-list-table.php:321 inc/functions-role-groups.php:43 msgid "WordPress %s" msgid_plural "WordPress %s" msgstr[0] "" @@ -92,15 +169,89 @@ msgstr[1] "" msgid "View all roles" msgstr "" -#: _assets/class-capability-list-table.php:359 -msgid "Filter" +#: _assets/class-caps.php:67 +msgid "Label" +msgstr "" + +#: _assets/class-caps.php:69 +msgid "Groups" +msgstr "" + +#: _assets/class-caps.php:114 +msgid "Selected caps deleted." +msgstr "" + +#: _assets/class-caps.php:133 +msgid "%s cap deleted." msgstr "" -#: _assets/page-capabilities.php:45 _assets/page-capabilities.php:93 -#: admin/class-settings.php:133 +#: _assets/class-caps.php:172 _assets/class-manage-caps.php:86 +#: _assets/class-manage-caps.php:92 _assets/page-capabilities.php:45 +#: _assets/page-capabilities.php:93 admin/views/class-view-general.php:72 msgid "Capabilities" msgstr "" +#: _assets/class-caps.php:212 admin/class-roles.php:210 +#: admin/functions-help.php:46 admin/views/class-view-addons.php:176 +msgid "Overview" +msgstr "" + +#: _assets/class-caps.php:221 admin/class-roles.php:219 +msgid "Screen Content" +msgstr "" + +#: _assets/class-caps.php:230 admin/class-roles.php:228 +msgid "Available Actions" +msgstr "" + +#: _assets/class-caps.php:239 admin/class-roles.php:237 +msgid "Bulk Actions" +msgstr "" + +#: _assets/class-caps.php:258 +msgid "This screen provides access to all of your user caps. Caps are a method of grouping users. They are made up of capabilities (caps), which give permission to users to perform specific actions on the site." +msgstr "" + +#: _assets/class-caps.php:272 admin/class-roles.php:270 +msgid "You can customize the display of this screen‘s contents in a number of ways:" +msgstr "" + +#: _assets/class-caps.php:276 +msgid "You can hide/display columns based on your needs and decide how many caps to list per screen using the Screen Options tab." +msgstr "" + +#: _assets/class-caps.php:277 +msgid "You can filter the list of caps by types using the text links in the upper left. The default view is to show all caps." +msgstr "" + +#: _assets/class-caps.php:291 +msgid "Hovering over a row in the caps list will display action links that allow you to manage your cap. You can perform the following actions:" +msgstr "" + +#: _assets/class-caps.php:295 +msgid "Edit takes you to the editing screen for that cap. You can also reach that screen by clicking on the cap name." +msgstr "" + +#: _assets/class-caps.php:296 +msgid "Delete removes your cap from this list and permanently deletes it." +msgstr "" + +#: _assets/class-caps.php:297 +msgid "Clone copies the cap and takes you to the new cap screen to further edit it." +msgstr "" + +#: _assets/class-caps.php:298 +msgid "Users takes you to the users screen and lists the users that have that cap." +msgstr "" + +#: _assets/class-caps.php:312 +msgid "You can permanently delete multiple caps at once. Select the caps you want to act on using the checkboxes, then select the action you want to take from the Bulk Actions menu and click Apply." +msgstr "" + +#: _assets/class-manage-caps.php:89 +msgid "Edit Capability" +msgstr "" + #: _assets/page-capabilities.php:69 msgid "%s capability deleted. Not really. This is just a message to output until the functionality is working." msgstr "" @@ -109,8 +260,7 @@ msgstr "" msgid "No capability selected to delete." msgstr "" -#: _assets/page-capabilities.php:96 admin/class-meta-box-custom-cap.php:88 -#: admin/class-role-edit.php:260 admin/class-roles.php:171 +#: _assets/page-capabilities.php:96 msgid "Add New" msgstr "" @@ -118,703 +268,990 @@ msgstr "" msgid "Are you sure you want to delete this capability? This is a permanent action and cannot be undone." msgstr "" -#: admin/class-cap-control.php:115 admin/functions-admin.php:51 +#: admin/class-cap-control.php:118 admin/functions-admin.php:48 msgid "Grant %s capability" msgstr "" -#: admin/class-cap-control.php:116 admin/functions-admin.php:52 +#: admin/class-cap-control.php:119 admin/functions-admin.php:49 msgid "Deny %s capability" msgstr "" -#: admin/class-cap-tabs.php:174 +#: admin/class-cap-tabs.php:165 +msgid "All" +msgstr "" + +#: admin/class-cap-tabs.php:194 msgid "Edit Capabilities: %s" msgstr "" -#: admin/class-manage-roles.php:87 admin/class-role-edit.php:257 +#: admin/class-manage-roles.php:89 admin/class-role-edit.php:298 msgid "Edit Role" msgstr "" -#: admin/class-meta-box-content-permissions.php:99 admin/class-settings.php:125 -#: admin/class-settings.php:398 -msgid "Content Permissions" +#: admin/class-manage-users.php:97 +msgid "Role added to selected users." +msgstr "" + +#: admin/class-manage-users.php:102 +msgid "Role removed from selected users." +msgstr "" + +#: admin/class-manage-users.php:106 +msgid "The current user’s role must have user editing capabilities." +msgstr "" + +#: admin/class-manage-users.php:107 +msgid "Role removed from other selected users." +msgstr "" + +#: admin/class-manage-users.php:162 admin/class-manage-users.php:237 +msgid "One of the selected users is not a member of this site." +msgstr "" + +#: admin/class-manage-users.php:326 admin/class-manage-users.php:330 +msgid "Add role…" +msgstr "" + +#: admin/class-manage-users.php:334 +msgid "Add" msgstr "" -#: admin/class-meta-box-content-permissions.php:132 -msgid "Limit access to this post's content to users of the selected roles." +#: admin/class-manage-users.php:337 admin/class-manage-users.php:341 +msgid "Remove role…" msgstr "" -#: admin/class-meta-box-content-permissions.php:152 -msgid "If no roles are selected, everyone can view the content. The post author, any users who can edit this post, and users with the %s capability can view the content regardless of role." +#: admin/class-manage-users.php:345 +msgid "Remove" msgstr "" -#: admin/class-meta-box-content-permissions.php:156 -msgid "Custom error message:" +#: admin/class-manage-users.php:382 +msgid "None" msgstr "" -#: admin/class-meta-box-content-permissions.php:158 -msgid "Message shown to users that do not have permission to view the post." +#: admin/class-meta-box-content-permissions.php:115 +#: admin/views/class-view-general.php:63 admin/views/class-view-general.php:362 +msgid "Content Permissions" msgstr "" -#: admin/class-meta-box-custom-cap.php:71 admin/functions-help.php:94 +#: admin/class-meta-box-content-permissions.php:180 +#: admin/views/class-view-general.php:76 +msgid "Error Message" +msgstr "" + +#: admin/class-meta-box-content-permissions.php:190 +msgid "Limit access to the content to users of the selected roles." +msgstr "" + +#: admin/class-meta-box-content-permissions.php:210 +msgid "If no roles are selected, everyone can view the content. The author, any users who can edit the content, and users with the %s capability can view the content regardless of role." +msgstr "" + +#: admin/class-meta-box-custom-cap.php:73 admin/functions-help.php:94 msgid "Custom Capability" msgstr "" -#: admin/class-meta-box-publish-role.php:65 admin/class-roles.php:66 -#: inc/functions-admin-bar.php:35 -msgid "Role" +#: admin/class-meta-box-custom-cap.php:90 +msgctxt "capability" +msgid "Add New" msgstr "" -#: admin/class-meta-box-publish-role.php:98 +#: admin/class-meta-box-publish-role.php:100 msgid "Users:" msgstr "" -#: admin/class-meta-box-publish-role.php:104 +#: admin/class-meta-box-publish-role.php:106 msgid "Granted:" msgstr "" -#: admin/class-meta-box-publish-role.php:110 +#: admin/class-meta-box-publish-role.php:112 msgid "Denied:" msgstr "" -#: admin/class-meta-box-publish-role.php:121 +#: admin/class-meta-box-publish-role.php:123 msgctxt "delete role" msgid "Delete" msgstr "" -#: admin/class-meta-box-publish-role.php:128 +#: admin/class-meta-box-publish-role.php:130 msgid "Update" msgstr "" -#: admin/class-meta-box-publish-role.php:128 +#: admin/class-meta-box-publish-role.php:130 msgid "Add Role" msgstr "" -#: admin/class-role-edit.php:90 members.php:165 members.php:176 -msgid "Whoah, partner!" -msgstr "" - -#: admin/class-role-edit.php:97 +#: admin/class-role-edit.php:99 msgid "The requested role to edit does not exist." msgstr "" -#: admin/class-role-edit.php:189 +#: admin/class-role-edit.php:226 msgid "%s role updated." msgstr "" -#: admin/class-role-edit.php:193 +#: admin/class-role-edit.php:230 msgid "The %s role is not editable. This means that it is most likely added via another plugin for a special use or that you do not have permission to edit it." msgstr "" -#: admin/class-role-edit.php:197 admin/class-role-new.php:224 +#: admin/class-role-edit.php:234 +msgid "The %s role is typically the most important role on the site. Please take extreme caution that you do not inadvertently remove necessary capabilities." +msgstr "" + +#: admin/class-role-edit.php:238 admin/class-role-new.php:226 msgid "The %s role has been created." msgstr "" -#: admin/class-role-edit.php:279 admin/class-role-new.php:325 -#: admin/class-roles.php:65 admin/functions-help.php:62 +#: admin/class-role-edit.php:301 admin/class-roles.php:173 +msgctxt "role" +msgid "Add New" +msgstr "" + +#: admin/class-role-edit.php:320 admin/class-role-new.php:327 +#: admin/class-roles.php:67 admin/functions-help.php:62 msgid "Role Name" msgstr "" -#: admin/class-role-edit.php:285 admin/class-role-new.php:331 -#: inc/class-widget-users.php:227 +#: admin/class-role-edit.php:326 admin/class-role-new.php:333 +#: inc/class-widget-users.php:228 msgid "Role:" msgstr "" -#: admin/class-role-list-table.php:229 +#: admin/class-role-list-table.php:232 msgid "Default Role" msgstr "" -#: admin/class-role-list-table.php:233 +#: admin/class-role-list-table.php:236 msgid "Your Role" msgstr "" -#: admin/class-role-list-table.php:334 admin/class-role-new.php:333 -#: admin/functions-admin.php:49 -msgid "Edit" -msgstr "" - -#: admin/class-role-list-table.php:344 -msgid "View" -msgstr "" - -#: admin/class-role-list-table.php:349 +#: admin/class-role-list-table.php:352 msgid "Clone" msgstr "" -#: admin/class-role-list-table.php:353 +#: admin/class-role-list-table.php:356 msgid "Change Default" msgstr "" -#: admin/class-role-list-table.php:357 admin/class-roles.php:67 -#: admin/functions-cap-groups.php:193 inc/class-widget-users.php:57 +#: admin/class-role-list-table.php:360 admin/class-roles.php:69 +#: inc/class-widget-users.php:59 inc/functions-cap-groups.php:121 msgid "Users" msgstr "" -#: admin/class-role-new.php:107 admin/class-role-new.php:308 +#: admin/class-role-list-table.php:410 +msgid "Has Users %s" +msgid_plural "Has Users %s" +msgstr[0] "" +msgstr[1] "" + +#: admin/class-role-list-table.php:415 +msgid "No Users %s" +msgid_plural "No Users %s" +msgstr[0] "" +msgstr[1] "" + +#: admin/class-role-list-table.php:420 +msgid "Editable %s" +msgid_plural "Editable %s" +msgstr[0] "" +msgstr[1] "" + +#: admin/class-role-list-table.php:425 +msgid "Uneditable %s" +msgid_plural "Uneditable %s" +msgstr[0] "" +msgstr[1] "" + +#: admin/class-role-new.php:109 admin/class-role-new.php:310 msgid "Add New Role" msgstr "" -#: admin/class-role-new.php:233 +#: admin/class-role-new.php:235 msgid "You must enter a valid role." msgstr "" -#: admin/class-role-new.php:237 +#: admin/class-role-new.php:239 msgid "The %s role already exists." msgstr "" -#: admin/class-role-new.php:241 +#: admin/class-role-new.php:243 msgid "You must enter a valid role name." msgstr "" -#: admin/class-role-new.php:308 +#: admin/class-role-new.php:310 msgid "Clone Role" msgstr "" -#: admin/class-role-new.php:326 +#: admin/class-role-new.php:328 msgid "%s Clone" msgstr "" -#: admin/class-role-new.php:326 +#: admin/class-role-new.php:328 msgid "Enter role name" msgstr "" -#: admin/class-roles.php:68 +#: admin/class-roles.php:70 msgid "Granted" msgstr "" -#: admin/class-roles.php:69 +#: admin/class-roles.php:71 msgid "Denied" msgstr "" -#: admin/class-roles.php:110 +#: admin/class-roles.php:112 msgid "Selected roles deleted." msgstr "" -#: admin/class-roles.php:129 +#: admin/class-roles.php:131 msgid "%s role deleted." msgstr "" -#: admin/class-roles.php:208 admin/functions-help.php:46 -msgid "Overview" -msgstr "" - -#: admin/class-roles.php:217 -msgid "Screen Content" -msgstr "" - -#: admin/class-roles.php:226 -msgid "Available Actions" -msgstr "" - -#: admin/class-roles.php:235 -msgid "Bulk Actions" -msgstr "" - -#: admin/class-roles.php:254 +#: admin/class-roles.php:256 msgid "This screen provides access to all of your user roles. Roles are a method of grouping users. They are made up of capabilities (caps), which give permission to users to perform specific actions on the site." msgstr "" -#: admin/class-roles.php:268 -msgid "You can customize the display of this screen‘s contents in a number of ways:" -msgstr "" - -#: admin/class-roles.php:272 +#: admin/class-roles.php:274 msgid "You can hide/display columns based on your needs and decide how many roles to list per screen using the Screen Options tab." msgstr "" -#: admin/class-roles.php:273 +#: admin/class-roles.php:275 msgid "You can filter the list of roles by types using the text links in the upper left. The default view is to show all roles." msgstr "" -#: admin/class-roles.php:287 +#: admin/class-roles.php:289 msgid "Hovering over a row in the roles list will display action links that allow you to manage your role. You can perform the following actions:" msgstr "" -#: admin/class-roles.php:291 +#: admin/class-roles.php:293 msgid "Edit takes you to the editing screen for that role. You can also reach that screen by clicking on the role name." msgstr "" -#: admin/class-roles.php:292 +#: admin/class-roles.php:294 msgid "Delete removes your role from this list and permanently deletes it." msgstr "" -#: admin/class-roles.php:293 +#: admin/class-roles.php:295 msgid "Clone copies the role and takes you to the new role screen to further edit it." msgstr "" -#: admin/class-roles.php:294 +#: admin/class-roles.php:296 msgid "Users takes you to the users screen and lists the users that have that role." msgstr "" -#: admin/class-roles.php:308 +#: admin/class-roles.php:310 msgid "You can permanently delete multiple roles at once. Select the roles you want to act on using the checkboxes, then select the action you want to take from the Bulk Actions menu and click Apply." msgstr "" -#: admin/class-settings.php:70 admin/class-settings.php:362 -msgid "Members Settings" -msgstr "" - -#: admin/class-settings.php:71 +#: admin/class-settings.php:174 admin/class-settings.php:175 +#: admin/class-settings.php:275 msgctxt "admin screen" msgid "Members" msgstr "" -#: admin/class-settings.php:124 -msgid "Roles and Capabilities" -msgstr "" - -#: admin/class-settings.php:126 admin/class-settings.php:407 -msgid "Sidebar Widgets" -msgstr "" - -#: admin/class-settings.php:127 admin/class-settings.php:416 -msgid "Private Site" +#: admin/class-user-edit.php:97 admin/class-user-new.php:106 +msgid "User Roles" msgstr "" -#: admin/class-settings.php:132 -msgid "Role Manager" +#: admin/functions-admin.php:47 +msgid "OK" msgstr "" -#: admin/class-settings.php:134 -msgid "Multiple User Roles" +#: admin/functions-admin.php:50 +msgid "Are you sure you want to delete this role? This is a permanent action and cannot be undone." msgstr "" -#: admin/class-settings.php:137 -msgid "Enable Permissions" +#: admin/functions-help.php:23 +msgid "Documentation" msgstr "" -#: admin/class-settings.php:138 -msgid "Error Message" +#: admin/functions-help.php:24 +msgid "Support Forums" msgstr "" -#: admin/class-settings.php:141 -msgid "Login Widget" +#: admin/functions-help.php:29 +msgid "For more information:" msgstr "" -#: admin/class-settings.php:142 -msgid "Users Widget" +#: admin/functions-help.php:78 +msgid "Edit Capabilities" msgstr "" -#: admin/class-settings.php:145 -msgid "Enable Private Site" +#: admin/functions-help.php:109 +msgid "This screen allows you to edit an individual role and its capabilities." msgstr "" -#: admin/class-settings.php:146 -msgid "Disable Feed" +#: admin/functions-help.php:114 +msgid "Visit the %s page in the WordPress Codex to see a complete list of roles, capabilities, and their definitions." msgstr "" -#: admin/class-settings.php:147 -msgid "Feed Error Message" +#: admin/functions-help.php:115 admin/views/class-view-general.php:62 +msgid "Roles and Capabilities" msgstr "" -#: admin/class-settings.php:188 -msgid "Your roles and capabilities will not revert back to their previous settings after deactivating or uninstalling this plugin, so use this feature wisely." +#: admin/functions-help.php:130 +msgid "The role name field allows you to enter a human-readable name for your role." msgstr "" -#: admin/class-settings.php:203 -msgid "Enable the role manager." +#: admin/functions-help.php:134 +msgid "The machine-readable version of the role appears below the name field, which you can edit. This can only have lowercase letters, numbers, or underscores." msgstr "" -#: admin/class-settings.php:218 -msgid "Denied capabilities should always overrule granted capabilities." +#: admin/functions-help.php:148 +msgid "The capabilities edit box is made up of tabs that separate capabilities into groups. You may take the following actions for each capability:" msgstr "" -#: admin/class-settings.php:233 -msgid "Allow users to be assigned more than a single role." +#: admin/functions-help.php:152 +msgid "Grant allows you to grant the role a capability." msgstr "" -#: admin/class-settings.php:248 -msgid "Enable the content permissions feature." +#: admin/functions-help.php:153 +msgid "Deny allows you to explicitly deny the role a capability." msgstr "" -#: admin/class-settings.php:283 -msgid "Enable the login form widget." +#: admin/functions-help.php:154 +msgid "You may also opt to neither grant nor deny the role a capability." msgstr "" -#: admin/class-settings.php:298 -msgid "Enable the users widget." +#: admin/functions-help.php:168 +msgid "The custom capability box allows you to create a custom capability for the role. After hitting the Add New button, it will add the capability to the Custom tab in the Edit Capabilities box." msgstr "" -#: admin/class-settings.php:313 -msgid "Redirect all logged-out users to the login page before allowing them to view the site." +#: admin/functions-settings.php:35 inc/functions-cap-groups.php:42 +msgid "General" msgstr "" -#: admin/class-settings.php:328 -msgid "Show error message for feed items." +#: admin/functions-settings.php:46 +msgid "Add-Ons" msgstr "" -#: admin/class-settings.php:367 -msgid "Update Settings" +#: admin/views/class-view-addons.php:53 +msgid "There are currently no add-ons to show. Please try again later." msgstr "" -#: admin/class-settings.php:389 -msgid "Role and Capabilities" +#: admin/views/class-view-addons.php:99 admin/views/class-view-addons.php:194 +msgid "Purchase" msgstr "" -#: admin/class-settings.php:422 admin/functions-help.php:23 -msgid "Documentation" +#: admin/views/class-view-addons.php:103 admin/views/class-view-addons.php:107 +#: admin/views/class-view-addons.php:185 +msgid "Download" msgstr "" -#: admin/class-settings.php:423 admin/functions-help.php:24 -msgid "Support Forums" +#: admin/views/class-view-addons.php:121 +msgid "By %s" msgstr "" -#: admin/class-settings.php:424 -msgid "Users, Roles, and Capabilities" +#: admin/views/class-view-addons.php:145 +msgid "%s+ Active Installs" msgstr "" -#: admin/class-settings.php:440 -msgid "The role manager allows you to manage roles on your site by giving you the ability to create, edit, and delete any role. Note that changes to roles do not change settings for the Members plugin. You are literally changing data in your WordPress database. This plugin feature merely provides an interface for you to make these changes." +#: admin/views/class-view-addons.php:213 +msgid "The Add-Ons screen allows you to view available add-ons for the Members plugin. You can download some plugins directly. Others may be available to purchase." msgstr "" -#: admin/class-settings.php:444 -msgid "Tick the checkbox for denied capabilities to always take precedence over granted capabilities when there is a conflict. This is only relevant when using multiple roles per user." +#: admin/views/class-view-addons.php:227 +msgid "Some plugins may be available for direct download. In such cases, you can click the download button to get a ZIP file of the plugin." msgstr "" -#: admin/class-settings.php:448 -msgid "The multiple user roles feature allows you to assign more than one role to each user from the edit user screen." +#: admin/views/class-view-addons.php:241 +msgid "Some add-ons may require purchase before downloading them. Clicking the purchase button will take you off-site to view the add-on in more detail." msgstr "" -#: admin/class-settings.php:462 -msgid "The content permissions features adds a meta box to the edit post screen that allows you to grant permissions for who can read the post content based on the user's role. Only users of roles with the %s capability will be able to use this component." +#: admin/views/class-view-general.php:64 admin/views/class-view-general.php:371 +msgid "Sidebar Widgets" msgstr "" -#: admin/class-settings.php:476 -msgid "The sidebar widgets feature adds additional widgets for use in your theme's sidebars." +#: admin/views/class-view-general.php:65 admin/views/class-view-general.php:380 +msgid "Private Site" msgstr "" -#: admin/class-settings.php:490 -msgid "The private site feature redirects all users who are not logged into the site to the login page, creating an entirely private site. You may also replace your feed content with a custom error message." +#: admin/views/class-view-general.php:70 +msgid "Role Manager" msgstr "" -#: admin/class-user-edit.php:92 -msgid "User Roles" +#: admin/views/class-view-general.php:71 +msgid "Multiple User Roles" msgstr "" -#: admin/functions-admin.php:50 -msgid "OK" +#: admin/views/class-view-general.php:75 +msgid "Enable Permissions" msgstr "" -#: admin/functions-admin.php:53 -msgid "Are you sure you want to delete this role? This is a permanent action and cannot be undone." +#: admin/views/class-view-general.php:79 +msgid "Login Widget" msgstr "" -#: admin/functions-admin.php:180 -msgid "None" +#: admin/views/class-view-general.php:80 +msgid "Users Widget" msgstr "" -#: admin/functions-cap-groups.php:106 -msgid "All" +#: admin/views/class-view-general.php:83 +msgid "Enable Private Site" msgstr "" -#: admin/functions-cap-groups.php:116 -msgid "General" +#: admin/views/class-view-general.php:84 +msgid "REST API" msgstr "" -#: admin/functions-cap-groups.php:165 -msgid "Taxonomies" +#: admin/views/class-view-general.php:85 +msgid "Disable Feed" msgstr "" -#: admin/functions-cap-groups.php:175 -msgid "Appearance" +#: admin/views/class-view-general.php:86 +msgid "Feed Error Message" msgstr "" -#: admin/functions-cap-groups.php:184 -msgid "Plugins" +#: admin/views/class-view-general.php:128 +msgid "Your roles and capabilities will not revert back to their previous settings after deactivating or uninstalling this plugin, so use this feature wisely." msgstr "" -#: admin/functions-cap-groups.php:202 -msgid "Custom" +#: admin/views/class-view-general.php:143 +msgid "Enable the role manager." msgstr "" -#: admin/functions-help.php:29 -msgid "For more information:" +#: admin/views/class-view-general.php:161 +msgid "Denied capabilities should always overrule granted capabilities." msgstr "" -#: admin/functions-help.php:78 -msgid "Edit Capabilities" +#: admin/views/class-view-general.php:168 +msgid "Show human-readable capabilities when possible." msgstr "" -#: admin/functions-help.php:109 -msgid "This screen allows you to edit an individual role and its capabilities." +#: admin/views/class-view-general.php:186 +msgid "Allow users to be assigned more than a single role." msgstr "" -#: admin/functions-help.php:123 -msgid "The role name field allows you to enter a human-readable name for your role." +#: admin/views/class-view-general.php:201 +msgid "Enable the content permissions feature." msgstr "" -#: admin/functions-help.php:127 -msgid "The machine-readable version of the role appears below the name field, which you can edit. This can only have lowercase letters, numbers, or underscores." +#: admin/views/class-view-general.php:236 +msgid "Enable the login form widget." msgstr "" -#: admin/functions-help.php:141 -msgid "The capabilities edit box is made up of tabs that separate capabilities into groups. You may take the following actions for each capability:" +#: admin/views/class-view-general.php:251 +msgid "Enable the users widget." msgstr "" -#: admin/functions-help.php:145 -msgid "Grant allows you to grant the role a capability." +#: admin/views/class-view-general.php:266 +msgid "Redirect all logged-out users to the login page before allowing them to view the site." msgstr "" -#: admin/functions-help.php:146 -msgid "Deny allows you to explicitly deny the role a capability." +#: admin/views/class-view-general.php:281 +msgid "Require authentication for access to the REST API." msgstr "" -#: admin/functions-help.php:147 -msgid "You may also opt to neither grant nor deny the role a capability." +#: admin/views/class-view-general.php:296 +msgid "Show error message for feed items." msgstr "" -#: admin/functions-help.php:161 -msgid "The custom capability box allows you to create a custom capability for the role. After hitting the Add New button, it will add the capability to the Custom tab in the Edit Capabilities box." +#: admin/views/class-view-general.php:332 +msgid "Update Settings" msgstr "" -#: admin/functions-role-groups.php:111 -msgid "Mine" +#: admin/views/class-view-general.php:353 +msgid "Role and Capabilities" msgstr "" -#: admin/functions-role-groups.php:121 -msgid "Has Users" +#: admin/views/class-view-general.php:399 +msgid "The role manager allows you to manage roles on your site by giving you the ability to create, edit, and delete any role. Note that changes to roles do not change settings for the Members plugin. You are literally changing data in your WordPress database. This plugin feature merely provides an interface for you to make these changes." msgstr "" -#: admin/functions-role-groups.php:122 -msgid "Has Users %s" -msgid_plural "Has Users %s" -msgstr[0] "" -msgstr[1] "" - -#: admin/functions-role-groups.php:130 -msgid "No Users" +#: admin/views/class-view-general.php:403 +msgid "The multiple user roles feature allows you to assign more than one role to each user from the edit user screen." msgstr "" -#: admin/functions-role-groups.php:131 -msgid "No Users %s" -msgid_plural "No Users %s" -msgstr[0] "" -msgstr[1] "" - -#: admin/functions-role-groups.php:139 -msgid "Editable" +#: admin/views/class-view-general.php:407 +msgid "Tick the checkbox for denied capabilities to always take precedence over granted capabilities when there is a conflict. This is only relevant when using multiple roles per user." msgstr "" -#: admin/functions-role-groups.php:140 -msgid "Editable %s" -msgid_plural "Editable %s" -msgstr[0] "" -msgstr[1] "" - -#: admin/functions-role-groups.php:148 -msgid "Uneditable" +#: admin/views/class-view-general.php:411 +msgid "Tick the checkbox to show human-readable capabilities when possible. Note that custom capabilities and capabilities from third-party plugins will show the machine-readable capability name unless they are registered." msgstr "" -#: admin/functions-role-groups.php:149 -msgid "Uneditable %s" -msgid_plural "Uneditable %s" -msgstr[0] "" -msgstr[1] "" - -#: admin/functions-role-groups.php:157 -msgid "WordPress" +#: admin/views/class-view-general.php:425 +msgid "The content permissions features adds a meta box to the edit post screen that allows you to grant permissions for who can read the post content based on the user's role. Only users of roles with the %s capability will be able to use this component." msgstr "" -#: admin/tmpl/cap-section.php:20 admin/tmpl/cap-section.php:28 -msgid "Grant" +#: admin/views/class-view-general.php:439 +msgid "The sidebar widgets feature adds additional widgets for use in your theme's sidebars." msgstr "" -#: admin/tmpl/cap-section.php:21 admin/tmpl/cap-section.php:29 -msgid "Deny" +#: admin/views/class-view-general.php:453 +msgid "The private site feature redirects all users who are not logged into the site to the login page, creating an entirely private site. You may also replace your feed content with a custom error message." msgstr "" -#: inc/class-widget-login.php:42 +#: inc/class-widget-login.php:44 msgid "A widget that allows users to log into your site." msgstr "" -#: inc/class-widget-login.php:53 +#: inc/class-widget-login.php:55 msgid "Members: Login Form" msgstr "" -#: inc/class-widget-login.php:57 inc/class-widget-login.php:60 +#: inc/class-widget-login.php:59 inc/class-widget-login.php:62 msgid "Log In" msgstr "" -#: inc/class-widget-login.php:58 +#: inc/class-widget-login.php:60 msgid "Username" msgstr "" -#: inc/class-widget-login.php:59 +#: inc/class-widget-login.php:61 msgid "Password" msgstr "" -#: inc/class-widget-login.php:61 +#: inc/class-widget-login.php:63 msgid "Remember Me" msgstr "" -#: inc/class-widget-login.php:71 +#: inc/class-widget-login.php:73 msgid "Please log into the site." msgstr "" -#: inc/class-widget-login.php:72 +#: inc/class-widget-login.php:74 msgid "You are currently logged in." msgstr "" -#: inc/class-widget-login.php:207 inc/class-widget-users.php:207 +#: inc/class-widget-login.php:209 inc/class-widget-users.php:208 msgid "Title:" msgstr "" -#: inc/class-widget-login.php:211 +#: inc/class-widget-login.php:213 msgid "Username Label:" msgstr "" -#: inc/class-widget-login.php:215 +#: inc/class-widget-login.php:217 msgid "Password Label:" msgstr "" -#: inc/class-widget-login.php:219 +#: inc/class-widget-login.php:221 msgid "Log In Label:" msgstr "" -#: inc/class-widget-login.php:223 +#: inc/class-widget-login.php:225 msgid "Remember Me Label:" msgstr "" -#: inc/class-widget-login.php:231 +#: inc/class-widget-login.php:233 msgid "Username Value:" msgstr "" -#: inc/class-widget-login.php:235 +#: inc/class-widget-login.php:237 msgid "Username Field ID:" msgstr "" -#: inc/class-widget-login.php:239 +#: inc/class-widget-login.php:241 msgid "Remember Me Field ID:" msgstr "" -#: inc/class-widget-login.php:243 +#: inc/class-widget-login.php:245 msgid "Password Field ID:" msgstr "" -#: inc/class-widget-login.php:247 +#: inc/class-widget-login.php:249 msgid "Submit Button ID:" msgstr "" -#: inc/class-widget-login.php:258 +#: inc/class-widget-login.php:260 msgid "\"Remember me\" checkbox?" msgstr "" -#: inc/class-widget-login.php:264 +#: inc/class-widget-login.php:266 msgid "Check \"remember me\"?" msgstr "" -#: inc/class-widget-login.php:270 +#: inc/class-widget-login.php:272 msgid "Display avatar?" msgstr "" -#: inc/class-widget-login.php:274 +#: inc/class-widget-login.php:276 msgid "Logged out text:" msgstr "" -#: inc/class-widget-login.php:279 +#: inc/class-widget-login.php:281 msgid "Logged in text:" msgstr "" -#: inc/class-widget-users.php:42 +#: inc/class-widget-users.php:44 msgid "Provides the ability to list the users of the site." msgstr "" -#: inc/class-widget-users.php:53 +#: inc/class-widget-users.php:55 msgid "Members: Users" msgstr "" -#: inc/class-widget-users.php:183 +#: inc/class-widget-users.php:185 msgid "Ascending" msgstr "" -#: inc/class-widget-users.php:184 +#: inc/class-widget-users.php:186 msgid "Descending" msgstr "" -#: inc/class-widget-users.php:188 +#: inc/class-widget-users.php:190 msgid "Display Name" msgstr "" -#: inc/class-widget-users.php:189 +#: inc/class-widget-users.php:191 msgid "Email" msgstr "" -#: inc/class-widget-users.php:190 +#: inc/class-widget-users.php:192 msgid "ID" msgstr "" -#: inc/class-widget-users.php:191 +#: inc/class-widget-users.php:193 msgid "Nice Name" msgstr "" -#: inc/class-widget-users.php:192 +#: inc/class-widget-users.php:194 msgid "Post Count" msgstr "" -#: inc/class-widget-users.php:193 +#: inc/class-widget-users.php:195 msgid "Registered" msgstr "" -#: inc/class-widget-users.php:194 +#: inc/class-widget-users.php:196 msgid "URL" msgstr "" -#: inc/class-widget-users.php:195 +#: inc/class-widget-users.php:197 msgid "Login" msgstr "" -#: inc/class-widget-users.php:211 +#: inc/class-widget-users.php:212 msgid "Order By:" msgstr "" -#: inc/class-widget-users.php:219 +#: inc/class-widget-users.php:220 msgid "Order:" msgstr "" -#: inc/class-widget-users.php:235 +#: inc/class-widget-users.php:237 msgid "Limit:" msgstr "" -#: inc/class-widget-users.php:239 +#: inc/class-widget-users.php:241 msgid "Offset:" msgstr "" -#: inc/class-widget-users.php:247 +#: inc/class-widget-users.php:249 msgid "Include:" msgstr "" -#: inc/class-widget-users.php:251 +#: inc/class-widget-users.php:253 msgid "Exclude:" msgstr "" -#: inc/class-widget-users.php:255 +#: inc/class-widget-users.php:257 msgid "Search:" msgstr "" -#: inc/class-widget-users.php:259 +#: inc/class-widget-users.php:261 msgid "Meta Key:" msgstr "" -#: inc/class-widget-users.php:267 +#: inc/class-widget-users.php:269 msgid "Meta Value:" msgstr "" -#: inc/functions-options.php:116 +#: inc/functions-cap-groups.php:92 +msgid "Taxonomies" +msgstr "" + +#: inc/functions-cap-groups.php:103 +msgid "Appearance" +msgstr "" + +#: inc/functions-cap-groups.php:112 +msgid "Plugins" +msgstr "" + +#: inc/functions-cap-groups.php:130 +msgid "Custom" +msgstr "" + +#: inc/functions-capabilities.php:57 +msgid "Edit Dashboard" +msgstr "" + +#: inc/functions-capabilities.php:58 +msgid "Edit Files" +msgstr "" + +#: inc/functions-capabilities.php:59 +msgid "Export" +msgstr "" + +#: inc/functions-capabilities.php:60 +msgid "Import" +msgstr "" + +#: inc/functions-capabilities.php:61 +msgid "Manage Links" +msgstr "" + +#: inc/functions-capabilities.php:62 +msgid "Manage Options" +msgstr "" + +#: inc/functions-capabilities.php:63 +msgid "Moderate Comments" +msgstr "" + +#: inc/functions-capabilities.php:64 +msgid "Read" +msgstr "" + +#: inc/functions-capabilities.php:65 +msgid "Unfiltered HTML" +msgstr "" + +#: inc/functions-capabilities.php:66 +msgid "Update Core" +msgstr "" + +#: inc/functions-capabilities.php:69 +msgid "Delete Others' Posts" +msgstr "" + +#: inc/functions-capabilities.php:70 +msgid "Delete Posts" +msgstr "" + +#: inc/functions-capabilities.php:71 +msgid "Delete Private Posts" +msgstr "" + +#: inc/functions-capabilities.php:72 +msgid "Delete Published Posts" +msgstr "" + +#: inc/functions-capabilities.php:73 +msgid "Edit Others' Posts" +msgstr "" + +#: inc/functions-capabilities.php:74 +msgid "Edit Posts" +msgstr "" + +#: inc/functions-capabilities.php:75 +msgid "Edit Private Posts" +msgstr "" + +#: inc/functions-capabilities.php:76 +msgid "Edit Published Posts" +msgstr "" + +#: inc/functions-capabilities.php:77 +msgid "Publish Posts" +msgstr "" + +#: inc/functions-capabilities.php:78 +msgid "Read Private Posts" +msgstr "" + +#: inc/functions-capabilities.php:81 +msgid "Delete Others' Pages" +msgstr "" + +#: inc/functions-capabilities.php:82 +msgid "Delete Pages" +msgstr "" + +#: inc/functions-capabilities.php:83 +msgid "Delete Private Pages" +msgstr "" + +#: inc/functions-capabilities.php:84 +msgid "Delete Published Pages" +msgstr "" + +#: inc/functions-capabilities.php:85 +msgid "Edit Others' Pages" +msgstr "" + +#: inc/functions-capabilities.php:86 +msgid "Edit Pages" +msgstr "" + +#: inc/functions-capabilities.php:87 +msgid "Edit Private Pages" +msgstr "" + +#: inc/functions-capabilities.php:88 +msgid "Edit Published Pages" +msgstr "" + +#: inc/functions-capabilities.php:89 +msgid "Publish Pages" +msgstr "" + +#: inc/functions-capabilities.php:90 +msgid "Read Private Pages" +msgstr "" + +#: inc/functions-capabilities.php:93 +msgid "Upload Files" +msgstr "" + +#: inc/functions-capabilities.php:96 +msgid "Manage Categories" +msgstr "" + +#: inc/functions-capabilities.php:99 +msgid "Delete Themes" +msgstr "" + +#: inc/functions-capabilities.php:100 +msgid "Edit Theme Options" +msgstr "" + +#: inc/functions-capabilities.php:101 +msgid "Edit Themes" +msgstr "" + +#: inc/functions-capabilities.php:102 +msgid "Install Themes" +msgstr "" + +#: inc/functions-capabilities.php:103 +msgid "Switch Themes" +msgstr "" + +#: inc/functions-capabilities.php:104 +msgid "Update Themes" +msgstr "" + +#: inc/functions-capabilities.php:107 +msgid "Activate Plugins" +msgstr "" + +#: inc/functions-capabilities.php:108 +msgid "Delete Plugins" +msgstr "" + +#: inc/functions-capabilities.php:109 +msgid "Edit Plugins" +msgstr "" + +#: inc/functions-capabilities.php:110 +msgid "Install Plugins" +msgstr "" + +#: inc/functions-capabilities.php:111 +msgid "Update Plugins" +msgstr "" + +#: inc/functions-capabilities.php:114 +msgid "Create Roles" +msgstr "" + +#: inc/functions-capabilities.php:115 +msgid "Create Users" +msgstr "" + +#: inc/functions-capabilities.php:116 +msgid "Delete Roles" +msgstr "" + +#: inc/functions-capabilities.php:117 +msgid "Delete Users" +msgstr "" + +#: inc/functions-capabilities.php:118 +msgid "Edit Roles" +msgstr "" + +#: inc/functions-capabilities.php:119 +msgid "Edit Users" +msgstr "" + +#: inc/functions-capabilities.php:120 +msgid "List Roles" +msgstr "" + +#: inc/functions-capabilities.php:121 +msgid "List Users" +msgstr "" + +#: inc/functions-capabilities.php:122 +msgid "Promote Users" +msgstr "" + +#: inc/functions-capabilities.php:123 +msgid "Remove Users" +msgstr "" + +#: inc/functions-capabilities.php:126 +msgid "Restrict Content" +msgstr "" + +#: inc/functions-capabilities.php:141 +msgid "Assign Categories" +msgstr "" + +#: inc/functions-capabilities.php:142 +msgid "Edit Categories" +msgstr "" + +#: inc/functions-capabilities.php:143 +msgid "Delete Categories" +msgstr "" + +#: inc/functions-capabilities.php:144 +msgid "Assign Post Tags" +msgstr "" + +#: inc/functions-capabilities.php:145 +msgid "Edit Post Tags" +msgstr "" + +#: inc/functions-capabilities.php:146 +msgid "Delete Post Tags" +msgstr "" + +#: inc/functions-capabilities.php:147 +msgid "Manage Post Tags" +msgstr "" + +#: inc/functions-options.php:134 msgid "Sorry, but you do not have permission to view this content." msgstr "" -#: inc/functions-options.php:117 +#: inc/functions-options.php:135 msgid "You must be logged into the site to view this content." msgstr "" -#: members.php:187 +#: inc/functions-private-site.php:163 +msgid "You are not currently logged in." +msgstr "" + +#: inc/functions-private-site.php:187 +msgid "You do not currently have access to the \"%s\" site. If you believe you should have access, please contact your network administrator." +msgstr "" + +#: inc/functions-private-site.php:194 +msgid "If you reached this page by accident and meant to visit one of your own sites, try one of the following links." +msgstr "" + +#: inc/functions-role-groups.php:42 +msgid "WordPress" +msgstr "" + +#: members.php:151 msgid "Method does not exist." msgstr "" + +#: members.php:282 +msgid "Members requires PHP version %1$s. You are running version %2$s. Please upgrade and try again." +msgstr "" #. Plugin Name of the plugin/theme msgid "Members" msgstr "" #. Plugin URI of the plugin/theme -msgid "http://themehybrid.com/plugins/members" +msgid "https://themehybrid.com/plugins/members" msgstr "" #. Description of the plugin/theme @@ -826,5 +1263,5 @@ msgid "Justin Tadlock" msgstr "" #. Author URI of the plugin/theme -msgid "http://themehybrid.com" +msgid "https://themehybrid.com" msgstr "" From ea7ab94c78b1cf336c6481998d4eb6434704c534 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 19 Jul 2017 10:28:46 -0500 Subject: [PATCH 099/157] Use `members_get_role()`. --- admin/class-cap-tabs.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/class-cap-tabs.php b/admin/class-cap-tabs.php index 165adb2..3961b42 100644 --- a/admin/class-cap-tabs.php +++ b/admin/class-cap-tabs.php @@ -101,11 +101,11 @@ public function __construct( $role = '', $has_caps = array() ) { // Check if we have a role. if ( $role ) { - $this->role = get_role( $role ); + $this->role = members_get_role( $role ); // If no explicit caps were passed in, use the role's caps. if ( ! $has_caps ) - $this->has_caps = $this->role->capabilities; + $this->has_caps = $this->role->caps; } // Add sections and controls. From 1a425d042eee7247b9b4bcb59f65836d2927acfa Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 19 Jul 2017 11:29:15 -0500 Subject: [PATCH 100/157] Update readme files. --- readme.md | 4 ++-- readme.txt | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/readme.md b/readme.md index 515a3aa..1a6f51d 100644 --- a/readme.md +++ b/readme.md @@ -17,13 +17,13 @@ It puts you in control over permissions on your site by providing a user interfa ## Professional Support -If you need professional plugin support from me, the plugin author, you can access the support forums at [Theme Hybrid](https://themehybrid.com/board/topics), which is a professional WordPress help/support site where I handle support for all my plugins and themes for a community of 60,000+ users (and growing). +If you need professional plugin support from me, the plugin author, you can access the support forums at [Theme Hybrid](https://themehybrid.com/board/topics), which is a professional WordPress help/support site where I handle support for all my plugins and themes for a community of 75,000+ users (and growing). ## Copyright and License This project is licensed under the [GNU GPL](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html), version 2 or later. -2009 – 2016 © [Justin Tadlock](http://justintadlock.com). +2009 – 2017 © [Justin Tadlock](http://justintadlock.com). ## Documentation diff --git a/readme.txt b/readme.txt index 9d458df..36f8a90 100644 --- a/readme.txt +++ b/readme.txt @@ -3,21 +3,21 @@ Contributors: greenshady Donate link: https://themehybrid.com/donate Tags: admin, role, roles, member, members, profile, shortcode, user, users, widget, widgets -Requires at least: 4.3 -Tested up to: 4.7.2 -Stable tag: 1.1.3 +Requires at least: 4.7 +Tested up to: 4.8 +Stable tag: 2.0.0 The most powerful user, role, and capability management plugin for WordPress. == Description == -Members is a plugin that extends your control over your blog. It's a user, role, and capability management plugin that was created to make WordPress a more powerful CMS. +Members is a plugin that extends your control over your blog. It's a user, role, and capability editor plugin that was created to make WordPress a more powerful CMS. It puts you in control over permissions on your site by providing a user interface (UI) for WordPress' powerful role and cap system, which is traditionally only available to developers who know how to code this by hand. ### Plugin Features -* **Role Manager:** Allows you to edit, create, and delete roles as well as capabilities for these roles. +* **Role Editor:** Allows you to edit, create, and delete roles as well as capabilities for these roles. * **Multiple User Roles:** Give one, two, or even more roles to any user. * **Explicitly Deny Capabilities:** Deny specific caps to specific user roles. * **Clone Roles:** Build a new role by cloning an existing role. @@ -39,7 +39,7 @@ The Members plugin is a massive project with 1,000s of lines of code to maintain ### Professional Support -If you need professional plugin support from me, the plugin author, you can access the support forums at [Theme Hybrid](https://themehybrid.com/board/topics), which is a professional WordPress help/support site where I handle support for all my plugins and themes for a community of 60,000+ users (and growing). +If you need professional plugin support from me, the plugin author, you can access the support forums at [Theme Hybrid](https://themehybrid.com/board/topics), which is a professional WordPress help/support site where I handle support for all my plugins and themes for a community of 75,000+ users (and growing). ### Plugin Development From 8fff93bad107dfc7982e8aebcce3a60373b22ea8 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 19 Jul 2017 12:34:20 -0500 Subject: [PATCH 101/157] Big ass change log update for 2.0.0. --- changelog.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/changelog.md b/changelog.md index bd74e09..94bc007 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,46 @@ # Change Log +## [2.0.0] - 2017-07-19 + +### Added + +* Roles states on the manage role screen now have array keys so they can more easily be overwritten. +* Created a new admin view system, where there can be multiple views ("tabs", if you like) on the settings screen and other potential screens in the future. +* Added an "Add-Ons" view for the Members Settings page, which lists add-ons for the plugin. The default add-ons are pulled from Theme Hybrid. +* Created an add-ons API for other developers to list their own add-ons. +* Created a capability registration system and API for plugin developers to register their capabilities with Members. The major benefit of this is having internationalized labels for capabilities. +* Registered all of the core capabilities with human-readable, internationalized text labels so that users who do not speak English can benefit from capability translations. +* Added the `members_enable_{$post_type}_content_permissions` filter hook to allow developers to enable/disable content permissions per post type. +* Removed the core "Change Role" feature on the manage users screen and replaced it with an "Add Role" and "Remove Role" feature for bulk editing users. Note that this only appears when multiple roles is enabled. +* Add a multi-role checkbox on the Add User screen when multiple roles are enabled. +* Added a `members_has_post_roles()` conditional tag for checking if a post has content permissions roles assigned to it. +* Added the `operator` parameter, which accepts a value of `!`, for the `[members_access]` shortcode. This allows users to negate the role or cap they've passed in. + +### Changed + +* Created a `.wp-tab-panel` wrapper around the user roles checklist on the edit user screen. This is to prevent long lists of roles from taking up too much screen space. +* Moved the All capability tab to the bottom of the capability tabs list. +* Removed the All cap group, since it is not a true cap group. +* Removed the All, Mine, Active, Inactive, Editable, and Uneditable role groups. These are merely views for the role management screen. They are not true role groups. +* Created a new, internal registry class for storing various collections of data. Note that this does break back-compat for developers who were directly access factory classes in previous versions rather than using the wrapper functions. +* Old classes were added to the `Members` namespace or `Members\Admin` namespace. Again, this breaks back-compat for anyone not using the appropriate wrapper functions. This also bumps the requirement to PHP 5.3.0+. +* Changed the text in the Content Permissions meta box to not specifically use the term "post". +* Changed the Content Permissions meta box to have a tabbed UI so that it doesn't take up so much screen space. +* Replaced the basic textarea with the WP editor in the Content Permissions meta box. + +### Fixed + +* Removes the `customize_changeset` and `custom_css` post type cap groups so that they don't appear in the capability tabs on the edit role screen. +* No longer save content permissions on autosave or for post revisions. +* Prevent users from adding the internal core WP `do_not_allow` capability to their role. +* On multisite with the private site feature enabled, block access to logged-in users who do not have access to the specific blog. +* Make sure the comments show an error in the comments feed if they belong to a private post. + +### Security + +* General hardening and use of some better functions for escaping. +* Added a private REST API option for users who are utilizing the private site feature. Users will likely want to enable this. Otherwise, their "private site" is exposed via the REST API endpoints. + ## [1.1.3] - 2017-02-06 ### Fixed From 97ed3f690f5b01a5acb03d5093cc2a8804083da6 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 19 Jul 2017 12:41:51 -0500 Subject: [PATCH 102/157] Minor adjustments to the change log. --- changelog.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/changelog.md b/changelog.md index 94bc007..a548125 100644 --- a/changelog.md +++ b/changelog.md @@ -4,7 +4,6 @@ ### Added -* Roles states on the manage role screen now have array keys so they can more easily be overwritten. * Created a new admin view system, where there can be multiple views ("tabs", if you like) on the settings screen and other potential screens in the future. * Added an "Add-Ons" view for the Members Settings page, which lists add-ons for the plugin. The default add-ons are pulled from Theme Hybrid. * Created an add-ons API for other developers to list their own add-ons. @@ -18,11 +17,12 @@ ### Changed +* Roles states on the manage role screen now have array keys so they can more easily be overwritten. * Created a `.wp-tab-panel` wrapper around the user roles checklist on the edit user screen. This is to prevent long lists of roles from taking up too much screen space. * Moved the All capability tab to the bottom of the capability tabs list. * Removed the All cap group, since it is not a true cap group. * Removed the All, Mine, Active, Inactive, Editable, and Uneditable role groups. These are merely views for the role management screen. They are not true role groups. -* Created a new, internal registry class for storing various collections of data. Note that this does break back-compat for developers who were directly access factory classes in previous versions rather than using the wrapper functions. +* Created a new, internal registry class for storing various collections of data. Note that this does break back-compat for developers who were directly accessing factory classes in previous versions rather than using the wrapper functions. * Old classes were added to the `Members` namespace or `Members\Admin` namespace. Again, this breaks back-compat for anyone not using the appropriate wrapper functions. This also bumps the requirement to PHP 5.3.0+. * Changed the text in the Content Permissions meta box to not specifically use the term "post". * Changed the Content Permissions meta box to have a tabbed UI so that it doesn't take up so much screen space. @@ -30,11 +30,10 @@ ### Fixed -* Removes the `customize_changeset` and `custom_css` post type cap groups so that they don't appear in the capability tabs on the edit role screen. * No longer save content permissions on autosave or for post revisions. * Prevent users from adding the internal core WP `do_not_allow` capability to their role. * On multisite with the private site feature enabled, block access to logged-in users who do not have access to the specific blog. -* Make sure the comments show an error in the comments feed if they belong to a private post. +* Make sure comments show an error in the comments feed if they belong to a private post. ### Security From c5c61bdbc678f7238cd7150bedd57e53df8d5631 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 19 Jul 2017 12:48:31 -0500 Subject: [PATCH 103/157] Update plugin tags. --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 36f8a90..1c99761 100644 --- a/readme.txt +++ b/readme.txt @@ -2,7 +2,7 @@ Contributors: greenshady Donate link: https://themehybrid.com/donate -Tags: admin, role, roles, member, members, profile, shortcode, user, users, widget, widgets +Tags: capabilities, roles, members, users Requires at least: 4.7 Tested up to: 4.8 Stable tag: 2.0.0 From 79b2b6fc390b18cae18256f688866d5a6c79155f Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 19 Jul 2017 12:51:08 -0500 Subject: [PATCH 104/157] Version bump to 2.0.0. --- members.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/members.php b/members.php index 04268e9..3fbc05d 100644 --- a/members.php +++ b/members.php @@ -3,7 +3,7 @@ * Plugin Name: Members * Plugin URI: https://themehybrid.com/plugins/members * Description: A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private. - * Version: 2.0.0-dev + * Version: 2.0.0 * Author: Justin Tadlock * Author URI: https://themehybrid.com * Text Domain: members From be57d4ff0e35581547f11bc585053da6427358d3 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 21 Jul 2017 17:09:44 -0500 Subject: [PATCH 105/157] Version bump to 2.0.1-dev. --- members.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/members.php b/members.php index 3fbc05d..54802b9 100644 --- a/members.php +++ b/members.php @@ -3,7 +3,7 @@ * Plugin Name: Members * Plugin URI: https://themehybrid.com/plugins/members * Description: A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private. - * Version: 2.0.0 + * Version: 2.0.1-dev * Author: Justin Tadlock * Author URI: https://themehybrid.com * Text Domain: members @@ -25,7 +25,7 @@ * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * @package Members - * @version 2.0.0 + * @version 2.0.1 * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link https://themehybrid.com/plugins/members From 893a85818a31db0c08bcf734a45c77051e78d3d3 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 21 Jul 2017 17:13:50 -0500 Subject: [PATCH 106/157] Add the `show_human_caps` option to the settings validation callback. Otherwise, the setting isn't validated and saved properly. --- admin/views/class-view-general.php | 1 + 1 file changed, 1 insertion(+) diff --git a/admin/views/class-view-general.php b/admin/views/class-view-general.php index cf80255..645e5e3 100644 --- a/admin/views/class-view-general.php +++ b/admin/views/class-view-general.php @@ -99,6 +99,7 @@ function validate_settings( $settings ) { // Validate true/false checkboxes. $settings['role_manager'] = ! empty( $settings['role_manager'] ) ? true : false; $settings['explicit_denied_caps'] = ! empty( $settings['explicit_denied_caps'] ) ? true : false; + $settings['show_human_caps'] = ! empty( $settings['show_human_caps'] ) ? true : false; $settings['multi_roles'] = ! empty( $settings['multi_roles'] ) ? true : false; $settings['content_permissions'] = ! empty( $settings['content_permissions'] ) ? true : false; $settings['login_form_widget'] = ! empty( $settings['login_form_widget'] ) ? true : false; From 8f46fe5084241bcc1f8ab76a1c74cfebc9ccb114 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 21 Jul 2017 17:16:18 -0500 Subject: [PATCH 107/157] Bumps the priority of all the default cap groups back 5. Leaves the general group the same. --- inc/functions-cap-groups.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/inc/functions-cap-groups.php b/inc/functions-cap-groups.php index ea9f4ec..6a78e6b 100644 --- a/inc/functions-cap-groups.php +++ b/inc/functions-cap-groups.php @@ -81,7 +81,7 @@ function members_register_default_cap_groups() { 'label' => $type->labels->name, 'caps' => $has_caps, 'icon' => $icon, - 'priority' => 5 + 'priority' => 10 ) ); } @@ -93,7 +93,7 @@ function members_register_default_cap_groups() { 'caps' => members_get_taxonomy_group_caps(), 'icon' => 'dashicons-tag', 'diff_added' => true, - 'priority' => 10 + 'priority' => 15 ) ); @@ -102,7 +102,7 @@ function members_register_default_cap_groups() { array( 'label' => esc_html__( 'Appearance', 'members' ), 'icon' => 'dashicons-admin-appearance', - 'priority' => 15 + 'priority' => 20 ) ); @@ -111,7 +111,7 @@ function members_register_default_cap_groups() { array( 'label' => esc_html__( 'Plugins', 'members' ), 'icon' => 'dashicons-admin-plugins', - 'priority' => 20 + 'priority' => 25 ) ); @@ -120,7 +120,7 @@ function members_register_default_cap_groups() { array( 'label' => esc_html__( 'Users', 'members' ), 'icon' => 'dashicons-admin-users', - 'priority' => 25 + 'priority' => 30 ) ); From 1619b0f91e07de993b8449bf4d8f03df8d374ae5 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sun, 23 Jul 2017 14:51:38 -0500 Subject: [PATCH 108/157] Change `$user` to `$old_user_data`. Otherwise, we can't properly handle removing all roles from a user on the edit user screen. Fixes: https://github.com/justintadlock/members/issues/145 This also completes the fix for the original ticket: https://github.com/justintadlock/members/issues/129 --- admin/class-user-edit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/class-user-edit.php b/admin/class-user-edit.php index b9eacdf..57dcf98 100644 --- a/admin/class-user-edit.php +++ b/admin/class-user-edit.php @@ -172,7 +172,7 @@ public function role_update( $user_id, $old_user_data ) { } else { // Loop through the current user roles. - foreach ( (array) $user->roles as $old_role ) { + foreach ( (array) $old_user_data->roles as $old_role ) { // Remove the role if it is editable. if ( members_is_role_editable( $old_role ) ) From e536069cefe139578e46cb39c36885475b9edd35 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Tue, 25 Jul 2017 15:48:08 -0500 Subject: [PATCH 109/157] Better handling of the PHP 5.3.0+ minimum requirement. Instead of just checking on activation, we check before loading the files. This version also puts up an admin notice and deactivates the plugin if not meeting the min. requirements. --- members.php | 52 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/members.php b/members.php index 54802b9..3ac56d3 100644 --- a/members.php +++ b/members.php @@ -176,6 +176,16 @@ private function setup() { */ private function includes() { + // Check if we meet the minimum PHP version. + if ( version_compare( PHP_VERSION, $this->php_version, '<' ) ) { + + // Add admin notice. + add_action( 'admin_notices', array( $this, 'php_admin_notice' ) ); + + // Bail. + return; + } + // Load class files. require_once( $this->dir . 'inc/class-capability.php' ); require_once( $this->dir . 'inc/class-cap-group.php' ); @@ -278,11 +288,7 @@ public function activation() { deactivate_plugins( plugin_basename( __FILE__ ) ); // Add an error message and die. - wp_die( sprintf( - __( 'Members requires PHP version %1$s. You are running version %2$s. Please upgrade and try again.', 'members' ), - $this->php_version, - PHP_VERSION - ) ); + wp_die( $this->get_min_php_message() ); } // Get the administrator role. @@ -298,6 +304,42 @@ public function activation() { $role->add_cap( 'restrict_content' ); // Edit per-post content permissions. } } + + /** + * Returns a message noting the minimum version of PHP required. + * + * @since 2.0.1 + * @access private + * @return void + */ + private function get_min_php_message() { + + return sprintf( + __( 'Members requires PHP version %1$s. You are running version %2$s. Please upgrade and try again.', 'members' ), + $this->php_version, + PHP_VERSION + ); + } + + /** + * Outputs the admin notice that the user needs to upgrade their PHP version. It also + * auto-deactivates the plugin. + * + * @since 2.0.1 + * @access public + * @return void + */ + public function php_admin_notice() { + + // Output notice. + printf( + '

    %s

    ', + esc_html( $this->get_min_php_message() ) + ); + + // Make sure the plugin is deactivated. + deactivate_plugins( plugin_basename( __FILE__ ) ); + } } /** From dc703b73eebd72d65f58dbe98a34a7b6c8b0cce8 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 25 Aug 2017 10:29:34 -0500 Subject: [PATCH 110/157] First pass at fixing roles not being added to new users created in a multisite setup. See: https://github.com/justintadlock/members/issues/153 --- admin/class-user-new.php | 85 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 3 deletions(-) diff --git a/admin/class-user-new.php b/admin/class-user-new.php index 8ebb0e5..2ed7cbc 100644 --- a/admin/class-user-new.php +++ b/admin/class-user-new.php @@ -53,6 +53,21 @@ private function setup_actions() { // Only run our customization on the 'user-edit.php' page in the admin. add_action( 'load-user-new.php', array( $this, 'load' ) ); + + if ( is_multisite() ) { + + add_filter( 'signup_user_meta', array( $this, 'mu_signup_user_meta' ) ); + + // Note that `add_new_user_to_blog()` is called with a priority of 10. That + // function sets the role. So, we need to execute after that. + add_action( 'wpmu_activate_user', array( $this, 'mu_activate_user' ), 15, 3 ); + + } else { + + // Sets the new user's roles. + add_action( 'user_register', array( $this, 'user_register' ) ); + } + } /** @@ -67,9 +82,6 @@ public function load() { // Adds the profile fields. add_action( 'user_new_form', array( $this, 'profile_fields' ) ); - // Sets the new user's roles. - add_action( 'user_register', array( $this, 'user_register' ) ); - // Handle scripts. add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) ); add_action( 'admin_footer', array( $this, 'print_scripts' ), 25 ); @@ -187,6 +199,73 @@ public function user_register( $user_id ) { } } + public function signup_user_meta( $meta ) { + + // If the current user can't promote users or edit this particular user, bail. + if ( ! current_user_can( 'promote_users' ) ) + return; + + // Is this a role change? + if ( ! isset( $_POST['members_new_user_roles_nonce'] ) || ! wp_verify_nonce( $_POST['members_new_user_roles_nonce'], 'new_user_roles' ) ) + return; + + // If we have an array of roles. + if ( ! empty( $_POST['members_user_roles'] ) ) { + + // Sanitize the posted roles. + $new_roles = array_map( 'members_sanitize_role', $_POST['members_user_roles'] ); + + $meta['members_user_roles'] = array(); + + foreach ( $new_roles as $new_role ) { + + if ( members_is_role_editable( $new_role ) ) + $meta['members_user_roles'][] = $new_role; + } + + // Makes sure that the `new_role` meta gets passed through. WP needs this when first setting + // up the user signup. We're going to fix roles later. + if ( empty( $_REQUEST['role'] ) || ! $meta['new_role'] && isset( $meta['members_user_roles'][0] ) ) { + + $meta['new_role'] = $meta['members_user_roles'][0]; + } + } + + return $meta; + } + + public function mu_activate_user( $user_id, $password, $meta ) { + + // Create a new user object. + $user = new \WP_User( $user_id ); + + // If we have an array of roles. + if ( ! empty( $meta['members_user_roles'] ) ) { + + // Get the current user roles. + $old_roles = (array) $user->roles; + + // Sanitize the posted roles. + $new_roles = array_map( 'members_sanitize_role', $meta['members_user_roles'] ); + + // Loop through the posted roles. + foreach ( $new_roles as $new_role ) { + + // If the user doesn't already have the role, add it. + if ( ! in_array( $new_role, (array) $user->roles ) ) + $user->add_role( $new_role ); + } + + // Loop through the current user roles. + foreach ( $old_roles as $old_role ) { + + // If the role is not in the new roles array, remove it. + if ( ! in_array( $old_role, $new_roles ) ) + $user->remove_role( $old_role ); + } + } + } + /** * Enqueue scripts. * From 720fae9c1a160d682d56ff2419aa5c2f305975a0 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 25 Aug 2017 10:33:59 -0500 Subject: [PATCH 111/157] Correct typo function name. Reference: https://github.com/justintadlock/members/issues/153 --- admin/class-user-new.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/class-user-new.php b/admin/class-user-new.php index 2ed7cbc..c62679d 100644 --- a/admin/class-user-new.php +++ b/admin/class-user-new.php @@ -199,7 +199,7 @@ public function user_register( $user_id ) { } } - public function signup_user_meta( $meta ) { + public function mu_signup_user_meta( $meta ) { // If the current user can't promote users or edit this particular user, bail. if ( ! current_user_can( 'promote_users' ) ) From 8917cf31a18f7b0ea7885e9bd5cdeadea5deb0f3 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 27 Sep 2017 13:12:18 -0500 Subject: [PATCH 112/157] Super admins should be able to see private sites, even if they're not a member of the blog. --- inc/functions-private-site.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/inc/functions-private-site.php b/inc/functions-private-site.php index 11c7204..6f6e9ad 100644 --- a/inc/functions-private-site.php +++ b/inc/functions-private-site.php @@ -78,13 +78,17 @@ function members_is_private_rest_api() { */ function members_please_log_in() { + // If private blog is not enabled, bail. + if ( ! members_is_private_blog() ) + return; + // If this is a multisite instance and the user is logged into the network. - if ( members_is_private_blog() && is_multisite() && is_user_logged_in() && ! is_user_member_of_blog() ) { + if ( is_multisite() && is_user_logged_in() && ! is_user_member_of_blog() && ! is_super_admin() ) { members_ms_private_blog_die(); } // Check if the private blog feature is active and if the user is not logged in. - if ( members_is_private_blog() && ! is_user_logged_in() && members_is_private_page() ) { + if ( ! is_user_logged_in() && members_is_private_page() ) { auth_redirect(); exit; From 573dd364a8feb43cc956c5d13b31ddb187a4614f Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 27 Sep 2017 13:52:35 -0500 Subject: [PATCH 113/157] Make sure role labels are translated where the plugin outputs them. Fixes: https://github.com/justintadlock/members/issues/157 Note that fixing this ticket brought up another issue, which is that core WP outputs the role in some places. This is out of scope for this commit, so a second ticket was created: https://github.com/justintadlock/members/issues/158 --- admin/class-meta-box-content-permissions.php | 2 +- inc/functions-roles.php | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/admin/class-meta-box-content-permissions.php b/admin/class-meta-box-content-permissions.php index 3e1b68a..f24c428 100644 --- a/admin/class-meta-box-content-permissions.php +++ b/admin/class-meta-box-content-permissions.php @@ -198,7 +198,7 @@ public function meta_box( $post ) {
  • diff --git a/inc/functions-roles.php b/inc/functions-roles.php index 322355c..2852a33 100644 --- a/inc/functions-roles.php +++ b/inc/functions-roles.php @@ -40,7 +40,7 @@ function members_register_default_roles( $wp_roles ) { foreach ( $wp_roles->roles as $name => $object ) { $args = array( - 'label' => $object['name'], + 'label' => members_translate_role_hook( $object['name'], $name ), 'caps' => $object['capabilities'] ); @@ -247,7 +247,23 @@ function members_sanitize_role( $role ) { function members_translate_role( $role ) { global $wp_roles; - return apply_filters( 'members_translate_role', translate_user_role( $wp_roles->role_names[ $role ] ), $role ); + return members_translate_role_hook( $wp_roles->role_names[ $role ], $role ); +} + +/** + * Hook for translating user roles. I needed to separate this from the primary + * `members_translate_role()` function in case `$wp_roles` was not yet available + * but both the role and role label were. + * + * @since 2.0.1 + * @access public + * @param string $label + * @param string $role + * @return string + */ +function members_translate_role_hook( $label, $role ) { + + return apply_filters( 'members_translate_role', translate_user_role( $label ), $role ); } /** From 9c51f6c6ffc5a49f9878441c178ff35c1a08d7b2 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 27 Sep 2017 15:13:15 -0500 Subject: [PATCH 114/157] In a multisite scenario with the multiple roles per user featured enabled, account for the scenario where no roles are given to the new user. We're going to give the new user the default role. Note that this is different from a single-site setup, which doesn't require that a new user have a role. This commit also cleans up the code in previous commits addressed at this issue. Fixes (I hope): https://github.com/justintadlock/members/issues/153 --- admin/class-user-new.php | 42 ++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/admin/class-user-new.php b/admin/class-user-new.php index c62679d..ef59872 100644 --- a/admin/class-user-new.php +++ b/admin/class-user-new.php @@ -199,15 +199,25 @@ public function user_register( $user_id ) { } } + /** + * Called on multisite when a new user is created. We need to store the roles + * as part of the signup metadata. These will get assigned to the user once + * the user has been activated. + * + * @since 2.0.1 + * @access public + * @param array $meta + * @return array + */ public function mu_signup_user_meta( $meta ) { // If the current user can't promote users or edit this particular user, bail. if ( ! current_user_can( 'promote_users' ) ) - return; + return $meta; - // Is this a role change? + // Verify the new role nonce? if ( ! isset( $_POST['members_new_user_roles_nonce'] ) || ! wp_verify_nonce( $_POST['members_new_user_roles_nonce'], 'new_user_roles' ) ) - return; + return $meta; // If we have an array of roles. if ( ! empty( $_POST['members_user_roles'] ) ) { @@ -223,25 +233,41 @@ public function mu_signup_user_meta( $meta ) { $meta['members_user_roles'][] = $new_role; } - // Makes sure that the `new_role` meta gets passed through. WP needs this when first setting - // up the user signup. We're going to fix roles later. + // Makes sure that the `new_role` meta gets passed through. WP needs this + // when first setting up the user signup. We're going to fix roles later. if ( empty( $_REQUEST['role'] ) || ! $meta['new_role'] && isset( $meta['members_user_roles'][0] ) ) { $meta['new_role'] = $meta['members_user_roles'][0]; } + + // If no roles were chosen and no new role is set, give the new user the default role. + } elseif ( empty( $meta['new_role'] ) ) { + + $meta['new_role'] = get_option( 'default_role' ); } return $meta; } + /** + * Callback function when a new user is activated in multisite. This function + * gets the roles we stored as meta upon signup and assigns them to the user. + * + * @since 2.0.1 + * @access public + * @param int $user_id + * @param string $password + * @param array $meta + * @return void + */ public function mu_activate_user( $user_id, $password, $meta ) { - // Create a new user object. - $user = new \WP_User( $user_id ); - // If we have an array of roles. if ( ! empty( $meta['members_user_roles'] ) ) { + // Create a new user object. + $user = new \WP_User( $user_id ); + // Get the current user roles. $old_roles = (array) $user->roles; From b2ed66fa6d130b0976230d9be211eba98d0f9af2 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 27 Sep 2017 16:27:17 -0500 Subject: [PATCH 115/157] Filter the user signup activation email. And remove the core WP filter on this. We need to get rid of the core email because of its hardcoded `$_REQUEST['role']` usage. This commit address the latest issue in https://github.com/justintadlock/members/issues/153 --- admin/class-user-new.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/admin/class-user-new.php b/admin/class-user-new.php index ef59872..5029cc0 100644 --- a/admin/class-user-new.php +++ b/admin/class-user-new.php @@ -62,6 +62,9 @@ private function setup_actions() { // function sets the role. So, we need to execute after that. add_action( 'wpmu_activate_user', array( $this, 'mu_activate_user' ), 15, 3 ); + // Hook into the notification email. + add_filter( 'wpmu_signup_user_notification_email', 'mu_user_notify_email', 5 ); + } else { // Sets the new user's roles. @@ -292,6 +295,27 @@ public function mu_activate_user( $user_id, $password, $meta ) { } } + /** + * The core WP function `admin_created_user_email()` relies on a hardcoded + * `$_REQUEST['role']`. So, we're hijacking the email and sending our own. + * + * @since 2.0.1 + * @access public + * @param string $text + * @return string + */ + public function ms_user_notify_email( $text ) { + + remove_filter( 'wpmu_signup_user_notification_email', 'admin_created_user_email' ); + + return sprintf( + // Translators: 1 is the site name, 2 is the site URL, and %%s is replaced with the activate URL. + esc_html__( "You've been invited to join %1$s at %2$s. Please click the following link to activate your user account: %%s", 'members' ), + esc_html( get_bloginfo( 'name' ) ), + esc_url( home_url() ) + ); + } + /** * Enqueue scripts. * From 829b781b1e628fed1c97023e0c2e23a6efd517aa Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 27 Sep 2017 16:32:28 -0500 Subject: [PATCH 116/157] Correct hook callback fix on previous commit. Ref: https://github.com/justintadlock/members/issues/153 --- admin/class-user-new.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/class-user-new.php b/admin/class-user-new.php index 5029cc0..9e51360 100644 --- a/admin/class-user-new.php +++ b/admin/class-user-new.php @@ -63,7 +63,7 @@ private function setup_actions() { add_action( 'wpmu_activate_user', array( $this, 'mu_activate_user' ), 15, 3 ); // Hook into the notification email. - add_filter( 'wpmu_signup_user_notification_email', 'mu_user_notify_email', 5 ); + add_filter( 'wpmu_signup_user_notification_email', array( $this, 'mu_user_notify_email' ), 5 ); } else { From d771f1c7247aa4b3c0d6cfb4a0f0d683d0db427d Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 28 Sep 2017 12:24:11 -0500 Subject: [PATCH 117/157] Don't show the multi-role selection form field when adding a new user on multisite. There were numerous issues associated with this that could not be addressed at this stage. The commit fixes the issue where no role was being set when adding a new user in multisite. Fixes: https://github.com/justintadlock/members/issues/153 --- admin/class-user-new.php | 138 ++------------------------------------- 1 file changed, 6 insertions(+), 132 deletions(-) diff --git a/admin/class-user-new.php b/admin/class-user-new.php index 9e51360..0d87cc1 100644 --- a/admin/class-user-new.php +++ b/admin/class-user-new.php @@ -48,29 +48,17 @@ private function __construct() {} private function setup_actions() { // If multiple roles per user is not enabled, bail. - if ( ! members_multiple_user_roles_enabled() ) + // + // @since 2.0.1 Added a check to not run on multisite. + // @link https://github.com/justintadlock/members/issues/153 + if ( ! members_multiple_user_roles_enabled() || is_multisite() ) return; // Only run our customization on the 'user-edit.php' page in the admin. add_action( 'load-user-new.php', array( $this, 'load' ) ); - if ( is_multisite() ) { - - add_filter( 'signup_user_meta', array( $this, 'mu_signup_user_meta' ) ); - - // Note that `add_new_user_to_blog()` is called with a priority of 10. That - // function sets the role. So, we need to execute after that. - add_action( 'wpmu_activate_user', array( $this, 'mu_activate_user' ), 15, 3 ); - - // Hook into the notification email. - add_filter( 'wpmu_signup_user_notification_email', array( $this, 'mu_user_notify_email' ), 5 ); - - } else { - - // Sets the new user's roles. - add_action( 'user_register', array( $this, 'user_register' ) ); - } - + // Sets the new user's roles. + add_action( 'user_register', array( $this, 'user_register' ) ); } /** @@ -202,120 +190,6 @@ public function user_register( $user_id ) { } } - /** - * Called on multisite when a new user is created. We need to store the roles - * as part of the signup metadata. These will get assigned to the user once - * the user has been activated. - * - * @since 2.0.1 - * @access public - * @param array $meta - * @return array - */ - public function mu_signup_user_meta( $meta ) { - - // If the current user can't promote users or edit this particular user, bail. - if ( ! current_user_can( 'promote_users' ) ) - return $meta; - - // Verify the new role nonce? - if ( ! isset( $_POST['members_new_user_roles_nonce'] ) || ! wp_verify_nonce( $_POST['members_new_user_roles_nonce'], 'new_user_roles' ) ) - return $meta; - - // If we have an array of roles. - if ( ! empty( $_POST['members_user_roles'] ) ) { - - // Sanitize the posted roles. - $new_roles = array_map( 'members_sanitize_role', $_POST['members_user_roles'] ); - - $meta['members_user_roles'] = array(); - - foreach ( $new_roles as $new_role ) { - - if ( members_is_role_editable( $new_role ) ) - $meta['members_user_roles'][] = $new_role; - } - - // Makes sure that the `new_role` meta gets passed through. WP needs this - // when first setting up the user signup. We're going to fix roles later. - if ( empty( $_REQUEST['role'] ) || ! $meta['new_role'] && isset( $meta['members_user_roles'][0] ) ) { - - $meta['new_role'] = $meta['members_user_roles'][0]; - } - - // If no roles were chosen and no new role is set, give the new user the default role. - } elseif ( empty( $meta['new_role'] ) ) { - - $meta['new_role'] = get_option( 'default_role' ); - } - - return $meta; - } - - /** - * Callback function when a new user is activated in multisite. This function - * gets the roles we stored as meta upon signup and assigns them to the user. - * - * @since 2.0.1 - * @access public - * @param int $user_id - * @param string $password - * @param array $meta - * @return void - */ - public function mu_activate_user( $user_id, $password, $meta ) { - - // If we have an array of roles. - if ( ! empty( $meta['members_user_roles'] ) ) { - - // Create a new user object. - $user = new \WP_User( $user_id ); - - // Get the current user roles. - $old_roles = (array) $user->roles; - - // Sanitize the posted roles. - $new_roles = array_map( 'members_sanitize_role', $meta['members_user_roles'] ); - - // Loop through the posted roles. - foreach ( $new_roles as $new_role ) { - - // If the user doesn't already have the role, add it. - if ( ! in_array( $new_role, (array) $user->roles ) ) - $user->add_role( $new_role ); - } - - // Loop through the current user roles. - foreach ( $old_roles as $old_role ) { - - // If the role is not in the new roles array, remove it. - if ( ! in_array( $old_role, $new_roles ) ) - $user->remove_role( $old_role ); - } - } - } - - /** - * The core WP function `admin_created_user_email()` relies on a hardcoded - * `$_REQUEST['role']`. So, we're hijacking the email and sending our own. - * - * @since 2.0.1 - * @access public - * @param string $text - * @return string - */ - public function ms_user_notify_email( $text ) { - - remove_filter( 'wpmu_signup_user_notification_email', 'admin_created_user_email' ); - - return sprintf( - // Translators: 1 is the site name, 2 is the site URL, and %%s is replaced with the activate URL. - esc_html__( "You've been invited to join %1$s at %2$s. Please click the following link to activate your user account: %%s", 'members' ), - esc_html( get_bloginfo( 'name' ) ), - esc_url( home_url() ) - ); - } - /** * Enqueue scripts. * From d7f95f9381511603789063448d665ede42e2d180 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 28 Sep 2017 12:36:54 -0500 Subject: [PATCH 118/157] Bump the callback priority on `user_register` up a little to make sure it runs earlier than the default. --- admin/class-user-new.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/class-user-new.php b/admin/class-user-new.php index 0d87cc1..2252578 100644 --- a/admin/class-user-new.php +++ b/admin/class-user-new.php @@ -58,7 +58,7 @@ private function setup_actions() { add_action( 'load-user-new.php', array( $this, 'load' ) ); // Sets the new user's roles. - add_action( 'user_register', array( $this, 'user_register' ) ); + add_action( 'user_register', array( $this, 'user_register' ), 5 ); } /** From ccb2a382f5ee0265fe42d7614d02b5abe34edd3a Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 28 Sep 2017 14:01:13 -0500 Subject: [PATCH 119/157] Update change log. --- changelog.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/changelog.md b/changelog.md index a548125..df92dfe 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,20 @@ # Change Log +## [2.0.1] - 2017-09-28 + +### Changed + +* Cap groups registered by the plugin bumped up 5 in priority. Primarily, this was to make sure post type cap groups were registered earlier than the default of `10`. +* Better handling of the PHP notice. We're going to check prior to loading any other code and add an admin notice if the site doesn't meet minimum requirements. + +### Fixed + +* The `show_human_caps` setting was not properly saving because it wasn't accounted for in the validation callback. +* Make sure to use the correct `$old_user_data` variable when removing all roles from a user. Otherwise, this doesn't work. +* Super admins should be able to see any private site when multisite is enabled. +* Make sure that role labels (where the plugin outputs them) are the translated version. +* Multi-role selection has been removed for the Add New User screen on multisite installs. This was to address multiple issues in core with hardcoded values that the plugin couldn't filter. The feature may return in the future in a different form. Note that this doesn't change single-site installs. + ## [2.0.0] - 2017-07-19 ### Added From 39a95c871d5d613287587006df9f73244dbbbbaf Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 28 Sep 2017 14:14:29 -0500 Subject: [PATCH 120/157] Update `readme.txt`. --- readme.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/readme.txt b/readme.txt index 1c99761..1ba56fd 100644 --- a/readme.txt +++ b/readme.txt @@ -4,8 +4,11 @@ Contributors: greenshady Donate link: https://themehybrid.com/donate Tags: capabilities, roles, members, users Requires at least: 4.7 -Tested up to: 4.8 -Stable tag: 2.0.0 +Tested up to: 4.8.2 +Requires PHP: 5.3 +Stable tag: 2.0.1 +License: GPLv2 or later +License URI: http://www.gnu.org/licenses/gpl-2.0.html The most powerful user, role, and capability management plugin for WordPress. From 1c92db7a954eed0e7044c31da0a8ef25e171e2ca Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 28 Sep 2017 14:20:53 -0500 Subject: [PATCH 121/157] Domain path should be `/lang`. --- members.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/members.php b/members.php index 3ac56d3..4680493 100644 --- a/members.php +++ b/members.php @@ -7,7 +7,7 @@ * Author: Justin Tadlock * Author URI: https://themehybrid.com * Text Domain: members - * Domain Path: /languages + * Domain Path: /lang * * The members plugin was created because the WordPress community is lacking a solid permissions * plugin that is both open source and works completely within the confines of the APIs in WordPress. From 1b71c9555f2e7a295be595a71cc9d9d8ef50f14f Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 28 Sep 2017 14:24:57 -0500 Subject: [PATCH 122/157] Version bump to 2.0.1. --- members.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/members.php b/members.php index 4680493..5171675 100644 --- a/members.php +++ b/members.php @@ -3,7 +3,7 @@ * Plugin Name: Members * Plugin URI: https://themehybrid.com/plugins/members * Description: A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private. - * Version: 2.0.1-dev + * Version: 2.0.1 * Author: Justin Tadlock * Author URI: https://themehybrid.com * Text Domain: members From 428d0138f31d53bb245b64ef9044ac3b624f4ceb Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 3 Nov 2017 14:38:00 -0500 Subject: [PATCH 123/157] This commit makes several changes dealing with editing roles on a multisite setup. Primarily, the issue is that no user (even administrators) should have permission to edit roles in a multisite setup unless that user is a Super Admin. The first step is that administrators are no longer granted the `create_roles`, `edit_roles`, and `delete_roles` capabilities when the plugin is activated. Super admins can later grant these caps on a case-by-case basis if necessary. Several network-specific capabilities are now hidden and cannot be added to any role, regardless of the user's permissions. All hidden caps (including the newly-hidden network caps) are now blocked on both the PHP and JavaScript side of the edit/new role screen. This change also removes the link to the edit role screen when a user doesn't have permission to actually edit the role (previously, it simply wouldn't load the screen). Hat tip to @johnbillion. --- admin/class-role-edit.php | 8 ++++---- admin/class-role-list-table.php | 8 ++++++-- admin/class-role-new.php | 12 ++++++------ admin/functions-admin.php | 3 ++- inc/functions-capabilities.php | 17 +++++++++++++++++ js/edit-role.js | 6 ++++-- js/edit-role.min.js | 2 +- members.php | 17 +++++++++++------ 8 files changed, 51 insertions(+), 22 deletions(-) diff --git a/admin/class-role-edit.php b/admin/class-role-edit.php index ffb6337..535c4b2 100644 --- a/admin/class-role-edit.php +++ b/admin/class-role-edit.php @@ -120,12 +120,12 @@ public function load() { check_admin_referer( 'edit_role', 'members_edit_role_nonce' ); // Get the granted and denied caps. - $grant_caps = ! empty( $_POST['grant-caps'] ) ? array_unique( $_POST['grant-caps'] ) : array(); - $deny_caps = ! empty( $_POST['deny-caps'] ) ? array_unique( $_POST['deny-caps'] ) : array(); + $grant_caps = ! empty( $_POST['grant-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['grant-caps'] ) ) : array(); + $deny_caps = ! empty( $_POST['deny-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['deny-caps'] ) ) : array(); // Get the new (custom) granted and denied caps. - $grant_new_caps = ! empty( $_POST['grant-new-caps'] ) ? array_unique( $_POST['grant-new-caps'] ) : array(); - $deny_new_caps = ! empty( $_POST['deny-new-caps'] ) ? array_unique( $_POST['deny-new-caps'] ) : array(); + $grant_new_caps = ! empty( $_POST['grant-new-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['grant-new-caps'] ) ) : array(); + $deny_new_caps = ! empty( $_POST['deny-new-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['deny-new-caps'] ) ) : array(); // Get the all and custom cap group objects. $all_group = members_get_cap_group( 'all' ); diff --git a/admin/class-role-list-table.php b/admin/class-role-list-table.php index 1265d9c..0530d42 100644 --- a/admin/class-role-list-table.php +++ b/admin/class-role-list-table.php @@ -248,7 +248,11 @@ protected function column_title( $role ) { } // Add the title and role states. - $title = sprintf( '%s%s', esc_url( members_get_edit_role_url( $role ) ), esc_html( members_get_role( $role )->label ), $role_states ); + if ( current_user_can( 'edit_roles' ) ) + $title = sprintf( '%s%s', esc_url( members_get_edit_role_url( $role ) ), esc_html( members_get_role( $role )->label ), $role_states ); + + else + $title = sprintf( '%s%s', esc_html( members_get_role( $role )->label ), $role_states ); return apply_filters( 'members_manage_roles_column_role_name', $title, $role ); } @@ -341,7 +345,7 @@ protected function handle_row_actions( $role, $column_name, $primary ) { $actions['delete'] = sprintf( '%s', esc_url( members_get_delete_role_url( $role ) ), esc_html__( 'Delete', 'members' ) ); // If the role cannot be edited. - } else { + } elseif ( current_user_can( 'edit_roles' ) ) { // Add the view role link. $actions['view'] = sprintf( '%s', esc_url( members_get_edit_role_url( $role ) ), esc_html__( 'View', 'members' ) ); diff --git a/admin/class-role-new.php b/admin/class-role-new.php index c366fba..dba5fe6 100644 --- a/admin/class-role-new.php +++ b/admin/class-role-new.php @@ -161,8 +161,8 @@ public function load() { // Check if any capabilities were selected. if ( isset( $_POST['grant-caps'] ) || isset( $_POST['deny-caps'] ) ) { - $grant_caps = ! empty( $_POST['grant-caps'] ) ? array_unique( $_POST['grant-caps'] ) : array(); - $deny_caps = ! empty( $_POST['deny-caps'] ) ? array_unique( $_POST['deny-caps'] ) : array(); + $grant_caps = ! empty( $_POST['grant-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['grant-caps'] ) ) : array(); + $deny_caps = ! empty( $_POST['deny-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['deny-caps'] ) ) : array(); foreach ( $_m_caps as $cap ) { @@ -174,14 +174,14 @@ public function load() { } } - $grant_new_caps = ! empty( $_POST['grant-new-caps'] ) ? array_unique( $_POST['grant-new-caps'] ) : array(); - $deny_new_caps = ! empty( $_POST['deny-new-caps'] ) ? array_unique( $_POST['deny-new-caps'] ) : array(); + $grant_new_caps = ! empty( $_POST['grant-new-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['grant-new-caps'] ) ) : array(); + $deny_new_caps = ! empty( $_POST['deny-new-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['deny-new-caps'] ) ) : array(); foreach ( $grant_new_caps as $grant_new_cap ) { $_cap = members_sanitize_cap( $grant_new_cap ); - if ( 'do_not_allow' !== $_cap && ! in_array( $_cap, $_m_caps ) ) + if ( ! in_array( $_cap, $_m_caps ) ) $new_caps[ $_cap ] = true; } @@ -189,7 +189,7 @@ public function load() { $_cap = members_sanitize_cap( $deny_new_cap ); - if ( 'do_not_allow' !== $_cap && ! in_array( $_cap, $_m_caps ) ) + if ( ! in_array( $_cap, $_m_caps ) ) $new_caps[ $_cap ] = false; } diff --git a/admin/functions-admin.php b/admin/functions-admin.php index 378c99a..297e093 100644 --- a/admin/functions-admin.php +++ b/admin/functions-admin.php @@ -47,7 +47,8 @@ function members_admin_register_scripts() { 'button_role_ok' => esc_html__( 'OK', 'members' ), 'label_grant_cap' => esc_html__( 'Grant %s capability', 'members' ), 'label_deny_cap' => esc_html__( 'Deny %s capability', 'members' ), - 'ays_delete_role' => esc_html__( 'Are you sure you want to delete this role? This is a permanent action and cannot be undone.', 'members' ) + 'ays_delete_role' => esc_html__( 'Are you sure you want to delete this role? This is a permanent action and cannot be undone.', 'members' ), + 'hidden_caps' => members_get_hidden_caps() ); wp_localize_script( 'members-edit-role', 'members_i18n', $i18n ); diff --git a/inc/functions-capabilities.php b/inc/functions-capabilities.php index 8b12bba..16de513 100644 --- a/inc/functions-capabilities.php +++ b/inc/functions-capabilities.php @@ -372,6 +372,23 @@ function members_get_hidden_caps() { // This is always a hidden cap and should never be added to the caps list. $caps[] = 'do_not_allow'; + // Network-level caps. + // These shouldn't show on single-site installs anyway. + // On multisite installs, they should only appear for super-admins. + if ( ! is_multisite() || ( is_multisite() && ! is_super_admin() ) ) { + + $caps[] = 'create_sites'; + $caps[] = 'delete_sites'; + $caps[] = 'manage_network'; + $caps[] = 'manage_sites'; + $caps[] = 'manage_network_users'; + $caps[] = 'manage_network_plugins'; + $caps[] = 'manage_network_themes'; + $caps[] = 'manage_network_options'; + $caps[] = 'setup_network'; + $caps[] = 'upgrade_network'; + } + // Unfiltered uploads. if ( is_multisite() || ! defined( 'ALLOW_UNFILTERED_UPLOADS' ) || ! ALLOW_UNFILTERED_UPLOADS ) $caps[] = 'unfiltered_upload'; diff --git a/js/edit-role.js b/js/edit-role.js index 74d6855..0f2ae5a 100644 --- a/js/edit-role.js +++ b/js/edit-role.js @@ -325,7 +325,8 @@ jQuery( document ).ready( function() { function() { // If there's a value in the input, enable the add new button. - if ( 'do_not_allow' !== jQuery( this ).val() ) { + //if ( 'do_not_allow' !== jQuery( this ).val() ) { + if ( -1 === jQuery.inArray( jQuery( this ).val(), members_i18n.hidden_caps ) ) { jQuery( '#members-add-new-cap' ).prop( 'disabled', false ); @@ -364,7 +365,8 @@ jQuery( document ).ready( function() { if ( new_cap ) { // Don't allow the 'do_not_allow' cap. - if ( 'do_not_allow' === new_cap ) { + //if ( 'do_not_allow' === new_cap ) { + if ( -1 !== jQuery.inArray( jQuery( this ).val(), members_i18n.hidden_caps ) ) { return; } diff --git a/js/edit-role.min.js b/js/edit-role.min.js index e1d1436..d7011c6 100644 --- a/js/edit-role.min.js +++ b/js/edit-role.min.js @@ -1 +1 @@ -jQuery(document).ready(function(){function e(e){e=e.toLowerCase().trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,""),jQuery(".role-slug").text(e)}function r(){var e=jQuery("#members-tab-all input[data-grant-cap]:checked").length,r=jQuery("#members-tab-all input[data-deny-cap]:checked").length,t=jQuery('#members-tab-custom input[name="grant-new-caps[]"]:checked').length,a=jQuery('#members-tab-custom input[name="deny-new-caps[]"]:checked').length;jQuery("#submitdiv .granted-count").text(e+t),jQuery("#submitdiv .denied-count").text(r+a)}function t(e){var r="grant",t="deny";jQuery(e).attr("data-deny-cap")&&(r="deny",t="grant");var a=jQuery(e).attr("data-"+r+"-cap");jQuery(e).prop("checked")?(jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!0),jQuery("input[data-"+t+'-cap="'+a+'"]').prop("checked",!1)):jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!1)}jQuery(".members-delete-role-link").click(function(){return window.confirm(members_i18n.ays_delete_role)}),jQuery('input[name="role_name"]').keyup(function(){jQuery('input[name="role"]').val()||e(this.value)}),jQuery('input[name="role"], .role-ok-button').hide(),jQuery(document).on("click",".role-edit-button.closed",function(){jQuery(this).removeClass("closed").addClass("open").text(members_i18n.button_role_ok),jQuery('input[name="role"]').show(),jQuery('input[name="role"]').trigger("focus"),jQuery('input[name="role"]').attr("value",jQuery(".role-slug").text())}),jQuery(document).on("click",".role-edit-button.open",function(){jQuery(this).removeClass("open").addClass("closed").text(members_i18n.button_role_edit),jQuery('input[name="role"]').hide();var r=jQuery('input[name="role"]').val();e(r?r:jQuery('input[name="role_name"]').val())}),jQuery('input[name="role"]').keypress(function(e){if(13===e.keyCode)return jQuery(".role-edit-button").click().trigger("focus"),e.preventDefault(),!1}),jQuery('.users_page_role-new input[name="role_name"]').val()||jQuery(".users_page_role-new #publish").prop("disabled",!0),jQuery('.users_page_role-new input[name="role_name"]').on("input",function(){jQuery(this).val()?jQuery(".users_page_role-new #publish").prop("disabled",!1):jQuery(".users_page_role-new #publish").prop("disabled",!0)});var a=wp.template("members-cap-section"),n=wp.template("members-cap-control");"undefined"!=typeof members_sections&&"undefined"!=typeof members_controls&&(_.each(members_sections,function(e){jQuery(".members-tab-wrap").append(a(e))}),_.each(members_controls,function(e){jQuery("#members-tab-"+e.section+" tbody").append(n(e))})),jQuery(".members-cap-tabs .members-tab-content").hide(),jQuery(".members-cap-tabs .members-tab-content:first-child").show(),jQuery(".members-tab-nav :first-child").attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(".members-tab-nav :first-child a").text()),jQuery(".members-tab-nav li a").click(function(e){e.preventDefault();var r=jQuery(this).attr("href");jQuery(this).parents(".members-cap-tabs").find(".members-tab-content").hide(),jQuery(this).parents(".members-cap-tabs").find(r).show(),jQuery(this).parents(".members-cap-tabs").find(".members-tab-title").attr("aria-selected","false"),jQuery(this).parent().attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(this).text())}),r(),jQuery(document).on("change",".members-cap-checklist input[data-grant-cap], .members-cap-checklist input[data-deny-cap]",function(){t(this),r()}),jQuery(document).on("click",".editable-role .members-cap-checklist button",function(){var e=jQuery(this).closest(".members-cap-checklist"),r=jQuery(e).find("input[data-grant-cap]"),t=jQuery(e).find("input[data-deny-cap]");jQuery(r).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!0).change()):jQuery(t).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!1).change()):jQuery(r).prop("checked",!0).change()}),jQuery(document).on("hover",".editable-role .members-cap-checklist button",function(){jQuery(".members-cap-checklist button:focus").not(this).blur()}),postboxes.add_postbox_toggles(pagenow),jQuery("#newcapdiv button.handlediv").attr("type","button"),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery("#members-new-cap-field").on("input",function(){"do_not_allow"!==jQuery(this).val()?jQuery("#members-add-new-cap").prop("disabled",!1):jQuery("#members-add-new-cap").prop("disabled",!0)}),jQuery("#members-new-cap-field").keypress(function(e){if(13===e.keyCode)return jQuery("#members-add-new-cap").click(),e.preventDefault(),!1}),jQuery("#members-add-new-cap").click(function(){var e=jQuery("#members-new-cap-field").val();if(e=e.trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,"")){if("do_not_allow"===e)return;jQuery('a[href="#members-tab-custom"]').trigger("click"),members_i18n.label_grant_cap=members_i18n.label_grant_cap.replace(/%s/g,""+e+""),members_i18n.label_deny_cap=members_i18n.label_deny_cap.replace(/%s/g,""+e+"");var r={cap:e,readonly:"",name:{grant:"grant-new-caps[]",deny:"deny-new-caps[]"},is_granted_cap:!0,is_denied_cap:!1,label:{cap:e,grant:members_i18n.label_grant_cap,deny:members_i18n.label_deny_cap}};jQuery("#members-tab-custom tbody").prepend(n(r));var t=jQuery('[data-grant-cap="'+e+'"]').parents(".members-cap-checklist");jQuery(t).addClass("members-highlight"),setTimeout(function(){jQuery(t).removeClass("members-highlight")},500),jQuery("#members-new-cap-field").val(""),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery('.members-cap-checklist input[data-grant-cap="'+e+'"]').trigger("change")}})}); \ No newline at end of file +jQuery(document).ready(function(){function e(e){e=e.toLowerCase().trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,""),jQuery(".role-slug").text(e)}function r(){var e=jQuery("#members-tab-all input[data-grant-cap]:checked").length,r=jQuery("#members-tab-all input[data-deny-cap]:checked").length,t=jQuery('#members-tab-custom input[name="grant-new-caps[]"]:checked').length,a=jQuery('#members-tab-custom input[name="deny-new-caps[]"]:checked').length;jQuery("#submitdiv .granted-count").text(e+t),jQuery("#submitdiv .denied-count").text(r+a)}function t(e){var r="grant",t="deny";jQuery(e).attr("data-deny-cap")&&(r="deny",t="grant");var a=jQuery(e).attr("data-"+r+"-cap");jQuery(e).prop("checked")?(jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!0),jQuery("input[data-"+t+'-cap="'+a+'"]').prop("checked",!1)):jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!1)}jQuery(".members-delete-role-link").click(function(){return window.confirm(members_i18n.ays_delete_role)}),jQuery('input[name="role_name"]').keyup(function(){jQuery('input[name="role"]').val()||e(this.value)}),jQuery('input[name="role"], .role-ok-button').hide(),jQuery(document).on("click",".role-edit-button.closed",function(){jQuery(this).removeClass("closed").addClass("open").text(members_i18n.button_role_ok),jQuery('input[name="role"]').show(),jQuery('input[name="role"]').trigger("focus"),jQuery('input[name="role"]').attr("value",jQuery(".role-slug").text())}),jQuery(document).on("click",".role-edit-button.open",function(){jQuery(this).removeClass("open").addClass("closed").text(members_i18n.button_role_edit),jQuery('input[name="role"]').hide();var r=jQuery('input[name="role"]').val();e(r?r:jQuery('input[name="role_name"]').val())}),jQuery('input[name="role"]').keypress(function(e){if(13===e.keyCode)return jQuery(".role-edit-button").click().trigger("focus"),e.preventDefault(),!1}),jQuery('.users_page_role-new input[name="role_name"]').val()||jQuery(".users_page_role-new #publish").prop("disabled",!0),jQuery('.users_page_role-new input[name="role_name"]').on("input",function(){jQuery(this).val()?jQuery(".users_page_role-new #publish").prop("disabled",!1):jQuery(".users_page_role-new #publish").prop("disabled",!0)});var a=wp.template("members-cap-section"),n=wp.template("members-cap-control");"undefined"!=typeof members_sections&&"undefined"!=typeof members_controls&&(_.each(members_sections,function(e){jQuery(".members-tab-wrap").append(a(e))}),_.each(members_controls,function(e){jQuery("#members-tab-"+e.section+" tbody").append(n(e))})),jQuery(".members-cap-tabs .members-tab-content").hide(),jQuery(".members-cap-tabs .members-tab-content:first-child").show(),jQuery(".members-tab-nav :first-child").attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(".members-tab-nav :first-child a").text()),jQuery(".members-tab-nav li a").click(function(e){e.preventDefault();var r=jQuery(this).attr("href");jQuery(this).parents(".members-cap-tabs").find(".members-tab-content").hide(),jQuery(this).parents(".members-cap-tabs").find(r).show(),jQuery(this).parents(".members-cap-tabs").find(".members-tab-title").attr("aria-selected","false"),jQuery(this).parent().attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(this).text())}),r(),jQuery(document).on("change",".members-cap-checklist input[data-grant-cap], .members-cap-checklist input[data-deny-cap]",function(){t(this),r()}),jQuery(document).on("click",".editable-role .members-cap-checklist button",function(){var e=jQuery(this).closest(".members-cap-checklist"),r=jQuery(e).find("input[data-grant-cap]"),t=jQuery(e).find("input[data-deny-cap]");jQuery(r).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!0).change()):jQuery(t).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!1).change()):jQuery(r).prop("checked",!0).change()}),jQuery(document).on("hover",".editable-role .members-cap-checklist button",function(){jQuery(".members-cap-checklist button:focus").not(this).blur()}),postboxes.add_postbox_toggles(pagenow),jQuery("#newcapdiv button.handlediv").attr("type","button"),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery("#members-new-cap-field").on("input",function(){-1===jQuery.inArray(jQuery(this).val(),members_i18n.hidden_caps)?jQuery("#members-add-new-cap").prop("disabled",!1):jQuery("#members-add-new-cap").prop("disabled",!0)}),jQuery("#members-new-cap-field").keypress(function(e){if(13===e.keyCode)return jQuery("#members-add-new-cap").click(),e.preventDefault(),!1}),jQuery("#members-add-new-cap").click(function(){var e=jQuery("#members-new-cap-field").val();if(e=e.trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,"")){if(-1!==jQuery.inArray(jQuery(this).val(),members_i18n.hidden_caps))return;jQuery('a[href="#members-tab-custom"]').trigger("click"),members_i18n.label_grant_cap=members_i18n.label_grant_cap.replace(/%s/g,""+e+""),members_i18n.label_deny_cap=members_i18n.label_deny_cap.replace(/%s/g,""+e+"");var r={cap:e,readonly:"",name:{grant:"grant-new-caps[]",deny:"deny-new-caps[]"},is_granted_cap:!0,is_denied_cap:!1,label:{cap:e,grant:members_i18n.label_grant_cap,deny:members_i18n.label_deny_cap}};jQuery("#members-tab-custom tbody").prepend(n(r));var t=jQuery('[data-grant-cap="'+e+'"]').parents(".members-cap-checklist");jQuery(t).addClass("members-highlight"),setTimeout(function(){jQuery(t).removeClass("members-highlight")},500),jQuery("#members-new-cap-field").val(""),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery('.members-cap-checklist input[data-grant-cap="'+e+'"]').trigger("change")}})}); \ No newline at end of file diff --git a/members.php b/members.php index 5171675..d1cd6e3 100644 --- a/members.php +++ b/members.php @@ -3,7 +3,7 @@ * Plugin Name: Members * Plugin URI: https://themehybrid.com/plugins/members * Description: A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private. - * Version: 2.0.1 + * Version: 2.0.2-dev * Author: Justin Tadlock * Author URI: https://themehybrid.com * Text Domain: members @@ -25,7 +25,7 @@ * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * @package Members - * @version 2.0.1 + * @version 2.0.2 * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link https://themehybrid.com/plugins/members @@ -297,11 +297,16 @@ public function activation() { // If the administrator role exists, add required capabilities for the plugin. if ( ! empty( $role ) ) { - $role->add_cap( 'list_roles' ); // View roles in backend. - $role->add_cap( 'create_roles' ); // Create new roles. - $role->add_cap( 'delete_roles' ); // Delete existing roles. - $role->add_cap( 'edit_roles' ); // Edit existing roles/caps. $role->add_cap( 'restrict_content' ); // Edit per-post content permissions. + $role->add_cap( 'list_roles' ); // View roles in backend. + + // Do not allow administrators to edit, create, or delete roles + // in a multisite setup. Super admins should assign these manually. + if ( ! is_multisite() ) { + $role->add_cap( 'create_roles' ); // Create new roles. + $role->add_cap( 'delete_roles' ); // Delete existing roles. + $role->add_cap( 'edit_roles' ); // Edit existing roles/caps. + } } } From 3ff98e629ee9f31adf24686da0da6dee65fa514c Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 3 Nov 2017 14:46:42 -0500 Subject: [PATCH 124/157] Network-specific caps shouldn't even appear for super admins in multisite. Eventually, we'll handle this in a network role/cap management plugin. --- inc/functions-capabilities.php | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/inc/functions-capabilities.php b/inc/functions-capabilities.php index 16de513..4148756 100644 --- a/inc/functions-capabilities.php +++ b/inc/functions-capabilities.php @@ -374,20 +374,17 @@ function members_get_hidden_caps() { // Network-level caps. // These shouldn't show on single-site installs anyway. - // On multisite installs, they should only appear for super-admins. - if ( ! is_multisite() || ( is_multisite() && ! is_super_admin() ) ) { - - $caps[] = 'create_sites'; - $caps[] = 'delete_sites'; - $caps[] = 'manage_network'; - $caps[] = 'manage_sites'; - $caps[] = 'manage_network_users'; - $caps[] = 'manage_network_plugins'; - $caps[] = 'manage_network_themes'; - $caps[] = 'manage_network_options'; - $caps[] = 'setup_network'; - $caps[] = 'upgrade_network'; - } + // On multisite installs, they should be handled by a network-specific role manager. + $caps[] = 'create_sites'; + $caps[] = 'delete_sites'; + $caps[] = 'manage_network'; + $caps[] = 'manage_sites'; + $caps[] = 'manage_network_users'; + $caps[] = 'manage_network_plugins'; + $caps[] = 'manage_network_themes'; + $caps[] = 'manage_network_options'; + $caps[] = 'setup_network'; + $caps[] = 'upgrade_network'; // Unfiltered uploads. if ( is_multisite() || ! defined( 'ALLOW_UNFILTERED_UPLOADS' ) || ! ALLOW_UNFILTERED_UPLOADS ) From a3561f140bc1a132b73ccfe0d6c3434ee0c79718 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 3 Nov 2017 15:26:53 -0500 Subject: [PATCH 125/157] Allow the `setup_network` cap on single site but not multisite because it's required for actually setting up a multisite network. --- inc/functions-capabilities.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/inc/functions-capabilities.php b/inc/functions-capabilities.php index 4148756..0ca1953 100644 --- a/inc/functions-capabilities.php +++ b/inc/functions-capabilities.php @@ -383,9 +383,12 @@ function members_get_hidden_caps() { $caps[] = 'manage_network_plugins'; $caps[] = 'manage_network_themes'; $caps[] = 'manage_network_options'; - $caps[] = 'setup_network'; $caps[] = 'upgrade_network'; + // This cap is needed on single site to set up a multisite network. + if ( is_multisite() ) + $caps[] = 'setup_network'; + // Unfiltered uploads. if ( is_multisite() || ! defined( 'ALLOW_UNFILTERED_UPLOADS' ) || ! ALLOW_UNFILTERED_UPLOADS ) $caps[] = 'unfiltered_upload'; From 591e95a07096cdd01647cf7754120124d94b3b87 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 6 Nov 2017 12:15:48 -0600 Subject: [PATCH 126/157] With any luck, this finally fixes the role label translation issue. Added a `get()` method to the `Role` class for getting its properties. Primarily, we're using this to run the `$label` property through `members_translate_role()`. Fixes: https://github.com/justintadlock/members/issues/157 --- admin/class-role-edit.php | 12 ++++++------ admin/class-role-list-table.php | 4 ++-- admin/class-role-new.php | 2 +- admin/class-roles.php | 2 +- admin/class-user-edit.php | 2 +- admin/class-user-new.php | 2 +- inc/class-role.php | 17 +++++++++++++++++ inc/class-widget-users.php | 2 +- inc/functions-deprecated.php | 2 +- inc/functions-roles.php | 2 +- inc/functions-users.php | 2 +- 11 files changed, 33 insertions(+), 16 deletions(-) diff --git a/admin/class-role-edit.php b/admin/class-role-edit.php index 535c4b2..ab3162d 100644 --- a/admin/class-role-edit.php +++ b/admin/class-role-edit.php @@ -208,7 +208,7 @@ public function load() { members_register_role( $this->role->name, array( - 'label' => $this->members_role->label, + 'label' => $this->members_role->get( 'label' ), 'caps' => $this->role->capabilities ) ); @@ -223,19 +223,19 @@ public function load() { // If successful update. if ( $this->role_updated ) - add_settings_error( 'members_edit_role', 'role_updated', sprintf( esc_html__( '%s role updated.', 'members' ), members_get_role( $this->role->name )->label ), 'updated' ); + add_settings_error( 'members_edit_role', 'role_updated', sprintf( esc_html__( '%s role updated.', 'members' ), members_get_role( $this->role->name )->get( 'label' ) ), 'updated' ); // If the role is not editable. if ( ! $this->is_editable ) - add_settings_error( 'members_edit_role', 'role_uneditable', sprintf( esc_html__( 'The %s role is not editable. This means that it is most likely added via another plugin for a special use or that you do not have permission to edit it.', 'members' ), members_get_role( $this->role->name )->label ) ); + add_settings_error( 'members_edit_role', 'role_uneditable', sprintf( esc_html__( 'The %s role is not editable. This means that it is most likely added via another plugin for a special use or that you do not have permission to edit it.', 'members' ), members_get_role( $this->role->name )->get( 'label' ) ) ); // If editing the core administrator role. if ( 'administrator' === $this->role->name ) - add_settings_error( 'members_edit_role', 'role_is_admin', sprintf( esc_html__( 'The %s role is typically the most important role on the site. Please take extreme caution that you do not inadvertently remove necessary capabilities.', 'members' ), members_get_role( $this->role->name )->label ) ); + add_settings_error( 'members_edit_role', 'role_is_admin', sprintf( esc_html__( 'The %s role is typically the most important role on the site. Please take extreme caution that you do not inadvertently remove necessary capabilities.', 'members' ), members_get_role( $this->role->name )->get( 'label' ) ) ); // If a new role was added (redirect from new role screen). if ( isset( $_GET['message'] ) && 'role_added' === $_GET['message'] ) - add_settings_error( 'members_edit_role', 'role_added', sprintf( esc_html__( 'The %s role has been created.', 'members' ), members_get_role( $this->role->name )->label ), 'updated' ); + add_settings_error( 'members_edit_role', 'role_added', sprintf( esc_html__( 'The %s role has been created.', 'members' ), members_get_role( $this->role->name )->get( 'label' ) ), 'updated' ); // Load page hook. do_action( 'members_load_role_edit' ); @@ -318,7 +318,7 @@ public function page() { ?>
    - +
    diff --git a/admin/class-role-list-table.php b/admin/class-role-list-table.php index 0530d42..f8dac0d 100644 --- a/admin/class-role-list-table.php +++ b/admin/class-role-list-table.php @@ -249,10 +249,10 @@ protected function column_title( $role ) { // Add the title and role states. if ( current_user_can( 'edit_roles' ) ) - $title = sprintf( '%s%s', esc_url( members_get_edit_role_url( $role ) ), esc_html( members_get_role( $role )->label ), $role_states ); + $title = sprintf( '%s%s', esc_url( members_get_edit_role_url( $role ) ), esc_html( members_get_role( $role )->get( 'label' ) ), $role_states ); else - $title = sprintf( '%s%s', esc_html( members_get_role( $role )->label ), $role_states ); + $title = sprintf( '%s%s', esc_html( members_get_role( $role )->get( 'label' ) ), $role_states ); return apply_filters( 'members_manage_roles_column_role_name', $title, $role ); } diff --git a/admin/class-role-new.php b/admin/class-role-new.php index dba5fe6..89a6ce5 100644 --- a/admin/class-role-new.php +++ b/admin/class-role-new.php @@ -325,7 +325,7 @@ public function page() { ?>
    - +
    diff --git a/admin/class-roles.php b/admin/class-roles.php index eec32f3..6344b27 100644 --- a/admin/class-roles.php +++ b/admin/class-roles.php @@ -128,7 +128,7 @@ public function load() { if ( members_role_exists( $role ) ) { // Add role deleted message. - add_settings_error( 'members_roles', 'role_deleted', sprintf( esc_html__( '%s role deleted.', 'members' ), members_get_role( $role )->label ), 'updated' ); + add_settings_error( 'members_roles', 'role_deleted', sprintf( esc_html__( '%s role deleted.', 'members' ), members_get_role( $role )->get( 'label' ) ), 'updated' ); // Delete the role. members_delete_role( $role ); diff --git a/admin/class-user-edit.php b/admin/class-user-edit.php index 57dcf98..bf49af7 100644 --- a/admin/class-user-edit.php +++ b/admin/class-user-edit.php @@ -105,7 +105,7 @@ public function profile_fields( $user ) {
  • diff --git a/admin/class-user-new.php b/admin/class-user-new.php index 2252578..4934883 100644 --- a/admin/class-user-new.php +++ b/admin/class-user-new.php @@ -117,7 +117,7 @@ public function profile_fields() {
  • diff --git a/inc/class-role.php b/inc/class-role.php index c093481..9d50bc8 100644 --- a/inc/class-role.php +++ b/inc/class-role.php @@ -158,4 +158,21 @@ public function __construct( $name, $args = array() ) { $this->has_caps = 0 < $this->granted_cap_count; } } + + /** + * Magic method for getting media object properties. Let's keep from failing if a theme + * author attempts to access a property that doesn't exist. + * + * @since 2.0.2 + * @access public + * @param string $property + * @return mixed + */ + public function get( $property ) { + + if ( 'label' === $property ) + return members_translate_role( $this->name ); + + return isset( $this->$property ) ? $this->$property : false; + } } diff --git a/inc/class-widget-users.php b/inc/class-widget-users.php index 74c217d..f83c03b 100644 --- a/inc/class-widget-users.php +++ b/inc/class-widget-users.php @@ -229,7 +229,7 @@ function form( $instance ) {

    diff --git a/inc/functions-deprecated.php b/inc/functions-deprecated.php index 53703e9..2741f0f 100644 --- a/inc/functions-deprecated.php +++ b/inc/functions-deprecated.php @@ -41,7 +41,7 @@ function members_get_active_role_names() { $has_users = array(); foreach ( members_get_active_roles() as $role ) - $has_users[ $role ] = members_get_role( $role )->label; + $has_users[ $role ] = members_get_role( $role )->get( 'label' ); return $has_users; } diff --git a/inc/functions-roles.php b/inc/functions-roles.php index 2852a33..2cd4cc7 100644 --- a/inc/functions-roles.php +++ b/inc/functions-roles.php @@ -40,7 +40,7 @@ function members_register_default_roles( $wp_roles ) { foreach ( $wp_roles->roles as $name => $object ) { $args = array( - 'label' => members_translate_role_hook( $object['name'], $name ), + 'label' => $object['name'], 'caps' => $object['capabilities'] ); diff --git a/inc/functions-users.php b/inc/functions-users.php index 67423e8..56931b5 100644 --- a/inc/functions-users.php +++ b/inc/functions-users.php @@ -153,7 +153,7 @@ function members_get_user_role_names( $user_id ) { $names = array(); foreach ( $user->roles as $role ) - $names[ $role ] = members_get_role( $role )->label; + $names[ $role ] = members_get_role( $role )->get( 'label' ); return $names; } From e89a9db23b407a3355eceda5fb268bebf53d74bd Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 6 Nov 2017 12:28:14 -0600 Subject: [PATCH 127/157] Update the change log. --- changelog.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/changelog.md b/changelog.md index df92dfe..7ade0cf 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,15 @@ # Change Log +## [2.0.2] - 2017-11-06 + +### Fixed + +* Role labels should now be handled correctly where the plugin outputs them. This was not corrected in 2.0.1 as previously thought. + +### Security + +* Corrected a capability escalation issue on multisite where administrators could assign themselves network caps. Administrators are no longer given the `create_role`, `edit_role`, and `delete_role` caps on multisite. A Super Admin must manually set these caps if they want to grant them to a site administrator. Additionally, network caps are always blocked from being assigned. + ## [2.0.1] - 2017-09-28 ### Changed From 8befa787277ecde0398a01c6a9692f805c185398 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 6 Nov 2017 12:28:25 -0600 Subject: [PATCH 128/157] Readme updates. --- readme.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/readme.txt b/readme.txt index 1ba56fd..1e65903 100644 --- a/readme.txt +++ b/readme.txt @@ -4,9 +4,9 @@ Contributors: greenshady Donate link: https://themehybrid.com/donate Tags: capabilities, roles, members, users Requires at least: 4.7 -Tested up to: 4.8.2 +Tested up to: 4.8.3 Requires PHP: 5.3 -Stable tag: 2.0.1 +Stable tag: 2.0.2 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -80,6 +80,12 @@ When the plugin is first activated, it runs a script that sets specific capabili If, for some reason, you do have the administrator role and the role manager is still inaccessible to you, deactivate the plugin. Then, reactivate it. +### On multisite, why can't administrators cannot manage roles? + +If you have a multisite installation, only Super Admins can create, edit, and delete roles by default. This is a security measure to make sure that you absolutely trust sub-site admins to make these types of changes to roles. If you're certain you want to allow this, add the Create Roles (`create_roles`), Edit Roles (`edit_roles`), and/or Delete Roles (`delete_roles`) capabilities to the role on each sub-site where you want to allow this. + +_Note: This change was made in version 2.0.2 and has no effect on existing installs of Members on existing sub-sites._ + ### Help! I've locked myself out of my site! Please read the documentation for the plugin before actually using it, especially a plugin that controls permissions for your site. I cannot stress this enough. This is a powerful plugin that allows you to make direct changes to roles and capabilities in the database. From e34b775becc0b6260c8f240bc3f3e659453fc28e Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Mon, 6 Nov 2017 12:30:40 -0600 Subject: [PATCH 129/157] Version bump to 2.0.2. --- members.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/members.php b/members.php index d1cd6e3..d41b159 100644 --- a/members.php +++ b/members.php @@ -3,7 +3,7 @@ * Plugin Name: Members * Plugin URI: https://themehybrid.com/plugins/members * Description: A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private. - * Version: 2.0.2-dev + * Version: 2.0.2 * Author: Justin Tadlock * Author URI: https://themehybrid.com * Text Domain: members From 89636081bb0fb7dfb1154333fc161f0c91e5f655 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sun, 7 Jan 2018 11:28:44 -0600 Subject: [PATCH 130/157] Make sure to remove slashes from posted role label. Fixes: https://github.com/justintadlock/members/issues/176 --- admin/class-role-new.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/class-role-new.php b/admin/class-role-new.php index 89a6ce5..355ab33 100644 --- a/admin/class-role-new.php +++ b/admin/class-role-new.php @@ -195,7 +195,7 @@ public function load() { // Sanitize the new role name/label. We just want to strip any tags here. if ( ! empty( $_POST['role_name'] ) ) - $this->role_name = wp_strip_all_tags( $_POST['role_name'] ); + $this->role_name = wp_strip_all_tags( wp_unslash( $_POST['role_name'] ) ); // Sanitize the new role, removing any unwanted characters. if ( ! empty( $_POST['role'] ) ) From 2a1230ca723d622641eee6903b3566438bdbbacc Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 8 Feb 2018 16:12:46 -0600 Subject: [PATCH 131/157] Version bump to 2.0.3-dev. --- members.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/members.php b/members.php index d41b159..8a88deb 100644 --- a/members.php +++ b/members.php @@ -3,7 +3,7 @@ * Plugin Name: Members * Plugin URI: https://themehybrid.com/plugins/members * Description: A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private. - * Version: 2.0.2 + * Version: 2.0.3-dev * Author: Justin Tadlock * Author URI: https://themehybrid.com * Text Domain: members @@ -25,7 +25,7 @@ * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * @package Members - * @version 2.0.2 + * @version 2.0.3 * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link https://themehybrid.com/plugins/members From be701d6f09087b7a397c4186b122ddd75dca4707 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 8 Feb 2018 16:14:49 -0600 Subject: [PATCH 132/157] `wp_roles_init` may be called multiple times. Let's make sure that the only roles we register are within the `$wp_roles` object. Fixes: https://github.com/justintadlock/members/issues/181 --- inc/functions-roles.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/inc/functions-roles.php b/inc/functions-roles.php index 2cd4cc7..cb2a86f 100644 --- a/inc/functions-roles.php +++ b/inc/functions-roles.php @@ -46,6 +46,13 @@ function members_register_default_roles( $wp_roles ) { members_register_role( $name, $args ); } + + // Unset any roles that were registered previously but are not currently available. + foreach ( members_get_roles() as $role ) { + + if ( ! isset( $wp_roles->roles[ $role->name ] ) ) + members_unregister_role( $role->name ); + } } /** From ff868d3cb48e85a9da77d3e3fa20e1230bc42dab Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 18 Apr 2018 10:10:42 -0500 Subject: [PATCH 133/157] Version bump to 2.1.0-dev. --- members.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/members.php b/members.php index 8a88deb..21dbe75 100644 --- a/members.php +++ b/members.php @@ -3,7 +3,7 @@ * Plugin Name: Members * Plugin URI: https://themehybrid.com/plugins/members * Description: A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private. - * Version: 2.0.3-dev + * Version: 2.1.0-dev * Author: Justin Tadlock * Author URI: https://themehybrid.com * Text Domain: members @@ -25,7 +25,7 @@ * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * @package Members - * @version 2.0.3 + * @version 2.1.0 * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2017, Justin Tadlock * @link https://themehybrid.com/plugins/members From e1d5b1cdbb415276fd8dcf459c74eaecc3f0bc81 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 18 Apr 2018 12:18:41 -0500 Subject: [PATCH 134/157] Adds the `user_name`, `user_id`, and `user_email` parameters to the `[members_access]` shortcode. These work the same as the `role` and `capability` parameters. Multiple values can passed to a given parameter by separating the values with a comma. --- inc/functions-shortcodes.php | 53 ++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/inc/functions-shortcodes.php b/inc/functions-shortcodes.php index 3697724..dc16b0f 100644 --- a/inc/functions-shortcodes.php +++ b/inc/functions-shortcodes.php @@ -114,6 +114,9 @@ function members_access_check_shortcode( $attr, $content = null ) { $defaults = array( 'capability' => '', // Single capability or comma-separated multiple capabilities. 'role' => '', // Single role or comma-separated multiple roles. + 'user_id' => '', // Single user ID or comma-separated multiple IDs. + 'user_name' => '', // Single user name or comma-separated multiple names. + 'user_email' => '', // Single user email or comma-separated multiple emails. 'operator' => 'or' // Only the `!` operator is supported for now. Everything else falls back to `or`. ); @@ -147,6 +150,56 @@ function members_access_check_shortcode( $attr, $content = null ) { return members_current_user_has_role( $roles ) ? do_shortcode( $content ) : ''; } + $user_id = 0; + $user_name = $user_email = ''; + + if ( is_user_logged_in() ) { + + $user = wp_get_current_user(); + $user_id = get_current_user_id(); + $user_name = $user->user_login; + $user_email = $user->user_email; + } + + // If the current user has one of the user ids. + if ( $attr['user_id'] ) { + + // Get the user IDs. + $ids = array_map( 'trim', explode( ',', $attr['user_id'] ) ); + + if ( '!' === $operator ) { + return in_array( $user_id, $ids ) ? '' : do_shortcode( $content ); + } + + return in_array( $user_id, $ids ) ? do_shortcode( $content ) : ''; + } + + // If the current user has one of the user names. + if ( $attr['user_name'] ) { + + // Get the user names. + $names = array_map( 'trim', explode( ',', $attr['user_name'] ) ); + + if ( '!' === $operator ) { + return in_array( $user_name, $names ) ? '' : do_shortcode( $content ); + } + + return in_array( $user_name, $names ) ? do_shortcode( $content ) : ''; + } + + // If the current user has one of the user emails. + if ( $attr['user_email'] ) { + + // Get the user emails. + $emails = array_map( 'trim', explode( ',', $attr['user_email'] ) ); + + if ( '!' === $operator ) { + return in_array( $user_email, $emails ) ? '' : do_shortcode( $content ); + } + + return in_array( $user_email, $emails ) ? do_shortcode( $content ) : ''; + } + // Return an empty string if we've made it to this point. return ''; } From 2e0f48ad41b8c3a247d6759580349e87eb9ff989 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 18 Apr 2018 13:48:13 -0500 Subject: [PATCH 135/157] Bring in the fix from the dev branch to fix the invalid icon URL. --- admin/class-addon.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/class-addon.php b/admin/class-addon.php index 2ccc1c1..c4f4e2a 100644 --- a/admin/class-addon.php +++ b/admin/class-addon.php @@ -168,6 +168,6 @@ public function __construct( $name, $args = array() ) { $this->name = sanitize_key( $name ); if ( ! $this->icon_url ) - $this->icon_url = members_plugin()->dir_uri . 'img/addon.png'; + $this->icon_url = members_plugin()->uri . 'img/icon-addon.png'; } } From 7dc5d5a9abfce1e07c4ad60e51a6c1f61a223da4 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 18 Apr 2018 13:50:33 -0500 Subject: [PATCH 136/157] Adds the `icon-members-core-create-caps.png` file to keep resources off the ThemeHybrid.com server. --- img/icon-members-core-create-caps.png | Bin 0 -> 2332 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 img/icon-members-core-create-caps.png diff --git a/img/icon-members-core-create-caps.png b/img/icon-members-core-create-caps.png new file mode 100644 index 0000000000000000000000000000000000000000..8ac82856592fce8c2d3980057591c27c9c52ed93 GIT binary patch literal 2332 zcma);dpy&N8^^yJO3cxPv^blN7fvq6HBPxr!kPTaPmW9EK9n){h-|7OS{T2ROG=7S zDRaqf2+6G)k&xT4Y}075nT=h}et-9Ropb(rKF{m*{PlS~&-?RayPa`XQaG#t0Duzm zw^Qx_0Fp`&AP<(74}0xQq(wH|{y+8rKpM1^yR{sK-Y}8CVto10WoL05pNUfIRSbt%?(=y1X?bzxq_Mp`w+oe=^aURCf4J>njf;mu1c;pm~7A` zem+!kSKHkD6%9Ky+K$6jC@&9Q=#T2Kur^KB>}}7ny6wwg$S+Kba_;Q*ot#!Livg)b z%nn4AlXTfs)r(DMCTP6R0(`{6#>U;_1pv<(vb9n_{V7aqW=-TQ;+G6$&|$bEOAGvtl|&Y&9FcrJvb+^6FA3^|Owst3-3XjrIr`%_#s@RUn& z%Bc+8D)Zay*pI9bP}+8t`9#qZG@ojvb!z~wEo^N?#|m{A;I&`+MN}~tMXr!gF4zl? zJouLR0(e@J*dUH#CFD=G!`th<5x%2SL9}_=$w%Z@BA~VE+4`k4rv2 z+3%Vve&9{XgYX6l5I{#bcfk4~H-33|`1z8Ow~R*uw<}t+$^l${t0F)K{CJx=i38Hj ztP&qJ3=HbeNVU31)$YW+z%2vN+n#PYGhw5QeDL)M?(DcgBb)J%CiJT2EyqWJr&|7C z2fVaJ&3f_nJlR$cs$Zj$l;+=TPq6eQ9W}>K%u**Cjqn?MqS=7~y|_oGh%!vSo`*rG$Cw25$c}bnudWGSne(EsM%}KeRwi*Uu=;Q`q?4G?s={!|OFz(fT71j=K9uDSW zU$yb;E3$mic_C+yr6g2FPL}aGCF_bsg|cqv=LBw;+jDqJcAwo=x|jOQ$iZk*-`cXa z_m>p*UOm%&Pa^;m(%??(<|^j6D=W9s-C*0R_*)-ex! ze}`7@$CfPRw3}cDL%3ZfJ%60`3b{#O8N}-Jj35*P)#}&YvDeC`{QKXthu0K5qAm_Wx*_}jy+$k8jIIj_3;AhznpI=Msim|DN zdaZ(7(sBbg!Td*sADC2Xo~L6n)zEKb<&9l4~^;Q!t0$wU#)us8oS33qOmUJ}4q#90IUQy)B z>*nRkYyM8F@PP@ll_Ww+d!M96Y9HmAEI}mHb;9mfgXU$sH9I>FMDCU&&|#YGy^{MM z3eE|78JN(v>buYK@`c?LD72+T;banLo^71>Lm&^{=1O-}+ zZ9i7L$UOU1KQmaHu$bBlwJiZN3m}%~v(uNEOCu#~O+OT|D$8AD35$`15rA}a8pt(t zW*wkM-u*M*Dga(4Cn#IEwTrMQuzRcAJa!c}4KZ|BjI$RiG_wQ<_G zG#l5HgY_GljVMHkt%eq$KALCu*m&Fscf+&$dM0{IKN+- }P)fu&fG$MlEsdB91E zJ24~seleie`NJ?Xrz0u5&;k6I;Cd!>S`b#fe+?9nY0Q&Tx`aULGus6=30f)2xlt>mZVz z(HDJg~zN%^j} zI4MF`$Fu!z+QOT1ieXk8w52#bDzS)nSTj>>8GhFZJ8H^rPCQ}Z3Lf-&H|VR&+T~}` zmw7aMm%CD6gGsQHzfi;(b#MR=qCQ&fEbq}W$SAsa$rWfbNDFy%@rEjOIAdkH4lqq> z{$$+jK6+_Fj<9aOt5ovBGZH*Fw)il;LeJ3AU!hv9yIt4HEk-1lUeP}k<8k*N)95>A z{w}({AO6?&6Y_7)jC7zqEOAPp%BoI*H&Ei^Lp7}&n+~)|5uXHn$PMJ^Kq4nt6s+*) zX8d*|Ft&F_+!u^_UI5Vyvrhsey}hH=(kO*rg5I|gt+o_9Ui|c0(Hu+j?}3Lt1-*W` z8GzS!^uGWVQH}hJ#5AGxN;Ur#v4$tpcdw$Kc{Z3cUdlc2Bj>G@i(xvsO?PuLUc$6U z@~Lz|>1DNO5^)2Udiq=Cz$wng#x&PEs=?OOU)@4s3pGo!o+3}oXZfDzjLnaA0QDb{ s5xv)s{X@uq?-T(3?m2L?kf;U%6o0y#Zh$dX`rZIY$1|sDPX=E53vr<=4FCWD literal 0 HcmV?d00001 From 317ea17cf14d30bc08c3dbb9d2c21e2f744d6856 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 18 Apr 2018 13:54:52 -0500 Subject: [PATCH 137/157] Add a check for whether a page ID was returned when checking WooCommerce compatibility in the private site feature. Props @jorenmartijn Fixes https://github.com/justintadlock/members/issues/182 --- inc/functions-private-site.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/functions-private-site.php b/inc/functions-private-site.php index 6f6e9ad..0ccd178 100644 --- a/inc/functions-private-site.php +++ b/inc/functions-private-site.php @@ -114,7 +114,7 @@ function members_is_private_page() { if ( class_exists( 'WooCommerce' ) ) { $page_id = get_option( 'woocommerce_myaccount_page_id' ); - if ( is_page( $page_id ) ) + if ( $page_id && is_page( $page_id ) ) $is_private = false; } From 15e3cdfc7a6b30bb560ee08dcc08653e6c5cd1a3 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 19 Apr 2018 12:36:36 -0500 Subject: [PATCH 138/157] Update `changelog.md`. --- changelog.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/changelog.md b/changelog.md index 7ade0cf..3bb1dee 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,20 @@ # Change Log +## [2.1.0] - 2018-04-19 + +### Added + +* `user_name` parameter for the `[members_access]` shortcode. +* `user_id` parameter for the `[members_access]` shortcode. +* `user_email` parameter for the `[members_access]` shortcode. +* `icon-members-core-create-caps.png` file for local access to the corresponding add-on thumbnail. + +### Fixed + +* Incorrect roles (or empty roles) appearing on sub-sites when running multisite. +* Invalid icon URL on the Settings > Members > Add-ons admin screen. +* Fix for WooCommerce empty page ID in the private site feature. + ## [2.0.2] - 2017-11-06 ### Fixed From 259f6b56946f555ee6a0176d198a3d9d42e2703b Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 19 Apr 2018 12:55:18 -0500 Subject: [PATCH 139/157] Update copyright dates. --- admin/class-addon.php | 2 +- admin/class-cap-control.php | 2 +- admin/class-cap-section.php | 2 +- admin/class-cap-tabs.php | 2 +- admin/class-manage-roles.php | 2 +- admin/class-manage-users.php | 2 +- admin/class-meta-box-content-permissions.php | 2 +- admin/class-meta-box-custom-cap.php | 2 +- admin/class-meta-box-publish-role.php | 2 +- admin/class-role-edit.php | 2 +- admin/class-role-list-table.php | 2 +- admin/class-role-new.php | 2 +- admin/class-roles.php | 2 +- admin/class-settings.php | 2 +- admin/class-user-edit.php | 2 +- admin/class-user-new.php | 2 +- admin/functions-addons.php | 2 +- admin/functions-admin.php | 2 +- admin/functions-help.php | 2 +- admin/functions-settings.php | 2 +- admin/tmpl/cap-control.php | 2 +- admin/tmpl/cap-section.php | 2 +- admin/views/class-view-addons.php | 2 +- admin/views/class-view-general.php | 2 +- admin/views/class-view.php | 2 +- inc/class-cap-group.php | 2 +- inc/class-capability.php | 2 +- inc/class-registry.php | 2 +- inc/class-role-group.php | 2 +- inc/class-role.php | 2 +- inc/class-widget-login.php | 2 +- inc/class-widget-users.php | 2 +- inc/functions-admin-bar.php | 2 +- inc/functions-cap-groups.php | 2 +- inc/functions-capabilities.php | 2 +- inc/functions-deprecated.php | 2 +- inc/functions-options.php | 2 +- inc/functions-private-site.php | 2 +- inc/functions-role-groups.php | 2 +- inc/functions-roles.php | 2 +- inc/functions-shortcodes.php | 2 +- inc/functions-users.php | 2 +- inc/functions-widgets.php | 2 +- inc/functions.php | 2 +- inc/template.php | 2 +- members.php | 2 +- readme.md | 2 +- 47 files changed, 47 insertions(+), 47 deletions(-) diff --git a/admin/class-addon.php b/admin/class-addon.php index c4f4e2a..5947ef1 100644 --- a/admin/class-addon.php +++ b/admin/class-addon.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-cap-control.php b/admin/class-cap-control.php index 58615d6..27d1ad6 100644 --- a/admin/class-cap-control.php +++ b/admin/class-cap-control.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-cap-section.php b/admin/class-cap-section.php index 12ef8ce..d53354b 100644 --- a/admin/class-cap-section.php +++ b/admin/class-cap-section.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-cap-tabs.php b/admin/class-cap-tabs.php index 3961b42..46ab2d3 100644 --- a/admin/class-cap-tabs.php +++ b/admin/class-cap-tabs.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-manage-roles.php b/admin/class-manage-roles.php index 5a46043..0d6726d 100644 --- a/admin/class-manage-roles.php +++ b/admin/class-manage-roles.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-manage-users.php b/admin/class-manage-users.php index 033dabb..644d697 100644 --- a/admin/class-manage-users.php +++ b/admin/class-manage-users.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-meta-box-content-permissions.php b/admin/class-meta-box-content-permissions.php index f24c428..0cfde3a 100644 --- a/admin/class-meta-box-content-permissions.php +++ b/admin/class-meta-box-content-permissions.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-meta-box-custom-cap.php b/admin/class-meta-box-custom-cap.php index 727378a..c77ec53 100644 --- a/admin/class-meta-box-custom-cap.php +++ b/admin/class-meta-box-custom-cap.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-meta-box-publish-role.php b/admin/class-meta-box-publish-role.php index 080807b..5db555c 100644 --- a/admin/class-meta-box-publish-role.php +++ b/admin/class-meta-box-publish-role.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-role-edit.php b/admin/class-role-edit.php index ab3162d..f555b66 100644 --- a/admin/class-role-edit.php +++ b/admin/class-role-edit.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-role-list-table.php b/admin/class-role-list-table.php index f8dac0d..b64287d 100644 --- a/admin/class-role-list-table.php +++ b/admin/class-role-list-table.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-role-new.php b/admin/class-role-new.php index 355ab33..efa5e99 100644 --- a/admin/class-role-new.php +++ b/admin/class-role-new.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-roles.php b/admin/class-roles.php index 6344b27..6dd8b29 100644 --- a/admin/class-roles.php +++ b/admin/class-roles.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-settings.php b/admin/class-settings.php index fed3133..86bc09c 100644 --- a/admin/class-settings.php +++ b/admin/class-settings.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-user-edit.php b/admin/class-user-edit.php index bf49af7..e35e5d5 100644 --- a/admin/class-user-edit.php +++ b/admin/class-user-edit.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/class-user-new.php b/admin/class-user-new.php index 4934883..0d4270f 100644 --- a/admin/class-user-new.php +++ b/admin/class-user-new.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/functions-addons.php b/admin/functions-addons.php index 111d463..671a24b 100644 --- a/admin/functions-addons.php +++ b/admin/functions-addons.php @@ -6,7 +6,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/functions-admin.php b/admin/functions-admin.php index 297e093..145f4ff 100644 --- a/admin/functions-admin.php +++ b/admin/functions-admin.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/functions-help.php b/admin/functions-help.php index 1af6b66..a439630 100644 --- a/admin/functions-help.php +++ b/admin/functions-help.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/functions-settings.php b/admin/functions-settings.php index 1b800c8..767d06f 100644 --- a/admin/functions-settings.php +++ b/admin/functions-settings.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/tmpl/cap-control.php b/admin/tmpl/cap-control.php index 4bdf729..e401d03 100644 --- a/admin/tmpl/cap-control.php +++ b/admin/tmpl/cap-control.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/tmpl/cap-section.php b/admin/tmpl/cap-section.php index 0fe0a06..63d5ea6 100644 --- a/admin/tmpl/cap-section.php +++ b/admin/tmpl/cap-section.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/views/class-view-addons.php b/admin/views/class-view-addons.php index 936fc1e..c160832 100644 --- a/admin/views/class-view-addons.php +++ b/admin/views/class-view-addons.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/views/class-view-general.php b/admin/views/class-view-general.php index 645e5e3..6eb317f 100644 --- a/admin/views/class-view-general.php +++ b/admin/views/class-view-general.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/admin/views/class-view.php b/admin/views/class-view.php index 5a8c330..a78742b 100644 --- a/admin/views/class-view.php +++ b/admin/views/class-view.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-cap-group.php b/inc/class-cap-group.php index d37e816..e7bfa94 100644 --- a/inc/class-cap-group.php +++ b/inc/class-cap-group.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-capability.php b/inc/class-capability.php index 652606c..0319354 100644 --- a/inc/class-capability.php +++ b/inc/class-capability.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-registry.php b/inc/class-registry.php index c935277..31b9941 100644 --- a/inc/class-registry.php +++ b/inc/class-registry.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-role-group.php b/inc/class-role-group.php index 3adbd97..f46f889 100644 --- a/inc/class-role-group.php +++ b/inc/class-role-group.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-role.php b/inc/class-role.php index 9d50bc8..e1ace22 100644 --- a/inc/class-role.php +++ b/inc/class-role.php @@ -6,7 +6,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-widget-login.php b/inc/class-widget-login.php index dae4d47..30959bb 100644 --- a/inc/class-widget-login.php +++ b/inc/class-widget-login.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/class-widget-users.php b/inc/class-widget-users.php index f83c03b..24f1f28 100644 --- a/inc/class-widget-users.php +++ b/inc/class-widget-users.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-admin-bar.php b/inc/functions-admin-bar.php index 7a4d43c..00db921 100644 --- a/inc/functions-admin-bar.php +++ b/inc/functions-admin-bar.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-cap-groups.php b/inc/functions-cap-groups.php index 6a78e6b..65f4d1d 100644 --- a/inc/functions-cap-groups.php +++ b/inc/functions-cap-groups.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-capabilities.php b/inc/functions-capabilities.php index 0ca1953..2c92f82 100644 --- a/inc/functions-capabilities.php +++ b/inc/functions-capabilities.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-deprecated.php b/inc/functions-deprecated.php index 2741f0f..afaf047 100644 --- a/inc/functions-deprecated.php +++ b/inc/functions-deprecated.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-options.php b/inc/functions-options.php index 1c349d0..4a29086 100644 --- a/inc/functions-options.php +++ b/inc/functions-options.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-private-site.php b/inc/functions-private-site.php index 0ccd178..3380859 100644 --- a/inc/functions-private-site.php +++ b/inc/functions-private-site.php @@ -7,7 +7,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-role-groups.php b/inc/functions-role-groups.php index bc4a022..24c47f7 100644 --- a/inc/functions-role-groups.php +++ b/inc/functions-role-groups.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Admin * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-roles.php b/inc/functions-roles.php index cb2a86f..01a0596 100644 --- a/inc/functions-roles.php +++ b/inc/functions-roles.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-shortcodes.php b/inc/functions-shortcodes.php index dc16b0f..dda5621 100644 --- a/inc/functions-shortcodes.php +++ b/inc/functions-shortcodes.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-users.php b/inc/functions-users.php index 56931b5..4311e9f 100644 --- a/inc/functions-users.php +++ b/inc/functions-users.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions-widgets.php b/inc/functions-widgets.php index 1fd43d4..ca35ae2 100644 --- a/inc/functions-widgets.php +++ b/inc/functions-widgets.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/functions.php b/inc/functions.php index d365143..55b689d 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/inc/template.php b/inc/template.php index 4e688c1..70c6b62 100644 --- a/inc/template.php +++ b/inc/template.php @@ -5,7 +5,7 @@ * @package Members * @subpackage Includes * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/members.php b/members.php index 21dbe75..77ea32b 100644 --- a/members.php +++ b/members.php @@ -27,7 +27,7 @@ * @package Members * @version 2.1.0 * @author Justin Tadlock - * @copyright Copyright (c) 2009 - 2017, Justin Tadlock + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ diff --git a/readme.md b/readme.md index 1a6f51d..50407a7 100644 --- a/readme.md +++ b/readme.md @@ -23,7 +23,7 @@ If you need professional plugin support from me, the plugin author, you can acce This project is licensed under the [GNU GPL](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html), version 2 or later. -2009 – 2017 © [Justin Tadlock](http://justintadlock.com). +2009 – 2018 © [Justin Tadlock](http://justintadlock.com). ## Documentation From 76dd7f819d85d7fa06725e205ee2a0ddc7a4b200 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 19 Apr 2018 13:05:56 -0500 Subject: [PATCH 140/157] Do a soft bump of the PHP requirement to 5.6+. The code still supports 5.3+, but we're prepping for 3.0.0 when we'll have a hard 5.6+ requirement. --- changelog.md | 4 ++++ readme.txt | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 3bb1dee..ab3eb52 100644 --- a/changelog.md +++ b/changelog.md @@ -15,6 +15,10 @@ * Invalid icon URL on the Settings > Members > Add-ons admin screen. * Fix for WooCommerce empty page ID in the private site feature. +### Changed + +* Bumped minimum PHP requirement to 5.6+. However, the code should still work on PHP 5.3. This is in preparation for a hard requirement of 5.6+ when version 3.0.0 is released. + ## [2.0.2] - 2017-11-06 ### Fixed diff --git a/readme.txt b/readme.txt index 1e65903..8cb50e1 100644 --- a/readme.txt +++ b/readme.txt @@ -5,7 +5,7 @@ Donate link: https://themehybrid.com/donate Tags: capabilities, roles, members, users Requires at least: 4.7 Tested up to: 4.8.3 -Requires PHP: 5.3 +Requires PHP: 5.6 Stable tag: 2.0.2 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html From 02e5ede8dd8114bc372a5e47eb6cd44a5a6280b4 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 19 Apr 2018 13:13:45 -0500 Subject: [PATCH 141/157] Update `readme.txt`. --- readme.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/readme.txt b/readme.txt index 8cb50e1..212edff 100644 --- a/readme.txt +++ b/readme.txt @@ -4,9 +4,9 @@ Contributors: greenshady Donate link: https://themehybrid.com/donate Tags: capabilities, roles, members, users Requires at least: 4.7 -Tested up to: 4.8.3 +Tested up to: 4.9 Requires PHP: 5.6 -Stable tag: 2.0.2 +Stable tag: 2.1.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -72,7 +72,9 @@ You can also [view the readme](https://github.com/justintadlock/members/blob/mas ### Minimum PHP requirements. -Since version 2.0.0 of Members, PHP 5.3.0+ is required to use the plugin. The plugin will not allow itself to be activated and will output an error message if an earlier version of PHP is detected. +Since version 2.1.0 of Members, PHP 5.6+ is a soft requirement to use the plugin. The plugin will still work on PHP 5.3+, but it is not recommended. + +When Members version 3.0.0 is released, PHP 5.6+ will be a hard requirement and won't work on older versions of PHP. ### I can't access the "Role Manager" features. From 7c397fd8018e2d11aff04631cf6f4921bb093e97 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 19 Apr 2018 13:16:41 -0500 Subject: [PATCH 142/157] Update `readme.md` to include info on the new `[members_access]` shortcode. --- readme.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/readme.md b/readme.md index 50407a7..6a04598 100644 --- a/readme.md +++ b/readme.md @@ -99,6 +99,14 @@ The `[members_access]` shortcode is for hiding content from particular roles and [members_access role="editor"]Hide this content from everyone but editors.[/members_access] +The plugin accepts the following parameters (mixing and matching won't work): + +* `role` - A single or comma-separated list of roles. +* `capability` - A single or comma-separated list of capabilities. +* `user_name` - A single or comma-separated list of usernames. +* `user_id` - A single or comma-separated list of user IDs. +* `user_email` - A single or comma-separated list of user email addresses. + **Parameters:** * `capability`: A capability that has been assigned to a role. From 8f27987b69c261280fa345898887aa802bcc9607 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 19 Apr 2018 14:09:26 -0500 Subject: [PATCH 143/157] Version bump to 2.1.0. --- members.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/members.php b/members.php index 77ea32b..890a659 100644 --- a/members.php +++ b/members.php @@ -3,7 +3,7 @@ * Plugin Name: Members * Plugin URI: https://themehybrid.com/plugins/members * Description: A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private. - * Version: 2.1.0-dev + * Version: 2.1.0 * Author: Justin Tadlock * Author URI: https://themehybrid.com * Text Domain: members From bfd25e35e01c8d0c74088246926b8f04d31c72b8 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Thu, 18 Jul 2019 20:26:21 -0500 Subject: [PATCH 144/157] Make sure denied caps are always an array. Fixes: https://github.com/justintadlock/members/issues/216 --- inc/functions-users.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/inc/functions-users.php b/inc/functions-users.php index 4311e9f..8a5e1bd 100644 --- a/inc/functions-users.php +++ b/inc/functions-users.php @@ -38,7 +38,7 @@ function members_user_has_cap_filter( $allcaps, $caps, $args, $user ) { return $allcaps; // Get the denied caps. - $denied_caps = array_keys( $allcaps, false ); + $denied_caps = array_keys( (array) $allcaps, false ); // Loop through the user's roles and find any denied caps. foreach ( (array) $user->roles as $role ) { @@ -47,8 +47,12 @@ function members_user_has_cap_filter( $allcaps, $caps, $args, $user ) { $role_obj = get_role( $role ); // If we have an object, merge it's denied caps. - if ( ! is_null( $role_obj ) ) - $denied_caps = array_merge( $denied_caps, array_keys( $role_obj->capabilities, false ) ); + if ( ! is_null( $role_obj ) ) { + $denied_caps = array_merge( + (array) $denied_caps, + array_keys( (array) $role_obj->capabilities, false ) + ); + } } // If there are any denied caps, make sure they take precedence. From 1831b17aef0ef7c8c935fd5b6a099458a72849c0 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 19 Jul 2019 17:47:04 -0500 Subject: [PATCH 145/157] Updates the add-ons admin screen with a new design and pro upgrade section. Adds a donation section for funding 3.0. --- admin/class-settings.php | 1 + admin/config/addons.php | 40 +++++++++ admin/functions-addons.php | 42 +-------- admin/functions-settings.php | 11 +++ admin/views/class-view-addons.php | 123 +++++++++++++------------- admin/views/class-view-donate.php | 75 ++++++++++++++++ css/admin.css | 76 ++++++++++++++++ img/icon-addon.png | Bin 6006 -> 20572 bytes img/icon-members-core-create-caps.png | Bin 2332 -> 0 bytes img/icon-members-role-hierarchy.png | Bin 6006 -> 0 bytes img/icon-members-role-levels.png | Bin 6245 -> 0 bytes img/members-admin-access.svg | 1 + img/members-block-permissions.svg | 1 + img/members-core-create-caps.svg | 1 + img/members-privacy-caps.svg | 1 + img/members-role-hierarchy.svg | 1 + img/members-role-levels.svg | 1 + img/members.svg | 1 + 18 files changed, 273 insertions(+), 102 deletions(-) create mode 100644 admin/config/addons.php create mode 100644 admin/views/class-view-donate.php delete mode 100644 img/icon-members-core-create-caps.png delete mode 100644 img/icon-members-role-hierarchy.png delete mode 100644 img/icon-members-role-levels.png create mode 100644 img/members-admin-access.svg create mode 100644 img/members-block-permissions.svg create mode 100644 img/members-core-create-caps.svg create mode 100644 img/members-privacy-caps.svg create mode 100644 img/members-role-hierarchy.svg create mode 100644 img/members-role-levels.svg create mode 100644 img/members.svg diff --git a/admin/class-settings.php b/admin/class-settings.php index 86bc09c..82838d0 100644 --- a/admin/class-settings.php +++ b/admin/class-settings.php @@ -92,6 +92,7 @@ private function includes() { require_once( members_plugin()->dir . 'admin/views/class-view.php' ); require_once( members_plugin()->dir . 'admin/views/class-view-general.php' ); require_once( members_plugin()->dir . 'admin/views/class-view-addons.php' ); + require_once( members_plugin()->dir . 'admin/views/class-view-donate.php' ); } /** diff --git a/admin/config/addons.php b/admin/config/addons.php new file mode 100644 index 0000000..c5e17cf --- /dev/null +++ b/admin/config/addons.php @@ -0,0 +1,40 @@ + array( + 'url' => 'https://themehybrid.com/plugins/members-privacy-caps', + 'title' => 'Members - Privacy Caps', + 'excerpt' => 'Creates additional capabilities for control over WordPress’ privacy and personal data features (GDPR).' + ), + + 'members-admin-access' => array( + 'url' => 'https://themehybrid.com/plugins/members-admin-access', + 'title' => 'Members - Admin Access', + 'excerpt' => 'Allows site administrators to control which users have access to the WordPress admin via role.', + ), + + 'members-core-create-caps' => array( + 'url' => 'https://themehybrid.com/plugins/members-core-create-caps', + 'title' => 'Members - Core Create Caps', + 'excerpt' => 'Adds the create_posts and create_pages caps to posts/pages to separate them from their edit_* counterparts, providing more flexible editing capabilities.' + ), + + 'members-role-levels' => array( + 'url' => 'https://themehybrid.com/plugins/members-role-levels', + 'title' => 'Members - Role Levels', + 'excerpt' => 'Exposes the old user levels system, which fixes the WordPress author drop-down bug when users don’t have a role with one of the assigned levels.' + ), + + 'members-role-hierarchy' => array( + 'url' => 'https://themehybrid.com/plugins/members-role-hierarchy', + 'title' => 'Members - Role Hierarchy', + 'excerpt' => 'Add-on plugin for Members, which creates a hierarchical roles system.' + ), + + 'members-block-permissions' => array( + 'url' => '', + 'title' => 'Members - Block Permissions', + 'excerpt' => '

    COMING SOON!

    Hide or show blocks in the WordPress block editor (Gutenberg).

    ' + ) +); diff --git a/admin/functions-addons.php b/admin/functions-addons.php index 671a24b..abe35e0 100644 --- a/admin/functions-addons.php +++ b/admin/functions-addons.php @@ -24,49 +24,13 @@ */ function members_register_default_addons() { - // Get the transient where the Members addons are stored on-site. - $data = get_transient( 'members_addons' ); - - if ( ! $data || ! is_array( $data ) ) { - - // `localhost` is the sandbox URL. - // $url = 'http://localhost/api/th/v1/plugins?addons=members'; - $url = 'https://themehybrid.com/api/th/v1/plugins?addons=members'; - - // Get data from the remote URL. - $response = wp_remote_get( $url ); - - // Bail if we get no response. - if ( is_wp_error( $response ) ) - return; - - // Decode the data that we got. - $data = json_decode( wp_remote_retrieve_body( $response ) ); - } + $data = include members_plugin()->dir . 'admin/config/addons.php'; // If we have an array of data, let's roll. if ( ! empty( $data ) && is_array( $data ) ) { - // Set the transient with the new data. - set_transient( 'members_addons', $data, 7 * DAY_IN_SECONDS ); - - foreach ( $data as $addon ) { - - $args = array( - 'title' => $addon->title, - 'excerpt' => $addon->excerpt, - 'url' => $addon->url, - 'purchase_url' => $addon->meta->purchase_url, - 'download_url' => $addon->meta->download_url, - 'rating' => $addon->meta->rating, - 'rating_count' => $addon->meta->rating_count, - 'install_count' => $addon->meta->install_count, - 'icon_url' => $addon->media->icon->url, - 'author_url' => $addon->author->url, - 'author_name' => $addon->author->name - ); - - members_register_addon( $addon->slug, $args ); + foreach ( $data as $addon => $options ) { + members_register_addon( $addon, $options ); } } } diff --git a/admin/functions-settings.php b/admin/functions-settings.php index 767d06f..de2583f 100644 --- a/admin/functions-settings.php +++ b/admin/functions-settings.php @@ -48,6 +48,17 @@ function members_register_default_settings_views( $manager ) { ) ) ); + + // Register add-ons view. + $manager->register_view( + new \Members\Admin\View_Donate( + 'donate', + array( + 'label' => esc_html__( 'Help Fund Version 3.0', 'members' ), + 'priority' => 100 + ) + ) + ); } /** diff --git a/admin/views/class-view-addons.php b/admin/views/class-view-addons.php index c160832..dd6ca11 100644 --- a/admin/views/class-view-addons.php +++ b/admin/views/class-view-addons.php @@ -20,6 +20,17 @@ */ class View_Addons extends View { + /** + * Enqueues scripts/styles. + * + * @since 2.2.0 + * @access public + * @return void + */ + public function enqueue() { + wp_enqueue_style( 'members-admin', members_plugin()->uri . 'css/admin.css' ); + } + /** * Renders the settings page. * @@ -36,6 +47,41 @@ public function template() { $addons = members_get_addons(); ?> +
    + +
    + +
    + +
    + + +
    +

    + +

    +

    + +

    +

    + +

    +

    + +

    +
    +
    + +
    + +
    + +
    +
    @@ -74,85 +120,36 @@ public function addon_card( $addon ) { ?> - -

    hEHbW>lYFP_EKRU|gs=o|`IK9F(gtvEhwiKsz zF(@0tSl5P=eXhMkfUt3;HK9e%o|#9Ubnlqt0c!&q+O@mE??&P|8fQDUmdO53xQoa4{Z zxAXRMEU9d+Ig=QbrOK2fZ<5kyR>HjV2~nQf&XcCtclBakXMD2F#E3dHnOah-JMsgO zs?~qVVe_$_%a9D?4+feAM+u|3`a#!|t+a#EVAguSwl<$Z{*-zuvD1S#`2wK0sMWAN zUSeoU%{vi>h%(MRUl`IpxJP)3#-1iU+4$|lVZdd^(~*)L-z^`~mELXWsxSWGAhr_u zT$5ilqL!(0B-&#Z?aYV_^EcA1_unAZL_W-QJ1^<9?O zDMw9+KvOM7IX#+jKz~OXOqg2c+>?lRV@OAJlvQRWN4ZYe+&pc4)7ZOv{>`OOYlG$Y zII4XPdebPav|hAq`Nwx?iQw8DZ9tEgM)pp+1zS9uodk(Npn{6U#8F63wkSQ#Z>aBS z{dn2EV%%SPau!1S-i&&$T6(Qp4Ju9z1&_y8;p~&!2BNcf8&9>saYld^N(33d%&7Za z+-)3ryu$D8h_0eSi=w6?il`F27>mD7mG$4!66t*=qYsq*L3!}0ZLE~i;QbsYNRJSAFV`8r_MU=1SrB&OGQ8dXqU;)3cy?;xBDpgOvK!yh0s++aa(fYdaF@eUw`86n ztqy{d$$Lt<=hnm(5f@Z>l*wHl4702>B(_>3-_7hs+QS-gZq20m|DBhgr=sVQZ_Op# zkL3HYtWL{eM@TI!2I-GI zh7X6`DVzaqf^Ru3?^5B??iwOm|Jw(%W7?7r&=AL~O)QMf zRDYdRZM%`{=mRgdeU3iUJoqgm3H(;Si*8XvS#IKL^mm~I68Ct-t-sdv#)>-%Z_Z+w z;byS$!t|vxKP22>#ouExZZNvwb=R~TSoKMHY#7h#D1C!09q-_?=o8RI);Vt-Tg5nj z1eql4N^8|Aa~_cu-@^Z>L|o@+tmO~v4!At_fx)bN+DKnCGs&;Y+^l3CGTF*J*U1lt zQbzcX`-d8_pr7jd7Qa#IT8Il+2(O!GidJYbeY$mNLE_}xw#;~(b)81ahr)(~)&IP<2;P+Cgox1+ zhNPqr5W|#{%>dyO^UZ=mk{jY*odAmm8@5+VKf$FXRLZ55;cpj4@1`;3>n)jkd1)LD zK1MAI@k2~mDTpcwPNYxDe8gx_vG+?w3XhGc79ff!EGlYcCAxIpLye}{z3dc?5 z`^XM(C&~}+h>0p#h_e8GX%O|&no}3^WmaJ)%juSTC)H0QuqIpD^UjpKuXt702I#XV z35Q$xC=saxF&r~Gqe9;m(@7J4`Jn(%gseVa?c9w7s@-W`8}BiArx7Ag96DTa5i<>T z$!IyG^Z5Ey20A!NMG-+wuBrTF^$IT2?g#1of`k3l1>cgsa7Y-xE^Vpm8J&*Sm zqChD^Asv=?kS|L%b|}_AK01A{c9mT6d7EBI${*YJxoua1royh(@ z>z@?$zh?yub$^t)HOCS+`=roEq#tNs@Bf1+!FogfC@UV2s2IeyyDB^$7&M4&B^L5> z&C0b}x+7obiTKLZUSR*~%ZKqzBK+(~P97d^0s}trb09Gc+>MCRIkaA@EfQKK#c<;X znyZ0)wLlk(qlpwqHwxfTq9N9Dt-bs@9(7HQ7w8g9{bciHv>?zPZ(VV#{?j9DGXiez zsn}+Zgq_ErAa{AsRgB3c=uWZ3S>KxR6=x1xBW=Y(4qMh|TCKXMc@qY^wV#40;b_y1FvEpwyW=x{vg}(s#e=d((@Tu}*2^d+bQwp?SZGL2H-@7~iDP3%Udlupc<1+fyP!yQNw) ziU&a9v38HV&q8t)-cmUpDh98jl+uIIV9?vr`X_}`r>hh3TL?rbjt(1-2 z!P4t_QOfE143uQP*1epbtMF*QQ$e?dZ>ablZ>`iyE^7hF^U2T_bm@T}l+ z22=%kxEFn#rkZlf24UjeZqU@R$LuTOss+Dl+{ufsPAPkhD=4T2DwVIYEOoY=4>t~Q#XH{s&nMm8}} z2u`*9hVPLL0m|nm&MesNI>#qwgFH=@QI?)2AH37w#BNZS+Z>Eflg@qFAM7NtM;tOd zCt!jB3XTvaKrb2Q7=5spN6x?Uj)OQukcgxw7Dj%_dM#ts2+Z0f9`@ETTF}u&2 z#D?@;EHd)Sg@cSI{w814<;R=;Lkvaw0|WOMF_yFf!$OE@bM!vpCS1zF3%stTO?LEa zJ&67kD-)L0?XM!bn5(+vwf-Vg? z)1LV_0BPv%DO&N=7WaKaA0T}UF5f;W$mK6HkYh2mtPJeCcbm@-xqN}ik>(7!_(d1$ z`VfJ=Z9|9KC9J*{yTy({X2dyooZNV3lhrAtqh*^ukpD1|Fb->DS83kQJNPBOiq6q{tTjzRrDBp6T zr1>3)G2xrZ@&=h^1DWW{$04hjVwn2hW;&diJ8$}?Y3=)TP1ue91duf`h`3Iml9G~& zipq_js;d+pc3$4zZmzBgx6Ep++G9hY5I!3Eqm`OKhyC`4fB!|}53co(1OE2qKg{}r z1OCC|f6w}TfC#|${{7UK-S^TRy$4Tuw$k2K z*0(7d(eqm0yb6yiD2z6k&Fyk9+k3LWpos#d7!9U0uHxQ(uRCWC$px)t~R*!OuS=tn@A81?+W6Be0fD0x2mm9jiy_C(fQ95b^ zmXoBLs#9s`drhin0$x<-&UZO7)q~b<^dz#`t951mh+=zf=EZQx;JB|7IeIA+ z*eQ!U>*s<=D+cVHEkkahvR9z)F*ANXf0Yd2Wo6wSY}&B6yNY`8ent-^UGK{eHdG0zNRG8@*w>BQjuUxLyU0Yh)7l;&$YJ>WmIHT!LZ01~Vy zQIaSz!z!NhGuv{Kr0T(hE_OF1v$3I_WoWVrN35*xGSF5U5=`X_VD~H*H%kQLcTUrR z*7R0uCr7d2(3n<|zX$o9-~8LxpG7o32g;5DnO-#;myhK6GR-1}rQzk6531y@9OyO_ z)9b73Y41$kn|b;{a4jzR`L2S$)UY#g)Y7wmGc;9%R?6zski01OJaCNtp!A~KPa!b! zKxXEgHLm@rWL3q--J75+A5z?Gd=M=K_G8J)Yhj_6C+J{f&UKRJ_dOj$A^~#bZe9c@ ztDv6SGSV8q&KAZB{v4}pR}~;f&$CZp@MF;We}|ui8`Y@nsVO|fck_EMzD11nnj@VJ zmg^lVFDthQ`-GIV*mf5f6@L2V=osBdtJ@CEIyy&>nqW*y3tT<^#XYnHCy9X(_jg&n zP4O2(DAuQ1A}sv&p4!^BwY8nj`Q@oVtv|g;{kp}v{eMS;e~MZDujl_RXz%a@fWo-4 VUSU-*8>>(D9CtrOpSym}4t*(`*-~GF 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 z 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 From e00ba78fa439f3c5af80058ce1d216d770dcd754 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Wed, 12 Jul 2017 13:17:28 -0500 Subject: [PATCH 074/157] Remove most of the `_dir` and `_uri` paths. We're going with a simpler `Members_Plugin::dir` and `Members_Plugin::uri` to handle all includes. --- admin/class-roles.php | 2 +- admin/class-settings.php | 8 +- admin/functions-admin.php | 10 +-- admin/views/class-view-addons.php | 8 +- inc/functions-widgets.php | 4 +- members.php | 138 +++++++++--------------------- 6 files changed, 58 insertions(+), 112 deletions(-) diff --git a/admin/class-roles.php b/admin/class-roles.php index e761824..eec32f3 100644 --- a/admin/class-roles.php +++ b/admin/class-roles.php @@ -162,7 +162,7 @@ public function enqueue() { */ public function page() { - require_once( members_plugin()->admin_dir . 'class-role-list-table.php' ); ?> + require_once( members_plugin()->dir . 'admin/class-role-list-table.php' ); ?>

    -
    - - excerpt ) ); ?> - -

    - %s', esc_url( $addon->author_url ), esc_html( $addon->author_name ) ); ?> - - -

    - +
    + excerpt ) ); ?>
    - rating && $addon->rating_count ) || $addon->install_count ) : ?> - -
    - - rating && $addon->rating_count ) : ?> - -
    - 'rating', 'rating' => floatval( $addon->rating ), 'number' => absint( $addon->rating_count ) ) ); ?> - -
    - - - - install_count ) : ?> - -
    - install_count ) ) - ); ?> -
    - - - -
    - - - + * @copyright Copyright (c) 2009 - 2018, Justin Tadlock + * @link https://themehybrid.com/plugins/members + * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + */ + +namespace Members\Admin; + +/** + * Sets up and handles the donate settings view. + * + * @since 2.2.0 + * @access public + */ +class View_Donate extends View { + + /** + * Enqueues scripts/styles. + * + * @since 2.2.0 + * @access public + * @return void + */ + public function enqueue() { + wp_enqueue_style( 'members-admin', members_plugin()->uri . 'css/admin.css' ); + } + + /** + * Renders the settings page. + * + * @since 2.2.0 + * @access public + * @return void + */ + public function template() { ?> + +
    + +
    + +
    + +

    + +

    + +

    + +

    + +

    + +

    + +

    + +

    +

    + +

    + +
    + +
    + +
    + + ?n;cml*ySuyV(7*eVp9Gqarq5}f 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 diff --git a/img/icon-members-core-create-caps.png b/img/icon-members-core-create-caps.png deleted file mode 100644 index 8ac82856592fce8c2d3980057591c27c9c52ed93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2332 zcma);dpy&N8^^yJO3cxPv^blN7fvq6HBPxr!kPTaPmW9EK9n){h-|7OS{T2ROG=7S zDRaqf2+6G)k&xT4Y}075nT=h}et-9Ropb(rKF{m*{PlS~&-?RayPa`XQaG#t0Duzm zw^Qx_0Fp`&AP<(74}0xQq(wH|{y+8rKpM1^yR{sK-Y}8CVto10WoL05pNUfIRSbt%?(=y1X?bzxq_Mp`w+oe=^aURCf4J>njf;mu1c;pm~7A` zem+!kSKHkD6%9Ky+K$6jC@&9Q=#T2Kur^KB>}}7ny6wwg$S+Kba_;Q*ot#!Livg)b z%nn4AlXTfs)r(DMCTP6R0(`{6#>U;_1pv<(vb9n_{V7aqW=-TQ;+G6$&|$bEOAGvtl|&Y&9FcrJvb+^6FA3^|Owst3-3XjrIr`%_#s@RUn& z%Bc+8D)Zay*pI9bP}+8t`9#qZG@ojvb!z~wEo^N?#|m{A;I&`+MN}~tMXr!gF4zl? zJouLR0(e@J*dUH#CFD=G!`th<5x%2SL9}_=$w%Z@BA~VE+4`k4rv2 z+3%Vve&9{XgYX6l5I{#bcfk4~H-33|`1z8Ow~R*uw<}t+$^l${t0F)K{CJx=i38Hj ztP&qJ3=HbeNVU31)$YW+z%2vN+n#PYGhw5QeDL)M?(DcgBb)J%CiJT2EyqWJr&|7C z2fVaJ&3f_nJlR$cs$Zj$l;+=TPq6eQ9W}>K%u**Cjqn?MqS=7~y|_oGh%!vSo`*rG$Cw25$c}bnudWGSne(EsM%}KeRwi*Uu=;Q`q?4G?s={!|OFz(fT71j=K9uDSW zU$yb;E3$mic_C+yr6g2FPL}aGCF_bsg|cqv=LBw;+jDqJcAwo=x|jOQ$iZk*-`cXa z_m>p*UOm%&Pa^;m(%??(<|^j6D=W9s-C*0R_*)-ex! ze}`7@$CfPRw3}cDL%3ZfJ%60`3b{#O8N}-Jj35*P)#}&YvDeC`{QKXthu0K5qAm_Wx*_}jy+$k8jIIj_3;AhznpI=Msim|DN zdaZ(7(sBbg!Td*sADC2Xo~L6n)zEKb<&9l4~^;Q!t0$wU#)us8oS33qOmUJ}4q#90IUQy)B z>*nRkYyM8F@PP@ll_Ww+d!M96Y9HmAEI}mHb;9mfgXU$sH9I>FMDCU&&|#YGy^{MM z3eE|78JN(v>buYK@`c?LD72+T;banLo^71>Lm&^{=1O-}+ zZ9i7L$UOU1KQmaHu$bBlwJiZN3m}%~v(uNEOCu#~O+OT|D$8AD35$`15rA}a8pt(t zW*wkM-u*M*Dga(4Cn#IEwTrMQuzRcAJa!c}4KZ|BjI$RiG_wQ<_G zG#l5HgY_GljVMHkt%eq$KALCu*m&Fscf+&$dM0{IKN+- }P)fu&fG$MlEsdB91E zJ24~seleie`NJ?Xrz0u5&;k6I;Cd!>S`b#fe+?9nY0Q&Tx`aULGus6=30f)2xlt>mZVz z(HDJg~zN%^j} zI4MF`$Fu!z+QOT1ieXk8w52#bDzS)nSTj>>8GhFZJ8H^rPCQ}Z3Lf-&H|VR&+T~}` zmw7aMm%CD6gGsQHzfi;(b#MR=qCQ&fEbq}W$SAsa$rWfbNDFy%@rEjOIAdkH4lqq> z{$$+jK6+_Fj<9aOt5ovBGZH*Fw)il;LeJ3AU!hv9yIt4HEk-1lUeP}k<8k*N)95>A z{w}({AO6?&6Y_7)jC7zqEOAPp%BoI*H&Ei^Lp7}&n+~)|5uXHn$PMJ^Kq4nt6s+*) zX8d*|Ft&F_+!u^_UI5Vyvrhsey}hH=(kO*rg5I|gt+o_9Ui|c0(Hu+j?}3Lt1-*W` z8GzS!^uGWVQH}hJ#5AGxN;Ur#v4$tpcdw$Kc{Z3cUdlc2Bj>G@i(xvsO?PuLUc$6U z@~Lz|>1DNO5^)2Udiq=Cz$wng#x&PEs=?OOU)@4s3pGo!o+3}oXZfDzjLnaA0QDb{ s5xv)s{X@uq?-T(3?m2L?kf;U%6o0y#Zh$dX`rZIY$1|sDPX=E53vr<=4FCWD diff --git a/img/icon-members-role-hierarchy.png b/img/icon-members-role-hierarchy.png deleted file mode 100644 index 3b31c16b9e66501383807b89c48f503e0e176e56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6006 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 diff --git a/img/icon-members-role-levels.png b/img/icon-members-role-levels.png deleted file mode 100644 index 47b6897ef199dbd24def4ffb4fda5f80ac4b5bb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6245 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 \ No newline at end of file diff --git a/img/members-block-permissions.svg b/img/members-block-permissions.svg new file mode 100644 index 0000000..78b27d8 --- /dev/null +++ b/img/members-block-permissions.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/members-core-create-caps.svg b/img/members-core-create-caps.svg new file mode 100644 index 0000000..cb4dc56 --- /dev/null +++ b/img/members-core-create-caps.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/members-privacy-caps.svg b/img/members-privacy-caps.svg new file mode 100644 index 0000000..905d0fe --- /dev/null +++ b/img/members-privacy-caps.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/members-role-hierarchy.svg b/img/members-role-hierarchy.svg new file mode 100644 index 0000000..845df8f --- /dev/null +++ b/img/members-role-hierarchy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/members-role-levels.svg b/img/members-role-levels.svg new file mode 100644 index 0000000..1245a44 --- /dev/null +++ b/img/members-role-levels.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/members.svg b/img/members.svg new file mode 100644 index 0000000..99981d3 --- /dev/null +++ b/img/members.svg @@ -0,0 +1 @@ + \ No newline at end of file From d75a440ecfd2f376ab92a8e774416923dbc2816f Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 19 Jul 2019 18:16:25 -0500 Subject: [PATCH 146/157] Link to users list for a specific role when editing that role. Also links the user count on the role list table. Fixes: https://github.com/justintadlock/members/issues/197 --- admin/class-meta-box-publish-role.php | 15 +++++++++++++-- admin/class-role-list-table.php | 16 +++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/admin/class-meta-box-publish-role.php b/admin/class-meta-box-publish-role.php index 5db555c..e3aff98 100644 --- a/admin/class-meta-box-publish-role.php +++ b/admin/class-meta-box-publish-role.php @@ -97,8 +97,19 @@ public function meta_box( $role ) {
    - - + + + + + + + +
    diff --git a/admin/class-role-list-table.php b/admin/class-role-list-table.php index b64287d..225f991 100644 --- a/admin/class-role-list-table.php +++ b/admin/class-role-list-table.php @@ -278,7 +278,21 @@ protected function column_role( $role ) { * @return string */ protected function column_users( $role ) { - return apply_filters( 'members_manage_roles_column_users', members_get_role_user_count( $role ), $role ); + + $user_count = members_get_role_user_count( $role ); + + $output = number_format_i18n( $user_count ); + + if ( 0 < absint( $user_count ) && current_user_can( 'list_users' ) ) { + + $output = sprintf( + '%s', + esc_url( add_query_arg( 'role', $role, admin_url( 'users.php' ) ) ), + $output + ); + } + + return apply_filters( 'members_manage_roles_column_users', $output, $role ); } /** From 78abc37f3fdfe417bd135ff877200c7e27f03e22 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 19 Jul 2019 18:17:36 -0500 Subject: [PATCH 147/157] Version bump to 2.2.0-alpha. --- members.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/members.php b/members.php index 890a659..0e80b42 100644 --- a/members.php +++ b/members.php @@ -3,7 +3,7 @@ * Plugin Name: Members * Plugin URI: https://themehybrid.com/plugins/members * Description: A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private. - * Version: 2.1.0 + * Version: 2.2.0-alpha * Author: Justin Tadlock * Author URI: https://themehybrid.com * Text Domain: members From 2cf49f373cc4c6362c4b927423e4423f7cde785d Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 19 Jul 2019 18:28:31 -0500 Subject: [PATCH 148/157] Make sure we have a valid post object when checking if a user can view a post. Fixes: https://github.com/justintadlock/members/issues/183 --- inc/template.php | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/inc/template.php b/inc/template.php index 70c6b62..29df3fe 100644 --- a/inc/template.php +++ b/inc/template.php @@ -29,8 +29,12 @@ function members_can_user_view_post( $user_id, $post_id = '' ) { // If no post ID is given, assume we're in The Loop and get the current post's ID. - if ( ! $post_id ) + if ( ! $post_id ) { $post_id = get_the_ID(); + } + + // Get post object. + $post = get_post( $post_id ); // Assume the user can view the post at this point. */ $can_view = true; @@ -38,7 +42,7 @@ function members_can_user_view_post( $user_id, $post_id = '' ) { // The plugin is only going to handle permissions if the 'content permissions' feature // is active. If not active, the user can always view the post. However, developers // can roll their own handling of this and filter `members_can_user_view_post`. - if ( members_content_permissions_enabled() ) { + if ( $post instanceof \WP_Post && members_content_permissions_enabled() ) { // Get the roles selected by the user. $roles = members_get_post_roles( $post_id ); @@ -55,9 +59,6 @@ function members_can_user_view_post( $user_id, $post_id = '' ) { // to disprove this. $can_view = false; - // Get the post object. - $post = get_post( $post_id ); - // Get the post type object. $post_type = get_post_type_object( $post->post_type ); @@ -92,11 +93,15 @@ function members_can_user_view_post( $user_id, $post_id = '' ) { // Set to `FALSE` to avoid hierarchical checking. if ( apply_filters( 'members_check_parent_post_permission', $check_parent, $post_id, $user_id ) ) { - $parent_id = get_post( $post_id )->post_parent; + if ( $post instanceof \WP_Post ) { - // If the post has a parent, check if the user has permission to view it. - if ( 0 < $parent_id ) - $can_view = members_can_user_view_post( $user_id, $parent_id ); + $parent_id = $post->post_parent; + + // If the post has a parent, check if the user has permission to view it. + if ( 0 < $parent_id ) { + $can_view = members_can_user_view_post( $user_id, $parent_id ); + } + } } // Allow developers to overwrite the final return value. From b4c39b2e6d39755b923fe750080f1fbdbea6243c Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 19 Jul 2019 19:57:25 -0500 Subject: [PATCH 149/157] Typo fix. Fixes: https://github.com/justintadlock/members/pull/192 Props: @burhandodhy --- readme.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.txt b/readme.txt index 212edff..2cd2451 100644 --- a/readme.txt +++ b/readme.txt @@ -30,7 +30,7 @@ It puts you in control over permissions on your site by providing a user interfa * **Private Site:** You can make your site and its feed completely private if you want. * **Plugin Integration:** Members is highly recommended by other WordPress developers. Many existing plugins integrate their custom roles and caps directly into it. -For more info, vist the [Members plugin home page](https://themehybrid.com/plugins/members). +For more info, visit the [Members plugin home page](https://themehybrid.com/plugins/members). ### Like this plugin? @@ -108,4 +108,4 @@ If upgrading from a version prior to 2.0.0, please note that the plugin now requ == Changelog == -The change log is located in the `changelog.md` file in the plugin folder. You may also [view the change log](https://github.com/justintadlock/members/blob/master/changelog.md) online. \ No newline at end of file +The change log is located in the `changelog.md` file in the plugin folder. You may also [view the change log](https://github.com/justintadlock/members/blob/master/changelog.md) online. From 9f048c44e1bf7657c3ddf5bcaedce3253ec23451 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 19 Jul 2019 20:00:46 -0500 Subject: [PATCH 150/157] Update change log. --- changelog.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/changelog.md b/changelog.md index ab3eb52..d0d93af 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,23 @@ # Change Log +## [2.2.0] - 2019-07-19 + +### Added + +- Settings page sub-view for donations. + +### Fixed + +- Makes sure that we have a post object when determining whether a user can view a given post. +- Makes sure that denied capabilities are an array when filtering `user_has_cap`. +- Typo in `readme.txt`. + +### Changed + +- Links user count on edit role screen to users by role page. +- Links user count on manage roles screen to users by role page. +- Updated the add-ons sub-view with design changes and a "pro" section. + ## [2.1.0] - 2018-04-19 ### Added From 740c3602fead711a412ffed9037b2e7b526b8811 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Fri, 19 Jul 2019 20:12:24 -0500 Subject: [PATCH 151/157] Update POT file. --- lang/members.pot | 171 ++++++++++++++++++++++++++++------------------- 1 file changed, 104 insertions(+), 67 deletions(-) diff --git a/lang/members.pot b/lang/members.pot index 3420939..d6fb307 100644 --- a/lang/members.pot +++ b/lang/members.pot @@ -1,14 +1,14 @@ -# Copyright (C) 2017 Members +# Copyright (C) 2019 Members # This file is distributed under the same license as the Members package. msgid "" msgstr "" -"Project-Id-Version: Members 2.0.0-dev\n" +"Project-Id-Version: Members 2.2.0-alpha\n" "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/members\n" -"POT-Creation-Date: 2017-07-18 22:34:50+00:00\n" +"POT-Creation-Date: 2019-07-20 01:10:06+00:00\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2017-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: 2019-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -75,7 +75,7 @@ msgstr "" msgid "Deny" msgstr "" -#: _assets/class-cap-list-table.php:377 admin/class-role-list-table.php:337 +#: _assets/class-cap-list-table.php:377 admin/class-role-list-table.php:355 #: admin/class-role-new.php:335 admin/functions-admin.php:46 msgid "Edit" msgstr "" @@ -83,17 +83,17 @@ msgstr "" #: _assets/class-cap-list-table.php:381 _assets/class-cap-list-table.php:520 #: _assets/class-capability-list-table.php:264 #: _assets/class-capability-list-table.php:387 -#: admin/class-role-list-table.php:341 admin/class-role-list-table.php:490 +#: admin/class-role-list-table.php:359 admin/class-role-list-table.php:508 msgid "Delete" msgstr "" -#: _assets/class-cap-list-table.php:387 admin/class-role-list-table.php:347 +#: _assets/class-cap-list-table.php:387 admin/class-role-list-table.php:365 msgid "View" msgstr "" #: _assets/class-cap-list-table.php:452 #: _assets/class-capability-list-table.php:319 -#: admin/class-role-list-table.php:400 +#: admin/class-role-list-table.php:418 msgid "All %s" msgid_plural "All %s" msgstr[0] "" @@ -101,7 +101,7 @@ msgstr[1] "" #: _assets/class-cap-list-table.php:464 #: _assets/class-capability-list-table.php:320 -#: admin/class-role-list-table.php:405 +#: admin/class-role-list-table.php:423 msgid "Mine %s" msgid_plural "Mine %s" msgstr[0] "" @@ -192,7 +192,7 @@ msgid "Capabilities" msgstr "" #: _assets/class-caps.php:212 admin/class-roles.php:210 -#: admin/functions-help.php:46 admin/views/class-view-addons.php:176 +#: admin/functions-help.php:46 admin/views/class-view-addons.php:173 msgid "Overview" msgstr "" @@ -329,7 +329,7 @@ msgid "None" msgstr "" #: admin/class-meta-box-content-permissions.php:115 -#: admin/views/class-view-general.php:63 admin/views/class-view-general.php:362 +#: admin/views/class-view-general.php:63 admin/views/class-view-general.php:363 msgid "Content Permissions" msgstr "" @@ -355,28 +355,34 @@ msgctxt "capability" msgid "Add New" msgstr "" -#: admin/class-meta-box-publish-role.php:100 +#: admin/class-meta-box-publish-role.php:104 +msgid "%s User" +msgid_plural "%s Users" +msgstr[0] "" +msgstr[1] "" + +#: admin/class-meta-box-publish-role.php:110 msgid "Users:" msgstr "" -#: admin/class-meta-box-publish-role.php:106 +#: admin/class-meta-box-publish-role.php:117 msgid "Granted:" msgstr "" -#: admin/class-meta-box-publish-role.php:112 +#: admin/class-meta-box-publish-role.php:123 msgid "Denied:" msgstr "" -#: admin/class-meta-box-publish-role.php:123 +#: admin/class-meta-box-publish-role.php:134 msgctxt "delete role" msgid "Delete" msgstr "" -#: admin/class-meta-box-publish-role.php:130 +#: admin/class-meta-box-publish-role.php:141 msgid "Update" msgstr "" -#: admin/class-meta-box-publish-role.php:130 +#: admin/class-meta-box-publish-role.php:141 msgid "Add Role" msgstr "" @@ -423,38 +429,38 @@ msgstr "" msgid "Your Role" msgstr "" -#: admin/class-role-list-table.php:352 +#: admin/class-role-list-table.php:370 msgid "Clone" msgstr "" -#: admin/class-role-list-table.php:356 +#: admin/class-role-list-table.php:374 msgid "Change Default" msgstr "" -#: admin/class-role-list-table.php:360 admin/class-roles.php:69 +#: admin/class-role-list-table.php:378 admin/class-roles.php:69 #: inc/class-widget-users.php:59 inc/functions-cap-groups.php:121 msgid "Users" msgstr "" -#: admin/class-role-list-table.php:410 +#: admin/class-role-list-table.php:428 msgid "Has Users %s" msgid_plural "Has Users %s" msgstr[0] "" msgstr[1] "" -#: admin/class-role-list-table.php:415 +#: admin/class-role-list-table.php:433 msgid "No Users %s" msgid_plural "No Users %s" msgstr[0] "" msgstr[1] "" -#: admin/class-role-list-table.php:420 +#: admin/class-role-list-table.php:438 msgid "Editable %s" msgid_plural "Editable %s" msgstr[0] "" msgstr[1] "" -#: admin/class-role-list-table.php:425 +#: admin/class-role-list-table.php:443 msgid "Uneditable %s" msgid_plural "Uneditable %s" msgstr[0] "" @@ -540,13 +546,13 @@ msgstr "" msgid "You can permanently delete multiple roles at once. Select the roles you want to act on using the checkboxes, then select the action you want to take from the Bulk Actions menu and click Apply." msgstr "" -#: admin/class-settings.php:174 admin/class-settings.php:175 -#: admin/class-settings.php:275 +#: admin/class-settings.php:175 admin/class-settings.php:176 +#: admin/class-settings.php:276 msgctxt "admin screen" msgid "Members" msgstr "" -#: admin/class-user-edit.php:97 admin/class-user-new.php:106 +#: admin/class-user-edit.php:97 admin/class-user-new.php:109 msgid "User Roles" msgstr "" @@ -622,44 +628,75 @@ msgstr "" msgid "Add-Ons" msgstr "" -#: admin/views/class-view-addons.php:53 -msgid "There are currently no add-ons to show. Please try again later." +#: admin/functions-settings.php:57 +msgid "Help Fund Version 3.0" msgstr "" -#: admin/views/class-view-addons.php:99 admin/views/class-view-addons.php:194 -msgid "Purchase" +#: admin/views/class-view-addons.php:65 +msgid "Go Pro With Members Add-ons" msgstr "" -#: admin/views/class-view-addons.php:103 admin/views/class-view-addons.php:107 -#: admin/views/class-view-addons.php:185 -msgid "Download" +#: admin/views/class-view-addons.php:68 +msgid "Take your membership site to the next level with add-ons. Pro users also enjoy live chat support and support forum access." +msgstr "" + +#: admin/views/class-view-addons.php:71 +msgid "Upgrade To Pro" msgstr "" -#: admin/views/class-view-addons.php:121 -msgid "By %s" +#: admin/views/class-view-addons.php:74 +msgid "Purchase Support-Only Membership" msgstr "" -#: admin/views/class-view-addons.php:145 -msgid "%s+ Active Installs" +#: admin/views/class-view-addons.php:99 +msgid "There are currently no add-ons to show. Please try again later." +msgstr "" + +#: admin/views/class-view-addons.php:182 +msgid "Download" msgstr "" -#: admin/views/class-view-addons.php:213 +#: admin/views/class-view-addons.php:191 +msgid "Purchase" +msgstr "" + +#: admin/views/class-view-addons.php:210 msgid "The Add-Ons screen allows you to view available add-ons for the Members plugin. You can download some plugins directly. Others may be available to purchase." msgstr "" -#: admin/views/class-view-addons.php:227 +#: admin/views/class-view-addons.php:224 msgid "Some plugins may be available for direct download. In such cases, you can click the download button to get a ZIP file of the plugin." msgstr "" -#: admin/views/class-view-addons.php:241 +#: admin/views/class-view-addons.php:238 msgid "Some add-ons may require purchase before downloading them. Clicking the purchase button will take you off-site to view the add-on in more detail." msgstr "" -#: admin/views/class-view-general.php:64 admin/views/class-view-general.php:371 +#: admin/views/class-view-donate.php:50 +msgid "Donate Toward Future Development" +msgstr "" + +#: admin/views/class-view-donate.php:54 +msgid "The Members plugin needs funding to cover development costs toward version 3.0." +msgstr "" + +#: admin/views/class-view-donate.php:58 +msgid "Members itself will always remain free as long as I'm able to work on it. However, it is easily my largest and most complex plugin. A major update takes 100s of hours of development. If every user would donate just $1, it would fund fulltime development of this plugin for at least 3 years. Of course, it's not a reality that everyone is able donate. Pitching in any amount will help." +msgstr "" + +#: admin/views/class-view-donate.php:62 +msgid "Donate Via PayPal" +msgstr "" + +#: admin/views/class-view-donate.php:65 +msgid "Learn More" +msgstr "" + +#: admin/views/class-view-general.php:64 admin/views/class-view-general.php:372 msgid "Sidebar Widgets" msgstr "" -#: admin/views/class-view-general.php:65 admin/views/class-view-general.php:380 +#: admin/views/class-view-general.php:65 admin/views/class-view-general.php:381 msgid "Private Site" msgstr "" @@ -699,83 +736,83 @@ msgstr "" msgid "Feed Error Message" msgstr "" -#: admin/views/class-view-general.php:128 +#: admin/views/class-view-general.php:129 msgid "Your roles and capabilities will not revert back to their previous settings after deactivating or uninstalling this plugin, so use this feature wisely." msgstr "" -#: admin/views/class-view-general.php:143 +#: admin/views/class-view-general.php:144 msgid "Enable the role manager." msgstr "" -#: admin/views/class-view-general.php:161 +#: admin/views/class-view-general.php:162 msgid "Denied capabilities should always overrule granted capabilities." msgstr "" -#: admin/views/class-view-general.php:168 +#: admin/views/class-view-general.php:169 msgid "Show human-readable capabilities when possible." msgstr "" -#: admin/views/class-view-general.php:186 +#: admin/views/class-view-general.php:187 msgid "Allow users to be assigned more than a single role." msgstr "" -#: admin/views/class-view-general.php:201 +#: admin/views/class-view-general.php:202 msgid "Enable the content permissions feature." msgstr "" -#: admin/views/class-view-general.php:236 +#: admin/views/class-view-general.php:237 msgid "Enable the login form widget." msgstr "" -#: admin/views/class-view-general.php:251 +#: admin/views/class-view-general.php:252 msgid "Enable the users widget." msgstr "" -#: admin/views/class-view-general.php:266 +#: admin/views/class-view-general.php:267 msgid "Redirect all logged-out users to the login page before allowing them to view the site." msgstr "" -#: admin/views/class-view-general.php:281 +#: admin/views/class-view-general.php:282 msgid "Require authentication for access to the REST API." msgstr "" -#: admin/views/class-view-general.php:296 +#: admin/views/class-view-general.php:297 msgid "Show error message for feed items." msgstr "" -#: admin/views/class-view-general.php:332 +#: admin/views/class-view-general.php:333 msgid "Update Settings" msgstr "" -#: admin/views/class-view-general.php:353 +#: admin/views/class-view-general.php:354 msgid "Role and Capabilities" msgstr "" -#: admin/views/class-view-general.php:399 +#: admin/views/class-view-general.php:400 msgid "The role manager allows you to manage roles on your site by giving you the ability to create, edit, and delete any role. Note that changes to roles do not change settings for the Members plugin. You are literally changing data in your WordPress database. This plugin feature merely provides an interface for you to make these changes." msgstr "" -#: admin/views/class-view-general.php:403 +#: admin/views/class-view-general.php:404 msgid "The multiple user roles feature allows you to assign more than one role to each user from the edit user screen." msgstr "" -#: admin/views/class-view-general.php:407 +#: admin/views/class-view-general.php:408 msgid "Tick the checkbox for denied capabilities to always take precedence over granted capabilities when there is a conflict. This is only relevant when using multiple roles per user." msgstr "" -#: admin/views/class-view-general.php:411 +#: admin/views/class-view-general.php:412 msgid "Tick the checkbox to show human-readable capabilities when possible. Note that custom capabilities and capabilities from third-party plugins will show the machine-readable capability name unless they are registered." msgstr "" -#: admin/views/class-view-general.php:425 +#: admin/views/class-view-general.php:426 msgid "The content permissions features adds a meta box to the edit post screen that allows you to grant permissions for who can read the post content based on the user's role. Only users of roles with the %s capability will be able to use this component." msgstr "" -#: admin/views/class-view-general.php:439 +#: admin/views/class-view-general.php:440 msgid "The sidebar widgets feature adds additional widgets for use in your theme's sidebars." msgstr "" -#: admin/views/class-view-general.php:453 +#: admin/views/class-view-general.php:454 msgid "The private site feature redirects all users who are not logged into the site to the login page, creating an entirely private site. You may also replace your feed content with a custom error message." msgstr "" @@ -1223,15 +1260,15 @@ msgstr "" msgid "You must be logged into the site to view this content." msgstr "" -#: inc/functions-private-site.php:163 +#: inc/functions-private-site.php:167 msgid "You are not currently logged in." msgstr "" -#: inc/functions-private-site.php:187 +#: inc/functions-private-site.php:191 msgid "You do not currently have access to the \"%s\" site. If you believe you should have access, please contact your network administrator." msgstr "" -#: inc/functions-private-site.php:194 +#: inc/functions-private-site.php:198 msgid "If you reached this page by accident and meant to visit one of your own sites, try one of the following links." msgstr "" @@ -1243,7 +1280,7 @@ msgstr "" msgid "Method does not exist." msgstr "" -#: members.php:282 +#: members.php:323 msgid "Members requires PHP version %1$s. You are running version %2$s. Please upgrade and try again." msgstr "" #. Plugin Name of the plugin/theme From 2a881c195135b677c037ae8aafbdfd5907d6404c Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sat, 20 Jul 2019 05:03:27 -0500 Subject: [PATCH 152/157] Update readme with an example of how denied caps work. Fixes: https://github.com/justintadlock/members/issues/178 --- readme.md | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 6a04598..3ebb57a 100644 --- a/readme.md +++ b/readme.md @@ -67,9 +67,35 @@ Every capability can have one of three "states" for a role. The role can be *gr * **Denying** a capability means that the role's users are explicitly denied permission. * A role that is neither granted nor denied a capability simply doesn't have that capability. -**Note #1:** If you were using a pre-1.0.0 version of Members, the concept of denied capabilities was not built in. In those versions, you could only grant or remove a capability. +**Note:** When assigning multiple roles to a single user that have a conflicting capability (e.g., granted `publish_posts` and denied `published_posts` cap), it's best to enable the denied capabilities override via the Members Settings screen. This will consistently make sure that denied capabilities always overrule granted capabilities. With this setting disabled, WordPress will decide based on the *last* role given to the user, which can mean for extremely inconsistent behavior depending on the roles a user has. -**Note #2:** When assigning multiple roles to a single user that have a conflicting capability (e.g., granted `publish_posts` and denied `published_posts` cap), it's best to enable the denied capabilities override via the Members Settings screen. This will consistently make sure that denied capabilities always overrule granted capabilities. With this setting disabled, WordPress will decide based on the *last* role given to the user, which can mean for extremely inconsistent behavior depending on the roles a user has. +#### How denied capabilities work + +Suppose the **Super** role is *granted* these capabilities: + +* `edit_posts` + +Then, suppose the **Duper** role is *granted* these capabilities: + +- `publish_posts` +- `edit_products` + +Now, further suppose **User A** has the **Super** role because you want them to edit posts. However, you also want **User A** to be able to edit products so you assign them the **Duper** role. Suddenly, **User A** is *granted* the following capabilities: + +- `edit_posts` +- `publish_posts` +- `edit_products` + +For whatever reason you don't ever want users with the **Super** role to be able to publish posts. Now you have a problem. One way to solve this is to create a third role with just the caps that you want and give that single role to **User A**. However, that becomes cumbersome on larger sites with many roles. + +Instead, you could explicitly *deny* the publish posts capability to the **Super** role. When you do that, **User A** is only *granted* the following capabilities: + +- `edit_posts` +- `edit_products` + +And is denied the following capabilities: + +- `publish_posts` ### Multiple user roles From bb65a39c44b61495a3e0daf00b3c0db28e435ddc Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sat, 20 Jul 2019 05:18:25 -0500 Subject: [PATCH 153/157] Use minified CSS. --- admin/views/class-view-addons.php | 2 +- admin/views/class-view-donate.php | 2 +- css/admin.min.css | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/admin/views/class-view-addons.php b/admin/views/class-view-addons.php index dd6ca11..caec054 100644 --- a/admin/views/class-view-addons.php +++ b/admin/views/class-view-addons.php @@ -28,7 +28,7 @@ class View_Addons extends View { * @return void */ public function enqueue() { - wp_enqueue_style( 'members-admin', members_plugin()->uri . 'css/admin.css' ); + wp_enqueue_style( 'members-admin' ); } /** diff --git a/admin/views/class-view-donate.php b/admin/views/class-view-donate.php index c246a0a..5b972bb 100644 --- a/admin/views/class-view-donate.php +++ b/admin/views/class-view-donate.php @@ -28,7 +28,7 @@ class View_Donate extends View { * @return void */ public function enqueue() { - wp_enqueue_style( 'members-admin', members_plugin()->uri . 'css/admin.css' ); + wp_enqueue_style( 'members-admin' ); } /** diff --git a/css/admin.min.css b/css/admin.min.css index 5133c16..dc522be 100644 --- a/css/admin.min.css +++ b/css/admin.min.css @@ -1 +1 @@ -@media only screen and (min-width:783px){.users_page_roles .column-denied_caps,.users_page_roles .column-granted_caps,.users_page_roles .column-users{width:100px;text-align:center}}.members-title-div #titlewrap input{padding:0 8px;font-size:1.7em;line-height:normal;height:1.7em;width:100%;outline:0;margin:0 0 3px;background-color:#fff}.members-title-div input[name=role]{font-size:13px;height:22px;margin:0;width:16em}#tabcapsdiv{margin-top:1em}#tabcapsdiv>.hndle{padding:10px;border-bottom:1px solid #eee}#members-cp .inside,#tabcapsdiv .inside{margin:0;padding:0}.members-cap-tabs,.members-tabs{overflow:hidden;background:#fff;background:linear-gradient(90deg,#fafafa 0,#fafafa 20%,#fff 20%,#fff 100%)}@media only screen and (max-width:782px){.members-cap-tabs,.members-tabs{background:linear-gradient(90deg,#fafafa 0,#fafafa 48px,#fff 48px,#fff 100%)}}.members-cap-tabs .members-tab-nav,.members-tabs .members-tab-nav{position:relative;float:left;list-style:none;width:20%;line-height:1em;margin:0 0 -1px 0;padding:0;background-color:#fafafa;border-right:1px solid #eee;box-sizing:border-box}.members-cap-tabs .members-tab-nav li,.members-tabs .members-tab-nav li{display:block;position:relative;margin:0;padding:0;line-height:20px}.members-cap-tabs .members-tab-nav li a,.members-tabs .members-tab-nav li a{display:block;margin:0;padding:10px;line-height:20px!important;text-decoration:none;border-bottom:1px solid #eee;box-shadow:none}.members-cap-tabs .members-tab-nav li a .dashicons,.members-tabs .members-tab-nav li a .dashicons{line-height:20px;margin-right:3px}.members-cap-tabs .members-tab-nav li[aria-selected=true] a,.members-tabs .members-tab-nav li[aria-selected=true] a{position:relative;font-weight:700;color:#555;background-color:#e0e0e0}@media only screen and (max-width:782px){.members-cap-tabs .members-tab-nav,.members-tabs .members-tab-nav{width:48px}.members-cap-tabs .members-tab-nav li a .dashicons,.members-tabs .members-tab-nav li a .dashicons{width:24px;height:24px;font-size:24px;line-height:24px}.members-tab-nav li .dashicons::before{width:24px;height:24px}.members-tab-nav li .label{overflow:hidden;position:absolute;top:-1000em;left:-1000em;width:1px;height:1px}}.members-cap-tabs .members-tab-wrap,.members-tabs .members-tab-wrap{float:left;width:80%;margin-left:-1px}@media only screen and (max-width:782px){.members-cap-tabs .members-tab-wrap,.members-tabs .members-tab-wrap{width:calc(100% - 48px)}}#members-cp .members-tab-content{padding:10px;border-left:1px solid #e5e5e5}@media only screen and (min-width:850px){#side-sortables .members-tabs{background:#fff}#side-sortables .members-tabs .members-tab-wrap{width:100%}#side-sortables .members-tabs .members-tab-nav{display:table;width:100%}#side-sortables .members-tabs .members-tab-nav li{display:table-cell;text-align:center;border-right:1px solid #eee}#side-sortables .members-tabs .members-tab-nav li:last-of-type{border-right:none}#side-sortables .members-tabs .members-tab-nav li a{padding:10px 0}#side-sortables .members-tabs .members-tab-nav .dashicons{width:24px;height:24px;font-size:24px;line-height:24px}#side-sortables .members-tabs .members-tab-nav .dashicons::before{width:24px;height:24px}#side-sortables .members-tabs .members-tab-nav .label{overflow:hidden;position:absolute;top:-1000em;left:-1000em;width:1px;height:1px}}.members-tabs .members-tabs-label{display:block!important;font-weight:700;display:inline-block;margin-bottom:4px}.members-tabs .butterbean-control-checkbox .members-tabs-label{display:inline!important}.members-tabs .members-tabs-description{display:block;font-style:italic;margin-top:4px}.members-tabs .members-tabs-label+.members-tabs-description{margin-top:0;margin-bottom:4px}#tabcapsdiv table{border-right:none;border-top:none;border-bottom:none}#tabcapsdiv table td,#tabcapsdiv table th{padding:10px;padding-bottom:10px;border-bottom:1px solid #eee;font-size:13px;line-height:20px}#tabcapsdiv table td{padding:9px}#tabcapsdiv tbody tr:last-of-type td{border-bottom:none}#tabcapsdiv tfoot th{border-color:#eee}@media only screen and (max-width:782px){#tabcapsdiv table td,#tabcapsdiv table th{line-height:24px}}.members-roles-select .column-deny,.members-roles-select .column-grant{width:70px!important;text-align:center;display:table-cell!important;clear:none!important}.members-cap-tabs button{display:inline;margin:-4px;line-height:inherit;padding:4px 8px;border:1px solid transparent;background:0 0;border-radius:0;outline:0;-webkit-transition:all .25s ease-out;-moz-transition:all .25s ease-out;-o-transition:all .25s ease-out;transition:all .25s ease-out}.members-cap-tabs button:focus,.members-cap-tabs button:hover{border-color:#eee;background:#fafafa;cursor:pointer}.members-cap-tabs button:active{color:#0073aa;border-color:#0073aa}.members-cap-tabs button+.dashicons{display:none;margin-top:1px;margin-bottom:-1px;line-height:inherit}.members-cap-tabs button:focus+.dashicons,.members-cap-tabs button:hover+.dashicons{display:inline-block}.members-tab-content .members-highlight{background-color:rgba(0,115,170,.05)}.members-tab-content tbody{-webkit-transition:all 2s ease-in-out;-moz-transition:all 2s ease-in-out;-o-transition:all 2s ease-in-out;transition:all 2s ease-in-out}.members-cp-role-list-wrap{overflow:auto;min-height:42px;max-height:200px;padding:0 .9em;border:solid 1px #dfdfdf;background-color:#fdfdfd} \ No newline at end of file +.settings_page_members-settings .welcome-panel{margin-top:0;padding:40px 20px}.settings_page_members-settings .welcome-panel .about-description{margin:20px 0}.settings_page_members-settings .welcome-panel-content{margin:0}@media screen and (min-width:870px){.settings_page_members-settings .members-short-p{max-width:612px;margin-left:auto;margin-right:auto}.settings_page_members-settings .welcome-panel-content{text-align:center}}.settings_page_members-settings .welcome-panel .button.button-hero{margin-left:auto;margin-right:auto}.settings_page_members-settings .members-svg-wrap{display:inline-block;margin:0 auto 20px}@media screen and (max-width:870px){.settings_page_members-settings .welcome-panel{padding:20px}.settings_page_members-settings .members-svg-wrap{float:left;margin-right:28px}.settings_page_members-settings.rtl .members-svg-wrap{float:right;margin-right:0;margin-left:28px}}.settings_page_members-settings .members-svg-link{display:table-cell;text-align:center;width:128px;height:128px;background:#363b3f;color:#fff;padding:24px 16px 16px;border-radius:50%;box-sizing:border-box;border:4px solid #fff;box-shadow:0 0 0 4px #363b3f}.settings_page_members-settings .members-svg-link svg{max-width:84px;max-height:64px;width:auto;height:auto}@media only screen and (min-width:783px){.users_page_roles .column-users,.users_page_roles .column-granted_caps,.users_page_roles .column-denied_caps{width:100px;text-align:center}}.members-title-div #titlewrap input{padding:0 8px;font-size:1.7em;line-height:normal;height:1.7em;width:100%;outline:none;margin:0 0 3px;background-color:#fff}.members-title-div input[name="role"]{font-size:13px;height:22px;margin:0;width:16em}#tabcapsdiv{margin-top:1em}#tabcapsdiv>.hndle{padding:10px;border-bottom:1px solid #eee}#tabcapsdiv .inside,#members-cp .inside{margin:0;padding:0}.members-cap-tabs,.members-tabs{overflow:hidden;background:#fff;background:linear-gradient(90deg,#fafafa 0%,#fafafa 20%,#fff 20%,#fff 100%)}@media only screen and (max-width:782px){.members-cap-tabs,.members-tabs{background:linear-gradient(90deg,#fafafa 0%,#fafafa 48px,#fff 48px,#fff 100%)}}.members-cap-tabs .members-tab-nav,.members-tabs .members-tab-nav{position:relative;float:left;list-style:none;width:20%;line-height:1em;margin:0 0 -1px 0;padding:0;background-color:#fafafa;border-right:1px solid #eee;box-sizing:border-box}.members-cap-tabs .members-tab-nav li,.members-tabs .members-tab-nav li{display:block;position:relative;margin:0;padding:0;line-height:20px}.members-cap-tabs .members-tab-nav li a,.members-tabs .members-tab-nav li a{display:block;margin:0;padding:10px;line-height:20px!important;text-decoration:none;border-bottom:1px solid #eee;box-shadow:none}.members-cap-tabs .members-tab-nav li a .dashicons,.members-tabs .members-tab-nav li a .dashicons{line-height:20px;margin-right:3px}.members-cap-tabs .members-tab-nav li[aria-selected="true"] a,.members-tabs .members-tab-nav li[aria-selected="true"] a{position:relative;font-weight:700;color:#555;background-color:#e0e0e0}@media only screen and (max-width:782px){.members-cap-tabs .members-tab-nav,.members-tabs .members-tab-nav{width:48px}.members-cap-tabs .members-tab-nav li a .dashicons,.members-tabs .members-tab-nav li a .dashicons{width:24px;height:24px;font-size:24px;line-height:24px}.members-tab-nav li .dashicons::before,.members-tab-nav li .dashicons::before{width:24px;height:24px}.members-tab-nav li .label{overflow:hidden;position:absolute;top:-1000em;left:-1000em;width:1px;height:1px}}.members-cap-tabs .members-tab-wrap,.members-tabs .members-tab-wrap{float:left;width:80%;margin-left:-1px}@media only screen and (max-width:782px){.members-cap-tabs .members-tab-wrap,.members-tabs .members-tab-wrap{width:calc(100% - 48px)}}#members-cp .members-tab-content{padding:10px;border-left:1px solid #e5e5e5}@media only screen and (min-width:850px){#side-sortables .members-tabs{background:#fff}#side-sortables .members-tabs .members-tab-wrap{width:100%}#side-sortables .members-tabs .members-tab-nav{display:table;width:100%}#side-sortables .members-tabs .members-tab-nav li{display:table-cell;text-align:center;border-right:1px solid #eee}#side-sortables .members-tabs .members-tab-nav li:last-of-type{border-right:none}#side-sortables .members-tabs .members-tab-nav li a{padding:10px 0}#side-sortables .members-tabs .members-tab-nav .dashicons{width:24px;height:24px;font-size:24px;line-height:24px}#side-sortables .members-tabs .members-tab-nav .dashicons::before{width:24px;height:24px}#side-sortables .members-tabs .members-tab-nav .label{overflow:hidden;position:absolute;top:-1000em;left:-1000em;width:1px;height:1px}}.members-tabs .members-tabs-label{display:block!important;font-weight:700;display:inline-block;margin-bottom:4px}.members-tabs .butterbean-control-checkbox .members-tabs-label{display:inline!important}.members-tabs .members-tabs-description{display:block;font-style:italic;margin-top:4px}.members-tabs .members-tabs-label + .members-tabs-description{margin-top:0;margin-bottom:4px}#tabcapsdiv table{border-right:none;border-top:none;border-bottom:none}#tabcapsdiv table td,#tabcapsdiv table th{padding:10px;padding-bottom:10px;border-bottom:1px solid #eee;font-size:13px;line-height:20px}#tabcapsdiv table td{padding:9px}#tabcapsdiv tbody tr:last-of-type td{border-bottom:none}#tabcapsdiv tfoot th{border-color:#eee}@media only screen and (max-width:782px){#tabcapsdiv table td,#tabcapsdiv table th{line-height:24px}}.members-roles-select .column-grant,.members-roles-select .column-deny{width:70px!important;text-align:center;display:table-cell!important;clear:none!important}.members-cap-tabs button{display:inline;margin:-4px;line-height:inherit;padding:4px 8px;border:1px solid transparent;background:transparent;border-radius:0;outline:none;-webkit-transition:all 0.25s ease-out;-moz-transition:all 0.25s ease-out;-o-transition:all 0.25s ease-out;transition:all 0.25s ease-out}.members-cap-tabs button:hover,.members-cap-tabs button:focus{border-color:#eee;background:#fafafa;cursor:pointer}.members-cap-tabs button:active{color:#0073aa;border-color:#0073aa}.members-cap-tabs button + .dashicons{display:none;margin-top:1px;margin-bottom:-1px;line-height:inherit}.members-cap-tabs button:hover + .dashicons,.members-cap-tabs button:focus + .dashicons{display:inline-block}.members-tab-content .members-highlight{background-color:rgba(0,115,170,.05)}.members-tab-content tbody{-webkit-transition:all 2s ease-in-out;-moz-transition:all 2s ease-in-out;-o-transition:all 2s ease-in-out;transition:all 2s ease-in-out}.members-cp-role-list-wrap{overflow:auto;min-height:42px;max-height:200px;padding:0 .9em;border:solid 1px rgb(223,223,223);background-color:rgb(253,253,253)} From b716a96ec00dfd5d09c50e94bd94547524a4fa15 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sat, 20 Jul 2019 10:20:07 -0500 Subject: [PATCH 154/157] Remove support-only membership text link. --- admin/views/class-view-addons.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/admin/views/class-view-addons.php b/admin/views/class-view-addons.php index caec054..bb7d06c 100644 --- a/admin/views/class-view-addons.php +++ b/admin/views/class-view-addons.php @@ -70,9 +70,6 @@ public function template() {

    -

    - -

    From 19c93b8416ba546ea5bf2f13c428bcf12eeb5cba Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sat, 20 Jul 2019 10:21:02 -0500 Subject: [PATCH 155/157] Version bump to 2.2.0. --- members.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/members.php b/members.php index 0e80b42..50fd99b 100644 --- a/members.php +++ b/members.php @@ -3,7 +3,7 @@ * Plugin Name: Members * Plugin URI: https://themehybrid.com/plugins/members * Description: A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private. - * Version: 2.2.0-alpha + * Version: 2.2.0 * Author: Justin Tadlock * Author URI: https://themehybrid.com * Text Domain: members @@ -25,7 +25,7 @@ * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * @package Members - * @version 2.1.0 + * @version 2.2.0 * @author Justin Tadlock * @copyright Copyright (c) 2009 - 2018, Justin Tadlock * @link https://themehybrid.com/plugins/members From 72fe5465e625c50e653f94e6e2fb9d136c530da7 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sat, 20 Jul 2019 10:25:28 -0500 Subject: [PATCH 156/157] Update readme. --- readme.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/readme.txt b/readme.txt index 2cd2451..e5b3c7f 100644 --- a/readme.txt +++ b/readme.txt @@ -1,12 +1,12 @@ === Members === Contributors: greenshady -Donate link: https://themehybrid.com/donate +Donate link: https://themehybrid.com/plugins/members#donate Tags: capabilities, roles, members, users Requires at least: 4.7 -Tested up to: 4.9 +Tested up to: 5.2 Requires PHP: 5.6 -Stable tag: 2.1.0 +Stable tag: 2.2.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -36,8 +36,8 @@ For more info, visit the [Members plugin home page](https://themehybrid.com/plug The Members plugin is a massive project with 1,000s of lines of code to maintain. A major update can take weeks or months of work. I don't make any money directly from this plugin while other, similar plugins charge substantial fees to even download them or get updates. Please consider helping the cause by: -* [Making a donation](https://themehybrid.com/donate). -* [Signing up at my site](https://themehybrid.com/club). +* [Making a donation](https://themehybrid.com/plugins/members#donate). +* [Signing up at my site](https://themehybrid.com/plugins/members). * [Rating the plugin](https://wordpress.org/support/view/plugin-reviews/members?rate=5#postform). ### Professional Support From 7dbefeb53a9e7575bf681b97f00b96e21b73a6f4 Mon Sep 17 00:00:00 2001 From: Justin Tadlock Date: Sat, 20 Jul 2019 10:27:13 -0500 Subject: [PATCH 157/157] Correct date in change log. --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index d0d93af..31f87d3 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,6 @@ # Change Log -## [2.2.0] - 2019-07-19 +## [2.2.0] - 2019-07-20 ### Added