' .
__( 'Use the Access restrictions box to limit the visibility of posts, pages and other post types.', 'groups' ) .
'
' .
'
' .
__( 'You can select one or more capabilities that are enabled for access restriction.', 'groups' ) .
' ' .
__( 'Note that you must be a member of a group that has such a capability assigned.', 'groups' ) .
'
' .
'
' .
'' . __( 'Example:', 'groups' ) . '' .
'
' .
__( 'Let\'s assume that you want to limit the visibility of a post to members of the Premium group.', 'groups' ) .
'
' .
__( 'Enter Premium in the quick-create field located in the Access restrictions panel and save or update the post (or hit Enter).', 'groups' ) .
'
' .
'
' .
__( 'Using the quick-create field, you can create a new group and capability. The capability will be assigned to the group and enabled to enforce read access. Group names are case-sensitive, the name of the capability is the lower-case version of the name of the group. If the group already exists, a new capability is created and assigned to the existing group. If the capability already exists, it will be assigned to the group. If both already exist, the capability is enabled to enforce read access. In order to be able to use the capability, your user account will be assigned to the group.', 'groups' ) .
'
' .
'' . __( 'The manual way:', 'groups' ) . '' .
' ' .
__( 'Adding the group and capability manually and enabling it for access restriction', 'groups' ) .
'' .
'
' .
__( 'Try the quick-create field first. Unless you need a more complex setup, there is no reason to go this way instead.', 'groups' ) .
'
' .
'' .
'
' . __( 'Go to Groups > Groups and add the Premium group.', 'groups' ) . '
' .
'
' . __( 'Go to Groups > Capabilities and add the premium capability.', 'groups' ) . '
' .
'
' . __( 'Go to Groups > Groups and assign the premium capability to the Premium group.', 'groups' ) . '
' .
'
' . __( 'Go to Groups > Options and enable the premium capability to restrict access.', 'groups' ) . '
' .
'
' . __( 'Become a member of the Premium group - this is required so you can choose the premium capability to restrict access to a post.', 'groups' ) . '
' .
'
' . __( 'Edit the post for which you want to restrict access and choose* the premium capability.', 'groups' ) . '
' .
'' .
'
' .
__( '* For each capability, the groups that have the capability assigned are shown within parenthesis. You can choose a capability by typing part of the group\'s or the capability\'s name.', 'groups' ) .
'
';
$output .= sprintf( __( "Only groups or users that have one of the selected capabilities are allowed to read this %s.", 'groups' ), $post_singular_name );
$output .= '
';
$output .= '';
}
echo $output;
}
/**
* Invokes our save_post() if the post content is considered empty.
* This is required because even on an empty post, we want to allow to
* quick-create group and category as well as assign capabilities.
* At WordPress 3.6.1, this is the only way we can achieve that, because
* the save_post action is not invoked if the post content is considered
* empty.
*
* @param boolean $maybe_empty
* @param array $postarr
* @return boolean
*/
public static function wp_insert_post_empty_content( $maybe_empty, $postarr ) {
// Only consider invoking save_post() here, if the post content is
// considered to be empty at this stage. This is so we don't end up
// having save_post() invoked twice when the post is not empty.
if ( $maybe_empty ) {
$post_id = !empty( $postarr['ID'] ) ? $postarr['ID'] : !empty( $postarr['post_ID'] ) ? $postarr['post_ID'] : null;
if ( $post_id ) {
self::save_post( $post_id );
}
}
return $maybe_empty;
}
/**
* Save capability options.
*
* @param int $post_id
* @param mixed $post post data (not used here)
*/
public static function save_post( $post_id = null, $post = null ) {
if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) ) {
} else {
$post_type = get_post_type( $post_id );
$post_type_object = get_post_type_object( $post_type );
if ( $post_type_object && $post_type != 'attachment' ) {
$post_types_option = Groups_Options::get_option( Groups_Post_Access_Legacy::POST_TYPES, array() );
if ( !isset( $post_types_option[$post_type]['add_meta_box'] ) || $post_types_option[$post_type]['add_meta_box'] ) {
if ( isset( $_POST[self::NONCE] ) && wp_verify_nonce( $_POST[self::NONCE], self::SET_CAPABILITY ) ) {
$post_type = isset( $_POST['post_type'] ) ? $_POST['post_type'] : null;
if ( $post_type !== null ) {
// See http://codex.wordpress.org/Function_Reference/current_user_can 20130119 WP 3.5
// "... Some capability checks (like 'edit_post' or 'delete_page') require this [the post ID] be provided."
// If the post ID is not provided, it will throw:
// PHP Notice: Undefined offset: 0 in /var/www/groups-forums/wp-includes/capabilities.php on line 1067
$edit_post_type = 'edit_' . $post_type;
if ( $post_type_object = get_post_type_object( $post_type ) ) {
if ( !isset( $post_type_object->capabilities ) ) {
// get_post_type_capabilities() (WP 3.8) will throw a warning
// when trying to merge the missing property otherwise. It's either a
// bug or the function's documentation should make it clear that you
// have to provide that.
$post_type_object->capabilities = array();
}
$caps_object = get_post_type_capabilities( $post_type_object );
if ( isset( $caps_object->edit_post ) ) {
$edit_post_type = $caps_object->edit_post;
}
}
if ( current_user_can( $edit_post_type, $post_id ) ) {
// quick-create ?
if ( current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
if ( !empty( $_POST['quick-group-capability'] ) ) {
$creator_id = get_current_user_id();
$datetime = date( 'Y-m-d H:i:s', time() );
$name = ucfirst( strtolower( trim( $_POST['quick-group-capability'] ) ) );
if ( strlen( $name ) > 0 ) {
// create or obtain the group
if ( $group = Groups_Group::read_by_name( $name ) ) {
} else {
if ( $group_id = Groups_Group::create( compact( 'creator_id', 'datetime', 'name' ) ) ) {
$group = Groups_Group::read( $group_id );
}
}
// create or obtain the capability
$name = strtolower( $name );
if ( $capability = Groups_Capability::read_by_capability( $name ) ) {
} else {
if ( $capability_id = Groups_Capability::create( array( 'capability' => $name ) ) ) {
$capability = Groups_Capability::read( $capability_id );
}
}
if ( $group && $capability ) {
// add the capability to the group
if ( !Groups_Group_Capability::read( $group->group_id, $capability->capability_id ) ) {
Groups_Group_Capability::create(
array(
'group_id' => $group->group_id,
'capability_id' => $capability->capability_id
)
);
}
// enable the capability for access restriction
$valid_read_caps = Groups_Options::get_option( Groups_Post_Access_Legacy::READ_POST_CAPABILITIES, array( Groups_Post_Access_Legacy::READ_POST_CAPABILITY ) );
if ( !in_array( $capability->capability, $valid_read_caps ) ) {
$valid_read_caps[] = $capability->capability;
}
Groups_Options::update_option( Groups_Post_Access_Legacy::READ_POST_CAPABILITIES, $valid_read_caps );
// add the current user to the group
Groups_User_Group::create(
array(
'user_id' => get_current_user_id(),
'group_id' => $group->group_id
)
);
// put the capability ID in $_POST[self::CAPABILITY] so it is treated below
if ( empty( $_POST[self::CAPABILITY] ) ) {
$_POST[self::CAPABILITY] = array();
}
if ( !in_array( $capability->capability_id, $_POST[self::CAPABILITY] ) ) {
$_POST[self::CAPABILITY][] = $capability->capability_id;
}
}
}
}
}
// set
if ( self::user_can_restrict() ) {
$valid_read_caps = self::get_valid_read_caps_for_user();
foreach( $valid_read_caps as $valid_read_cap ) {
if ( $capability = Groups_Capability::read_by_capability( $valid_read_cap ) ) {
if ( !empty( $_POST[self::CAPABILITY] ) && is_array( $_POST[self::CAPABILITY] ) && in_array( $capability->capability_id, $_POST[self::CAPABILITY] ) ) {
Groups_Post_Access_Legacy::create( array(
'post_id' => $post_id,
'capability' => $capability->capability
) );
} else {
Groups_Post_Access_Legacy::delete( $post_id, $capability->capability );
}
}
}
}
// show groups
Groups_Options::update_user_option( self::SHOW_GROUPS, !empty( $_POST[self::SHOW_GROUPS] ) );
}
}
}
}
}
}
}
/**
* Enqueue scripts and styles.
*/
private static function enqueue() {
global $groups_version;
if ( !wp_script_is( 'selectize' ) ) {
wp_enqueue_script( 'selectize', GROUPS_PLUGIN_URL . 'js/selectize/selectize.min.js', array( 'jquery' ), $groups_version, false );
}
if ( !wp_style_is( 'selectize' ) ) {
wp_enqueue_style( 'selectize', GROUPS_PLUGIN_URL . 'css/selectize/selectize.bootstrap2.css', array(), $groups_version );
}
}
/**
* Render capabilities box for attachment post type (Media).
* @param array $form_fields
* @param object $post
* @return array
*/
public static function attachment_fields_to_edit( $form_fields, $post ) {
Groups_UIE::enqueue( 'select' );
$post_types_option = Groups_Options::get_option( Groups_Post_Access_Legacy::POST_TYPES, array() );
if ( !isset( $post_types_option['attachment']['add_meta_box'] ) || $post_types_option['attachment']['add_meta_box'] ) {
if ( self::user_can_restrict() ) {
$user = new Groups_User( get_current_user_id() );
$output = "";
$post_singular_name = __( 'Media', 'groups' );
$output .= __( "Enforce read access", 'groups' );
$read_caps = get_post_meta( $post->ID, Groups_Post_Access_Legacy::POSTMETA_PREFIX . Groups_Post_Access_Legacy::READ_POST_CAPABILITY );
$valid_read_caps = self::get_valid_read_caps_for_user();
// On attachments edited within the 'Insert Media' popup, the update is triggered too soon and we end up with only the last capability selected.
// This occurs when using normal checkboxes as well as the select below (Chosen and Selectize tested).
// With checkboxes it's even more confusing, it's actually better to have it using a select as below,
// because the visual feedback corresponds with what is assigned.
// See http://wordpress.org/support/topic/multiple-access-restrictions-for-media-items-are-not-saved-in-grid-view
// and https://core.trac.wordpress.org/ticket/28053 - this is an issue with multiple value fields and should
// be fixed within WordPress.
// $output .= '
';
$output .= sprintf( __( "Only groups or users that have one of the selected capabilities are allowed to read this %s.", 'groups' ), $post_singular_name );
$output .= '
';
$form_fields['groups_access'] = array(
'label' => __( 'Access restrictions', 'groups' ),
'input' => 'html',
'html' => $output
);
}
}
return $form_fields;
}
/**
* Save capabilities for attachment post type (Media).
* When multiple attachments are saved, this is called once for each.
* @param array $post post data
* @param array $attachment attachment field data
* @return array
*/
public static function attachment_fields_to_save( $post, $attachment ) {
$post_types_option = Groups_Options::get_option( Groups_Post_Access_Legacy::POST_TYPES, array() );
if ( !isset( $post_types_option['attachment']['add_meta_box'] ) || $post_types_option['attachment']['add_meta_box'] ) {
// if we're here, we assume the user is allowed to edit attachments,
// but we still need to check if the user can restrict access
if ( self::user_can_restrict() ) {
$post_id = null;
if ( isset( $post['ID'] ) ) {
$post_id = $post['ID'];
} else if ( isset( $post['post_ID'] ) ) {
$post_id = $post['post_ID'];
}
if ( $post_id !== null ) {
$valid_read_caps = self::get_valid_read_caps_for_user();
foreach( $valid_read_caps as $valid_read_cap ) {
if ( $capability = Groups_Capability::read_by_capability( $valid_read_cap ) ) {
if ( !empty( $attachment[self::CAPABILITY] ) && is_array( $attachment[self::CAPABILITY] ) && in_array( $capability->capability_id, $attachment[self::CAPABILITY] ) ) {
Groups_Post_Access_Legacy::create( array(
'post_id' => $post_id,
'capability' => $capability->capability
) );
} else {
Groups_Post_Access_Legacy::delete( $post_id, $capability->capability );
}
}
}
}
}
}
return $post;
}
/**
* Returns true if the current user has at least one of the capabilities
* that can be used to restrict access to posts.
* @return boolean
*/
public static function user_can_restrict() {
$has_read_cap = false;
$user = new Groups_User( get_current_user_id() );
$valid_read_caps = Groups_Options::get_option( Groups_Post_Access_Legacy::READ_POST_CAPABILITIES, array( Groups_Post_Access_Legacy::READ_POST_CAPABILITY ) );
foreach( $valid_read_caps as $valid_read_cap ) {
if ( $capability = Groups_Capability::read_by_capability( $valid_read_cap ) ) {
if ( $user->can( $capability->capability_id ) ) {
$has_read_cap = true;
break;
}
}
}
return $has_read_cap;
}
/**
* @return array of valid read capabilities for the current or given user
*/
public static function get_valid_read_caps_for_user( $user_id = null ) {
$result = array();
$user = new Groups_User( $user_id === null ? get_current_user_id() : $user_id );
$valid_read_caps = Groups_Options::get_option( Groups_Post_Access_Legacy::READ_POST_CAPABILITIES, array( Groups_Post_Access_Legacy::READ_POST_CAPABILITY ) );
foreach( $valid_read_caps as $valid_read_cap ) {
if ( $capability = Groups_Capability::read_by_capability( $valid_read_cap ) ) {
if ( $user->can( $capability->capability ) ) {
$result[] = $valid_read_cap;
}
}
}
return $result;
}
}
Groups_Access_Meta_Boxes_Legacy::init();