| 1 |
<?php |
| 2 |
|
| 3 |
/** |
| 4 |
* bbPress REST API. |
| 5 |
* |
| 6 |
* @package bbPress |
| 7 |
* @subpackage REST |
| 8 |
*/ |
| 9 |
|
| 10 |
// Exit if accessed directly |
| 11 |
defined( 'ABSPATH' ) || exit; |
| 12 |
|
| 13 |
/** |
| 14 |
* REST API controller for bbPress post types. |
| 15 |
* |
| 16 |
* @since 2.6.17 |
| 17 |
*/ |
| 18 |
class BBP_REST_Posts_Controller extends WP_REST_Posts_Controller { |
| 19 |
|
| 20 |
/** |
| 21 |
* Checks if a post can be updated. |
| 22 |
* |
| 23 |
* @since 2.6.17 |
| 24 |
* |
| 25 |
* @param WP_REST_Request $request Full details about the request. |
| 26 |
* @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise. |
| 27 |
*/ |
| 28 |
public function update_item_permissions_check( $request ) { |
| 29 |
$retval = parent::update_item_permissions_check( $request ); |
| 30 |
|
| 31 |
if ( is_wp_error( $retval ) ) { |
| 32 |
return $retval; |
| 33 |
} |
| 34 |
|
| 35 |
$post = isset( $request['id'] ) ? get_post( $request['id'] ) : null; |
| 36 |
if ( ! empty( $post ) && ! $this->check_read_permission( $post ) ) { |
| 37 |
return new WP_Error( |
| 38 |
'bbp_rest_cannot_edit_forum_content', |
| 39 |
esc_html__( 'You are not allowed to edit this forum content.', 'bbpress' ), |
| 40 |
array( 'status' => rest_authorization_required_code() ) |
| 41 |
); |
| 42 |
} |
| 43 |
|
| 44 |
$forum_id = ! empty( $post ) ? bbp_get_forum_id( $post->ID ) : 0; |
| 45 |
$forum = bbp_get_forum( $forum_id ); |
| 46 |
|
| 47 |
if ( empty( $forum ) ) { |
| 48 |
return $retval; |
| 49 |
} |
| 50 |
|
| 51 |
$parent_changed = $request->has_param( 'parent' ) && ( (int) $request['parent'] !== (int) $forum->post_parent ); |
| 52 |
$status_changed = $request->has_param( 'status' ) && ( $request['status'] !== $forum->post_status ); |
| 53 |
$order_changed = $request->has_param( 'menu_order' ) && ( (int) $request['menu_order'] !== (int) $forum->menu_order ); |
| 54 |
|
| 55 |
if ( ( $parent_changed || $order_changed ) && ! current_user_can( 'assign_moderators' ) ) { |
| 56 |
return new WP_Error( |
| 57 |
'bbp_rest_cannot_edit_forum_structure', |
| 58 |
esc_html__( 'You are not allowed to change this forum structure.', 'bbpress' ), |
| 59 |
array( 'status' => rest_authorization_required_code() ) |
| 60 |
); |
| 61 |
} |
| 62 |
|
| 63 |
if ( $status_changed && ! current_user_can( 'manage_forum_attributes', $forum_id ) ) { |
| 64 |
return new WP_Error( |
| 65 |
'bbp_rest_cannot_edit_forum_visibility', |
| 66 |
esc_html__( 'You are not allowed to change this forum visibility.', 'bbpress' ), |
| 67 |
array( 'status' => rest_authorization_required_code() ) |
| 68 |
); |
| 69 |
} |
| 70 |
|
| 71 |
return $retval; |
| 72 |
} |
| 73 |
|
| 74 |
/** |
| 75 |
* Checks if a post type is allowed for permission checks. |
| 76 |
* |
| 77 |
* bbPress posts may be attachment parents even when their own REST routes |
| 78 |
* are disabled. |
| 79 |
* |
| 80 |
* @since 2.6.17 |
| 81 |
* |
| 82 |
* @param WP_Post_Type|string $post_type Post type object or name. |
| 83 |
* @return bool Whether the post type is allowed. |
| 84 |
*/ |
| 85 |
protected function check_is_post_type_allowed( $post_type ) { |
| 86 |
if ( ! is_object( $post_type ) ) { |
| 87 |
$post_type = get_post_type_object( $post_type ); |
| 88 |
} |
| 89 |
|
| 90 |
$types = array( bbp_get_forum_post_type(), bbp_get_topic_post_type(), bbp_get_reply_post_type() ); |
| 91 |
|
| 92 |
if ( ! empty( $post_type ) && in_array( $post_type->name, $types, true ) ) { |
| 93 |
return true; |
| 94 |
} |
| 95 |
|
| 96 |
return parent::check_is_post_type_allowed( $post_type ); |
| 97 |
} |
| 98 |
|
| 99 |
/** |
| 100 |
* Checks if a post can be read. |
| 101 |
* |
| 102 |
* @since 2.6.17 |
| 103 |
* |
| 104 |
* @param WP_Post $post Post object. |
| 105 |
* @return bool Whether the post can be read. |
| 106 |
*/ |
| 107 |
public function check_read_permission( $post ) { |
| 108 |
$post_type = get_post_type_object( $post->post_type ); |
| 109 |
if ( ! $this->check_is_post_type_allowed( $post_type ) ) { |
| 110 |
return false; |
| 111 |
} |
| 112 |
|
| 113 |
$can_read = parent::check_read_permission( $post ); |
| 114 |
$user_id = bbp_get_current_user_id(); |
| 115 |
|
| 116 |
// Get the forum ID for this post |
| 117 |
switch ( $post->post_type ) { |
| 118 |
case bbp_get_forum_post_type() : |
| 119 |
$forum_id = $post->ID; |
| 120 |
break; |
| 121 |
|
| 122 |
case bbp_get_topic_post_type() : |
| 123 |
$forum_id = bbp_get_topic_forum_id( $post->ID ); |
| 124 |
break; |
| 125 |
|
| 126 |
case bbp_get_reply_post_type() : |
| 127 |
$forum_id = bbp_get_reply_forum_id( $post->ID ); |
| 128 |
break; |
| 129 |
|
| 130 |
default : |
| 131 |
$forum_id = 0; |
| 132 |
break; |
| 133 |
} |
| 134 |
|
| 135 |
// Check access to restricted forums and their ancestors |
| 136 |
$restricted = ! empty( $forum_id ) && bbp_is_forum_restricted( $forum_id, true ); |
| 137 |
$moderator = $restricted && is_user_logged_in() && bbp_is_user_forum_moderator( $user_id, $forum_id ); |
| 138 |
|
| 139 |
// Allow filtered moderators to read the restricted forum object |
| 140 |
$moderator_can_read = $moderator |
| 141 |
&& ( bbp_get_forum_post_type() === $post->post_type ) |
| 142 |
&& in_array( $post->post_status, array( bbp_get_private_status_id(), bbp_get_hidden_status_id() ), true ); |
| 143 |
|
| 144 |
if ( ! $can_read && ! $moderator_can_read ) { |
| 145 |
return false; |
| 146 |
} |
| 147 |
|
| 148 |
return ! bbp_is_forum_restricted_for_user( $forum_id, $user_id ); |
| 149 |
} |
| 150 |
} |
| 151 |
|
| 152 |
/** |
| 153 |
* REST API controller for attachments to bbPress post types. |
| 154 |
* |
| 155 |
* @since 2.6.17 |
| 156 |
*/ |
| 157 |
class BBP_REST_Attachments_Controller extends WP_REST_Attachments_Controller { |
| 158 |
|
| 159 |
/** |
| 160 |
* Checks if an attachment can be read. |
| 161 |
* |
| 162 |
* @since 2.6.17 |
| 163 |
* |
| 164 |
* @param WP_Post $post Attachment post object. |
| 165 |
* @return bool Whether the attachment can be read. |
| 166 |
*/ |
| 167 |
public function check_read_permission( $post ) { |
| 168 |
$post_type = get_post_type_object( $post->post_type ); |
| 169 |
if ( ! $this->check_is_post_type_allowed( $post_type ) ) { |
| 170 |
return false; |
| 171 |
} |
| 172 |
|
| 173 |
// Inherit bbPress permissions from the attachment parent |
| 174 |
if ( ( 'inherit' === $post->post_status ) && ! empty( $post->post_parent ) ) { |
| 175 |
$parent = get_post( $post->post_parent ); |
| 176 |
$types = array( bbp_get_forum_post_type(), bbp_get_topic_post_type(), bbp_get_reply_post_type() ); |
| 177 |
|
| 178 |
if ( ! empty( $parent ) && in_array( $parent->post_type, $types, true ) ) { |
| 179 |
$controller = new BBP_REST_Posts_Controller( $parent->post_type ); |
| 180 |
|
| 181 |
return $controller->check_read_permission( $parent ); |
| 182 |
} |
| 183 |
} |
| 184 |
|
| 185 |
return parent::check_read_permission( $post ); |
| 186 |
} |
| 187 |
} |
| 188 |
|
| 189 |
/** |
| 190 |
* Use the bbPress controller for attachments when Core's is unchanged. |
| 191 |
* |
| 192 |
* @since 2.6.17 |
| 193 |
*/ |
| 194 |
function bbp_register_rest_attachment_controller() { |
| 195 |
$post_type = get_post_type_object( 'attachment' ); |
| 196 |
|
| 197 |
if ( ! empty( $post_type ) && ( 'WP_REST_Attachments_Controller' === $post_type->rest_controller_class ) ) { |
| 198 |
$post_type->rest_controller_class = 'BBP_REST_Attachments_Controller'; |
| 199 |
} |
| 200 |
} |
| 201 |
|