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