root/trunk/wp-includes/capabilities.php

Revision 7701, 12.4 kB (checked in by ryan, 3 months ago)

Default cap arg should be an empty array. Props tellyworth. fixes #5520

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