catalog = $catalog ?? new PatternCatalog(); $this->id = 'albert/view-pattern'; $this->label = __( 'View Pattern', 'albert-ai-butler' ); $this->description = __( 'Read one block pattern by name, including its block markup. Reuse the markup as the basis for new content. Find pattern names with find-patterns.', 'albert-ai-butler' ); $this->category = 'content'; $this->group = 'patterns'; $this->input_schema = $this->get_input_schema(); $this->output_schema = $this->get_output_schema(); $this->meta = [ 'mcp' => [ 'public' => true ], 'annotations' => Annotations::read( 'The `content` is valid block markup. To reuse it as an independent copy, pass it straight to ' . 'create/update as the `content` field, or adapt it. If `syncStatus` is `synced` (user patterns only), ' . 'you can instead insert it by reference so later edits to the pattern propagate everywhere: use ' . '`` with the pattern\'s `id`. A `registered` pattern is always a copy.' ), ]; parent::__construct(); } /** * Get the input schema. * * @return array * @since 1.5.0 */ protected function get_input_schema(): array { return [ 'type' => 'object', 'properties' => [ 'name' => [ 'type' => 'string', 'description' => 'The pattern name, as returned by find-patterns (e.g. "twentytwentyfour/hero", or a user pattern slug).', ], ], 'required' => [ 'name' ], ]; } /** * Get the output schema. * * @return array * @since 1.5.0 */ protected function get_output_schema(): array { return [ 'type' => 'object', 'properties' => [ 'name' => [ 'type' => 'string' ], 'title' => [ 'type' => 'string' ], 'description' => [ 'type' => 'string' ], 'categories' => [ 'type' => 'array', 'items' => [ 'type' => 'string' ], ], 'keywords' => [ 'type' => 'array', 'items' => [ 'type' => 'string' ], ], 'viewportWidth' => [ 'type' => [ 'integer', 'null' ] ], 'content' => [ 'type' => 'string' ], 'source' => [ 'type' => 'string' ], 'id' => [ 'type' => [ 'integer', 'null' ] ], 'syncStatus' => [ 'type' => 'string' ], ], 'required' => [ 'name', 'content', 'source' ], ]; } /** * Anyone who may compose content may read a pattern. * * @return bool|WP_Error * @since 1.5.0 */ public function check_permission(): bool|WP_Error { return $this->require_capability( 'edit_posts' ); } /** * Execute: return one pattern, or a not-found error. * * @param array $args Input parameters. * @return array|WP_Error * @since 1.5.0 */ public function execute( array $args ): array|WP_Error { $name = isset( $args['name'] ) && is_string( $args['name'] ) ? trim( $args['name'] ) : ''; if ( $name === '' ) { return new WP_Error( 'pattern_name_required', __( 'A pattern name is required.', 'albert-ai-butler' ), [ 'status' => 400 ] ); } $pattern = $this->catalog->get( $name ); if ( $pattern === null ) { return new WP_Error( 'pattern_not_found', /* translators: %s: pattern name. */ sprintf( __( 'No pattern named "%s" is registered on this site. Use find-patterns to list available names.', 'albert-ai-butler' ), $name ), [ 'status' => 404 ] ); } return $pattern; } }