GravityView  1.19.4
The best, easiest way to display Gravity Forms entries on your website.
class-gravityview-roles-capabilities.php
Go to the documentation of this file.
1 <?php
2 /**
3  * Roles and Capabilities
4  *
5  * @package GravityView
6  * @license GPL2+
7  * @since 1.14
8  * @author Katz Web Services, Inc.
9  * @link http://gravityview.co
10  * @copyright Copyright 2015, Katz Web Services, Inc.
11  */
12 
13 // Exit if accessed directly
14 defined( 'ABSPATH' ) || exit;
15 
16 /**
17  * GravityView Roles Class
18  *
19  * This class handles the role creation and assignment of capabilities for those roles.
20  *
21  * @since 1.15
22  */
24 
25  /**
26  * @var GravityView_Roles_Capabilities|null
27  */
28  static $instance = null;
29 
30  /**
31  * @since 1.15
32  * @return GravityView_Roles_Capabilities
33  */
34  public static function get_instance() {
35 
36  if( ! self::$instance ) {
37  self::$instance = new self;
38  }
39 
40  return self::$instance;
41  }
42 
43  /**
44  * Get things going
45  *
46  * @since 1.15
47  */
48  public function __construct() {
49  $this->add_hooks();
50  }
51 
52  /**
53  * @since 1.15
54  */
55  private function add_hooks() {
56  add_filter( 'members_get_capabilities', array( 'GravityView_Roles_Capabilities', 'merge_with_all_caps' ) );
57  add_action( 'members_register_cap_groups', array( $this, 'members_register_cap_group' ), 20 );
58  add_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 10, 4 );
59  add_action( 'admin_init', array( $this, 'add_caps') );
60  }
61 
62 
63  /**
64  * Add support for `gravityview_full_access` capability, and
65  *
66  * @see map_meta_cap()
67  *
68  * @since 1.15
69  *
70  * @param array $allcaps An array of all the user's capabilities.
71  * @param array $caps Actual capabilities for meta capability.
72  * @param array $args Optional parameters passed to has_cap(), typically object ID.
73  * @param WP_User|null $user The user object, in WordPress 3.7.0 or higher
74  *
75  * @return mixed
76  */
77  public function filter_user_has_cap( $usercaps = array(), $caps = array(), $args = array(), $user = NULL ) {
78 
79  // Empty caps_to_check array
80  if( ! $usercaps || ! $caps ) {
81  return $usercaps;
82  }
83 
84  /**
85  * Enable all GravityView caps_to_check if `gravityview_full_access` is enabled
86  */
87  if( ! empty( $usercaps['gravityview_full_access'] ) ) {
88 
89  $all_gravityview_caps = self::all_caps();
90 
91  foreach( $all_gravityview_caps as $gv_cap ) {
92  $usercaps[ $gv_cap ] = true;
93  }
94 
95  unset( $all_gravityview_caps );
96  }
97 
98  $usercaps = $this->add_gravity_forms_usercaps_to_gravityview_caps( $usercaps );
99 
100  return $usercaps;
101  }
102 
103  /**
104  * If a user has been assigned custom capabilities for Gravity Forms, but they haven't been assigned similar abilities
105  * in GravityView yet, we give temporary access to the permissions, until they're set.
106  *
107  * This is for custom roles that GravityView_Roles_Capabilities::add_caps() doesn't modify. If you have a
108  * custom role with the ability to edit any Gravity Forms entries (`gravityforms_edit_entries`), you would
109  * expect GravityView to match that capability, until the role has been updated with GravityView caps.
110  *
111  * @since 1.15
112  *
113  * @param array $usercaps User's allcaps array
114  *
115  * @return array
116  */
117  private function add_gravity_forms_usercaps_to_gravityview_caps( $usercaps ) {
118 
119  $gf_to_gv_caps = array(
120  'gravityforms_edit_entries' => 'gravityview_edit_others_entries',
121  'gravityforms_delete_entries' => 'gravityview_delete_others_entries',
122  'gravityforms_view_entry_notes' => 'gravityview_view_entry_notes',
123  'gravityforms_edit_entry_notes' => 'gravityview_delete_entry_notes',
124  );
125 
126  foreach ( $gf_to_gv_caps as $gf_cap => $gv_cap ) {
127  if ( isset( $usercaps[ $gf_cap ] ) && ! isset( $usercaps[ $gv_cap ] ) ) {
128  $usercaps[ $gv_cap ] = $usercaps[ $gf_cap ];
129  }
130  }
131 
132  return $usercaps;
133  }
134 
135  /**
136  * Add GravityView group to Members 1.x plugin management screen
137  * @see members_register_cap_group()
138  * @since 1.15
139  * @return void
140  */
142  if ( function_exists( 'members_register_cap_group' ) ) {
143 
144  $args = array(
145  'label' => __( 'GravityView', 'gravityview' ),
146  'icon' => 'gv-icon-astronaut-head',
147  'caps' => self::all_caps(),
148  'merge_added' => true,
149  'diff_added' => false,
150  );
151 
152  members_register_cap_group( 'gravityview', $args );
153  }
154  }
155 
156  /**
157  * Merge capabilities array with GravityView capabilities
158  *
159  * @since 1.15 Used to add GravityView caps to the Members plugin
160  * @param array $caps Existing capabilities
161  * @return array Modified capabilities array
162  */
163  public static function merge_with_all_caps( $caps ) {
164 
165  $return_caps = array_merge( $caps, self::all_caps() );
166 
167  return array_unique( $return_caps );
168  }
169 
170  /**
171  * Retrieves the global WP_Roles instance and instantiates it if necessary.
172  *
173  * @see wp_roles() This method uses the exact same code as wp_roles(), here for backward compatibility
174  *
175  * @global WP_Roles $wp_roles WP_Roles global instance.
176  *
177  * @return WP_Roles WP_Roles global instance if not already instantiated.
178  */
179  private function wp_roles() {
180  global $wp_roles;
181 
182  if ( ! isset( $wp_roles ) ) {
183  $wp_roles = new WP_Roles();
184  }
185 
186  return $wp_roles;
187  }
188 
189  /**
190  * Add capabilities to their respective roles if they don't already exist
191  * This could be simpler, but the goal is speed.
192  *
193  * @since 1.15
194  * @return void
195  */
196  public function add_caps() {
197 
198  $wp_roles = $this->wp_roles();
199 
200  if ( is_object( $wp_roles ) ) {
201 
202  $_use_db_backup = $wp_roles->use_db;
203 
204  /**
205  * When $use_db is true, add_cap() performs update_option() every time.
206  * We disable updating the database here, then re-enable it below.
207  */
208  $wp_roles->use_db = false;
209 
210  $capabilities = self::all_caps( false, false );
211 
212  foreach ( $capabilities as $role_slug => $role_caps ) {
213  foreach ( $role_caps as $cap ) {
214  $wp_roles->add_cap( $role_slug, $cap );
215  }
216  }
217 
218  /**
219  * Update the option, as it does in add_cap when $use_db is true
220  *
221  * @see WP_Roles::add_cap() Original code
222  */
223  update_option( $wp_roles->role_key, $wp_roles->roles );
224 
225  /**
226  * Restore previous $use_db setting
227  */
228  $wp_roles->use_db = $_use_db_backup;
229  }
230  }
231 
232  /**
233  * Get an array of GravityView capabilities
234  *
235  * @see get_post_type_capabilities()
236  *
237  * @since 1.15
238  *
239  * @param string $single_role If set, get the caps_to_check for a specific role. Pass 'all' to get all caps_to_check in a flat array. Default: `all`
240  * @param boolean $flat_array True: return all caps in a one-dimensional array. False: a multi-dimensional array with `$single_role` as keys and the caps as the values
241  *
242  * @return array If $role is set, flat array of caps_to_check. Otherwise, a multi-dimensional array of roles and their caps_to_check with the following keys: 'administrator', 'editor', 'author', 'contributor', 'subscriber'
243  */
244  public static function all_caps( $single_role = false, $flat_array = true ) {
245 
246  // Change settings
247  $administrator_caps = array(
248  'gravityview_full_access', // Grant access to all caps_to_check
249  'gravityview_view_settings',
250  'gravityview_edit_settings',
251  'gravityview_uninstall', // Ability to trigger the Uninstall @todo
252  'gravityview_contact_support', // Whether able to send a message to support via the Support Port
253  );
254 
255  // Edit, publish, delete own and others' stuff
256  $editor_caps = array(
257  'edit_others_gravityviews',
258  'read_private_gravityviews',
259  'delete_private_gravityviews',
260  'delete_others_gravityviews',
261  'edit_private_gravityviews',
262  'publish_gravityviews',
263  'delete_published_gravityviews',
264  'edit_published_gravityviews',
265  'copy_gravityviews', // For duplicate/clone View functionality
266 
267  // GF caps_to_check
268  'gravityview_edit_others_entries',
269  'gravityview_moderate_entries', // Approve or reject entries from the Admin; show/hide approval column in Entries screen
270  'gravityview_delete_others_entries',
271  'gravityview_add_entry_notes',
272  'gravityview_view_entry_notes',
273  'gravityview_delete_entry_notes',
274  'gravityview_email_entry_notes',
275  );
276 
277  // Edit, delete own stuff
278  $author_caps = array(
279  // GF caps_to_check
280  'gravityview_edit_entries',
281  'gravityview_edit_entry',
282  'gravityview_edit_form_entries', // This is similar to `gravityview_edit_entries`, but checks against a Form ID $object_id
283  'gravityview_delete_entries',
284  'gravityview_delete_entry',
285  );
286 
287  // Edit and delete drafts but not publish
288  $contributor_caps = array(
289  'edit_gravityviews', // Affects if you're able to see the Views menu in the Admin, and also if you're able to override cache using ?nocache
290  'delete_gravityviews',
291  'gravityview_getting_started', // Getting Started page access
292  'gravityview_support_port', // Display GravityView Support Port
293  );
294 
295  // Read only
296  $subscriber_caps = array(
297  'gravityview_view_entries',
298  'gravityview_view_others_entries',
299  );
300 
301  $subscriber = $subscriber_caps;
302  $contributor = array_merge( $contributor_caps, $subscriber_caps );
303  $author = array_merge( $author_caps, $contributor_caps, $subscriber_caps );
304  $editor = array_merge( $editor_caps, $author_caps, $contributor_caps, $subscriber_caps );
305  $administrator = array_merge( $administrator_caps, $editor_caps, $author_caps, $contributor_caps, $subscriber_caps );
306  $all = $administrator;
307 
308  // If role is set, return caps_to_check for just that role.
309  if( $single_role ) {
310  $caps = isset( ${$single_role} ) ? ${$single_role} : false;
311  return $flat_array ? $caps : array( $single_role => $caps );
312  }
313 
314  // Otherwise, return multi-dimensional array of all caps_to_check
315  return $flat_array ? $all : compact( 'administrator', 'editor', 'author', 'contributor', 'subscriber' );
316  }
317 
318  /**
319  * Check whether the current user has a capability
320  *
321  * @since 1.15
322  *
323  * @see WP_User::user_has_cap()
324  * @see https://codex.wordpress.org/Plugin_API/Filter_Reference/user_has_cap You can filter permissions based on entry/View/form ID using `user_has_cap` filter
325  *
326  * @see GFCommon::current_user_can_any
327  * @uses GFCommon::current_user_can_any
328  *
329  * @param string|array $caps_to_check Single capability or array of capabilities
330  * @param int|null $object_id (optional) Parameter can be used to check for capabilities against a specific object, such as a post or us
331  * @param int|null $user_id (optional) Check the capabilities for a user who is not necessarily the currently logged-in user
332  *
333  * @return bool True: user has at least one passed capability; False: user does not have any defined capabilities
334  */
335  public static function has_cap( $caps_to_check = '', $object_id = null, $user_id = null ) {
336 
337  if( ! is_user_logged_in() || empty( $caps_to_check ) ) {
338  return false;
339  }
340 
341  $has_cap = false;
342 
343  // Add full access caps for GV & GF
344  $caps_to_check = self::maybe_add_full_access_caps( $caps_to_check );
345 
346  foreach ( $caps_to_check as $cap ) {
347  if( ! is_null( $object_id ) ) {
348  $has_cap = $user_id ? user_can( $user_id, $cap, $object_id ) : current_user_can( $cap, $object_id );
349  } else {
350  $has_cap = $user_id ? user_can( $user_id, $cap ) : current_user_can( $cap );
351  }
352  // At the first successful response, stop checking
353  if( $has_cap ) {
354  break;
355  }
356  }
357 
358  return $has_cap;
359  }
360 
361  /**
362  * Add Gravity Forms and GravityView's "full access" caps when any other caps are checked against.
363  *
364  * @since 1.15
365 
366  * @param array $caps_to_check
367  *
368  * @return array
369  */
370  public static function maybe_add_full_access_caps( $caps_to_check = array() ) {
371 
372  $caps_to_check = (array)$caps_to_check;
373 
374  $all_gravityview_caps = self::all_caps();
375 
376  // Are there any $caps_to_check that are from GravityView?
377  if( $has_gravityview_caps = array_intersect( $caps_to_check, $all_gravityview_caps ) ) {
378  $caps_to_check[] = 'gravityview_full_access';
379  }
380 
381  $all_gravity_forms_caps = class_exists( 'GFCommon' ) ? GFCommon::all_caps() : array();
382 
383  // Are there any $caps_to_check that are from Gravity Forms?
384  if( $all_gravity_forms_caps = array_intersect( $caps_to_check, $all_gravity_forms_caps ) ) {
385  $caps_to_check[] = 'gform_full_access';
386  }
387 
388  return array_unique( $caps_to_check );
389  }
390 
391  /**
392  * Remove all GravityView caps_to_check from all roles
393  *
394  * @since 1.15
395  * @return void
396  */
397  public function remove_caps() {
398 
399  $wp_roles = $this->wp_roles();
400 
401  if ( is_object( $wp_roles ) ) {
402 
403  /** Remove all GravityView caps_to_check from all roles */
404  $capabilities = self::all_caps();
405 
406  // Loop through each role and remove GV caps_to_check
407  foreach( $wp_roles->get_names() as $role_slug => $role_name ) {
408  foreach ( $capabilities as $cap ) {
409  $wp_roles->remove_cap( $role_slug, $cap );
410  }
411  }
412  }
413  }
414 }
415 
416 add_action( 'init', array( 'GravityView_Roles_Capabilities', 'get_instance' ), 1 );
remove_caps()
Remove all GravityView caps_to_check from all roles.
wp_roles()
Retrieves the global WP_Roles instance and instantiates it if necessary.
static merge_with_all_caps($caps)
Merge capabilities array with GravityView capabilities.
add_gravity_forms_usercaps_to_gravityview_caps($usercaps)
If a user has been assigned custom capabilities for Gravity Forms, but they haven&#39;t been assigned sim...
add_caps()
Add capabilities to their respective roles if they don&#39;t already exist This could be simpler...
static has_cap($caps_to_check= '', $object_id=null, $user_id=null)
Check whether the current user has a capability.
members_register_cap_group()
Add GravityView group to Members 1.x plugin management screen.
filter_user_has_cap($usercaps=array(), $caps=array(), $args=array(), $user=NULL)
Add support for gravityview_full_access capability, and.
static maybe_add_full_access_caps($caps_to_check=array())
Add Gravity Forms and GravityView&#39;s "full access" caps when any other caps are checked against...
static all_caps($single_role=false, $flat_array=true)
Get an array of GravityView capabilities.