Skip to content

Commit

Permalink
Update docs and docblocks
Browse files Browse the repository at this point in the history
  • Loading branch information
chriszarate committed Dec 18, 2024
1 parent 912831c commit 0f1c17b
Show file tree
Hide file tree
Showing 21 changed files with 452 additions and 537 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

[![Launch in WordPress Playground](https://img.shields.io/badge/Launch%20in%20WordPress%20Playground-blue?style=for-the-badge)](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/Automattic/remote-data-blocks/trunk/blueprint.json)

[Launch the plugin in WordPress Playground](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/Automattic/remote-data-blocks/trunk/blueprint.json) and explore. An example API ("Conference Events") is included, or visit Settings > Remote Data Blocks to add your own. Visit the [workflows guide](docs/workflows/index.md) to dive in.
[Launch the plugin in WordPress Playground](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/Automattic/remote-data-blocks/trunk/blueprint.json) and explore. An example API ("Conference Event") is included, or visit Settings > Remote Data Blocks to add your own. Visit the [workflows guide](docs/workflows/index.md) to dive in.

## Installation

Expand Down
10 changes: 6 additions & 4 deletions docs/concepts/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@ Remote data blocks are custom blocks, but they are created and registered by our

## Data sources and queries

Each remote data block is associated with a **data source** and a **query** that defines how data is fetched, processed, and displayed. Simple data sources and queries can be configured via the plugin's settings screen, while others may require custom PHP code (see [extending](../extending/index.md)).
Each remote data block is associated with at least one **query** that defines how data is fetched, processed, and displayed. Queries delegate some logic to a **data source**, which can be reused by multiple queries.

Simple data sources and queries can be configured via the plugin's settings screen, while others may require custom PHP code (see [extending](../extending/index.md)).

## Data fetching

Data fetching is handled by the plugin and wraps `wp_remote_request`. When a request to your site resolves to one or more remote data blocks, the remote data will be fetched and potentially cached by our plugin. Multiple requests for the same data will be deduped, even if the requests are not cacheable.
Data fetching is handled by the plugin and wraps `wp_remote_request`. When a request to your site resolves to one or more remote data blocks, the remote data will be fetched and potentially cached by our plugin. Multiple requests for the same data within a single page load will be deduped, even if the requests are not cacheable.

### Caching

The plugin offers a caching layer for optimal performance and to help avoid rate limiting from remote data sources. If your WordPress environment has configured a [persistent object cache](https://developer.wordpress.org/reference/classes/wp_object_cache/#persistent-cache-plugins), it will be used. Otherwise, the plugin will utilize in-memory (per-request) caching. Deploying to production without a persistent object cache is not recommended.
The plugin offers a caching layer for optimal performance and to help avoid rate limiting from remote data sources. If your WordPress environment has configured a [persistent object cache](https://developer.wordpress.org/reference/classes/wp_object_cache/#persistent-cache-plugins), it will be used. Otherwise, the plugin will utilize in-memory (per-page-load) caching. Deploying to production without a persistent object cache is not recommended.

The default TTL for all cache objects is 60 seconds, but can be adjusted by extending the query class and [overriding the `get_cache_ttl` method](../extending/query.md#get_cache_ttl).
The default TTL for all cache objects is 60 seconds, but it can be [configured per query or per request](../extending/query.md#get_cache_ttl).

## Theming

Expand Down
19 changes: 11 additions & 8 deletions docs/extending/block-patterns.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Block patterns

Patterns allow you to represent your remote data if different ways. By default, the plugin registers a unstyled block pattern that you can use out of the box. You can create additional patterns in the WordPress Dashboard or programmatically using the `register_remote_data_block_pattern` function.
Patterns allow you to represent your remote data if different ways. By default, the plugin registers a unstyled block pattern that you can use out of the box. You can create additional patterns in the WordPress Dashboard or programmatically by passing a `patterns` property to your block options.

Example:

Expand All @@ -18,11 +18,14 @@ Example:
```

```php
function register_your_block_pattern() {
$block_name = 'Your Custom Block';
$block_pattern = file_get_contents( '/path/to/your-pattern.html' );

register_remote_data_block_pattern( $block_name, 'Pattern Title', $block_pattern );
}
add_action( 'init', 'YourNamespace\\register_your_block_pattern', 10, 0 );
register_remote_data_block( [
'title' => 'My Remote Data Block',
'queries' => [ /* ... */ ],
'patterns' => [
[
'title' => 'My Pattern',
'content' => file_get_contents( '/path/to/your-pattern.html' ),
],
],
] );
```
43 changes: 38 additions & 5 deletions docs/extending/block-registration.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,47 @@
# Block registration

Use the `register_remote_data_block` function to register your block and associate it with your query and data source.
Use the `register_remote_data_block` function to register your block and associate it with your query and data source. This example:

1. Creates a data source
2. Associates the data source with a query
3. Defines the output schema of a query, which tells the plugin how to map the query response to blocks.
4. Registers a remote data block.

```php
function register_your_custom_block() {
$block_name = 'Your Custom Block';
$your_data_source = new YourCustomDataSource();
$your_query = new YourCustomQuery( $your_data_source );
$data_source = HttpDataSource::from_array( [
'service_config' => [
'__version' => 1,
'display_name' => 'Example API',
'endpoint' => 'https://api.example.com/',
],
] );

$display_query = HttpQuery::from_array( [
'display_name' => 'Example Query',
'data_source' => $data_source,
'output_schema' => [
'type' => [
'id => [
'name' => 'ID',
'path' => '$.id',
'type' => 'id',
],
'title' => [
'name' => 'Title',
'path' => '$.title',
'type' => 'string',
],
],
],
] );

register_remote_data_block( $block_name, $your_query );
register_remote_data_block( [
'title' => 'My Block',
'queries' => [
'display' => $display_query,
],
] );
}
add_action( 'init', 'YourNamespace\\register_your_custom_block', 10, 0 );
```
54 changes: 18 additions & 36 deletions docs/extending/data-source.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,41 @@
# Data source

A data source defines basic reusable properties of an API and is required to define a [query](query.md).

## DataSourceInterface

At its simplest, a data source implements `DataSourceInterface` and describes itself with the following methods:

- `get_display_name(): string`: Return the display name of the data source.
- `get_image_url(): string|null`: Optionally, return an image URL that can represent the data source in UI.

## HttpDataSource

The `HttpDataSource` class implements `DataSourceInterface` and provides common reusable properties of an HTTP API:

- `get_endpoint(): string`: Returns the base URL of the API endpoint. This can be overridden by a query.
- `get_request_headers(): array`: Returns an associative array of HTTP headers to be sent with each request. This is a common place to set authentication headers such as `Authorization`. This array can be extended or overridden by a query.
A data source defines basic reusable properties of an API and is used by a [query](query.md) to reduce boilerplate. It allows helps this plugin represent your data source in the plugin settings screen and other UI.

## Example

Most HTTP-powered APIs can be represented by defining a class that extends `HttpDataSource`. Here's an example of a data source for US ZIP code data:

```php
class ZipCodeDataSource extends HttpDataSource {
public function get_display_name(): string {
return 'US ZIP codes';
}

public function get_endpoint(): string {
return 'https://api.zippopotam.us/us/';
}

public function get_request_headers(): array|WP_Error {
return [
$data_source = HttpDataSource::from_array( [
'service_config' => [
'__version' => 1,
'display_name' => 'Example API',
'endpoint' => 'https://api.example.com/',
'request_headers' => [
'Content-Type' => 'application/json',
];
}
}
'X-Api-Key': MY_API_KEY_CONSTANT,
],
],
] );
```

The logic to fetch data from the API is defined in a [query](query.md).
The configuration array passed to `from_array` is very flexible, so it's usually not necessary to extend `HttpDataSource`, but you can do so if you need to add custom behavior.

## Custom data source
## Custom data sources

APIs that do not use HTTP as transport may require a custom data source. Implement `DataSourceInterface` and provide methods that define reusable properties of your API. The actual implementation of your transport will likely be provided via a [custom query runner](./query-runner.md).
For APIs that use non-HTTP transports, you can also implement `DataSourceInterface` and provide methods that define reusable properties of your API. The actual implementation of your transport will need to be provided by a [custom query runner](./query-runner.md).

Here is an example of a data source for a WebDAV server:
Here is a theoretical example of a data source for a WebDAV server:

```php
class WebDavFilesDataSource implements DataSourceInterface {
public function get_display_name(): string {
return 'WebDAV Files';
return 'My WebDAV Files';
}

public function get_image_url(): null {
return null;
public function get_image_url(): string {
return 'https://example.com/webdav-icon.png';
}

public function get_webdav_root(): string {
Expand Down
6 changes: 3 additions & 3 deletions docs/extending/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ add_filter( 'remote_data_blocks_register_example_block', '__return_false' );
Filter the allowed URL schemes for this request. By default, only HTTPS is allowed, but it might be useful to relax this restriction in local environments.

```php
function custom_allowed_url_schemes( array $allowed_url_schemes, HttpQueryContext $query_context ): array {
function custom_allowed_url_schemes( array $allowed_url_schemes, HttpQueryInterface $query ): array {
// Modify the allowed URL schemes.
return $allowed_url_schemes;
}
Expand All @@ -48,7 +48,7 @@ add_filter( 'remote_data_blocks_allowed_url_schemes', 'custom_allowed_url_scheme
Filter the request details (method, options, url) before the HTTP request is dispatched.

```php
function custom_request_details( array $request_details, HttpQueryContext $query_context, array $input_variables ): array {
function custom_request_details( array $request_details, HttpQueryInterface $query, array $input_variables ): array {
// Modify the request details.
return $request_details;
}
Expand All @@ -60,7 +60,7 @@ add_filter( 'remote_data_blocks_request_details', 'custom_request_details', 10,
Filter the query response metadata, which are available as bindings for field shortcodes. In most cases, it is better to provide a custom query class and override the `get_response_metadata` method but this filter is available in case that is not possible.

```php
function custom_query_response_metadata( array $metadata, HttpQueryContext $query_context, array $input_variables ): array {
function custom_query_response_metadata( array $metadata, HttpQueryInterface $query, array $input_variables ): array {
// Modify the response metadata.
return $metadata;
}
Expand Down
13 changes: 6 additions & 7 deletions docs/extending/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ Data sources and queries can be configured on the settings screen, but sometimes

Here's a short overview of how data flows through the plugin when a post with a remote data block is rendered:

1. WordPress core loads the post content, parses the blocks, and recognizes that a paragraph block has a [block binding](https://make.wordpress.org/core/2024/03/06/new-feature-the-block-bindings-api/).
1. WordPress core loads the post content, parses the blocks, and recognizes that a paragraph block has a [block binding](../concepts/block-bindings.md).
2. WordPress core calls the block binding callback function: `BlockBindings::get_value()`.
3. The callback function inspects the paragraph block. Using the block context supplied by the parent remote data block, it determines which query to execute.
4. The query runner is loaded: `$query->get_query_runner()`.
5. The query runner executes the query: `$query_runner->execute()`.
6. Various properties of the query are requested by the query runner, including the endpoint, request headers, request method, and request body. Some of these properties are delegated to the data source (`$query->get_data_source()`).
7. The query is dispatched and the response data is inspected, formatted into a consistent shape, and returned to the block binding callback function.
8. The callback function extracts the requested field from the response data and returns it to WordPress core for rendering.
3. The callback function inspects the paragraph block. Using the block context supplied by the parent remote data block, it determines which [query](./query.md) to execute.
4. The query is executed: `$query->execute()` (usually by delegating to a [query runner](./query-runner.md)).
5. Various properties of the query are requested by the query runner, including the endpoint, request headers, request method, and request body. Some of these properties are delegated to the data source (`$query->get_data_source()`).
6. The query is dispatched and the response data is inspected, formatted into a consistent shape, and returned to the block binding callback function.
7. The callback function extracts the requested field from the response data and returns it to WordPress core for rendering.

## Customization

Expand Down
34 changes: 13 additions & 21 deletions docs/extending/query-runner.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,35 @@
# Query runner

A query runner executes a query and processes the results. The default `QueryRunner` used by the [`HttpQueryContext` class](query.md#HttpQueryContext) is designed to work with most APIs that transact over HTTP and return JSON, but you may want to provide a custom query runner if:
A query runner executes a query and processes the results. The default `QueryRunner` used by the [`HttpQuery` class](query.md) is designed to work with most APIs that transact over HTTP and return JSON, but you may want to provide a custom query runner if:

- Your API does not respond with JSON or requires custom deserialization logic.
- Your API uses a non-HTTP transport.
- You want to implement custom processing of the response data that is not possible with the provided filters.

## QueryRunner
## Custom QueryRunner for HTTP queries

If your API transacts over HTTP and you want to customize the query runner, consider extending the `QueryRunner` class and overriding select methods.
If your API transacts over HTTP and you want to customize the query runner, consider extending the `QueryRunner` class and providing an instance to your query via the `query_runner` option. Here are the methods

### execute( array $input_variables ): array|WP_Error
### execute( HttpQueryInterface $query, array $input_variables ): array|WP_Error

The `execute` method executes the query and returns the parsed data. The input variables for the current request are provided as an associative array (`[ $var_name => $value ]`).

### get_request_details( array $input_variables ): array|WP_Error
### deserialize_response( string $raw_response_data, array $input_variables ): mixed

By default, the `deserialize_response` assumes a JSON string and deserializes it using `json_decode`. Override this method to provide custom deserialization logic.

### get_request_details( HttpQueryInterface $query, array $input_variables ): array|WP_Error

The `get_request_details` method extracts and validates the request details provided by the query. The input variables for the current request are provided as an associative array (`[ $var_name => $value ]`). The return value is an associative array that provides the HTTP method, request options, origin, and URI.

### get_raw_response_data( array $input_variables ): array|WP_Error
### get_raw_response_data( HttpQueryInterface $query, array $input_variables ): array|WP_Error

The `get_raw_response_data` method dispatches the HTTP request and assembles the raw (pre-processed) response data. The input variables for the current request are provided as an associative array (`[ $var_name => $value ]`). The return value is an associative array that provides the response metadata and the raw response data.

### get_response_metadata( array $response_metadata, array $query_results ): array
### get_response_metadata( HttpQueryInterface $query, array $response_metadata, array $query_results ): array

The `get_response_metadata` method returns the response metadata for the query, which are available as bindings for [field shortcodes](field-shortcodes.md).

### map_fields( string|array|object|null $response_data, bool $is_collection ): ?array

The `map_fields` method maps fields from the API response data, adhering to the output schema defined by the query.

### get_field_value( array|string $field_value, string $default_value = '', string $field_type = 'string' ): string

The `get_field_value` method computes the field value based on the field type. Overriding this method can be useful if you have custom field types and want to format the value in a specific way (e.g., a custom date format).
## Custom query execution

## QueryRunnerInterface

If you want to implement a query runner from scratch, `QueryRunnerInterface` requires only a single method, `execute`:

### execute( array $input_variables ): array

The `execute` method executes the query and returns the parsed data. The input variables for the current request are provided as an associative array (`[ $var_name => $value ]`).
If your API uses a non-HTTP transport or you want full control over query execution, you should implement your own query that implements `QueryInterface` and provides a custom `execute` method.
Loading

0 comments on commit 0f1c17b

Please sign in to comment.