1 | <?php |
2 | /** |
3 | * WordPress Roles and Capabilities. |
4 | * |
5 | * @package WordPress |
6 | * @subpackage User |
7 | */ |
8 | |
9 | /** |
10 | * WordPress User Roles. |
11 | * |
12 | * The role option is simple, the structure is organized by role name that store |
13 | * the name in value of the 'name' key. The capabilities are stored as an array |
14 | * in the value of the 'capability' key. |
15 | * |
16 | * <code> |
17 | * array ( |
18 | * 'rolename' => array ( |
19 | * 'name' => 'rolename', |
20 | * 'capabilities' => array() |
21 | * ) |
22 | * ) |
23 | * </code> |
24 | * |
25 | * @since 2.0.0 |
26 | * @package WordPress |
27 | * @subpackage User |
28 | */ |
29 | class WP_Roles { |
30 | /** |
31 | * List of roles and capabilities. |
32 | * |
33 | * @since 2.0.0 |
34 | * @access public |
35 | * @var array |
36 | */ |
37 | var $roles; |
38 | |
39 | /** |
40 | * List of the role objects. |
41 | * |
42 | * @since 2.0.0 |
43 | * @access public |
44 | * @var array |
45 | */ |
46 | var $role_objects = array(); |
47 | |
48 | /** |
49 | * List of role names. |
50 | * |
51 | * @since 2.0.0 |
52 | * @access public |
53 | * @var array |
54 | */ |
55 | var $role_names = array(); |
56 | |
57 | /** |
58 | * Option name for storing role list. |
59 | * |
60 | * @since 2.0.0 |
61 | * @access public |
62 | * @var string |
63 | */ |
64 | var $role_key; |
65 | |
66 | /** |
67 | * Whether to use the database for retrieval and storage. |
68 | * |
69 | * @since 2.1.0 |
70 | * @access public |
71 | * @var bool |
72 | */ |
73 | var $use_db = true; |
74 | |
75 | /** |
76 | * PHP4 Constructor - Call {@link WP_Roles::_init()} method. |
77 | * |
78 | * @since 2.0.0 |
79 | * @access public |
80 | * |
81 | * @return WP_Roles |
82 | */ |
83 | function WP_Roles() { |
84 | $this->_init(); |
85 | } |
86 | |
87 | /** |
88 | * Set up the object properties. |
89 | * |
90 | * The role key is set to the current prefix for the $wpdb object with |
91 | * 'user_roles' appended. If the $wp_user_roles global is set, then it will |
92 | * be used and the role option will not be updated or used. |
93 | * |
94 | * @since 2.1.0 |
95 | * @access protected |
96 | * @uses $wpdb Used to get the database prefix. |
97 | * @global array $wp_user_roles Used to set the 'roles' property value. |
98 | */ |
99 | function _init () { |
100 | global $wpdb, $wp_user_roles; |
101 | $this->role_key = $wpdb->prefix . 'user_roles'; |
102 | if ( ! empty( $wp_user_roles ) ) { |
103 | $this->roles = $wp_user_roles; |
104 | $this->use_db = false; |
105 | } else { |
106 | $this->roles = get_option( $this->role_key ); |
107 | } |
108 | |
109 | if ( empty( $this->roles ) ) |
110 | return; |
111 | |
112 | $this->role_objects = array(); |
113 | $this->role_names = array(); |
114 | foreach ( (array) $this->roles as $role => $data ) { |
115 | $this->role_objects[$role] = new WP_Role( $role, $this->roles[$role]['capabilities'] ); |
116 | $this->role_names[$role] = $this->roles[$role]['name']; |
117 | } |
118 | } |
119 | |
120 | /** |
121 | * Add role name with capabilities to list. |
122 | * |
123 | * Updates the list of roles, if the role doesn't already exist. |
124 | * |
125 | * The capabilities are defined in the following format `array( 'read' => true );` |
126 | * To explicitly deny a role a capability you set the value for that capability to false. |
127 | * |
128 | * @since 2.0.0 |
129 | * @access public |
130 | * |
131 | * @param string $role Role name. |
132 | * @param string $display_name Role display name. |
133 | * @param array $capabilities List of role capabilities in the above format. |
134 | * @return null|WP_Role WP_Role object if role is added, null if already exists. |
135 | */ |
136 | function add_role( $role, $display_name, $capabilities = array() ) { |
137 | if ( isset( $this->roles[$role] ) ) |
138 | return; |
139 | |
140 | $this->roles[$role] = array( |
141 | 'name' => $display_name, |
142 | 'capabilities' => $capabilities |
143 | ); |
144 | if ( $this->use_db ) |
145 | update_option( $this->role_key, $this->roles ); |
146 | $this->role_objects[$role] = new WP_Role( $role, $capabilities ); |
147 | $this->role_names[$role] = $display_name; |
148 | return $this->role_objects[$role]; |
149 | } |
150 | |
151 | /** |
152 | * Remove role by name. |
153 | * |
154 | * @since 2.0.0 |
155 | * @access public |
156 | * |
157 | * @param string $role Role name. |
158 | */ |
159 | function remove_role( $role ) { |
160 | if ( ! isset( $this->role_objects[$role] ) ) |
161 | return; |
162 | |
163 | unset( $this->role_objects[$role] ); |
164 | unset( $this->role_names[$role] ); |
165 | unset( $this->roles[$role] ); |
166 | |
167 | if ( $this->use_db ) |
168 | update_option( $this->role_key, $this->roles ); |
169 | } |
170 | |
171 | /** |
172 | * Add capability to role. |
173 | * |
174 | * @since 2.0.0 |
175 | * @access public |
176 | * |
177 | * @param string $role Role name. |
178 | * @param string $cap Capability name. |
179 | * @param bool $grant Optional, default is true. Whether role is capable of performing capability. |
180 | */ |
181 | function add_cap( $role, $cap, $grant = true ) { |
182 | $this->roles[$role]['capabilities'][$cap] = $grant; |
183 | if ( $this->use_db ) |
184 | update_option( $this->role_key, $this->roles ); |
185 | } |
186 | |
187 | /** |
188 | * Remove capability from role. |
189 | * |
190 | * @since 2.0.0 |
191 | * @access public |
192 | * |
193 | * @param string $role Role name. |
194 | * @param string $cap Capability name. |
195 | */ |
196 | function remove_cap( $role, $cap ) { |
197 | unset( $this->roles[$role]['capabilities'][$cap] ); |
198 | if ( $this->use_db ) |
199 | update_option( $this->role_key, $this->roles ); |
200 | } |
201 | |
202 | /** |
203 | * Retrieve role object by name. |
204 | * |
205 | * @since 2.0.0 |
206 | * @access public |
207 | * |
208 | * @param string $role Role name. |
209 | * @return object|null Null, if role does not exist. WP_Role object, if found. |
210 | */ |
211 | function &get_role( $role ) { |
212 | if ( isset( $this->role_objects[$role] ) ) |
213 | return $this->role_objects[$role]; |
214 | else |
215 | return null; |
216 | } |
217 | |
218 | /** |
219 | * Retrieve list of role names. |
220 | * |
221 | * @since 2.0.0 |
222 | * @access public |
223 | * |
224 | * @return array List of role names. |
225 | */ |
226 | function get_names() { |
227 | return $this->role_names; |
228 | } |
229 | |
230 | /** |
231 | * Whether role name is currently in the list of available roles. |
232 | * |
233 | * @since 2.0.0 |
234 | * @access public |
235 | * |
236 | * @param string $role Role name to look up. |
237 | * @return bool |
238 | */ |
239 | function is_role( $role ) |
240 | { |
241 | return isset( $this->role_names[$role] ); |
242 | } |
243 | } |
244 | |
245 | /** |
246 | * WordPress Role class. |
247 | * |
248 | * @since 2.0.0 |
249 | * @package WordPress |
250 | * @subpackage User |
251 | */ |
252 | class WP_Role { |
253 | /** |
254 | * Role name. |
255 | * |
256 | * @since 2.0.0 |
257 | * @access public |
258 | * @var string |
259 | */ |
260 | var $name; |
261 | |
262 | /** |
263 | * List of capabilities the role contains. |
264 | * |
265 | * @since 2.0.0 |
266 | * @access public |
267 | * @var array |
268 | */ |
269 | var $capabilities; |
270 | |
271 | /** |
272 | * PHP4 Constructor - Set up object properties. |
273 | * |
274 | * The list of capabilities, must have the key as the name of the capability |
275 | * and the value a boolean of whether it is granted to the role. |
276 | * |
277 | * @since 2.0.0 |
278 | * @access public |
279 | * |
280 | * @param string $role Role name. |
281 | * @param array $capabilities List of capabilities. |
282 | * @return WP_Role |
283 | */ |
284 | function WP_Role( $role, $capabilities ) { |
285 | $this->name = $role; |
286 | $this->capabilities = $capabilities; |
287 | } |
288 | |
289 | /** |
290 | * Assign role a capability. |
291 | * |
292 | * @see WP_Roles::add_cap() Method uses implementation for role. |
293 | * @since 2.0.0 |
294 | * @access public |
295 | * |
296 | * @param string $cap Capability name. |
297 | * @param bool $grant Whether role has capability privilege. |
298 | */ |
299 | function add_cap( $cap, $grant = true ) { |
300 | global $wp_roles; |
301 | |
302 | if ( ! isset( $wp_roles ) ) |
303 | $wp_roles = new WP_Roles(); |
304 | |
305 | $this->capabilities[$cap] = $grant; |
306 | $wp_roles->add_cap( $this->name, $cap, $grant ); |
307 | } |
308 | |
309 | /** |
310 | * Remove capability from role. |
311 | * |
312 | * This is a container for {@link WP_Roles::remove_cap()} to remove the |
313 | * capability from the role. That is to say, that {@link |
314 | * WP_Roles::remove_cap()} implements the functionality, but it also makes |
315 | * sense to use this class, because you don't need to enter the role name. |
316 | * |
317 | * @since 2.0.0 |
318 | * @access public |
319 | * |
320 | * @param string $cap Capability name. |
321 | */ |
322 | function remove_cap( $cap ) { |
323 | global $wp_roles; |
324 | |
325 | if ( ! isset( $wp_roles ) ) |
326 | $wp_roles = new WP_Roles(); |
327 | |
328 | unset( $this->capabilities[$cap] ); |
329 | $wp_roles->remove_cap( $this->name, $cap ); |
330 | } |
331 | |
332 | /** |
333 | * Whether role has capability. |
334 | * |
335 | * The capabilities is passed through the 'role_has_cap' filter. The first |
336 | * parameter for the hook is the list of capabilities the class has |
337 | * assigned. The second parameter is the capability name to look for. The |
338 | * third and final parameter for the hook is the role name. |
339 | * |
340 | * @since 2.0.0 |
341 | * @access public |
342 | * |
343 | * @param string $cap Capability name. |
344 | * @return bool True, if user has capability. False, if doesn't have capability. |
345 | */ |
346 | function has_cap( $cap ) { |
347 | $capabilities = apply_filters( 'role_has_cap', $this->capabilities, $cap, $this->name ); |
348 | if ( !empty( $capabilities[$cap] ) ) |
349 | return $capabilities[$cap]; |
350 | else |
351 | return false; |
352 | } |
353 | |
354 | } |
355 | |
356 | /** |
357 | * WordPress User class. |
358 | * |
359 | * @since 2.0.0 |
360 | * @package WordPress |
361 | * @subpackage User |
362 | */ |
363 | class WP_User { |
364 | /** |
365 | * User data container. |
366 | * |
367 | * This will be set as properties of the object. |
368 | * |
369 | * @since 2.0.0 |
370 | * @access private |
371 | * @var array |
372 | */ |
373 | var $data; |
374 | |
375 | /** |
376 | * The user's ID. |
377 | * |
378 | * @since 2.1.0 |
379 | * @access public |
380 | * @var int |
381 | */ |
382 | var $ID = 0; |
383 | |
384 | /** |
385 | * The deprecated user's ID. |
386 | * |
387 | * @since 2.0.0 |
388 | * @access public |
389 | * @deprecated Use WP_User::$ID |
390 | * @see WP_User::$ID |
391 | * @var int |
392 | */ |
393 | var $id = 0; |
394 | |
395 | /** |
396 | * The individual capabilities the user has been given. |
397 | * |
398 | * @since 2.0.0 |
399 | * @access public |
400 | * @var array |
401 | */ |
402 | var $caps = array(); |
403 | |
404 | /** |
405 | * User metadata option name. |
406 | * |
407 | * @since 2.0.0 |
408 | * @access public |
409 | * @var string |
410 | */ |
411 | var $cap_key; |
412 | |
413 | /** |
414 | * The roles the user is part of. |
415 | * |
416 | * @since 2.0.0 |
417 | * @access public |
418 | * @var array |
419 | */ |
420 | var $roles = array(); |
421 | |
422 | /** |
423 | * All capabilities the user has, including individual and role based. |
424 | * |
425 | * @since 2.0.0 |
426 | * @access public |
427 | * @var array |
428 | */ |
429 | var $allcaps = array(); |
430 | |
431 | /** |
432 | * First name of the user. |
433 | * |
434 | * Created to prevent notices. |
435 | * |
436 | * @since 2.7.0 |
437 | * @access public |
438 | * @var string |
439 | */ |
440 | var $first_name = ''; |
441 | |
442 | /** |
443 | * Last name of the user. |
444 | * |
445 | * Created to prevent notices. |
446 | * |
447 | * @since 2.7.0 |
448 | * @access public |
449 | * @var string |
450 | */ |
451 | var $last_name = ''; |
452 | |
453 | /** |
454 | * The filter context applied to user data fields. |
455 | * |
456 | * @since 2.9.0 |
457 | * @access private |
458 | * @var string |
459 | */ |
460 | var $filter = null; |
461 | |
462 | /** |
463 | * PHP4 Constructor - Sets up the object properties. |
464 | * |
465 | * Retrieves the userdata and then assigns all of the data keys to direct |
466 | * properties of the object. Calls {@link WP_User::_init_caps()} after |
467 | * setting up the object's user data properties. |
468 | * |
469 | * @since 2.0.0 |
470 | * @access public |
471 | * |
472 | * @param int|string $id User's ID or username |
473 | * @param int $name Optional. User's username |
474 | * @return WP_User |
475 | */ |
476 | function WP_User( $id, $name = '' ) { |
477 | |
478 | if ( empty( $id ) && empty( $name ) ) |
479 | return; |
480 | |
481 | if ( ! is_numeric( $id ) ) { |
482 | $name = $id; |
483 | $id = 0; |
484 | } |
485 | |
486 | if ( ! empty( $id ) ) |
487 | $this->data = get_userdata( $id ); |
488 | else |
489 | $this->data = get_userdatabylogin( $name ); |
490 | |
491 | if ( empty( $this->data->ID ) ) |
492 | return; |
493 | |
494 | foreach ( get_object_vars( $this->data ) as $key => $value ) { |
495 | $this->{$key} = $value; |
496 | } |
497 | |
498 | $this->id = $this->ID; |
499 | $this->_init_caps(); |
500 | } |
501 | |
502 | /** |
503 | * Set up capability object properties. |
504 | * |
505 | * Will set the value for the 'cap_key' property to current database table |
506 | * prefix, followed by 'capabilities'. Will then check to see if the |
507 | * property matching the 'cap_key' exists and is an array. If so, it will be |
508 | * used. |
509 | * |
510 | * @since 2.1.0 |
511 | * |
512 | * @param string $cap_key Optional capability key |
513 | * @access protected |
514 | */ |
515 | function _init_caps( $cap_key = '' ) { |
516 | global $wpdb; |
517 | if ( empty($cap_key) ) |
518 | $this->cap_key = $wpdb->prefix . 'capabilities'; |
519 | else |
520 | $this->cap_key = $cap_key; |
521 | $this->caps = &$this->{$this->cap_key}; |
522 | if ( ! is_array( $this->caps ) ) |
523 | $this->caps = array(); |
524 | $this->get_role_caps(); |
525 | } |
526 | |
527 | /** |
528 | * Retrieve all of the role capabilities and merge with individual capabilities. |
529 | * |
530 | * All of the capabilities of the roles the user belongs to are merged with |
531 | * the users individual roles. This also means that the user can be denied |
532 | * specific roles that their role might have, but the specific user isn't |
533 | * granted permission to. |
534 | * |
535 | * @since 2.0.0 |
536 | * @uses $wp_roles |
537 | * @access public |
538 | */ |
539 | function get_role_caps() { |
540 | global $wp_roles; |
541 | |
542 | if ( ! isset( $wp_roles ) ) |
543 | $wp_roles = new WP_Roles(); |
544 | |
545 | //Filter out caps that are not role names and assign to $this->roles |
546 | if ( is_array( $this->caps ) ) |
547 | $this->roles = array_filter( array_keys( $this->caps ), array( &$wp_roles, 'is_role' ) ); |
548 | |
549 | //Build $allcaps from role caps, overlay user's $caps |
550 | $this->allcaps = array(); |
551 | foreach ( (array) $this->roles as $role ) { |
552 | $the_role =& $wp_roles->get_role( $role ); |
553 | $this->allcaps = array_merge( (array) $this->allcaps, (array) $the_role->capabilities ); |
554 | } |
555 | $this->allcaps = array_merge( (array) $this->allcaps, (array) $this->caps ); |
556 | } |
557 | |
558 | /** |
559 | * Add role to user. |
560 | * |
561 | * Updates the user's meta data option with capabilities and roles. |
562 | * |
563 | * @since 2.0.0 |
564 | * @access public |
565 | * |
566 | * @param string $role Role name. |
567 | */ |
568 | function add_role( $role ) { |
569 | $this->caps[$role] = true; |
570 | update_user_meta( $this->ID, $this->cap_key, $this->caps ); |
571 | $this->get_role_caps(); |
572 | $this->update_user_level_from_caps(); |
573 | } |
574 | |
575 | /** |
576 | * Remove role from user. |
577 | * |
578 | * @since 2.0.0 |
579 | * @access public |
580 | * |
581 | * @param string $role Role name. |
582 | */ |
583 | function remove_role( $role ) { |
584 | if ( !in_array($role, $this->roles) ) |
585 | return; |
586 | unset( $this->caps[$role] ); |
587 | update_user_meta( $this->ID, $this->cap_key, $this->caps ); |
588 | $this->get_role_caps(); |
589 | $this->update_user_level_from_caps(); |
590 | } |
591 | |
592 | /** |
593 | * Set the role of the user. |
594 | * |
595 | * This will remove the previous roles of the user and assign the user the |
596 | * new one. You can set the role to an empty string and it will remove all |
597 | * of the roles from the user. |
598 | * |
599 | * @since 2.0.0 |
600 | * @access public |
601 | * |
602 | * @param string $role Role name. |
603 | */ |
604 | function set_role( $role ) { |
605 | foreach ( (array) $this->roles as $oldrole ) |
606 | unset( $this->caps[$oldrole] ); |
607 | if ( !empty( $role ) ) { |
608 | $this->caps[$role] = true; |
609 | $this->roles = array( $role => true ); |
610 | } else { |
611 | $this->roles = false; |
612 | } |
613 | update_user_meta( $this->ID, $this->cap_key, $this->caps ); |
614 | $this->get_role_caps(); |
615 | $this->update_user_level_from_caps(); |
616 | do_action( 'set_user_role', $this->ID, $role ); |
617 | } |
618 | |
619 | /** |
620 | * Choose the maximum level the user has. |
621 | * |
622 | * Will compare the level from the $item parameter against the $max |
623 | * parameter. If the item is incorrect, then just the $max parameter value |
624 | * will be returned. |
625 | * |
626 | * Used to get the max level based on the capabilities the user has. This |
627 | * is also based on roles, so if the user is assigned the Administrator role |
628 | * then the capability 'level_10' will exist and the user will get that |
629 | * value. |
630 | * |
631 | * @since 2.0.0 |
632 | * @access public |
633 | * |
634 | * @param int $max Max level of user. |
635 | * @param string $item Level capability name. |
636 | * @return int Max Level. |
637 | */ |
638 | function level_reduction( $max, $item ) { |
639 | if ( preg_match( '/^level_(10|[0-9])$/i', $item, $matches ) ) { |
640 | $level = intval( $matches[1] ); |
641 | return max( $max, $level ); |
642 | } else { |
643 | return $max; |
644 | } |
645 | } |
646 | |
647 | /** |
648 | * Update the maximum user level for the user. |
649 | * |
650 | * Updates the 'user_level' user metadata (includes prefix that is the |
651 | * database table prefix) with the maximum user level. Gets the value from |
652 | * the all of the capabilities that the user has. |
653 | * |
654 | * @since 2.0.0 |
655 | * @access public |
656 | */ |
657 | function update_user_level_from_caps() { |
658 | global $wpdb; |
659 | $this->user_level = array_reduce( array_keys( $this->allcaps ), array( &$this, 'level_reduction' ), 0 ); |
660 | update_user_meta( $this->ID, $wpdb->prefix . 'user_level', $this->user_level ); |
661 | } |
662 | |
663 | /** |
664 | * Add capability and grant or deny access to capability. |
665 | * |
666 | * @since 2.0.0 |
667 | * @access public |
668 | * |
669 | * @param string $cap Capability name. |
670 | * @param bool $grant Whether to grant capability to user. |
671 | */ |
672 | function add_cap( $cap, $grant = true ) { |
673 | $this->caps[$cap] = $grant; |
674 | update_user_meta( $this->ID, $this->cap_key, $this->caps ); |
675 | } |
676 | |
677 | /** |
678 | * Remove capability from user. |
679 | * |
680 | * @since 2.0.0 |
681 | * @access public |
682 | * |
683 | * @param string $cap Capability name. |
684 | */ |
685 | function remove_cap( $cap ) { |
686 | if ( empty( $this->caps[$cap] ) ) |
687 | return; |
688 | unset( $this->caps[$cap] ); |
689 | update_user_meta( $this->ID, $this->cap_key, $this->caps ); |
690 | } |
691 | |
692 | /** |
693 | * Remove all of the capabilities of the user. |
694 | * |
695 | * @since 2.1.0 |
696 | * @access public |
697 | */ |
698 | function remove_all_caps() { |
699 | global $wpdb; |
700 | $this->caps = array(); |
701 | delete_user_meta( $this->ID, $this->cap_key ); |
702 | delete_user_meta( $this->ID, $wpdb->prefix . 'user_level' ); |
703 | $this->get_role_caps(); |
704 | } |
705 | |
706 | /** |
707 | * Whether user has capability or role name. |
708 | * |
709 | * This is useful for looking up whether the user has a specific role |
710 | * assigned to the user. The second optional parameter can also be used to |
711 | * check for capabilities against a specfic post. |
712 | * |
713 | * @since 2.0.0 |
714 | * @access public |
715 | * |
716 | * @param string|int $cap Capability or role name to search. |
717 | * @param int $post_id Optional. Post ID to check capability against specific post. |
718 | * @return bool True, if user has capability; false, if user does not have capability. |
719 | */ |
720 | function has_cap( $cap ) { |
721 | if ( is_numeric( $cap ) ) { |
722 | _deprecated_argument( __FUNCTION__, '2.0', __('Usage of user levels by plugins and themes is deprecated. Use roles and capabilities instead.') ); |
723 | $cap = $this->translate_level_to_cap( $cap ); |
724 | } |
725 | |
726 | $args = array_slice( func_get_args(), 1 ); |
727 | $args = array_merge( array( $cap, $this->ID ), $args ); |
728 | $caps = call_user_func_array( 'map_meta_cap', $args ); |
729 | |
730 | // Multisite super admin has all caps by definition, Unless specifically denied. |
731 | if ( is_multisite() && is_super_admin( $this->ID ) ) { |
732 | if ( in_array('do_not_allow', $caps) ) |
733 | return false; |
734 | return true; |
735 | } |
736 | |
737 | // Must have ALL requested caps |
738 | $capabilities = apply_filters( 'user_has_cap', $this->allcaps, $caps, $args ); |
739 | foreach ( (array) $caps as $cap ) { |
740 | //echo "Checking cap $cap<br />"; |
741 | if ( empty( $capabilities[$cap] ) || !$capabilities[$cap] ) |
742 | return false; |
743 | } |
744 | |
745 | return true; |
746 | } |
747 | |
748 | /** |
749 | * Convert numeric level to level capability name. |
750 | * |
751 | * Prepends 'level_' to level number. |
752 | * |
753 | * @since 2.0.0 |
754 | * @access public |
755 | * |
756 | * @param int $level Level number, 1 to 10. |
757 | * @return string |
758 | */ |
759 | function translate_level_to_cap( $level ) { |
760 | return 'level_' . $level; |
761 | } |
762 | |
763 | /** |
764 | * Set the blog to operate on. Defaults to the current blog. |
765 | * |
766 | * @since 3.0.0 |
767 | * |
768 | * @param int $blog_id Optional Blog ID, defaults to current blog. |
769 | */ |
770 | function for_blog( $blog_id = '' ) { |
771 | global $wpdb; |
772 | if ( ! empty( $blog_id ) ) |
773 | $cap_key = $wpdb->get_blog_prefix( $blog_id ) . 'capabilities'; |
774 | else |
775 | $cap_key = ''; |
776 | $this->_init_caps( $cap_key ); |
777 | } |
778 | } |
779 | |
780 | /** |
781 | * Map meta capabilities to primitive capabilities. |
782 | * |
783 | * This does not actually compare whether the user ID has the actual capability, |
784 | * just what the capability or capabilities are. Meta capability list value can |
785 | * be 'delete_user', 'edit_user', 'remove_user', 'promote_user', 'delete_post', |
786 | * 'delete_page', 'edit_post', 'edit_page', 'read_post', or 'read_page'. |
787 | * |
788 | * @since 2.0.0 |
789 | * |
790 | * @param string $cap Capability name. |
791 | * @param int $user_id User ID. |
792 | * @return array Actual capabilities for meta capability. |
793 | */ |
794 | function map_meta_cap( $cap, $user_id ) { |
795 | $args = array_slice( func_get_args(), 2 ); |
796 | $caps = array(); |
797 | |
798 | switch ( $cap ) { |
799 | case 'remove_user': |
800 | $caps[] = 'remove_users'; |
801 | break; |
802 | case 'delete_user': |
803 | $caps[] = 'delete_users'; |
804 | break; |
805 | case 'promote_user': |
806 | $caps[] = 'promote_users'; |
807 | break; |
808 | case 'edit_user': |
809 | // Allow user to edit itself |
810 | if ( isset( $args[0] ) && $user_id == $args[0] ) |
811 | break; |
812 | // Fall through |
813 | case 'edit_users': |
814 | // If multisite these caps are allowed only for super admins. |
815 | if ( is_multisite() && !is_super_admin( $user_id ) ) |
816 | $caps[] = 'do_not_allow'; |
817 | else |
818 | $caps[] = 'edit_users'; // Explicit due to primitive fall through |
819 | break; |
820 | case 'delete_post': |
821 | $author_data = get_userdata( $user_id ); |
822 | //echo "post ID: {$args[0]}<br />"; |
823 | $post = get_post( $args[0] ); |
824 | $post_type = get_post_type_object( $post->post_type ); |
825 | if ( $post_type && 'post' != $post_type->capability_type ) { |
826 | $args = array_merge( array( $post_type->cap->delete_post, $user_id ), $args ); |
827 | return call_user_func_array( 'map_meta_cap', $args ); |
828 | } |
829 | |
830 | if ( '' != $post->post_author ) { |
831 | $post_author_data = get_userdata( $post->post_author ); |
832 | } else { |
833 | //No author set yet so default to current user for cap checks |
834 | $post_author_data = $author_data; |
835 | } |
836 | |
837 | // If the user is the author... |
838 | if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID ) { |
839 | // If the post is published... |
840 | if ( 'publish' == $post->post_status ) { |
841 | $caps[] = 'delete_published_posts'; |
842 | } elseif ( 'trash' == $post->post_status ) { |
843 | if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true) ) |
844 | $caps[] = 'delete_published_posts'; |
845 | } else { |
846 | // If the post is draft... |
847 | $caps[] = 'delete_posts'; |
848 | } |
849 | } else { |
850 | // The user is trying to edit someone else's post. |
851 | $caps[] = 'delete_others_posts'; |
852 | // The post is published, extra cap required. |
853 | if ( 'publish' == $post->post_status ) |
854 | $caps[] = 'delete_published_posts'; |
855 | elseif ( 'private' == $post->post_status ) |
856 | $caps[] = 'delete_private_posts'; |
857 | } |
858 | break; |
859 | case 'delete_page': |
860 | $author_data = get_userdata( $user_id ); |
861 | //echo "post ID: {$args[0]}<br />"; |
862 | $page = get_page( $args[0] ); |
863 | $page_author_data = get_userdata( $page->post_author ); |
864 | //echo "current user id : $user_id, page author id: " . $page_author_data->ID . "<br />"; |
865 | // If the user is the author... |
866 | |
867 | if ('' != $page->post_author) { |
868 | $page_author_data = get_userdata( $page->post_author ); |
869 | } else { |
870 | //No author set yet so default to current user for cap checks |
871 | $page_author_data = $author_data; |
872 | } |
873 | |
874 | if ( is_object( $page_author_data ) && $user_id == $page_author_data->ID ) { |
875 | // If the page is published... |
876 | if ( $page->post_status == 'publish' ) { |
877 | $caps[] = 'delete_published_pages'; |
878 | } elseif ( 'trash' == $page->post_status ) { |
879 | if ('publish' == get_post_meta($page->ID, '_wp_trash_meta_status', true) ) |
880 | $caps[] = 'delete_published_pages'; |
881 | } else { |
882 | // If the page is draft... |
883 | $caps[] = 'delete_pages'; |
884 | } |
885 | } else { |
886 | // The user is trying to edit someone else's page. |
887 | $caps[] = 'delete_others_pages'; |
888 | // The page is published, extra cap required. |
889 | if ( $page->post_status == 'publish' ) |
890 | $caps[] = 'delete_published_pages'; |
891 | elseif ( $page->post_status == 'private' ) |
892 | $caps[] = 'delete_private_pages'; |
893 | } |
894 | break; |
895 | // edit_post breaks down to edit_posts, edit_published_posts, or |
896 | // edit_others_posts |
897 | case 'edit_post': |
898 | $author_data = get_userdata( $user_id ); |
899 | //echo "post ID: {$args[0]}<br />"; |
900 | $post = get_post( $args[0] ); |
901 | $post_type = get_post_type_object( $post->post_type ); |
902 | if ( $post_type && 'post' != $post_type->capability_type ) { |
903 | $args = array_merge( array( $post_type->cap->edit_post, $user_id ), $args ); |
904 | return call_user_func_array( 'map_meta_cap', $args ); |
905 | } |
906 | $post_author_data = get_userdata( $post->post_author ); |
907 | //echo "current user id : $user_id, post author id: " . $post_author_data->ID . "<br />"; |
908 | // If the user is the author... |
909 | if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID ) { |
910 | // If the post is published... |
911 | if ( 'publish' == $post->post_status ) { |
912 | $caps[] = 'edit_published_posts'; |
913 | } elseif ( 'trash' == $post->post_status ) { |
914 | if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true) ) |
915 | $caps[] = 'edit_published_posts'; |
916 | } else { |
917 | // If the post is draft... |
918 | $caps[] = 'edit_posts'; |
919 | } |
920 | } else { |
921 | // The user is trying to edit someone else's post. |
922 | $caps[] = 'edit_others_posts'; |
923 | // The post is published, extra cap required. |
924 | if ( 'publish' == $post->post_status ) |
925 | $caps[] = 'edit_published_posts'; |
926 | elseif ( 'private' == $post->post_status ) |
927 | $caps[] = 'edit_private_posts'; |
928 | } |
929 | break; |
930 | case 'edit_page': |
931 | $author_data = get_userdata( $user_id ); |
932 | //echo "post ID: {$args[0]}<br />"; |
933 | $page = get_page( $args[0] ); |
934 | $page_author_data = get_userdata( $page->post_author ); |
935 | //echo "current user id : $user_id, page author id: " . $page_author_data->ID . "<br />"; |
936 | // If the user is the author... |
937 | if ( is_object( $page_author_data ) && $user_id == $page_author_data->ID ) { |
938 | // If the page is published... |
939 | if ( 'publish' == $page->post_status ) { |
940 | $caps[] = 'edit_published_pages'; |
941 | } elseif ( 'trash' == $page->post_status ) { |
942 | if ('publish' == get_post_meta($page->ID, '_wp_trash_meta_status', true) ) |
943 | $caps[] = 'edit_published_pages'; |
944 | } else { |
945 | // If the page is draft... |
946 | $caps[] = 'edit_pages'; |
947 | } |
948 | } else { |
949 | // The user is trying to edit someone else's page. |
950 | $caps[] = 'edit_others_pages'; |
951 | // The page is published, extra cap required. |
952 | if ( 'publish' == $page->post_status ) |
953 | $caps[] = 'edit_published_pages'; |
954 | elseif ( 'private' == $page->post_status ) |
955 | $caps[] = 'edit_private_pages'; |
956 | } |
957 | break; |
958 | case 'read_post': |
959 | $post = get_post( $args[0] ); |
960 | $post_type = get_post_type_object( $post->post_type ); |
961 | if ( $post_type && 'post' != $post_type->capability_type ) { |
962 | $args = array_merge( array( $post_type->cap->read_post, $user_id ), $args ); |
963 | return call_user_func_array( 'map_meta_cap', $args ); |
964 | } |
965 | |
966 | if ( 'private' != $post->post_status ) { |
967 | $caps[] = 'read'; |
968 | break; |
969 | } |
970 | |
971 | $author_data = get_userdata( $user_id ); |
972 | $post_author_data = get_userdata( $post->post_author ); |
973 | if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID ) |
974 | $caps[] = 'read'; |
975 | else |
976 | $caps[] = 'read_private_posts'; |
977 | break; |
978 | case 'read_page': |
979 | $page = get_page( $args[0] ); |
980 | |
981 | if ( 'private' != $page->post_status ) { |
982 | $caps[] = 'read'; |
983 | break; |
984 | } |
985 | |
986 | $author_data = get_userdata( $user_id ); |
987 | $page_author_data = get_userdata( $page->post_author ); |
988 | if ( is_object( $page_author_data ) && $user_id == $page_author_data->ID ) |
989 | $caps[] = 'read'; |
990 | else |
991 | $caps[] = 'read_private_pages'; |
992 | break; |
993 | case 'unfiltered_upload': |
994 | if ( defined('ALLOW_UNFILTERED_UPLOADS') && ALLOW_UNFILTERED_UPLOADS && ( !is_multisite() || is_super_admin( $user_id ) ) ) |
995 | $caps[] = $cap; |
996 | else |
997 | $caps[] = 'do_not_allow'; |
998 | break; |
999 | case 'edit_files': |
1000 | case 'edit_plugins': |