PluginProbe
Groups – Memberships and Access Control / 1.10.3
Groups – Memberships and Access Control v1.10.3
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.3, at lib/access/class-groups-access-meta-boxes.php

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