root/trunk/wp-includes/capabilities.php

Revision 8646, 12.8 kB (checked in by ryan, 3 weeks ago)

Notice fixes. Props DD32. see #7509

  • Property svn:eol-style set to native
Line 
1 <?php
2
3 class WP_Roles {
4     var $roles;
5
6     var $role_objects = array();
7     var $role_names = array();
8     var $role_key;
9     var $use_db = true;
10
11     function WP_Roles() {
12         $this->_init();
13     }
14
15     function _init () {
16         global $wpdb;
17         global $wp_user_roles;
18         $this->role_key = $wpdb->prefix . 'user_roles';
19         if ( ! empty( $wp_user_roles ) ) {
20             $this->roles = $wp_user_roles;
21             $this->use_db = false;
22         } else {
23             $this->roles = get_option( $this->role_key );
24         }
25
26         if ( empty( $this->roles ) )
27             return;
28
29         $this->role_objects = array();
30         $this->role_names =  array();
31         foreach ( (array) $this->roles as $role => $data ) {
32             $this->role_objects[$role] = new WP_Role( $role, $this->roles[$role]['capabilities'] );
33             $this->role_names[$role] = $this->roles[$role]['name'];
34         }
35     }
36
37     function add_role( $role, $display_name, $capabilities = array() ) {
38         if ( isset( $this->roles[$role] ) )
39             return;
40
41         $this->roles[$role] = array(
42             'name' => $display_name,
43             'capabilities' => $capabilities
44             );
45         if ( $this->use_db )
46             update_option( $this->role_key, $this->roles );
47         $this->role_objects[$role] = new WP_Role( $role, $capabilities );
48         $this->role_names[$role] = $display_name;
49         return $this->role_objects[$role];
50     }
51
52     function remove_role( $role ) {
53         if ( ! isset( $this->role_objects[$role] ) )
54             return;
55
56         unset( $this->role_objects[$role] );
57         unset( $this->role_names[$role] );
58         unset( $this->roles[$role] );
59
60         if ( $this->use_db )
61             update_option( $this->role_key, $this->roles );
62     }
63
64     function add_cap( $role, $cap, $grant = true ) {
65         $this->roles[$role]['capabilities'][$cap] = $grant;
66         if ( $this->use_db )
67             update_option( $this->role_key, $this->roles );
68     }
69
70     function remove_cap( $role, $cap ) {
71         unset( $this->roles[$role]['capabilities'][$cap] );
72         if ( $this->use_db )
73             update_option( $this->role_key, $this->roles );
74     }
75
76     function &get_role( $role ) {
77         if ( isset( $this->role_objects[$role] ) )
78             return $this->role_objects[$role];
79         else
80             return null;
81     }
82
83     function get_names() {
84         return $this->role_names;
85     }
86
87     function is_role( $role )
88     {
89         return isset( $this->role_names[$role] );
90     }
91 }
92
93 class WP_Role {
94     var $name;
95     var $capabilities;
96
97     function WP_Role( $role, $capabilities ) {
98         $this->name = $role;
99         $this->capabilities = $capabilities;
100     }
101
102     function add_cap( $cap, $grant = true ) {
103         global $wp_roles;
104
105         if ( ! isset( $wp_roles ) )
106             $wp_roles = new WP_Roles();
107
108         $this->capabilities[$cap] = $grant;
109         $wp_roles->add_cap( $this->name, $cap, $grant );
110     }
111
112     function remove_cap( $cap ) {
113         global $wp_roles;
114
115         if ( ! isset( $wp_roles ) )
116             $wp_roles = new WP_Roles();
117
118         unset( $this->capabilities[$cap] );
119         $wp_roles->remove_cap( $this->name, $cap );
120     }
121
122     function has_cap( $cap ) {
123         $capabilities = apply_filters( 'role_has_cap', $this->capabilities, $cap, $this->name );
124         if ( !empty( $capabilities[$cap] ) )
125             return $capabilities[$cap];
126         else
127             return false;
128     }
129
130 }
131
132 class WP_User {
133     var $data;
134     var $ID = 0;
135     var $id = 0; // Deprecated, use $ID instead.
136     var $caps = array();
137     var $cap_key;
138     var $roles = array();
139     var $allcaps = array();
140     
141     var $first_name = '';
142     var $last_name = '';
143
144     function WP_User( $id, $name = '' ) {
145
146         if ( empty( $id ) && empty( $name ) )
147             return;
148
149         if ( ! is_numeric( $id ) ) {
150             $name = $id;
151             $id = 0;
152         }
153
154         if ( ! empty( $id ) )
155             $this->data = get_userdata( $id );
156         else
157             $this->data = get_userdatabylogin( $name );
158
159         if ( empty( $this->data->ID ) )
160             return;
161
162         foreach ( get_object_vars( $this->data ) as $key => $value ) {
163             $this->{$key} = $value;
164         }
165
166         $this->id = $this->ID;
167         $this->_init_caps();
168     }
169
170     function _init_caps() {
171         global $wpdb;
172         $this->cap_key = $wpdb->prefix . 'capabilities';
173         $this->caps = &$this->{$this->cap_key};
174         if ( ! is_array( $this->caps ) )
175             $this->caps = array();
176         $this->get_role_caps();
177     }
178
179     function get_role_caps() {
180         global $wp_roles;
181
182         if ( ! isset( $wp_roles ) )
183             $wp_roles = new WP_Roles();
184
185         //Filter out caps that are not role names and assign to $this->roles
186         if ( is_array( $this->caps ) )
187             $this->roles = array_filter( array_keys( $this->caps ), array( &$wp_roles, 'is_role' ) );
188
189         //Build $allcaps from role caps, overlay user's $caps
190         $this->allcaps = array();
191         foreach ( (array) $this->roles as $role ) {
192             $role = $wp_roles->get_role( $role );
193             $this->allcaps = array_merge( $this->allcaps, $role->capabilities );
194         }
195         $this->allcaps = array_merge( $this->allcaps, $this->caps );
196     }
197
198     function add_role( $role ) {
199         $this->caps[$role] = true;
200         update_usermeta( $this->ID, $this->cap_key, $this->caps );
201         $this->get_role_caps();
202         $this->update_user_level_from_caps();
203     }
204
205     function remove_role( $role ) {
206         if ( empty( $this->roles[$role] ) || ( count( $this->roles ) <= 1 ) )
207             return;
208         unset( $this->caps[$role] );
209         update_usermeta( $this->ID, $this->cap_key, $this->caps );
210         $this->get_role_caps();
211     }
212
213     function set_role( $role ) {
214         foreach ( (array) $this->roles as $oldrole )
215             unset( $this->caps[$oldrole] );
216         if ( !empty( $role ) ) {
217             $this->caps[$role] = true;
218             $this->roles = array( $role => true );
219         } else {
220             $this->roles = false;
221         }
222         update_usermeta( $this->ID, $this->cap_key, $this->caps );
223         $this->get_role_caps();
224         $this->update_user_level_from_caps();
225     }
226
227     function level_reduction( $max, $item ) {
228         if ( preg_match( '/^level_(10|[0-9])$/i', $item, $matches ) ) {
229             $level = intval( $matches[1] );
230             return max( $max, $level );
231         } else {
232             return $max;
233         }
234     }
235
236     function update_user_level_from_caps() {
237         global $wpdb;
238         $this->user_level = array_reduce( array_keys( $this->allcaps ), array( &$this, 'level_reduction' ), 0 );
239         update_usermeta( $this->ID, $wpdb->prefix.'user_level', $this->user_level );
240     }
241
242     function add_cap( $cap, $grant = true ) {
243         $this->caps[$cap] = $grant;
244         update_usermeta( $this->ID, $this->cap_key, $this->caps );
245     }
246
247     function remove_cap( $cap ) {
248         if ( empty( $this->caps[$cap] ) ) return;
249         unset( $this->caps[$cap] );
250         update_usermeta( $this->ID, $this->cap_key, $this->caps );
251     }
252
253     function remove_all_caps() {
254         global $wpdb;
255         $this->caps = array();
256         update_usermeta( $this->ID, $this->cap_key, '' );
257         update_usermeta( $this->ID, $wpdb->prefix.'user_level', '' );
258         $this->get_role_caps();
259     }
260
261     // has_cap( capability_or_role_name ) or
262     // has_cap( 'edit_post', post_id )
263     function has_cap( $cap ) {
264         if ( is_numeric( $cap ) )
265             $cap = $this->translate_level_to_cap( $cap );
266
267         $args = array_slice( func_get_args(), 1 );
268         $args = array_merge( array( $cap, $this->ID ), $args );
269         $caps = call_user_func_array( 'map_meta_cap', $args );
270         // Must have ALL requested caps
271         $capabilities = apply_filters( 'user_has_cap', $this->allcaps, $caps, $args );
272         foreach ( (array) $caps as $cap ) {
273             //echo "Checking cap $cap<br />";
274             if ( empty( $capabilities[$cap] ) || !$capabilities[$cap] )
275                 return false;
276         }
277
278         return true;
279     }
280
281     function translate_level_to_cap( $level ) {
282         return 'level_' . $level;
283     }
284
285 }
286
287 // Map meta capabilities to primitive capabilities.
288 function map_meta_cap( $cap, $user_id ) {
289     $args = array_slice( func_get_args(), 2 );
290     $caps = array();
291
292     switch ( $cap ) {
293     case 'delete_user':
294         $caps[] = 'delete_users';
295         break;
296     case 'edit_user':
297         if ( !isset( $args[0] ) || $user_id != $args[0] ) {
298             $caps[] = 'edit_users';
299         }
300         break;
301     case 'delete_post':
302         $author_data = get_userdata( $user_id );
303         //echo "post ID: {$args[0]}<br />";
304         $post = get_post( $args[0] );
305         if ( 'page' == $post->post_type ) {
306             $args = array_merge( array( 'delete_page', $user_id ), $args );
307             return call_user_func_array( 'map_meta_cap', $args );
308         }
309         $post_author_data = get_userdata( $post->post_author );
310         //echo "current user id : $user_id, post author id: " . $post_author_data->ID . "<br />";
311         // If the user is the author...
312         if ( $user_id == $post_author_data->ID ) {
313             // If the post is published...
314             if ( 'publish' == $post->post_status )
315                 $caps[] = 'delete_published_posts';
316             else
317                 // If the post is draft...
318                 $caps[] = 'delete_posts';
319         } else {
320             // The user is trying to edit someone else's post.
321             $caps[] = 'delete_others_posts';
322             // The post is published, extra cap required.
323             if ( 'publish' == $post->post_status )
324                 $caps[] = 'delete_published_posts';
325             elseif ( 'private' == $post->post_status )
326                 $caps[] = 'delete_private_posts';
327         }
328         break;
329     case 'delete_page':
330         $author_data = get_userdata( $user_id );
331         //echo "post ID: {$args[0]}<br />";
332         $page = get_page( $args[0] );
333         $page_author_data = get_userdata( $page->post_author );
334         //echo "current user id : $user_id, page author id: " . $page_author_data->ID . "<br />";
335         // If the user is the author...
336         if ( $user_id == $page_author_data->ID ) {
337             // If the page is published...
338             if ( $page->post_status == 'publish' )
339                 $caps[] = 'delete_published_pages';
340             else
341                 // If the page is draft...
342                 $caps[] = 'delete_pages';
343         } else {
344             // The user is trying to edit someone else's page.
345             $caps[] = 'delete_others_pages';
346             // The page is published, extra cap required.
347             if ( $page->post_status == 'publish' )
348                 $caps[] = 'delete_published_pages';
349             elseif ( $page->post_status == 'private' )
350                 $caps[] = 'delete_private_pages';
351         }
352         break;
353         // edit_post breaks down to edit_posts, edit_published_posts, or
354         // edit_others_posts
355     case 'edit_post':
356         $author_data = get_userdata( $user_id );
357         //echo "post ID: {$args[0]}<br />";
358         $post = get_post( $args[0] );
359         if ( 'page' == $post->post_type ) {
360             $args = array_merge( array( 'edit_page', $user_id ), $args );
361             return call_user_func_array( 'map_meta_cap', $args );
362         }
363         $post_author_data = get_userdata( $post->post_author );
364         //echo "current user id : $user_id, post author id: " . $post_author_data->ID . "<br />";
365         // If the user is the author...
366         if ( $user_id == $post_author_data->ID ) {
367             // If the post is published...
368             if ( 'publish' == $post->post_status )
369                 $caps[] = 'edit_published_posts';
370             else
371                 // If the post is draft...
372                 $caps[] = 'edit_posts';
373         } else {
374             // The user is trying to edit someone else's post.
375             $caps[] = 'edit_others_posts';
376             // The post is published, extra cap required.
377             if ( 'publish' == $post->post_status )
378                 $caps[] = 'edit_published_posts';
379             elseif ( 'private' == $post->post_status )
380                 $caps[] = 'edit_private_posts';
381         }
382         break;
383     case 'edit_page':
384         $author_data = get_userdata( $user_id );
385         //echo "post ID: {$args[0]}<br />";
386         $page = get_page( $args[0] );
387         $page_author_data = get_userdata( $page->post_author );
388         //echo "current user id : $user_id, page author id: " . $page_author_data->ID . "<br />";
389         // If the user is the author...
390         if ( $user_id == $page_author_data->ID ) {
391             // If the page is published...
392             if ( 'publish' == $page->post_status )
393                 $caps[] = 'edit_published_pages';
394             else
395                 // If the page is draft...
396                 $caps[] = 'edit_pages';
397         } else {
398             // The user is trying to edit someone else's page.
399             $caps[] = 'edit_others_pages';
400             // The page is published, extra cap required.
401             if ( 'publish' == $page->post_status )
402                 $caps[] = 'edit_published_pages';
403             elseif ( 'private' == $page->post_status )
404                 $caps[] = 'edit_private_pages';
405         }
406         break;
407     case 'read_post':
408         $post = get_post( $args[0] );
409         if ( 'page' == $post->post_type ) {
410             $args = array_merge( array( 'read_page', $user_id ), $args );
411             return call_user_func_array( 'map_meta_cap', $args );
412         }
413
414         if ( 'private' != $post->post_status ) {
415             $caps[] = 'read';
416             break;
417         }
418
419         $author_data = get_userdata( $user_id );
420         $post_author_data = get_userdata( $post->post_author );
421         if ( $user_id == $post_author_data->ID )
422             $caps[] = 'read';
423         else
424             $caps[] = 'read_private_posts';
425         break;
426     case 'read_page':
427         $page = get_page( $args[0] );
428
429         if ( 'private' != $page->post_status ) {
430             $caps[] = 'read';
431             break;
432         }
433
434         $author_data = get_userdata( $user_id );
435         $page_author_data = get_userdata( $page->post_author );
436         if ( $user_id == $page_author_data->ID )
437             $caps[] = 'read';
438         else
439             $caps[] = 'read_private_pages';
440         break;
441     default:
442         // If no meta caps match, return the original cap.
443         $caps[] = $cap;
444     }
445
446     return $caps;
447 }
448
449 // Capability checking wrapper around the global $current_user object.
450 function current_user_can( $capability ) {
451     $current_user = wp_get_current_user();
452
453     if ( empty( $current_user ) )
454         return false;
455
456     $args = array_slice( func_get_args(), 1 );
457     $args = array_merge( array( $capability ), $args );
458
459     return call_user_func_array( array( &$current_user, 'has_cap' ), $args );
460 }
461
462 // Convenience wrappers around $wp_roles.
463 function get_role( $role ) {
464     global $wp_roles;
465
466     if ( ! isset( $wp_roles ) )
467         $wp_roles = new WP_Roles();
468
469     return $wp_roles->get_role( $role );
470 }
471
472 function add_role( $role, $display_name, $capabilities = array() ) {
473     global $wp_roles;
474
475     if ( ! isset( $wp_roles ) )
476         $wp_roles = new WP_Roles();
477
478     return $wp_roles->add_role( $role, $display_name, $capabilities );
479 }
480
481 function remove_role( $role ) {
482     global $wp_roles;
483
484     if ( ! isset( $wp_roles ) )
485         $wp_roles = new WP_Roles();
486
487     return $wp_role