PluginProbe
Groups – Memberships and Access Control / 1.10.0
Groups – Memberships and Access Control v1.10.0
4.7.1 4.7.0 4.6.0 4.5.0 4.4.0 4.3.0 trunk 1.0.0-beta-1 1.0.0-beta-2 1.0.0-beta-3 1.0.0-beta-3b 1.0.0-beta-3c 1.0.0-beta-3d 1.1.4 1.1.5 1.10.0 1.10.1 1.10.2 1.10.3 1.11.0 1.11.1 1.11.2 1.11.3 1.12.0 1.13.0 All 131 releases
groups / lib / access / class-groups-access-meta-boxes.php

class-groups-access-meta-boxes.php in Groups – Memberships and Access Control 1.10.0, at lib/access/class-groups-access-meta-boxes.php

688 lines 30.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * class-groups-access-meta-boxes.php
4 *
5 * Copyright (c) "kento" Karim Rahimpur www.itthinx.com
6 *
7 * This code is released under the GNU General Public License.
8 * See COPYRIGHT.txt and LICENSE.txt.
9 *
10 * This code is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * This header and all notices must be kept intact.
16 *
17 * @author Karim Rahimpur
18 * @package groups
19 * @since groups 1.0.0
20 */
21
22 if ( !defined( 'ABSPATH' ) ) {
23 exit;
24 }
25
26 /**
27 * Adds meta boxes to edit screens.
28 *
29 * @link http://codex.wordpress.org/Function_Reference/add_meta_box
30 */
31 class Groups_Access_Meta_Boxes {
32
33 const NONCE = 'groups-meta-box-nonce';
34 const SET_CAPABILITY = 'set-capability';
35 const READ_ACCESS = 'read-access';
36 const CAPABILITY = 'capability';
37 const SHOW_GROUPS = 'access-meta-box-show-groups';
38
39 /**
40 * Sets up an init hook where actions and filters are added.
41 */
42 public static function init() {
43 add_action( 'init', array( __CLASS__, 'wp_init' ) );
44 add_action( 'admin_init', array(__CLASS__,'admin_init' ) );
45 }
46
47 /**
48 * Hooks for capabilities meta box and saving options.
49 */
50 public static function wp_init() {
51 if ( current_user_can( GROUPS_ACCESS_GROUPS ) ) {
52 require_once GROUPS_VIEWS_LIB . '/class-groups-uie.php';
53
54 add_action( 'add_meta_boxes', array( __CLASS__, "add_meta_boxes" ), 10, 2 );
55 add_action( 'save_post', array( __CLASS__, "save_post" ), 10, 2 );
56 add_filter( 'wp_insert_post_empty_content', array( __CLASS__, 'wp_insert_post_empty_content' ), 10, 2 );
57
58 add_filter( 'attachment_fields_to_edit', array( __CLASS__, 'attachment_fields_to_edit' ), 10, 2 );
59 add_filter( 'attachment_fields_to_save', array( __CLASS__, 'attachment_fields_to_save' ), 10, 2 );
60 }
61 }
62
63 /**
64 * Hooked on admin_init to register our action on admin_enqueue_scripts.
65 */
66 public static function admin_init() {
67 add_action( 'admin_enqueue_scripts', array( __CLASS__, 'admin_enqueue_scripts' ) );
68 }
69
70 /**
71 * Hooked on admin_enqueue_scripts to timely enqueue resources required
72 * on the media upload / attachment popup.
73 */
74 public static function admin_enqueue_scripts() {
75 global $pagenow;
76 if ( $pagenow == 'upload.php' ) {
77 Groups_UIE::enqueue( 'select' );
78 }
79
80 }
81
82 /**
83 * Triggered by init() to add capability meta box.
84 */
85 public static function add_meta_boxes( $post_type, $post = null ) {
86 global $wp_version;
87 $post_type_object = get_post_type_object( $post_type );
88 if ( $post_type_object && $post_type != 'attachment' ) {
89 $post_types_option = Groups_Options::get_option( Groups_Post_Access::POST_TYPES, array() );
90 if ( !isset( $post_types_option[$post_type]['add_meta_box'] ) || $post_types_option[$post_type]['add_meta_box'] ) {
91 if ( $wp_version < 3.3 ) {
92 $post_types = get_post_types();
93 foreach ( $post_types as $post_type ) {
94 add_meta_box(
95 "groups-access",
96 __( "Access restrictions", GROUPS_PLUGIN_DOMAIN ),
97 array( __CLASS__, "capability" ),
98 $post_type,
99 "side",
100 "high"
101 );
102 }
103 } else {
104 add_meta_box(
105 "groups-access",
106 __( "Access restrictions", GROUPS_PLUGIN_DOMAIN ),
107 array( __CLASS__, "capability" ),
108 null,
109 "side",
110 "high"
111 );
112 }
113
114 Groups_UIE::enqueue( 'select' );
115
116 if ( current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
117 if ( $screen = get_current_screen() ) {
118 $screen->add_help_tab( array(
119 'id' => 'groups-access',
120 'title' => __( 'Access restrictions', GROUPS_PLUGIN_DOMAIN ),
121 'content' =>
122 '<p>' .
123 '<strong>' . __( 'Access restrictions', GROUPS_PLUGIN_DOMAIN ) . '</strong>' .
124 '</p>' .
125 '<p>' .
126 __( 'Use the <em>Access restrictions</em> box to limit the visibility of posts, pages and other post types.', GROUPS_PLUGIN_DOMAIN ) .
127 '</p>' .
128 '<p>' .
129 __( 'You can select one or more capabilities that are enabled for access restriction.', GROUPS_PLUGIN_DOMAIN ) .
130 ' ' .
131 __( 'Note that you must be a member of a group that has such a capability assigned.', GROUPS_PLUGIN_DOMAIN ) .
132 '</p>' .
133 '<p>' .
134 '<strong>' . __( 'Example:', GROUPS_PLUGIN_DOMAIN ) . '</strong>' .
135 '</p>' .
136 __( 'Let\'s assume that you want to limit the visibility of a post to members of the <em>Premium</em> group.', GROUPS_PLUGIN_DOMAIN ) .
137 '<p>' .
138 '<strong>' . __( 'The quick way:', GROUPS_PLUGIN_DOMAIN ) . '</strong>' .
139 ' ' .
140 __( 'Using the quick-create field', GROUPS_PLUGIN_DOMAIN ) .
141 '</p>' .
142 __( 'Enter <em>Premium</em> in the quick-create field located in the Access restrictions panel and save or update the post (or hit Enter).', GROUPS_PLUGIN_DOMAIN ) .
143 '<p>' .
144 '<p>' .
145 __( '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_PLUGIN_DOMAIN ) .
146 '</p>' .
147 '<em>' . __( 'The manual way:', GROUPS_PLUGIN_DOMAIN ) . '</em>' .
148 ' ' .
149 __( 'Adding the group and capability manually and enabling it for access restriction', GROUPS_PLUGIN_DOMAIN ) .
150 '</p>' .
151 '<p>' .
152 __( 'Try the quick-create field first. Unless you need a more complex setup, there is no reason to go this way instead.', GROUPS_PLUGIN_DOMAIN ) .
153 '</p>' .
154 '<ol>' .
155 '<li>' . __( 'Go to <strong>Groups > Groups</strong> and add the <em>Premium</em> group.', GROUPS_PLUGIN_DOMAIN ) . '</li>' .
156 '<li>' . __( 'Go to <strong>Groups > Capabilities</strong> and add the <em>premium</em> capability.', GROUPS_PLUGIN_DOMAIN ) . '</li>' .
157 '<li>' . __( 'Go to <strong>Groups > Groups</strong> and assign the <em>premium</em> capability to the <em>Premium</em> group.', GROUPS_PLUGIN_DOMAIN ) . '</li>' .
158 '<li>' . __( 'Go to <strong>Groups > Options</strong> and enable the <em>premium</em> capability to restrict access.', GROUPS_PLUGIN_DOMAIN ) . '</li>' .
159 '<li>' . __( 'Become a member of the <em>Premium</em> group - this is required so you can choose the <em>premium</em> capability to restrict access to a post.', GROUPS_PLUGIN_DOMAIN ) . '</li>' .
160 '<li>' . __( 'Edit the post for which you want to restrict access and choose<sup>*</sup> the <em>premium</em> capability.', GROUPS_PLUGIN_DOMAIN ) . '</li>' .
161 '</ol>' .
162 '<p>' .
163 __( '<sup>*</sup> 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_PLUGIN_DOMAIN ) .
164 '</p>'
165 ) );
166 }
167 }
168 }
169 }
170 }
171
172 /**
173 * Render meta box for capabilities.
174 *
175 * @see do_meta_boxes()
176 *
177 * @param Object $object
178 * @param Object $box
179 */
180 public static function capability( $object = null, $box = null ) {
181
182 $output = "";
183
184 $show_groups = Groups_Options::get_user_option( self::SHOW_GROUPS, true );
185
186 $post_id = isset( $object->ID ) ? $object->ID : null;
187 $post_type = isset( $object->post_type ) ? $object->post_type : null;
188 $post_singular_name = __( "Post", GROUPS_PLUGIN_DOMAIN );
189 if ( $post_type !== null ) {
190 $post_type_object = get_post_type_object( $post_type );
191 $labels = isset( $post_type_object->labels ) ? $post_type_object->labels : null;
192 if ( $labels !== null ) {
193 if ( isset( $labels->singular_name ) ) {
194 $post_singular_name = __( $labels->singular_name );
195 }
196 }
197 }
198
199 $output .= wp_nonce_field( self::SET_CAPABILITY, self::NONCE, true, false );
200
201 if ( self::user_can_restrict() ) {
202 $user = new Groups_User( get_current_user_id() );
203 $output .= __( "Enforce read access", GROUPS_PLUGIN_DOMAIN );
204
205 $read_caps = get_post_meta( $post_id, Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ_POST_CAPABILITY );
206 $valid_read_caps = Groups_Options::get_option( Groups_Post_Access::READ_POST_CAPABILITIES, array( Groups_Post_Access::READ_POST_CAPABILITY ) );
207 $output .= '<div class="select-capability-container">';
208 $output .= sprintf(
209 '<select class="select capability" name="%s" multiple="multiple" placeholder="%s" data-placeholder="%s" title="%s">',
210 self::CAPABILITY . '[]',
211 __( 'Type and choose &hellip;', GROUPS_PLUGIN_DOMAIN),
212 __( 'Type and choose &hellip;', GROUPS_PLUGIN_DOMAIN),
213 __( 'Choose one or more capabilities to restrict access. Groups that grant access through the capabilities are shown in parenthesis. If no capabilities are available yet, you can use the quick-create box to create a group and capability enabled for access restriction on the fly.', GROUPS_PLUGIN_DOMAIN )
214 );
215 $output .= '<option value=""></option>';
216 foreach( $valid_read_caps as $valid_read_cap ) {
217 if ( $capability = Groups_Capability::read_by_capability( $valid_read_cap ) ) {
218 if ( $user->can( $capability->capability ) ) {
219 $c = new Groups_Capability( $capability->capability_id );
220 $groups = $c->groups;
221 $group_names = array();
222 if ( !empty( $groups ) ) {
223 foreach( $groups as $group ) {
224 $group_names[] = $group->name;
225 }
226 }
227 if ( count( $group_names ) > 0 ) {
228 $label_title = sprintf(
229 _n(
230 'Members of the %1$s group can access this %2$s through this capability.',
231 'Members of the %1$s groups can access this %2$s through this capability.',
232 count( $group_names ),
233 GROUPS_PLUGIN_DOMAIN
234 ),
235 wp_filter_nohtml_kses( implode( ',', $group_names ) ),
236 $post_singular_name
237 );
238 } else {
239 $label_title = __( 'No groups grant access through this capability. To grant access to group members using this capability, you should assign it to a group and enable the capability for access restriction.', GROUPS_PLUGIN_DOMAIN );
240 }
241 $output .= sprintf( '<option value="%s" %s>', esc_attr( $capability->capability_id ), in_array( $capability->capability, $read_caps ) ? ' selected="selected" ' : '' );
242 $output .= wp_filter_nohtml_kses( $capability->capability );
243 if ( $show_groups ) {
244 if ( count( $group_names ) > 0 ) {
245 $output .= ' ';
246 $output .= '(' . wp_filter_nohtml_kses( implode( ', ', $group_names ) ) . ')';
247 }
248 }
249 $output .= '</option>';
250 }
251 }
252 }
253 $output .= '</select>';
254
255 $output .= Groups_UIE::render_select( '.select.capability' );
256 // $output .= '<script type="text/javascript">';
257 // $output .= 'if (typeof jQuery !== "undefined"){';
258 // if ( self::WHICH_SELECT == 'chosen' ) {
259 // $output .= 'jQuery(".select.capability").chosen({width:"100%",search_contains:true});';
260 // } else {
261 // $output .= 'jQuery(".select.capability").selectize({plugins: ["remove_button"]});';
262 // }
263 // $output .= '}';
264 // $output .= '</script>';
265 // $output .= '<style type="text/css">';
266 // $output .= '.select-capability-container input[type="text"] { min-height: 2em; }';
267 // $output .= '</style>';
268 $output .= '</div>';
269
270 $output .= '<p class="description">';
271 $output .= sprintf( __( "Only groups or users that have one of the selected capabilities are allowed to read this %s.", GROUPS_PLUGIN_DOMAIN ), $post_singular_name );
272 $output .= '</p>';
273
274 $output .= '<p class="description">';
275 $output .= sprintf( '<label title="%s">', __( 'Click to toggle the display of groups that grant the capabilities.', GROUPS_PLUGIN_DOMAIN ) );
276 $output .= sprintf( '<input id="access-show-groups" type="checkbox" name="%s" %s />', esc_attr( self::SHOW_GROUPS ), $show_groups ? ' checked="checked" ' : '' );
277 $output .= ' ';
278 $output .= __( 'Show groups', GROUPS_PLUGIN_DOMAIN );
279 $output .= '</label>';
280 $output .= '</p>';
281 $output .= '<script type="text/javascript">';
282 $output .= 'if (typeof jQuery !== "undefined"){';
283 $output .= !$show_groups ? 'jQuery("span.groups.description").hide();' : '';
284 $output .= 'jQuery("#access-show-groups").click(function(){';
285 $output .= 'jQuery("span.groups.description").toggle();';
286 $output .= '});';
287 $output .= '}';
288 $output .= '</script>';
289 } else {
290 $output .= '<p class="description">';
291 $output .= sprintf( __( 'You cannot set any access restrictions.', GROUPS_PLUGIN_DOMAIN ), $post_singular_name );
292 $style = 'cursor:help;vertical-align:middle;';
293 if ( current_user_can( GROUPS_ADMINISTER_OPTIONS ) ) {
294 $style = 'cursor:pointer;vertical-align:middle;';
295 $output .= sprintf( '<a href="%s">', esc_url( admin_url( 'admin.php?page=groups-admin-options' ) ) );
296 }
297 $output .= sprintf( '<img style="%s" alt="?" title="%s" src="%s" />', $style, esc_attr( __( 'You must be in a group that has at least one capability enabled to enforce read access.', GROUPS_PLUGIN_DOMAIN ) ), esc_attr( GROUPS_PLUGIN_URL . 'images/help.png' ) );
298 if ( current_user_can( GROUPS_ADMINISTER_OPTIONS ) ) {
299 $output .= '</a>';
300 }
301 $output .= '</p>';
302 }
303
304 // quick-create
305 if ( current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
306 $style = 'cursor:help;vertical-align:middle;';
307 $output .= '<div class="quick-create-group-capability" style="margin:4px 0">';
308 $output .= '<label>';
309 $output .= sprintf( '<input style="width:100%%;margin-right:-20px;" id="quick-group-capability" name="quick-group-capability" class="quick-group-capability" type="text" value="" placeholder="%s"/>', __( 'Quick-create group &amp; capability', GROUPS_PLUGIN_DOMAIN ) );
310 $output .= sprintf(
311 '<img id="quick-create-help-icon" style="%s" alt="?" title="%s" src="%s" />',
312 $style,
313 esc_attr( __( 'You can create a new group and capability here. 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_PLUGIN_DOMAIN ) ),
314 esc_attr( GROUPS_PLUGIN_URL . 'images/help.png' )
315 );
316 $output .= '</label>';
317 $output .= '</div>';
318 $output .= '<script type="text/javascript">';
319 $output .= 'if (typeof jQuery !== "undefined"){';
320 $output .= 'jQuery("#quick-create-help-icon").click(function(){';
321 $output .= 'jQuery("#contextual-help-link").click();';
322 $output .= '});';
323 $output .= '}';
324 $output .= '</script>';
325 }
326
327 echo $output;
328 }
329
330 /**
331 * Invokes our save_post() if the post content is considered empty.
332 * This is required because even on an empty post, we want to allow to
333 * quick-create group and category as well as assign capabilities.
334 * At WordPress 3.6.1, this is the only way we can achieve that, because
335 * the save_post action is not invoked if the post content is considered
336 * empty.
337 *
338 * @param boolean $maybe_empty
339 * @param array $postarr
340 * @return boolean
341 */
342 public static function wp_insert_post_empty_content( $maybe_empty, $postarr ) {
343
344 // Only consider invoking save_post() here, if the post content is
345 // considered to be empty at this stage. This is so we don't end up
346 // having save_post() invoked twice when the post is not empty.
347 if ( $maybe_empty ) {
348 $post_id = !empty( $postarr['ID'] ) ? $postarr['ID'] : !empty( $postarr['post_ID'] ) ? $postarr['post_ID'] : null;
349 if ( $post_id ) {
350 self::save_post( $post_id );
351 }
352 }
353
354 return $maybe_empty;
355 }
356
357 /**
358 * Save capability options.
359 *
360 * @param int $post_id
361 * @param mixed $post post data (not used here)
362 */
363 public static function save_post( $post_id = null, $post = null ) {
364 if ( ( defined( "DOING_AUTOSAVE" ) && DOING_AUTOSAVE ) ) {
365 } else {
366 $post_type = get_post_type( $post_id );
367 $post_type_object = get_post_type_object( $post_type );
368 if ( $post_type_object && $post_type != 'attachment' ) {
369 $post_types_option = Groups_Options::get_option( Groups_Post_Access::POST_TYPES, array() );
370 if ( !isset( $post_types_option[$post_type]['add_meta_box'] ) || $post_types_option[$post_type]['add_meta_box'] ) {
371 if ( isset( $_POST[self::NONCE] ) && wp_verify_nonce( $_POST[self::NONCE], self::SET_CAPABILITY ) ) {
372 $post_type = isset( $_POST["post_type"] ) ? $_POST["post_type"] : null;
373 if ( $post_type !== null ) {
374 // See http://codex.wordpress.org/Function_Reference/current_user_can 20130119 WP 3.5
375 // "... Some capability checks (like 'edit_post' or 'delete_page') require this [the post ID] be provided."
376 // If the post ID is not provided, it will throw:
377 // PHP Notice: Undefined offset: 0 in /var/www/groups-forums/wp-includes/capabilities.php on line 1067
378 $edit_post_type = 'edit_' . $post_type;
379 if ( $post_type_object = get_post_type_object( $post_type ) ) {
380 if ( !isset( $post_type_object->capabilities ) ) {
381 // get_post_type_capabilities() (WP 3.8) will throw a warning
382 // when trying to merge the missing property otherwise. It's either a
383 // bug or the function's documentation should make it clear that you
384 // have to provide that.
385 $post_type_object->capabilities = array();
386 }
387 $caps_object = get_post_type_capabilities( $post_type_object );
388 if ( isset( $caps_object->edit_post ) ) {
389 $edit_post_type = $caps_object->edit_post;
390 }
391 }
392
393 if ( current_user_can( $edit_post_type, $post_id ) ) {
394 // quick-create ?
395 if ( current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
396 if ( !empty( $_POST['quick-group-capability'] ) ) {
397 $creator_id = get_current_user_id();
398 $datetime = date( 'Y-m-d H:i:s', time() );
399 $name = ucfirst( strtolower( trim( $_POST['quick-group-capability'] ) ) );
400 if ( strlen( $name ) > 0 ) {
401 // create or obtain the group
402 if ( $group = Groups_Group::read_by_name( $name ) ) {
403 } else {
404 if ( $group_id = Groups_Group::create( compact( 'creator_id', 'datetime', 'name' ) ) ) {
405 $group = Groups_Group::read( $group_id );
406 }
407 }
408 // create or obtain the capability
409 $name = strtolower( $name );
410 if ( $capability = Groups_Capability::read_by_capability( $name ) ) {
411 } else {
412 if ( $capability_id = Groups_Capability::create( array( 'capability' => $name ) ) ) {
413 $capability = Groups_Capability::read( $capability_id );
414 }
415 }
416 if ( $group && $capability ) {
417 // add the capability to the group
418 if ( !Groups_Group_Capability::read( $group->group_id, $capability->capability_id ) ) {
419 Groups_Group_Capability::create(
420 array(
421 'group_id' => $group->group_id,
422 'capability_id' => $capability->capability_id
423 )
424 );
425 }
426 // enable the capability for access restriction
427 $valid_read_caps = Groups_Options::get_option( Groups_Post_Access::READ_POST_CAPABILITIES, array( Groups_Post_Access::READ_POST_CAPABILITY ) );
428 if ( !in_array( $capability->capability, $valid_read_caps ) ) {
429 $valid_read_caps[] = $capability->capability;
430 }
431 Groups_Options::update_option( Groups_Post_Access::READ_POST_CAPABILITIES, $valid_read_caps );
432 // add the current user to the group
433 Groups_User_Group::create(
434 array(
435 'user_id' => get_current_user_id(),
436 'group_id' => $group->group_id
437 )
438 );
439 // put the capability ID in $_POST[self::CAPABILITY] so it is treated below
440 if ( empty( $_POST[self::CAPABILITY] ) ) {
441 $_POST[self::CAPABILITY] = array();
442 }
443 if ( !in_array( $capability->capability_id, $_POST[self::CAPABILITY] ) ) {
444 $_POST[self::CAPABILITY][] = $capability->capability_id;
445 }
446 }
447 }
448 }
449 }
450 // set
451 if ( self::user_can_restrict() ) {
452 $valid_read_caps = self::get_valid_read_caps_for_user();
453 foreach( $valid_read_caps as $valid_read_cap ) {
454 if ( $capability = Groups_Capability::read_by_capability( $valid_read_cap ) ) {
455 if ( !empty( $_POST[self::CAPABILITY] ) && is_array( $_POST[self::CAPABILITY] ) && in_array( $capability->capability_id, $_POST[self::CAPABILITY] ) ) {
456 Groups_Post_Access::create( array(
457 'post_id' => $post_id,
458 'capability' => $capability->capability
459 ) );
460 } else {
461 Groups_Post_Access::delete( $post_id, $capability->capability );
462 }
463 }
464 }
465 }
466 // show groups
467 Groups_Options::update_user_option( self::SHOW_GROUPS, !empty( $_POST[self::SHOW_GROUPS] ) );
468 }
469 }
470 }
471 }
472 }
473 }
474 }
475
476 /**
477 * Enqueue scripts and styles.
478 */
479 private static function enqueue() {
480 global $groups_version;
481 if ( self::WHICH_SELECT == 'chosen' ) {
482 if ( !wp_script_is( 'chosen' ) ) {
483 wp_enqueue_script( 'chosen', GROUPS_PLUGIN_URL . 'js/chosen/chosen.jquery.min.js', array( 'jquery' ), $groups_version, false );
484 }
485 if ( !wp_style_is( 'chosen' ) ) {
486 wp_enqueue_style( 'chosen', GROUPS_PLUGIN_URL . 'css/chosen/chosen.min.css', array(), $groups_version );
487 }
488 } else {
489 if ( !wp_script_is( 'selectize' ) ) {
490 wp_enqueue_script( 'selectize', GROUPS_PLUGIN_URL . 'js/selectize/selectize.min.js', array( 'jquery' ), $groups_version, false );
491 }
492 if ( !wp_style_is( 'selectize' ) ) {
493 wp_enqueue_style( 'selectize', GROUPS_PLUGIN_URL . 'css/selectize/selectize.bootstrap2.css', array(), $groups_version );
494 }
495 }
496 }
497
498 /**
499 * Render capabilities box for attachment post type (Media).
500 * @param array $form_fields
501 * @param object $post
502 * @return array
503 */
504 public static function attachment_fields_to_edit( $form_fields, $post ) {
505
506 Groups_UIE::enqueue( 'select' );
507
508 $post_types_option = Groups_Options::get_option( Groups_Post_Access::POST_TYPES, array() );
509 if ( !isset( $post_types_option['attachment']['add_meta_box'] ) || $post_types_option['attachment']['add_meta_box'] ) {
510 if ( self::user_can_restrict() ) {
511 $user = new Groups_User( get_current_user_id() );
512 $output = "";
513 $post_singular_name = __( 'Media', GROUPS_PLUGIN_DOMAIN );
514
515 $output .= __( "Enforce read access", GROUPS_PLUGIN_DOMAIN );
516 $read_caps = get_post_meta( $post->ID, Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ_POST_CAPABILITY );
517 $valid_read_caps = self::get_valid_read_caps_for_user();
518
519 // On attachments edited within the 'Insert Media' popup, the update is triggered too soon and we end up with only the last capability selected.
520 // This occurs when using normal checkboxes as well as the select below (Chosen and Selectize tested).
521 // With checkboxes it's even more confusing, it's actually better to have it using a select as below,
522 // because the visual feedback corresponds with what is assigned.
523 // See http://wordpress.org/support/topic/multiple-access-restrictions-for-media-items-are-not-saved-in-grid-view
524 // and https://core.trac.wordpress.org/ticket/28053 - this is an issue with multiple value fields and should
525 // be fixed within WordPress.
526
527 // $output .= '<div style="padding:0 1em;margin:1em 0;border:1px solid #ccc;border-radius:4px;">';
528 // $output .= '<ul>';
529 // foreach( $valid_read_caps as $valid_read_cap ) {
530 // if ( $capability = Groups_Capability::read_by_capability( $valid_read_cap ) ) {
531 // $checked = in_array( $capability->capability, $read_caps ) ? ' checked="checked" ' : '';
532 // $output .= '<li>';
533 // $output .= '<label>';
534 // $output .= '<input name="attachments[' . $post->ID . '][' . self::CAPABILITY . '][]" ' . $checked . ' type="checkbox" value="' . esc_attr( $capability->capability_id ) . '" />';
535 // $output .= wp_filter_nohtml_kses( $capability->capability );
536 // $output .= '</label>';
537 // $output .= '</li>';
538 // }
539 // }
540 // $output .= '</ul>';
541 // $output .= '</div>';
542
543 $show_groups = Groups_Options::get_user_option( self::SHOW_GROUPS, true );
544 $output .= '<div class="select-capability-container">';
545 $select_id = 'attachments-' . $post->ID . '-' . self::CAPABILITY;
546 $output .= sprintf(
547 '<select id="%s" class="select capability" name="%s" multiple="multiple" data-placeholder="%s" title="%s">',
548 $select_id,
549 'attachments[' . $post->ID . '][' . self::CAPABILITY . '][]',
550 __( 'Type and choose &hellip;', GROUPS_PLUGIN_DOMAIN),
551 __( 'Choose one or more capabilities to restrict access. Groups that grant access through the capabilities are shown in parenthesis. If no capabilities are available yet, you can use the quick-create box to create a group and capability enabled for access restriction on the fly.', GROUPS_PLUGIN_DOMAIN )
552 );
553 $output .= '<option value=""></option>';
554 foreach( $valid_read_caps as $valid_read_cap ) {
555 if ( $capability = Groups_Capability::read_by_capability( $valid_read_cap ) ) {
556 if ( $user->can( $capability->capability ) ) {
557 $c = new Groups_Capability( $capability->capability_id );
558 $groups = $c->groups;
559 $group_names = array();
560 if ( !empty( $groups ) ) {
561 foreach( $groups as $group ) {
562 $group_names[] = $group->name;
563 }
564 }
565 if ( count( $group_names ) > 0 ) {
566 $label_title = sprintf(
567 _n(
568 'Members of the %1$s group can access this %2$s through this capability.',
569 'Members of the %1$s groups can access this %2$s through this capability.',
570 count( $group_names ),
571 GROUPS_PLUGIN_DOMAIN
572 ),
573 wp_filter_nohtml_kses( implode( ',', $group_names ) ),
574 $post_singular_name
575 );
576 } else {
577 $label_title = __( 'No groups grant access through this capability. To grant access to group members using this capability, you should assign it to a group and enable the capability for access restriction.', GROUPS_PLUGIN_DOMAIN );
578 }
579 $output .= sprintf( '<option value="%s" %s>', esc_attr( $capability->capability_id ), in_array( $capability->capability, $read_caps ) ? ' selected="selected" ' : '' );
580 $output .= wp_filter_nohtml_kses( $capability->capability );
581 if ( $show_groups ) {
582 if ( count( $group_names ) > 0 ) {
583 $output .= ' ';
584 $output .= '(' . wp_filter_nohtml_kses( implode( ', ', $group_names ) ) . ')';
585 }
586 }
587 $output .= '</option>';
588 }
589 }
590 }
591 $output .= '</select>';
592
593 $output .= Groups_UIE::render_select( '#'.$select_id );
594
595 $output .= '</div>';
596
597 $output .= '<p class="description">';
598 $output .= sprintf( __( "Only groups or users that have one of the selected capabilities are allowed to read this %s.", GROUPS_PLUGIN_DOMAIN ), $post_singular_name );
599 $output .= '</p>';
600
601 $form_fields['groups_access'] = array(
602 'label' => __( 'Access restrictions', GROUPS_PLUGIN_DOMAIN ),
603 'input' => 'html',
604 'html' => $output
605 );
606 }
607 }
608 return $form_fields;
609 }
610
611 /**
612 * Save capabilities for attachment post type (Media).
613 * When multiple attachments are saved, this is called once for each.
614 * @param array $post post data
615 * @param array $attachment attachment field data
616 * @return array
617 */
618 public static function attachment_fields_to_save( $post, $attachment ) {
619 $post_types_option = Groups_Options::get_option( Groups_Post_Access::POST_TYPES, array() );
620 if ( !isset( $post_types_option['attachment']['add_meta_box'] ) || $post_types_option['attachment']['add_meta_box'] ) {
621 // if we're here, we assume the user is allowed to edit attachments,
622 // but we still need to check if the user can restrict access
623 if ( self::user_can_restrict() ) {
624 $post_id = null;
625 if ( isset( $post['ID'] ) ) {
626 $post_id = $post['ID'];
627 } else if ( isset( $post['post_ID'] ) ) {
628 $post_id = $post['post_ID'];
629 }
630 if ( $post_id !== null ) {
631 $valid_read_caps = self::get_valid_read_caps_for_user();
632 foreach( $valid_read_caps as $valid_read_cap ) {
633 if ( $capability = Groups_Capability::read_by_capability( $valid_read_cap ) ) {
634 if ( !empty( $attachment[self::CAPABILITY] ) && is_array( $attachment[self::CAPABILITY] ) && in_array( $capability->capability_id, $attachment[self::CAPABILITY] ) ) {
635 Groups_Post_Access::create( array(
636 'post_id' => $post_id,
637 'capability' => $capability->capability
638 ) );
639 } else {
640 Groups_Post_Access::delete( $post_id, $capability->capability );
641 }
642 }
643 }
644 }
645 }
646 }
647 return $post;
648 }
649
650 /**
651 * Returns true if the current user has at least one of the capabilities
652 * that can be used to restrict access to posts.
653 * @return boolean
654 */
655 public static function user_can_restrict() {
656 $has_read_cap = false;
657 $user = new Groups_User( get_current_user_id() );
658 $valid_read_caps = Groups_Options::get_option( Groups_Post_Access::READ_POST_CAPABILITIES, array( Groups_Post_Access::READ_POST_CAPABILITY ) );
659 foreach( $valid_read_caps as $valid_read_cap ) {
660 if ( $capability = Groups_Capability::read_by_capability( $valid_read_cap ) ) {
661 if ( $user->can( $capability->capability_id ) ) {
662 $has_read_cap = true;
663 break;
664 }
665 }
666 }
667 return $has_read_cap;
668 }
669
670 /**
671 * @return array of valid read capabilities for the current or given user
672 */
673 public static function get_valid_read_caps_for_user( $user_id = null ) {
674 $result = array();
675 $user = new Groups_User( $user_id === null ? get_current_user_id() : $user_id );
676 $valid_read_caps = Groups_Options::get_option( Groups_Post_Access::READ_POST_CAPABILITIES, array( Groups_Post_Access::READ_POST_CAPABILITY ) );
677 foreach( $valid_read_caps as $valid_read_cap ) {
678 if ( $capability = Groups_Capability::read_by_capability( $valid_read_cap ) ) {
679 if ( $user->can( $capability->capability ) ) {
680 $result[] = $valid_read_cap;
681 }
682 }
683 }
684 return $result;
685 }
686 }
687 Groups_Access_Meta_Boxes::init();
688