id = 'albert/delete-post'; $this->label = __( 'Delete Post', 'albert-ai-butler' ); $this->description = __( 'Delete a WordPress post permanently or move it to trash.', 'albert-ai-butler' ); $this->category = 'content'; $this->group = 'posts'; $this->input_schema = $this->get_input_schema(); $this->output_schema = $this->get_output_schema(); $this->meta = [ 'mcp' => [ 'public' => true, ], 'annotations' => Annotations::delete( 'This is not reversible through Albert. Confirm which post you have, with `albert/view-post` ' . 'on the id, before calling it, because an id from a stale list may now be a different ' . 'post.' ), ]; parent::__construct(); } /** * Get the input schema for this ability. * * @return array Input schema. * @since 1.0.0 */ protected function get_input_schema(): array { return [ 'type' => 'object', 'properties' => [ 'id' => [ 'type' => 'integer', 'description' => 'The post ID to delete', ], 'force' => [ 'type' => 'boolean', 'description' => 'Whether to bypass trash and force deletion', 'default' => false, ], ], 'required' => [ 'id' ], ]; } /** * Get the output schema for this ability. * * @return array Output schema. * @since 1.0.0 */ protected function get_output_schema(): array { return [ 'type' => 'object', 'properties' => [ 'id' => [ 'type' => 'integer' ], 'deleted' => [ 'type' => 'boolean' ], 'status' => [ 'type' => 'string' ], ], 'required' => [ 'id', 'deleted' ], ]; } /** * Check if current user has permission to execute this ability. * * Delegates to the REST API endpoint's own permission callback. * * @return bool|WP_Error True if permitted, WP_Error with details otherwise. * @since 1.0.0 */ public function check_permission(): bool|WP_Error { return $this->check_rest_permission( '/wp/v2/posts/(?P[\\d]+)', 'DELETE', 'delete_posts' ); } /** * Execute the ability - delete a post using WordPress REST API. * * @param array $args { * Input parameters. * * @type int $id Post ID (required). * @type bool $force Whether to bypass trash and force deletion. * } * @return array|WP_Error Deletion result on success, WP_Error on failure. * @since 1.0.0 */ public function execute( array $args ): array|WP_Error { $post_id = absint( $args['id'] ); // Check if post exists. $post = get_post( $post_id ); if ( ! $post ) { return new WP_Error( 'post_not_found', __( 'Post not found.', 'albert-ai-butler' ), [ 'status' => 404 ] ); } $force = ! empty( $args['force'] ); // Create REST request. $request = new WP_REST_Request( 'DELETE', '/wp/v2/posts/' . $post_id ); $request->set_param( 'force', $force ); // Execute the request. $response = rest_do_request( $request ); $server = rest_get_server(); $data = $server->response_to_data( $response, false ); // Check for errors. if ( is_wp_error( $data ) ) { return $data; } if ( $response->is_error() ) { return new WP_Error( $data['code'] ?? 'rest_error', $data['message'] ?? __( 'An error occurred while deleting the post.', 'albert-ai-butler' ), [ 'status' => $response->get_status() ] ); } // Return deletion result. return [ 'id' => $post_id, 'deleted' => true, 'status' => $force ? 'deleted' : 'trashed', ]; } }