post_type ); return $post_type_object && current_user_can( $post_type_object->cap->create_posts ); } public function update_item_permissions_check( WP_REST_Request $request ): bool { return current_user_can( 'edit_post', (int) $request['id'] ); } public function delete_item_permissions_check( WP_REST_Request $request ): bool { return current_user_can( 'delete_post', (int) $request['id'] ); } // Main Callback Methods --- /** * Retrieves a collection of placements. */ public function get_items( WP_REST_Request $request ): WP_REST_Response|WP_Error { $query_args = $this->build_query_args( $request ); $query = new WP_Query( $query_args ); if ( ! $query->have_posts() ) { return new WP_REST_Response( [], 200, [ 'X-WP-Total' => 0, 'X-WP-TotalPages' => 0, ] ); } _prime_post_caches( wp_list_pluck( $query->posts, 'ID' ), false, true ); $placement_repository = adpresso_get_placement_repository(); $items = []; foreach ( $query->posts as $post ) { // TODO: if we set process_data flag to false, conditions won't be summarized. $placement = $placement_repository->get( $post->ID, true ); if ( $placement ) { // condition_builder_data/edit_ui_sections are only needed by the edit modal (get_item()), not the list. $items[] = $placement->prepare_for_rest_response( false ); } } return new WP_REST_Response( $items, 200, [ 'X-WP-Total' => $query->found_posts, 'X-WP-TotalPages' => $query->max_num_pages, ] ); } /** * Retrieves a single placement. * * @param WP_REST_Request $request * * @return WP_REST_Response|WP_Error */ public function get_item( WP_REST_Request $request ): WP_REST_Response|WP_Error { $placement = adpresso_get_placement( (int) $request['id'] ); if ( ! $placement ) { return new WP_Error( 'rest_not_found', __( 'Placement not found.', 'adpresso' ), [ 'status' => 404 ] ); } return new WP_REST_Response( $placement->prepare_for_rest_response(), 200 ); } /** * Creates a single placement. * * @param WP_REST_Request $request * * @return WP_REST_Response|WP_Error */ public function create_item( WP_REST_Request $request ): WP_REST_Response|WP_Error { $placement = new Placement( null ); $saved_placement = adpresso_get_placement_repository()->save( $placement, $request->get_params() ); if ( ! $saved_placement ) { return new WP_Error( 'rest_cannot_create', __( 'Failed to create placement.', 'adpresso' ), [ 'status' => 500 ] ); } $response = new WP_REST_Response( $saved_placement->prepare_for_rest_response(), 201 ); $response->header( 'Location', rest_url( sprintf( '%s/%s/%d', $this->namespace, $this->rest_base, $saved_placement->get_id() ) ) ); return $response; } /** * Updates a single placement. * * @param WP_REST_Request $request * * @return WP_REST_Response|WP_Error */ public function update_item( WP_REST_Request $request ): WP_REST_Response|WP_Error { $placement = adpresso_get_placement( (int) $request['id'] ); if ( ! $placement ) { return new WP_Error( 'rest_not_found', __( 'Placement not found.', 'adpresso' ), [ 'status' => 404 ] ); } $saved_placement = adpresso_get_placement_repository()->save( $placement, $request->get_params() ); if ( ! $saved_placement ) { return new WP_Error( 'rest_cannot_update', __( 'Failed to update placement.', 'adpresso' ), [ 'status' => 500 ] ); } return new WP_REST_Response( $saved_placement->prepare_for_rest_response(), 200 ); } /** * Deletes a single placement. * * @param WP_REST_Request $request * * @return WP_REST_Response|WP_Error */ public function delete_item( WP_REST_Request $request ): WP_REST_Response|WP_Error { $placement = adpresso_get_placement( (int) $request['id'] ); if ( ! $placement ) { return new WP_Error( 'rest_not_found', __( 'Placement not found.', 'adpresso' ), [ 'status' => 404 ] ); } $previous_data = $placement->prepare_for_rest_response(); $force = (bool) $request['force']; // Same answer as WP core's posts endpoint: trashing twice is a client error, not a server failure. if ( ! $force && get_post_status( $placement->get_id() ) === 'trash' ) { return new WP_Error( 'rest_already_trashed', __( 'The placement has already been moved to the trash.', 'adpresso' ), [ 'status' => 410 ] ); } $result = adpresso_get_placement_repository()->delete( $placement, $force ); if ( ! $result ) { return new WP_Error( 'rest_cannot_delete', __( 'Failed to delete placement.', 'adpresso' ), [ 'status' => 500 ] ); } return new WP_REST_Response( [ 'deleted' => true, 'previous' => $previous_data ], 200 ); } // Schema and Parameter methods --- /** * Get collection parameters for the Placement entity. * * @return array */ protected function get_collection_params(): array { return [ 'page' => [ 'type' => 'integer', 'default' => 1, 'sanitize_callback' => 'absint' ], 'per_page' => [ 'type' => 'integer', 'default' => 100, 'sanitize_callback' => 'absint' ], 'orderby' => [ 'type' => 'string', 'default' => 'date', 'sanitize_callback' => 'sanitize_key' ], 'order' => [ 'type' => 'string', 'default' => 'desc', 'enum' => [ 'asc', 'desc' ] ], 's' => [ 'type' => 'string', 'default' => '', 'sanitize_callback' => 'sanitize_text_field' ], 'filters' => [ 'type' => 'object' ], ]; } /** * Get the endpoint args for the Placement entity. * * @param string $method * * @return array */ protected function get_endpoint_args_for_item_schema( string $method ): array { return [ 'title' => [ 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'required' => $method === WP_REST_Server::CREATABLE, ], 'status' => [ 'type' => 'string', 'enum' => [ 'publish', 'draft', 'pending', 'private' ] ], 'meta_data' => [ 'type' => 'object' ], ]; } /** * Builds query args by delegating to the QueryHandlerRegistry. */ protected function build_query_args( WP_REST_Request $request ): array { return parent::build_query_args( $request ); } }