PluginProbe
Groups – Memberships and Access Control / 4.7.0
Groups – Memberships and Access Control v4.7.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
← All changes | lib/admin/class-groups-admin-posts.php +449 -109 1.11.34.7.0 View file →
@@ -23,15 +23,37 @@
23 23 exit;
24 24 }
25 25
26 26 /**
27 - * Additions to post overview admin screens.
27 + * Additions to post overview admin screens:
28 + *
29 + * - Filter posts by group.
30 + * - Apply bulk actions to add or remove group access restrictions.
28 31 */
29 32 class Groups_Admin_Posts {
30 33
31 - const NOT_RESTRICTED = "#not-restricted#";
34 + /**
35 + * Field name.
36 + *
37 + * @var string
38 + */
39 + const GROUPS_READ = 'groups-read';
32 40
33 41 /**
42 + * Constant for not restricted.
43 + *
44 + * @var string NOT_RESTRICTED
45 + */
46 + const NOT_RESTRICTED = '#not-restricted#';
47 +
48 + /**
49 + * Constant for restricted.
50 + *
51 + * @var string RESTRICTED
52 + */
53 + const RESTRICTED = '#restricted#';
54 +
55 + /**
34 56 * Sets up an admin_init hook where our actions and filters are added.
35 57 */
36 58 public static function init() {
37 59 add_action( 'admin_init', array( __CLASS__, 'admin_init' ) );
@@ -41,14 +63,18 @@
41 63 * Adds actions and filters to handle filtering by access restriction
42 64 * capability.
43 65 */
44 66 public static function admin_init() {
45 - if ( current_user_can( GROUPS_ACCESS_GROUPS ) ) {
67 + if ( Groups_User::current_user_can( GROUPS_ACCESS_GROUPS ) ) {
46 68 add_action( 'admin_enqueue_scripts', array( __CLASS__, 'admin_enqueue_scripts' ) );
47 69 add_action( 'admin_head', array( __CLASS__, 'admin_head' ) );
48 70 add_action( 'restrict_manage_posts', array( __CLASS__, 'restrict_manage_posts' ) );
49 - add_filter( 'parse_query', array( __CLASS__, 'parse_query' ) );
71 + // add_filter( 'parse_query', array( __CLASS__, 'parse_query' ) );
50 72
73 + add_filter( 'posts_where', array( __CLASS__, 'posts_where' ), 10, 2 );
74 + add_filter( 'posts_join', array( __CLASS__, 'posts_join' ), 10, 2 );
75 + add_filter( 'posts_orderby', array( __CLASS__, 'posts_orderby' ), 10, 2 );
76 +
51 77 add_action( 'bulk_edit_custom_box', array( __CLASS__, 'bulk_edit_custom_box' ), 10, 2);
52 78 add_action( 'save_post', array( __CLASS__, 'save_post' ) );
53 79 }
54 80 }
@@ -60,12 +86,13 @@
60 86
61 87 global $pagenow;
62 88
63 89 if ( $pagenow == 'edit.php' ) {
64 - $post_type = isset( $_GET['post_type'] ) ? $_GET['post_type'] : 'post';
90 + $post_type = groups_sanitize_get( 'post_type' ) ?? 'post';
65 91 $post_types_option = Groups_Options::get_option( Groups_Post_Access::POST_TYPES, array() );
66 92 if ( !isset( $post_types_option[$post_type]['add_meta_box'] ) || $post_types_option[$post_type]['add_meta_box'] ) {
67 93 Groups_UIE::enqueue( 'select' );
94 + wp_enqueue_style( 'groups_admin_post' );
68 95 }
69 96 }
70 97 }
71 98
@@ -76,23 +103,26 @@
76 103
77 104 global $pagenow;
78 105
79 106 if ( $pagenow == 'edit.php' ) {
80 - $post_type = isset( $_GET['post_type'] ) ? $_GET['post_type'] : 'post';
107 + $post_type = groups_sanitize_get( 'post_type' ) ?? 'post';
81 108 $post_types_option = Groups_Options::get_option( Groups_Post_Access::POST_TYPES, array() );
82 109 if ( !isset( $post_types_option[$post_type]['add_meta_box'] ) || $post_types_option[$post_type]['add_meta_box'] ) {
83 110 echo '<style type="text/css">';
84 - echo '.groups-capabilities-container { display: inline-block; line-height: 24px; padding-bottom: 1em; vertical-align: top; margin-left: 4px; margin-right: 4px; }';
85 - echo '.groups-capabilities-container .groups-select-container { display: inline-block; vertical-align: top; }';
86 - echo '.groups-capabilities-container .groups-select-container select, .groups-bulk-container select.groups-action { float: none; margin-right: 4px; vertical-align: top; }';
87 - echo '.groups-capabilities-container .selectize-control { min-width: 128px; }';
88 - echo '.groups-capabilities-container .selectize-control, .groups-bulk-container select.groups-action { margin-right: 4px; vertical-align: top; }';
89 - echo '.groups-capabilities-container .selectize-input { font-size: inherit; line-height: 18px; padding: 1px 2px 2px 2px; vertical-align: middle; }';
90 - echo '.groups-capabilities-container .selectize-input input[type="text"] { font-size: inherit; vertical-align: middle; }';
91 - echo '.groups-capabilities-container input.button { margin-top: 1px; vertical-align: top; }';
111 + echo '.groups-groups-container { display: inline-block; line-height: 24px; padding-bottom: 1em; vertical-align: top; margin-left: 4px; margin-right: 4px; }';
112 + echo '.groups-groups-container .groups-select-container { display: inline-block; vertical-align: top; }';
113 + echo '.groups-groups-container .groups-select-container select, .groups-bulk-container select.groups-action { float: none; margin-right: 4px; vertical-align: top; }';
114 + echo '.groups-groups-container .selectize-control { min-width: 128px; }';
115 + echo '.groups-groups-container .selectize-control, .groups-bulk-container select.groups-action { margin-right: 4px; vertical-align: top; }';
116 + echo '.groups-groups-container .selectize-input { min-height: 30px; font-size: inherit; line-height: 18px; padding: 0 4px; vertical-align: middle; }';
117 + echo '.groups-groups-container .selectize-input input[type="text"] { font-size: inherit; vertical-align: middle; }';
118 + echo '.groups-groups-container input.button { margin-top: 1px; vertical-align: top; }';
92 119 echo '.inline-edit-row fieldset .capabilities-bulk-container label span.title { min-width: 5em; padding: 2px 1em; width: auto; }';
93 120 echo '.tablenav .actions { overflow: visible; }'; // this is important so that the selectize options aren't hidden
94 121 echo '.wp-list-table td { overflow: visible; }'; // idem for bulk actions
122 + echo 'label.groups-read-terms { vertical-align: middle; line-height: 28px; margin-right: 4px; }'; // Terms checkbox label
123 + echo 'label.groups-read-terms input[type="checkbox"] { height: 1rem; }'; // Terms checkbox
124 + echo 'th.column-groups, th.column-groups-read, th.column-capabilities { width:10%; }';
95 125 echo '</style>';
96 126 }
97 127 }
98 128 }
@@ -97,19 +127,19 @@
97 127 }
98 128 }
99 129
100 130 /**
101 - * Renders the access restriction field.
131 + * Renders the groups access restriction filter field.
102 132 */
103 133 public static function restrict_manage_posts() {
104 134
105 - global $pagenow, $wpdb;
135 + global $pagenow;
106 136
107 137 if ( is_admin() ) {
108 138
109 139 if ( $pagenow == 'edit.php' ) { // check that we're on the right screen
110 140
111 - $post_type = isset( $_GET['post_type'] ) ? $_GET['post_type'] : 'post';
141 + $post_type = groups_sanitize_get( 'post_type' ) ?? 'post';
112 142 $post_types_option = Groups_Options::get_option( Groups_Post_Access::POST_TYPES, array() );
113 143
114 144 if ( !isset( $post_types_option[$post_type]['add_meta_box'] ) || $post_types_option[$post_type]['add_meta_box'] ) {
115 145
@@ -115,36 +145,65 @@
115 145
116 146 $output = '';
117 147
118 148 // capabilities select
119 - $output .= '<div class="groups-capabilities-container">';
120 - $applicable_read_caps = Groups_Options::get_option( Groups_Post_Access::READ_POST_CAPABILITIES, array( Groups_Post_Access::READ_POST_CAPABILITY ) );
149 + $output .= '<div class="groups-groups-container">';
121 150 $output .= sprintf(
122 - '<select class="select capability" name="%s[]" multiple="multiple" placeholder="%s" data-placeholder="%s">',
123 - esc_attr( Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ_POST_CAPABILITY ),
124 - esc_attr( __( 'Access restrictions &hellip;', GROUPS_PLUGIN_DOMAIN ) ) ,
125 - esc_attr( __( 'Access restrictions &hellip;', GROUPS_PLUGIN_DOMAIN ) )
151 + '<select class="select group" name="%s[]" multiple="multiple" placeholder="%s" data-placeholder="%s">',
152 + esc_attr( Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ ),
153 + esc_attr__( 'Groups &hellip;', 'groups' ),
154 + esc_attr__( 'Groups &hellip;', 'groups' )
126 155 );
127 156
128 - $previous_selected = array();
129 - if ( !empty( $_GET[Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ_POST_CAPABILITY] ) ) {
130 - $previous_selected = $_GET[Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ_POST_CAPABILITY];
131 - if ( !is_array( $previous_selected ) ) {
132 - $previous_selected = array();
133 - }
157 + $read = groups_sanitize_get( Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ );
158 + if ( !is_array( $read ) ) {
159 + $read = array();
134 160 }
135 - $selected = in_array( self::NOT_RESTRICTED, $previous_selected ) ? ' selected="selected" ' : '';
136 - $output .= sprintf( '<option value="%s" %s >%s</option>', self::NOT_RESTRICTED, esc_attr( $selected ), esc_attr( __( '(only unrestricted)', GROUPS_PLUGIN_DOMAIN ) ) );
161 + $output .= sprintf(
162 + '<option value="%s" %s >%s</option>', self::NOT_RESTRICTED,
163 + esc_attr( in_array( self::NOT_RESTRICTED, $read ) ? ' selected="selected" ' : '' ),
164 + esc_attr__( '(none)', 'groups' )
165 + );
166 + $output .= sprintf(
167 + '<option value="%s" %s >%s</option>', self::RESTRICTED,
168 + esc_attr( in_array( self::RESTRICTED, $read ) ? ' selected="selected" ' : '' ),
169 + esc_attr__( '(any)', 'groups' )
170 + );
137 171
138 - foreach( $applicable_read_caps as $capability ) {
139 - $selected = in_array( $capability, $previous_selected ) ? ' selected="selected" ' : '';
140 - $output .= sprintf( '<option value="%s" %s >%s</option>', esc_attr( $capability ), esc_attr( $selected ), wp_filter_nohtml_kses( $capability ) );
172 + $groups = apply_filters(
173 + 'groups_admin_posts_restrict_manage_posts_get_groups',
174 + Groups_Group::get_groups(
175 + apply_filters(
176 + 'groups_admin_posts_restrict_manage_posts_get_groups_options',
177 + array( 'order_by' => 'name', 'order' => 'ASC' )
178 + )
179 + )
180 + );
181 + foreach ( $groups as $group ) {
182 + $selected = in_array( $group->group_id, $read ) ? ' selected="selected" ' : '';
183 + $output .= sprintf(
184 + '<option value="%s" %s >%s</option>',
185 + esc_attr( $group->group_id ),
186 + esc_attr( $selected ),
187 + $group->name ? stripslashes( wp_filter_nohtml_kses( $group->name ) ) : ''
188 + );
141 189 }
142 190 $output .= '</select>';
143 191 $output .= '</div>';
144 - $output .= Groups_UIE::render_select( '.select.capability' );
192 + $output .= Groups_UIE::render_select( '.select.group' );
145 193
146 - echo $output;
194 + if (
195 + function_exists( 'get_term_meta' ) && // >= WordPress 4.4.0 as we query the termmeta table
196 + class_exists( 'Groups_Restrict_Categories' ) &&
197 + method_exists( 'Groups_Restrict_Categories', 'get_controlled_taxonomies' ) &&
198 + method_exists( 'Groups_Restrict_Categories', 'get_term_read_groups' ) // >= Groups Restrict Categories 2.0.0, the method isn't used here but it wouldn't make any sense to query unless we're >= 2.0.0
199 + ) {
200 + $output .= sprintf( '<label class="groups-read-terms" title="%s">', esc_attr__( 'Also look for groups related to terms', 'groups' ) );
201 + $output .= sprintf( '<input type="checkbox" name="groups-read-terms" value="1" %s />', empty( groups_sanitize_get( 'groups-read-terms' ) ) ? '' : ' checked="checked" ' );
202 + $output .= esc_html__( 'Terms', 'groups' );
203 + $output .= '</label>';
204 + }
205 + echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
147 206 }
148 207
149 208 }
150 209 }
@@ -151,67 +210,72 @@
151 210
152 211 }
153 212
154 213 /**
155 - * Bulk-edit access restriction capabilities.
156 - *
214 + * Bulk-edit access restriction groups.
215 + *
157 216 * @param string $column_name
158 217 * @param string $post_type
159 218 */
160 219 public static function bulk_edit_custom_box( $column_name, $post_type ) {
161 220
162 - global $pagenow, $wpdb;
221 + global $pagenow;
163 222
164 - if ( $column_name == 'capabilities' ) {
165 -
223 + if ( $column_name == self::GROUPS_READ ) {
166 224 if ( $pagenow == 'edit.php' ) { // check that we're on the right screen
167 225
168 - $post_type = isset( $_GET['post_type'] ) ? $_GET['post_type'] : 'post';
226 + $post_type = groups_sanitize_get( 'post_type' ) ?? 'post';
169 227 $post_types_option = Groups_Options::get_option( Groups_Post_Access::POST_TYPES, array() );
170 228
171 229 if ( !isset( $post_types_option[$post_type]['add_meta_box'] ) || $post_types_option[$post_type]['add_meta_box'] ) {
172 230
173 231 $output = '<fieldset class="inline-edit-col-right">';
174 - $output .= '<div class="bulk-edit-groups">';
232 + $output .= '<div class="bulk-edit-groups" style="padding:0 0.5em;">';
175 233
176 234 // capability/access restriction bulk actions added through extra_tablenav()
177 - $output .= '<div id="capability-bulk-actions" class="capabilities-bulk-container" style="display:inline">';
235 + $output .= '<div id="group-bulk-actions" class="groups-bulk-container" style="display:inline">';
178 236
179 237 $output .= '<label style="display:inline;">';
180 238 $output .= '<span class="title">';
181 - $output .= __( 'Access Restrictions', GROUPS_PLUGIN_DOMAIN );
239 + $output .= _x( 'Groups', 'Bulk edit field label', 'groups' );
182 240 $output .= '</span>';
183 - $output .= '<select class="capabilities-action" name="capabilities-action">';
184 - $output .= '<option selected="selected" value="-1">' . __( '&mdash; No Change &mdash;', GROUPS_PLUGIN_DOMAIN ) . '</option>';
185 - $output .= '<option value="add-capability">' . __( 'Add restriction', GROUPS_PLUGIN_DOMAIN ) . '</option>';
186 - $output .= '<option value="remove-capability">' . __( 'Remove restriction', GROUPS_PLUGIN_DOMAIN ) . '</option>';
241 + $output .= '<select class="groups-action" name="groups-action">';
242 + $output .= '<option selected="selected" value="-1">' . esc_html__( '&mdash; No Change &mdash;', 'groups' ) . '</option>';
243 + $output .= '<option value="add-group">' . esc_html__( 'Add restriction', 'groups' ) . '</option>';
244 + $output .= '<option value="remove-group">' . esc_html__( 'Remove restriction', 'groups' ) . '</option>';
187 245 $output .= '</select>';
188 246 $output .= '</label>';
189 247
190 - $output .= '<div class="groups-capabilities-container">';
191 - $valid_read_caps = Groups_Access_Meta_Boxes::get_valid_read_caps_for_user();
248 + $include = Groups_Access_Meta_Boxes::get_user_can_restrict_group_ids( get_current_user_id() );
249 + $groups = Groups_Group::get_groups( array( 'order_by' => 'name', 'order' => 'ASC', 'include' => $include ) );
250 +
251 + $output .= '<div class="groups-groups-container">';
192 252 $output .= sprintf(
193 - '<select class="select bulk-capability" name="%s[]" multiple="multiple" placeholder="%s" data-placeholder="%s">',
194 - esc_attr( Groups_Post_Access::POSTMETA_PREFIX . 'bulk-' . Groups_Post_Access::READ_POST_CAPABILITY ),
195 - esc_attr( __( 'Choose access restrictions &hellip;', GROUPS_PLUGIN_DOMAIN ) ) ,
196 - esc_attr( __( 'Choose access restrictions &hellip;', GROUPS_PLUGIN_DOMAIN ) )
253 + '<select class="select bulk-group" name="%s[]" multiple="multiple" placeholder="%s" data-placeholder="%s">',
254 + esc_attr( Groups_Post_Access::POSTMETA_PREFIX . 'bulk-' . Groups_Post_Access::READ ),
255 + esc_attr__( 'Choose access restriction groups &hellip;', 'groups' ),
256 + esc_attr__( 'Choose access restriction groups &hellip;', 'groups' )
197 257 );
198 258
199 - foreach( $valid_read_caps as $capability ) {
200 - $output .= sprintf( '<option value="%s" >%s</option>', esc_attr( $capability ), wp_filter_nohtml_kses( $capability ) );
259 + foreach ( $groups as $group ) {
260 + $output .= sprintf(
261 + '<option value="%s" >%s</option>',
262 + esc_attr( $group->group_id ),
263 + $group->name ? stripslashes( wp_filter_nohtml_kses( $group->name ) ) : ''
264 + );
201 265 }
202 266 $output .= '</select>';
203 - $output .= '</div>'; // .groups-capabilities-container
204 - $output .= Groups_UIE::render_select( '.select.bulk-capability' );
267 + $output .= '</div>'; // .groups-groups-container
268 + $output .= Groups_UIE::render_select( '.select.bulk-group' );
205 269
206 - $output .= '</div>'; // .capabilities-bulk-container
270 + $output .= '</div>'; // .groups-bulk-container
207 271
208 272 $output .= '</div>'; // .bulk-edit-groups
209 273 $output .= '</fieldset>'; // .inline-edit-col-right
210 274
211 - $output .= wp_nonce_field( 'post-capability', 'bulk-post-capability-nonce', true, false );
275 + $output .= wp_nonce_field( 'post-group', 'bulk-post-group-nonce', true, false );
212 276
213 - echo $output;
277 + echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
214 278 }
215 279 }
216 280 }
217 281 }
@@ -216,34 +280,39 @@
216 280 }
217 281 }
218 282
219 283 /**
220 - * Handles access restriction capability modifications from bulk-editing.
284 + * Handles access restriction group modifications from bulk-editing.
221 285 * This is called once for each post that is included in bulk-editing.
222 286 * The fields that are handled here are rendered through the
223 287 * bulk_edit_custom_box() method in this class.
224 - *
288 + *
225 289 * @param int $post_id
226 290 */
227 291 public static function save_post( $post_id ) {
228 - if ( isset( $_REQUEST['capabilities-action'] ) ) {
229 - if ( wp_verify_nonce( $_REQUEST['bulk-post-capability-nonce'], 'post-capability' ) ) {
230 - $field = Groups_Post_Access::POSTMETA_PREFIX . 'bulk-' . Groups_Post_Access::READ_POST_CAPABILITY;
231 - if ( !empty( $_REQUEST[$field] ) && is_array( $_REQUEST[$field] ) ) {
292 + if ( isset( $_REQUEST['groups-action'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
293 + if ( groups_verify_request_nonce( 'bulk-post-group-nonce', 'post-group' ) ) {
294 + $read = groups_sanitize_request( Groups_Post_Access::POSTMETA_PREFIX . 'bulk-' . Groups_Post_Access::READ );
295 + if ( !empty( $read ) && is_array( $read ) ) {
232 296 if ( Groups_Access_Meta_Boxes::user_can_restrict() ) {
233 - $valid_read_caps = Groups_Access_Meta_Boxes::get_valid_read_caps_for_user();
234 - foreach( $_REQUEST[$field] as $capability_name ) {
235 - if ( $capability = Groups_Capability::read_by_capability( $capability_name ) ) {
236 - if ( in_array( $capability->capability, $valid_read_caps ) ) {
237 - switch( $_REQUEST['capabilities-action'] ) {
238 - case 'add-capability' :
297 + $include = Groups_Access_Meta_Boxes::get_user_can_restrict_group_ids();
298 + $groups = Groups_Group::get_groups( array( 'order_by' => 'name', 'order' => 'ASC', 'include' => $include ) );
299 + $group_ids = array();
300 + foreach ( $groups as $group ) {
301 + $group_ids[] = $group->group_id;
302 + }
303 + foreach ( $read as $group_id ) {
304 + if ( $group = Groups_Group::read( $group_id ) ) {
305 + if ( in_array( $group->group_id, $group_ids ) ) {
306 + switch ( groups_sanitize_request( 'groups-action' ) ) {
307 + case 'add-group' :
239 308 Groups_Post_Access::create( array(
240 309 'post_id' => $post_id,
241 - 'capability' => $capability->capability
310 + 'group_id' => $group->group_id
242 311 ) );
243 312 break;
244 - case 'remove-capability' :
245 - Groups_Post_Access::delete( $post_id, $capability->capability );
313 + case 'remove-group' :
314 + Groups_Post_Access::delete( $post_id, array( 'groups_read' => $group->group_id ) );
246 315 break;
247 316 }
248 317 }
249 318 }
@@ -254,11 +323,12 @@
254 323 }
255 324 }
256 325
257 326 /**
258 - * Query modifier to take the selected access restriction capability into
259 - * account.
260 - *
327 + * Query modifier to take the selected access restriction groups into account.
328 + *
329 + * @deprecated not used
330 + *
261 331 * @param WP_Query $query query object passed by reference
262 332 */
263 333 public static function parse_query( &$query ) {
264 334
@@ -267,67 +337,70 @@
267 337 if ( is_admin() ) {
268 338
269 339 if ( $pagenow == 'edit.php' ) { // check that we're on the right screen
270 340
271 - $post_type = isset( $_GET['post_type'] ) ? $_GET['post_type'] : 'post';
341 + $post_type = groups_sanitize_get( 'post_type' ) ?? 'post';
272 342 $post_types_option = Groups_Options::get_option( Groups_Post_Access::POST_TYPES, array() );
273 343
274 344 if ( !isset( $post_types_option[$post_type]['add_meta_box'] ) || $post_types_option[$post_type]['add_meta_box'] ) {
275 345
276 - if ( !empty( $_GET[Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ_POST_CAPABILITY] ) &&
277 - is_array( $_GET[Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ_POST_CAPABILITY] )
278 - ) {
346 + $read = groups_sanitize_get( Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ );
347 + if ( !is_array( $read ) ) {
348 + $read = array();
349 + }
279 350
351 + if ( count( $read ) > 0 ) {
352 +
280 353 $include_unrestricted = false;
281 - if ( in_array( self::NOT_RESTRICTED, $_GET[Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ_POST_CAPABILITY] ) ) {
354 + if ( in_array( self::NOT_RESTRICTED, $read ) ) {
282 355 $include_unrestricted = true;
283 356 }
284 357
285 - $capabilities = array();
286 - foreach ( $_GET[Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ_POST_CAPABILITY] as $capability ) {
287 - if ( Groups_Capability::read_by_capability( $capability ) ) {
288 - $capabilities[] = $capability;
358 + $group_ids = array();
359 + foreach ( $read as $group_id ) {
360 + if ( Groups_Group::read( $group_id ) ) {
361 + $group_ids[] = $group_id;
289 362 }
290 363 }
291 364
292 - if ( !empty( $capabilities ) ) {
365 + if ( !empty( $group_ids ) ) { // @phpstan-ignore empty.variable
293 366 if ( $include_unrestricted ) {
294 367 // meta_query does not handle a conjunction
295 368 // on the same meta field correctly
296 369 // (at least not up to WordPress 3.7.1)
297 -// $query->query_vars['meta_query'] = array (
298 -// 'relation' => 'OR',
299 -// array (
300 -// 'key' => Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ_POST_CAPABILITY,
301 -// 'value' => $capabilities,
302 -// 'compare' => 'IN'
303 -// ),
304 -// array (
305 -// 'key' => Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ_POST_CAPABILITY,
306 -// 'compare' => 'NOT EXISTS'
307 -// )
308 -// );
370 + // $query->query_vars['meta_query'] = array (
371 + // 'relation' => 'OR',
372 + // array (
373 + // 'key' => Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ,
374 + // 'value' => $group_ids,
375 + // 'compare' => 'IN'
376 + // ),
377 + // array (
378 + // 'key' => Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ,
379 + // 'compare' => 'NOT EXISTS'
380 + // )
381 + // );
309 382 // we'll limit it to show just unrestricted entries
310 383 // until the above is solved
311 - $query->query_vars['meta_query'] = array (
384 + $query->query_vars['meta_query'] = array ( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
312 385 array (
313 - 'key' => Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ_POST_CAPABILITY,
386 + 'key' => Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ,
314 387 'compare' => 'NOT EXISTS'
315 388 )
316 389 );
317 390 } else {
318 - $query->query_vars['meta_query'] = array (
391 + $query->query_vars['meta_query'] = array ( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
319 392 array (
320 - 'key' => Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ_POST_CAPABILITY,
321 - 'value' => $capabilities,
393 + 'key' => Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ,
394 + 'value' => $group_ids,
322 395 'compare' => 'IN'
323 396 )
324 397 );
325 398 }
326 399 } else if ( $include_unrestricted ) {
327 - $query->query_vars['meta_query'] = array (
400 + $query->query_vars['meta_query'] = array ( //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
328 401 array (
329 - 'key' => Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ_POST_CAPABILITY,
402 + 'key' => Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ,
330 403 'compare' => 'NOT EXISTS'
331 404 )
332 405 );
333 406 }
@@ -338,6 +411,273 @@
338 411 }
339 412
340 413 }
341 414
415 + /**
416 + * Filters out posts by group. This is used when you choose groups on the post admin screen so that
417 + * only those posts who are restricted by groups are shown.
418 + *
419 + * @param string $where
420 + * @param WP_Query $query
421 + *
422 + * @return string
423 + */
424 + public static function posts_where( $where, $query ) {
425 +
426 + global $wpdb;
427 +
428 + if ( self::extend_for_filter_groups_read( $query ) ) { // also checks that $_GET[Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ] is an array
429 +
430 + $post_in = array();
431 + $term_in = array();
432 +
433 + $filter_terms = false;
434 + if (
435 + !empty( $_GET['groups-read-terms'] ) && // phpcs:ignore WordPress.Security.NonceVerification.Recommended
436 + function_exists( 'get_term_meta' ) && // >= WordPress 4.4.0 as we query the termmeta table
437 + class_exists( 'Groups_Restrict_Categories' ) &&
438 + method_exists( 'Groups_Restrict_Categories', 'get_controlled_taxonomies' ) &&
439 + method_exists( 'Groups_Restrict_Categories', 'get_term_read_groups' ) // >= Groups Restrict Categories 2.0.0, the method isn't used here but it wouldn't make any sense to query unless we're >= 2.0.0
440 + ) {
441 + $filter_terms = true;
442 + }
443 +
444 + $read = groups_sanitize_get( Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ );
445 + if ( !is_array( $read ) ) {
446 + $read = array();
447 + }
448 +
449 + if ( in_array( self::NOT_RESTRICTED, $read ) ) {
450 + $condition =
451 + "SELECT ID post_id FROM $wpdb->posts " .
452 + "WHERE ID NOT IN (" .
453 + "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'groups-read'";
454 + if ( $filter_terms ) {
455 + $condition .=
456 + " UNION ALL " .
457 + "SELECT p.ID post_id FROM $wpdb->posts p " .
458 + "LEFT JOIN $wpdb->term_relationships tr ON p.ID = tr.object_id " .
459 + "LEFT JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id " .
460 + "LEFT JOIN $wpdb->termmeta tm ON tt.term_id = tm.term_id " .
461 + "WHERE tm.meta_key = 'groups-read'";
462 + }
463 + $condition .= ")";
464 + $post_in[] = $condition;
465 + }
466 +
467 + if ( in_array( self::RESTRICTED, $read ) ) {
468 + $condition = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'groups-read'";
469 + if ( $filter_terms ) {
470 + $condition .=
471 + " UNION ALL " .
472 + "SELECT p.ID post_id FROM $wpdb->posts p " .
473 + "LEFT JOIN $wpdb->term_relationships tr ON p.ID = tr.object_id " .
474 + "LEFT JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id " .
475 + "LEFT JOIN $wpdb->termmeta tm ON tt.term_id = tm.term_id " .
476 + "WHERE tm.meta_key = 'groups-read'";
477 + }
478 + $post_in[] = $condition;
479 + }
480 +
481 + $group_ids = array();
482 + foreach ( $read as $group_id ) {
483 + if ( $group_id = Groups_Utility::id( $group_id ) ) {
484 + if ( Groups_Group::read( $group_id ) ) {
485 + $group_ids[] = $group_id;
486 + }
487 + }
488 + }
489 +
490 + if ( !empty( $group_ids ) ) { // @phpstan-ignore empty.variable
491 + $groups = ' ( ' . implode( ',', esc_sql( $group_ids ) ) . ' ) ';
492 + $condition =
493 + "SELECT post_id FROM $wpdb->postmeta " .
494 + "WHERE meta_key = 'groups-read' AND meta_value IN $groups";
495 + if ( $filter_terms ) {
496 + $condition .=
497 + " UNION ALL " .
498 + "SELECT p.ID post_id FROM $wpdb->posts p " .
499 + "LEFT JOIN $wpdb->term_relationships tr ON p.ID = tr.object_id " .
500 + "LEFT JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id " .
501 + "LEFT JOIN $wpdb->termmeta tm ON tt.term_id = tm.term_id " .
502 + "WHERE tm.meta_key = 'groups-read' AND tm.meta_value IN $groups";
503 + }
504 + $post_in[] = $condition;
505 + }
506 +
507 + if ( count( $post_in ) > 0 ) {
508 + if (
509 + !empty( $_GET['groups-read-terms'] ) && // phpcs:ignore WordPress.Security.NonceVerification.Recommended
510 + function_exists( 'get_term_meta' ) && // >= WordPress 4.4.0 as we query the termmeta table
511 + class_exists( 'Groups_Restrict_Categories' ) &&
512 + method_exists( 'Groups_Restrict_Categories', 'get_controlled_taxonomies' ) &&
513 + method_exists( 'Groups_Restrict_Categories', 'get_term_read_groups' ) // >= Groups Restrict Categories 2.0.0, the method isn't used here but it wouldn't make any sense to query unless we're >= 2.0.0
514 + ) {
515 + $post_in = array_merge( $post_in, $term_in );
516 + }
517 + $id_in = implode( ' UNION ALL ', $post_in );
518 + $where .= " AND $wpdb->posts.ID IN ( $id_in ) ";
519 + }
520 +
521 + }
522 +
523 + return $where;
524 + }
525 +
526 + /**
527 + * Adds to the join to allow advanced sorting by group on the admin back end for post tables.
528 + *
529 + * @param string $join
530 + * @param WP_Query $query
531 + */
532 + public static function posts_join( $join, $query ) {
533 + global $wpdb;
534 + if ( self::extend_for_orderby_groups_read( $query ) ) {
535 + $group_table = _groups_get_tablename( 'group' );
536 + if ( function_exists( 'get_term_meta' ) ) { // >= WordPress 4.4.0 as we query the termmeta table
537 + $join .= "
538 + LEFT JOIN (
539 + SELECT p.ID post_id, GROUP_CONCAT(DISTINCT groups_read.group_name ORDER BY groups_read.group_name) groups
540 + FROM $wpdb->posts p
541 + LEFT JOIN (
542 + SELECT post_id, g.name group_name
543 + FROM $wpdb->postmeta pm
544 + LEFT JOIN $group_table g ON pm.meta_value = g.group_id
545 + WHERE pm.meta_key = 'groups-read'
546 + UNION ALL
547 + SELECT p.ID post_id, g.name group_name
548 + FROM $wpdb->posts p
549 + LEFT JOIN $wpdb->term_relationships tr ON p.ID = tr.object_id
550 + LEFT JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
551 + LEFT JOIN $wpdb->termmeta tm ON tt.term_id = tm.term_id
552 + LEFT JOIN $group_table g ON tm.meta_value = g.group_id
553 + WHERE tm.meta_key = 'groups-read'
554 + ) as groups_read ON p.ID = groups_read.post_id
555 + GROUP BY p.ID
556 + ) groups_tmp ON $wpdb->posts.ID = groups_tmp.post_id
557 + ";
558 + } else {
559 + $join .= "
560 + LEFT JOIN (
561 + SELECT p.ID post_id, GROUP_CONCAT(DISTINCT groups_read.group_name ORDER BY groups_read.group_name) groups
562 + FROM $wpdb->posts p
563 + LEFT JOIN (
564 + SELECT post_id, g.name group_name
565 + FROM $wpdb->postmeta pm
566 + LEFT JOIN $group_table g ON pm.meta_value = g.group_id
567 + WHERE pm.meta_key = 'groups-read'
568 + ) as groups_read ON p.ID = groups_read.post_id
569 + GROUP BY p.ID
570 + ) groups_tmp ON $wpdb->posts.ID = groups_tmp.post_id
571 + ";
572 + }
573 + }
574 + return $join;
575 + }
576 +
577 + /**
578 + * Extend the orderby clause to sort by groups related to the post and its terms.
579 + *
580 + * @param $string $orderby
581 + * @param WP_Query $query
582 + *
583 + * @return string
584 + */
585 + public static function posts_orderby( $orderby, $query ) {
586 + if ( self::extend_for_orderby_groups_read( $query ) ) {
587 + switch ( $query->get( 'order' ) ) {
588 + case 'desc' :
589 + case 'DESC' :
590 + $order = 'DESC';
591 + break;
592 + default :
593 + $order = 'ASC';
594 + }
595 + $prefix = ' groups_tmp.groups ' . $order;
596 + if ( !empty( $orderby ) ) {
597 + $prefix .= ' , ';
598 + }
599 + $orderby = $prefix . $orderby;
600 + }
601 + return $orderby;
602 + }
603 +
604 + /**
605 + * Check if we should apply our posts_join and posts_orderby filters. Used in those.
606 + *
607 + * @param WP_Query $query
608 + *
609 + * @return boolean
610 + */
611 + private static function extend_for_orderby_groups_read( &$query ) {
612 + $result = false;
613 + if ( is_admin() ) {
614 + // check if query is for a post type we handle
615 + $post_types = $query->get( 'post_type' );
616 + if ( !is_array( $post_types ) ) {
617 + $post_types = array( $post_types );
618 + }
619 + foreach ( $post_types as $post_type ) {
620 + $post_types_option = Groups_Options::get_option( Groups_Post_Access::POST_TYPES, array() );
621 + if (
622 + !isset( $post_types_option[$post_type]['add_meta_box'] ) ||
623 + $post_types_option[$post_type]['add_meta_box']
624 + ) {
625 + // only act on post etc. screens
626 + $screen = get_current_screen();
627 + if (
628 + !empty( $screen ) &&
629 + !empty( $screen->id ) &&
630 + ( $screen->id == 'edit-' . $post_type )
631 + ) {
632 + if ( $query->get( 'orderby' ) == self::GROUPS_READ ) {
633 + $result = true;
634 + break;
635 + }
636 + }
637 + }
638 + }
639 + }
640 + return $result;
641 + }
642 +
643 + /**
644 + * Check if we should apply our posts_where filter. Used in it.
645 + *
646 + * @param WP_Query $query
647 + *
648 + * @return boolean
649 + */
650 + private static function extend_for_filter_groups_read( &$query ) {
651 + $result = false;
652 + if ( is_admin() ) {
653 + // check if query is for a post type we handle
654 + $post_types = $query->get( 'post_type' );
655 + $post_types_option = Groups_Options::get_option( Groups_Post_Access::POST_TYPES, array() );
656 + if ( !is_array( $post_types ) ) {
657 + $post_types = array( $post_types );
658 + }
659 + foreach ( $post_types as $post_type ) {
660 + if (
661 + !isset( $post_types_option[$post_type]['add_meta_box'] ) ||
662 + $post_types_option[$post_type]['add_meta_box']
663 + ) {
664 + // only act on post etc. screens
665 + $screen = get_current_screen();
666 + if (
667 + !empty( $screen ) &&
668 + !empty( $screen->id ) &&
669 + ( $screen->id == 'edit-' . $post_type )
670 + ) {
671 + $read = groups_sanitize_get( Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ );
672 + if ( !empty( $read ) && is_array( $read ) ) {
673 + $result = true;
674 + break;
675 + }
676 + }
677 + }
678 + }
679 + }
680 + return $result;
681 + }
342 682 }
343 683 Groups_Admin_Posts::init();