post_type ) { return $caps; } $order_type = OrderUtil::get_order_type( $order_id ); $order_type_ob = $order_type ? get_post_type_object( $order_type ) : null; if ( ! ( $order_type_ob instanceof WP_Post_Type ) || ! $order_type_ob->map_meta_cap ) { return $caps; } $order = wc_get_order( $order_id ); if ( ! $order instanceof WC_Abstract_Order ) { return $caps; } switch ( $cap ) { case 'edit_post': return $this->map_edit_order_caps( $order, $order_type_ob, (int) $user_id, $post ); case 'delete_post': return $this->map_delete_order_caps( $order, $order_type_ob, (int) $user_id, $post ); case 'read_post': return $this->map_read_order_caps( $order, $order_type_ob, (int) $user_id, $post ); } } /** * Map edit capabilities for an HPOS order without a real order post. * * @param WC_Abstract_Order $order Order object. * @param WP_Post_Type $order_type_ob Order post type object. * @param int $user_id User ID. * @param WP_Post|null $post Placeholder post, if one exists. * @return string[] Required primitive capabilities. */ private function map_edit_order_caps( WC_Abstract_Order $order, WP_Post_Type $order_type_ob, int $user_id, ?WP_Post $post ): array { $status = $this->get_wp_status_for_order( $order ); $is_mine = $user_id === $this->get_author_id( $post ); if ( $is_mine ) { if ( $this->is_published_status( $status ) ) { return array( $order_type_ob->cap->edit_published_posts ); } if ( 'trash' === $status && $this->is_published_status( $this->get_trashed_status( $order ) ) ) { return array( $order_type_ob->cap->edit_published_posts ); } return array( $order_type_ob->cap->edit_posts ); } $caps = array( $order_type_ob->cap->edit_others_posts ); if ( $this->is_published_status( $status ) ) { $caps[] = $order_type_ob->cap->edit_published_posts; } elseif ( $this->is_private_status( $status ) ) { $caps[] = $order_type_ob->cap->edit_private_posts; } return $caps; } /** * Map delete capabilities for an HPOS order without a real order post. * * @param WC_Abstract_Order $order Order object. * @param WP_Post_Type $order_type_ob Order post type object. * @param int $user_id User ID. * @param WP_Post|null $post Placeholder post, if one exists. * @return string[] Required primitive capabilities. */ private function map_delete_order_caps( WC_Abstract_Order $order, WP_Post_Type $order_type_ob, int $user_id, ?WP_Post $post ): array { $status = $this->get_wp_status_for_order( $order ); $is_mine = $user_id === $this->get_author_id( $post ); if ( $is_mine ) { if ( $this->is_published_status( $status ) ) { return array( $order_type_ob->cap->delete_published_posts ); } if ( 'trash' === $status && $this->is_published_status( $this->get_trashed_status( $order ) ) ) { return array( $order_type_ob->cap->delete_published_posts ); } return array( $order_type_ob->cap->delete_posts ); } $caps = array( $order_type_ob->cap->delete_others_posts ); if ( $this->is_published_status( $status ) ) { $caps[] = $order_type_ob->cap->delete_published_posts; } elseif ( $this->is_private_status( $status ) ) { $caps[] = $order_type_ob->cap->delete_private_posts; } return $caps; } /** * Map read capabilities for an HPOS order without a real order post. * * @param WC_Abstract_Order $order Order object. * @param WP_Post_Type $order_type_ob Order post type object. * @param int $user_id User ID. * @param WP_Post|null $post Placeholder post, if one exists. * @return string[] Required primitive capabilities. */ private function map_read_order_caps( WC_Abstract_Order $order, WP_Post_Type $order_type_ob, int $user_id, ?WP_Post $post ): array { $status_obj = get_post_status_object( $this->get_wp_status_for_order( $order ) ); if ( ! $status_obj ) { return array( $order_type_ob->cap->edit_others_posts ); } if ( $status_obj->public || $user_id === $this->get_author_id( $post ) ) { return array( $order_type_ob->cap->read ); } if ( $status_obj->private ) { return array( $order_type_ob->cap->read_private_posts ); } return $this->map_edit_order_caps( $order, $order_type_ob, $user_id, $post ); } /** * Get the WordPress post status equivalent for an order. * * @param WC_Abstract_Order $order Order object. * @return string Post status. */ private function get_wp_status_for_order( WC_Abstract_Order $order ): string { $status = $order->get_status( 'edit' ); return wc_is_order_status( 'wc-' . $status ) ? 'wc-' . $status : $status; } /** * Check whether a post status should require published post caps. * * @param string $status Post status. * @return bool True when published caps should be required. */ private function is_published_status( string $status ): bool { $status_obj = get_post_status_object( $status ); return in_array( $status, array( 'publish', 'future' ), true ) || ( $status_obj && $status_obj->public ); } /** * Check whether a post status should require private post caps. * * @param string $status Post status. * @return bool True when private caps should be required. */ private function is_private_status( string $status ): bool { $status_obj = get_post_status_object( $status ); return 'private' === $status || ( $status_obj && $status_obj->private ); } /** * Get the previous status stored when an order is trashed. * * @param WC_Abstract_Order $order Order object. * @return string Previous post status. */ private function get_trashed_status( WC_Abstract_Order $order ): string { $status = $order->get_meta( '_wp_trash_meta_status', true, 'edit' ); return is_string( $status ) ? $status : ''; } /** * Get the author ID to use for WordPress-style capability checks. * * @param WP_Post|null $post Placeholder post, if one exists. * @return int Author ID. */ private function get_author_id( ?WP_Post $post ): int { if ( $post instanceof WP_Post && 0 < (int) $post->post_author ) { return (int) $post->post_author; } return 1; } }