Version Description
Download this release
Release Info
Developer | greenshady |
Plugin | Members |
Version | 1.1.2 |
Comparing to | |
See all releases |
Code changes from version 1.1.1 to 1.1.2
- admin/class-cap-group.php +34 -46
- admin/class-role-edit.php +29 -2
- admin/tmpl/cp-control-message.php +11 -0
- admin/tmpl/cp-control-role.php +25 -0
- admin/tmpl/cp-nav.php +1 -0
- admin/tmpl/cp-section.php +3 -0
- changelog.md +7 -0
- inc/functions-private-site.php +2 -2
- js/edit-post.js +157 -0
- members.php +2 -2
- readme.txt +1 -1
admin/class-cap-group.php
CHANGED
@@ -19,64 +19,58 @@
|
|
19 |
final class Members_Cap_Group {
|
20 |
|
21 |
/**
|
22 |
-
*
|
23 |
*
|
24 |
* @since 1.0.0
|
25 |
* @access protected
|
26 |
-
* @var
|
27 |
*/
|
28 |
-
|
29 |
|
30 |
/**
|
31 |
-
*
|
32 |
*
|
33 |
* @since 1.0.0
|
34 |
-
* @access
|
35 |
-
* @
|
36 |
-
* @return mixed
|
37 |
*/
|
38 |
-
public
|
39 |
-
|
40 |
-
return isset( $this->$property ) ? $this->args[ $property ] : null;
|
41 |
-
}
|
42 |
|
43 |
/**
|
44 |
-
*
|
45 |
*
|
46 |
* @since 1.0.0
|
47 |
-
* @access
|
48 |
-
* @
|
49 |
-
* @param mixed $value
|
50 |
-
* @return void
|
51 |
*/
|
52 |
-
public
|
53 |
-
|
54 |
-
if ( isset( $this->$property ) )
|
55 |
-
$this->args[ $property ] = $value;
|
56 |
-
}
|
57 |
|
58 |
/**
|
59 |
-
*
|
60 |
*
|
61 |
* @since 1.0.0
|
62 |
-
* @access
|
63 |
-
* @
|
64 |
-
* @return bool
|
65 |
*/
|
66 |
-
public
|
67 |
|
68 |
-
|
69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
|
71 |
/**
|
72 |
-
*
|
73 |
*
|
74 |
-
* @since
|
75 |
-
* @access
|
76 |
-
* @
|
77 |
-
* @return void
|
78 |
*/
|
79 |
-
public
|
80 |
|
81 |
/**
|
82 |
* Magic method to use in case someone tries to output the object as a string.
|
@@ -107,20 +101,14 @@ final class Members_Cap_Group {
|
|
107 |
*/
|
108 |
public function __construct( $name, $args = array() ) {
|
109 |
|
110 |
-
|
111 |
-
|
112 |
-
$defaults = array(
|
113 |
-
'label' => '',
|
114 |
-
'icon' => 'dashicons-admin-generic',
|
115 |
-
'caps' => array( 'read' ),
|
116 |
-
'merge_added' => true,
|
117 |
-
'diff_added' => false,
|
118 |
-
);
|
119 |
|
120 |
-
|
|
|
|
|
121 |
|
122 |
-
$this->
|
123 |
|
124 |
-
$this->
|
125 |
}
|
126 |
}
|
19 |
final class Members_Cap_Group {
|
20 |
|
21 |
/**
|
22 |
+
* Name/ID for the group.
|
23 |
*
|
24 |
* @since 1.0.0
|
25 |
* @access protected
|
26 |
+
* @var string
|
27 |
*/
|
28 |
+
public $name = '';
|
29 |
|
30 |
/**
|
31 |
+
* Internationalized text label for the group.
|
32 |
*
|
33 |
* @since 1.0.0
|
34 |
+
* @access protected
|
35 |
+
* @var string
|
|
|
36 |
*/
|
37 |
+
public $label = '';
|
|
|
|
|
|
|
38 |
|
39 |
/**
|
40 |
+
* Icon for the group. This can be a dashicons class or a custom class.
|
41 |
*
|
42 |
* @since 1.0.0
|
43 |
+
* @access protected
|
44 |
+
* @var string
|
|
|
|
|
45 |
*/
|
46 |
+
public $icon = 'dashicons-admin-generic';
|
|
|
|
|
|
|
|
|
47 |
|
48 |
/**
|
49 |
+
* Capabilities for the group.
|
50 |
*
|
51 |
* @since 1.0.0
|
52 |
+
* @access protected
|
53 |
+
* @var array
|
|
|
54 |
*/
|
55 |
+
public $caps = array( 'read' );
|
56 |
|
57 |
+
/**
|
58 |
+
* Whether to merge this groups caps with the added caps array.
|
59 |
+
*
|
60 |
+
* @since 1.0.0
|
61 |
+
* @access protected
|
62 |
+
* @var bool
|
63 |
+
*/
|
64 |
+
public $merge_added = true;
|
65 |
|
66 |
/**
|
67 |
+
* Whether to remove previously-added caps from this group's caps.
|
68 |
*
|
69 |
+
* @since 1.0.0
|
70 |
+
* @access protected
|
71 |
+
* @var bool
|
|
|
72 |
*/
|
73 |
+
public $diff_added = false;
|
74 |
|
75 |
/**
|
76 |
* Magic method to use in case someone tries to output the object as a string.
|
101 |
*/
|
102 |
public function __construct( $name, $args = array() ) {
|
103 |
|
104 |
+
foreach ( array_keys( get_object_vars( $this ) ) as $key ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
|
106 |
+
if ( isset( $args[ $key ] ) )
|
107 |
+
$this->$key = $args[ $key ];
|
108 |
+
}
|
109 |
|
110 |
+
$this->name = sanitize_key( $name );
|
111 |
|
112 |
+
$this->caps = members_remove_hidden_caps( $this->caps );
|
113 |
}
|
114 |
}
|
admin/class-role-edit.php
CHANGED
@@ -125,6 +125,13 @@ final class Members_Admin_Role_Edit {
|
|
125 |
$grant_new_caps = ! empty( $_POST['grant-new-caps'] ) ? array_unique( $_POST['grant-new-caps'] ) : array();
|
126 |
$deny_new_caps = ! empty( $_POST['deny-new-caps'] ) ? array_unique( $_POST['deny-new-caps'] ) : array();
|
127 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
// Set the $role_updated variable to true.
|
129 |
$this->role_updated = true;
|
130 |
|
@@ -159,8 +166,11 @@ final class Members_Admin_Role_Edit {
|
|
159 |
$_cap = members_sanitize_cap( $grant_new_cap );
|
160 |
|
161 |
// If not an existing cap, add it.
|
162 |
-
if ( ! in_array( $_cap, $this->capabilities ) )
|
163 |
$this->role->add_cap( $_cap );
|
|
|
|
|
|
|
164 |
}
|
165 |
|
166 |
// Loop through the custom denied caps.
|
@@ -169,8 +179,25 @@ final class Members_Admin_Role_Edit {
|
|
169 |
$_cap = members_sanitize_cap( $deny_new_cap );
|
170 |
|
171 |
// If not a granted cap and not an existing cap, add it.
|
172 |
-
if ( ! in_array( $_cap, $this->capabilities ) && ! in_array( $_cap, $grant_new_caps ) )
|
173 |
$this->role->add_cap( $_cap, false );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
}
|
175 |
|
176 |
// Add the updated role to the role factory.
|
125 |
$grant_new_caps = ! empty( $_POST['grant-new-caps'] ) ? array_unique( $_POST['grant-new-caps'] ) : array();
|
126 |
$deny_new_caps = ! empty( $_POST['deny-new-caps'] ) ? array_unique( $_POST['deny-new-caps'] ) : array();
|
127 |
|
128 |
+
// Get the all and custom cap group objects.
|
129 |
+
$all_group = members_get_cap_group( 'all' );
|
130 |
+
$custom_group = members_get_cap_group( 'custom' );
|
131 |
+
|
132 |
+
// New caps to push to cap groups on update.
|
133 |
+
$push_caps = array();
|
134 |
+
|
135 |
// Set the $role_updated variable to true.
|
136 |
$this->role_updated = true;
|
137 |
|
166 |
$_cap = members_sanitize_cap( $grant_new_cap );
|
167 |
|
168 |
// If not an existing cap, add it.
|
169 |
+
if ( ! in_array( $_cap, $this->capabilities ) ) {
|
170 |
$this->role->add_cap( $_cap );
|
171 |
+
|
172 |
+
$push_caps[] = $_cap;
|
173 |
+
}
|
174 |
}
|
175 |
|
176 |
// Loop through the custom denied caps.
|
179 |
$_cap = members_sanitize_cap( $deny_new_cap );
|
180 |
|
181 |
// If not a granted cap and not an existing cap, add it.
|
182 |
+
if ( ! in_array( $_cap, $this->capabilities ) && ! in_array( $_cap, $grant_new_caps ) ) {
|
183 |
$this->role->add_cap( $_cap, false );
|
184 |
+
|
185 |
+
$push_caps[] = $_cap;
|
186 |
+
}
|
187 |
+
}
|
188 |
+
|
189 |
+
// If there are new caps, add them to the all and custom groups.
|
190 |
+
if ( $push_caps ) {
|
191 |
+
|
192 |
+
if ( $all_group ) {
|
193 |
+
$all_group->caps[] = $_cap;
|
194 |
+
sort( $all_group->caps );
|
195 |
+
}
|
196 |
+
|
197 |
+
if ( $custom_group ) {
|
198 |
+
$custom_group->caps[] = $_cap;
|
199 |
+
sort( $custom_group->caps );
|
200 |
+
}
|
201 |
}
|
202 |
|
203 |
// Add the updated role to the role factory.
|
admin/tmpl/cp-control-message.php
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<label>
|
2 |
+
<# if ( data.label ) { #>
|
3 |
+
<span class="members-cp-label">{{ data.label }}</span>
|
4 |
+
<# } #>
|
5 |
+
|
6 |
+
<textarea name="members_access_error" class="widefat">{{{ data.value }}}</textarea>
|
7 |
+
|
8 |
+
<# if ( data.description ) { #>
|
9 |
+
<span class="members-cp-description">{{{ data.description }}}</span>
|
10 |
+
<# } #>
|
11 |
+
</label>
|
admin/tmpl/cp-control-role.php
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<# if ( data.label ) { #>
|
2 |
+
<span class="members-cp-label">{{ data.label }}</span>
|
3 |
+
<# } #>
|
4 |
+
|
5 |
+
<# if ( data.desciption ) { #>
|
6 |
+
<span class="members-cp-description">{{{ data.description }}}</span>
|
7 |
+
<# } #>
|
8 |
+
|
9 |
+
<div class="members-cp-role-list-wrap">
|
10 |
+
|
11 |
+
<ul class="members-cp-role-list">
|
12 |
+
|
13 |
+
<# _.each( data.roles ), function( label, choice ) { #>
|
14 |
+
|
15 |
+
<li>
|
16 |
+
<label>
|
17 |
+
<input type="checkbox" name="members_access_role[]" value="{{ data.choice }}" <# if ( -1 !== _.indexOf( data.value, choice ) ) { #> checked="checked" <# } #> />
|
18 |
+
{{ label }}
|
19 |
+
</label>
|
20 |
+
</li>
|
21 |
+
|
22 |
+
<# } ); #>
|
23 |
+
|
24 |
+
</ul>
|
25 |
+
</div>
|
admin/tmpl/cp-nav.php
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
<a href="#members-cp-section-{{ data.name }}"><i class="{{ data.icon }}" aria-hidden="true"></i><span class="label">{{ data.label }}</span></a>
|
admin/tmpl/cp-section.php
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<# if ( data.desciption ) { #>
|
2 |
+
{{{ data.description }}}
|
3 |
+
<# } #>
|
changelog.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1 |
# Change Log
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
## [1.1.1] - 2016-01-09
|
4 |
|
5 |
### Changed
|
1 |
# Change Log
|
2 |
|
3 |
+
## [1.1.2] - 2016-06-20
|
4 |
+
|
5 |
+
### Fixed
|
6 |
+
|
7 |
+
* Bug where custom capabilities would not appear after updating role.
|
8 |
+
* Make BuddyPress activation page public in private site mode.
|
9 |
+
|
10 |
## [1.1.1] - 2016-01-09
|
11 |
|
12 |
### Changed
|
inc/functions-private-site.php
CHANGED
@@ -64,8 +64,8 @@ function members_please_log_in() {
|
|
64 |
// Check if the private blog feature is active and if the user is not logged in.
|
65 |
if ( members_is_private_blog() && ! is_user_logged_in() ) {
|
66 |
|
67 |
-
// If using BuddyPress and on the register page, don't do anything.
|
68 |
-
if ( function_exists( 'bp_is_current_component' ) && bp_is_current_component( 'register' ) )
|
69 |
return;
|
70 |
|
71 |
// Redirect to the login page.
|
64 |
// Check if the private blog feature is active and if the user is not logged in.
|
65 |
if ( members_is_private_blog() && ! is_user_logged_in() ) {
|
66 |
|
67 |
+
// If using BuddyPress and on the register/activate page, don't do anything.
|
68 |
+
if ( function_exists( 'bp_is_current_component' ) && ( bp_is_current_component( 'register' ) || bp_is_current_component( 'activate' ) ) )
|
69 |
return;
|
70 |
|
71 |
// Redirect to the login page.
|
js/edit-post.js
ADDED
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
( function() {
|
2 |
+
|
3 |
+
// Bail if we don't have the JSON, which is passed in via `wp_localize_script()`.
|
4 |
+
if ( _.isUndefined( members_cp_data ) ) {
|
5 |
+
return;
|
6 |
+
}
|
7 |
+
|
8 |
+
/* === Models === */
|
9 |
+
|
10 |
+
// Section model (each section belongs to a manager).
|
11 |
+
var Section = Backbone.Model.extend( {
|
12 |
+
defaults : {
|
13 |
+
name : '',
|
14 |
+
label : '',
|
15 |
+
description : '',
|
16 |
+
icon : '',
|
17 |
+
selected : false
|
18 |
+
}
|
19 |
+
} );
|
20 |
+
|
21 |
+
// Control model (each control belongs to a manager and section).
|
22 |
+
var Control = Backbone.Model.extend( {
|
23 |
+
defaults : {
|
24 |
+
name : '',
|
25 |
+
type : '',
|
26 |
+
label : '',
|
27 |
+
description : '',
|
28 |
+
value : '',
|
29 |
+
choices : {},
|
30 |
+
attr : '',
|
31 |
+
section : ''
|
32 |
+
}
|
33 |
+
} );
|
34 |
+
|
35 |
+
/* === Collections === */
|
36 |
+
|
37 |
+
// Collection of sections.
|
38 |
+
var Sections = Backbone.Collection.extend( {
|
39 |
+
model : Section
|
40 |
+
} );
|
41 |
+
|
42 |
+
/* === Views === */
|
43 |
+
|
44 |
+
// Section view. Handles the output of a section.
|
45 |
+
var Section_View = Backbone.View.extend( {
|
46 |
+
tagName : 'div',
|
47 |
+
template : wp.template( 'members-cp-section' ),
|
48 |
+
attributes : function() {
|
49 |
+
return {
|
50 |
+
'id' : 'members-cp-section-' + this.model.get( 'name' ),
|
51 |
+
'class' : 'members-cp-section,
|
52 |
+
'aria-hidden' : ! this.model.get( 'selected' )
|
53 |
+
};
|
54 |
+
},
|
55 |
+
initialize : function( options ) {
|
56 |
+
this.model.on( 'change', this.onchange, this );
|
57 |
+
},
|
58 |
+
render : function() {
|
59 |
+
|
60 |
+
this.el.innerHTML = this.template( this.model.toJSON() );
|
61 |
+
|
62 |
+
return this;
|
63 |
+
},
|
64 |
+
onchange : function() {
|
65 |
+
|
66 |
+
// Set the view's `aria-hidden` attribute based on whether the model is selected.
|
67 |
+
this.el.setAttribute( 'aria-hidden', ! this.model.get( 'selected' ) );
|
68 |
+
},
|
69 |
+
} );
|
70 |
+
|
71 |
+
// Nav view.
|
72 |
+
var Nav_View = Backbone.View.extend( {
|
73 |
+
template : wp.template( 'members-cp-nav' ),
|
74 |
+
tagName : 'li',
|
75 |
+
attributes : function() {
|
76 |
+
return {
|
77 |
+
'aria-selected' : this.model.get( 'selected' )
|
78 |
+
};
|
79 |
+
},
|
80 |
+
initialize : function() {
|
81 |
+
this.model.on( 'change', this.render, this );
|
82 |
+
this.model.on( 'change', this.onchange, this );
|
83 |
+
},
|
84 |
+
render : function() {
|
85 |
+
|
86 |
+
this.el.innerHTML = this.template( this.model.toJSON() );
|
87 |
+
|
88 |
+
return this;
|
89 |
+
},
|
90 |
+
events : {
|
91 |
+
'click a' : 'onselect'
|
92 |
+
},
|
93 |
+
onchange : function() {
|
94 |
+
|
95 |
+
// Set the `aria-selected` attibute based on the model selected state.
|
96 |
+
this.el.setAttribute( 'aria-selected', this.model.get( 'selected' ) );
|
97 |
+
},
|
98 |
+
onselect : function( event ) {
|
99 |
+
event.preventDefault();
|
100 |
+
|
101 |
+
// Loop through each of the models in the collection and set them to inactive.
|
102 |
+
_.each( this.model.collection.models, function( m ) {
|
103 |
+
|
104 |
+
m.set( 'selected', false );
|
105 |
+
}, this );
|
106 |
+
|
107 |
+
// Set this view's model to selected.
|
108 |
+
this.model.set( 'selected', true );
|
109 |
+
}
|
110 |
+
} );
|
111 |
+
|
112 |
+
// Control view. Handles the output of a control.
|
113 |
+
var Control_View = Backbone.View.extend( {
|
114 |
+
tagName : 'div',
|
115 |
+
template : wp.template( 'members-cp-control' ),
|
116 |
+
attributes : function() {
|
117 |
+
return {
|
118 |
+
'id' : 'members-cp-control-' + this.model.get( 'name' ),
|
119 |
+
'class' : 'members-cp-control'
|
120 |
+
};
|
121 |
+
},
|
122 |
+
render : function() {
|
123 |
+
|
124 |
+
this.el.innerHTML = this.template( this.model.toJSON() );
|
125 |
+
return this;
|
126 |
+
}
|
127 |
+
} );
|
128 |
+
|
129 |
+
var sections = new Sections();
|
130 |
+
|
131 |
+
_.each( members_cp_data.sections ), function( data ) {
|
132 |
+
|
133 |
+
sections.add( new Section( data ) );
|
134 |
+
}
|
135 |
+
|
136 |
+
sections.forEach( function( section, i ) ) {
|
137 |
+
|
138 |
+
var nav_view = new Nav_View( { model : section } );
|
139 |
+
var section_view = new Section_View( { model : section } );
|
140 |
+
|
141 |
+
document.querySelector( '#members-cp .members-cp-nav' ).appendChild( nav_view.render().el );
|
142 |
+
document.querySelector( '#members-cp .members-cp-content' ).appendChild( section_view.render().el );
|
143 |
+
|
144 |
+
// If the first model, set it to selected.
|
145 |
+
section.set( 'selected', 0 == i );
|
146 |
+
}, this );
|
147 |
+
|
148 |
+
_.each( members_cp_data.controls ), function( data ) {
|
149 |
+
|
150 |
+
var control = new Control( data );
|
151 |
+
|
152 |
+
var view = new Control_View( { model : control } );
|
153 |
+
|
154 |
+
document.getElementById( '#members-cp-section-' + control.get( 'section' ) ).appendChild( view.render().el );
|
155 |
+
} );
|
156 |
+
|
157 |
+
}() );
|
members.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Members
|
4 |
* Plugin URI: http://themehybrid.com/plugins/members
|
5 |
* 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.
|
6 |
-
* Version: 1.1.
|
7 |
* Author: Justin Tadlock
|
8 |
* Author URI: http://themehybrid.com
|
9 |
* Text Domain: members
|
@@ -25,7 +25,7 @@
|
|
25 |
* write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
26 |
*
|
27 |
* @package Members
|
28 |
-
* @version 1.1.
|
29 |
* @author Justin Tadlock <justin@justintadlock.com>
|
30 |
* @copyright Copyright (c) 2009 - 2016, Justin Tadlock
|
31 |
* @link http://themehybrid.com/plugins/members
|
3 |
* Plugin Name: Members
|
4 |
* Plugin URI: http://themehybrid.com/plugins/members
|
5 |
* 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.
|
6 |
+
* Version: 1.1.2
|
7 |
* Author: Justin Tadlock
|
8 |
* Author URI: http://themehybrid.com
|
9 |
* Text Domain: members
|
25 |
* write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
26 |
*
|
27 |
* @package Members
|
28 |
+
* @version 1.1.2
|
29 |
* @author Justin Tadlock <justin@justintadlock.com>
|
30 |
* @copyright Copyright (c) 2009 - 2016, Justin Tadlock
|
31 |
* @link http://themehybrid.com/plugins/members
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Contributors: greenshady
|
|
4 |
Donate link: http://themehybrid.com/donate
|
5 |
Tags: admin, role, roles, member, members, profile, shortcode, user, users, widget, widgets
|
6 |
Requires at least: 4.3
|
7 |
-
Stable tag: 1.1.
|
8 |
|
9 |
The most powerful user, role, and capability management plugin for WordPress.
|
10 |
|
4 |
Donate link: http://themehybrid.com/donate
|
5 |
Tags: admin, role, roles, member, members, profile, shortcode, user, users, widget, widgets
|
6 |
Requires at least: 4.3
|
7 |
+
Stable tag: 1.1.2
|
8 |
|
9 |
The most powerful user, role, and capability management plugin for WordPress.
|
10 |
|