Skip to content

Commit

Permalink
Merge commit 'ae8398b4d46e4eeab35ecee5b4a60c87da597ede' into release/…
Browse files Browse the repository at this point in the history
…v0.1.1

# Conflicts:
#	readme.txt
  • Loading branch information
jasonbahl committed Jun 30, 2022
2 parents 2eaf09c + ae8398b commit 6a24257
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 179 deletions.
131 changes: 2 additions & 129 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,130 +1,3 @@
# Welcome

Install the plugin in your WP environment. It is dependent on wp-grapqhl also being installed.

Save a graphql query string for future use by an easy usable sha 256 hash or an alias name.

## Saving Queries

When submiting a query from your client, in the POST request provide a `queryId={value}` parameter with the submitted data. This `queryId` becomes the alias name of the saved query. It can then be used in future requests to invoke the query.

Example POST data:

```
{
"query": "{
posts {
nodes {
title
}
}
}"
"queryId": "query-get-posts-title"
}
```

After that successful POST request, you can use the GET request to invoke the query by queryId.

docker run -v $PWD:/app composer install --optimize-autoloader

```
https://domain.example/graphql?queryId=query-get-posts-title
```

## What about graphql variables?

Queries that require variables to execute the graphql query, will need the variables specified with each POST or GET request. The variables are not saved with the query string in the system.

Here is an example of invoking a saved query and providing variables.

If this is the saved query in the system,

POST

```
{
"query": "query ($count:Int) {
posts(first:$count) {
nodes {
title
}
}
}"
"queryId": "query-get-posts-title"
}
```

The GET request would look like this to provide variables for the request,

```
https://domain.example/graphql?queryId=query-get-posts-title&variables={"count":2}
```

## What about queries with multiple operation names?

Graphql query strings can contain multiple operations per string and an operation name is provided in the request to specify which query to invoke. The same is true for saved queries.

Below is an example of a query string containing multiple operations that can be saved with queryId "multiple-query-get-posts".

POST

```
{
"query": "
query GetPosts {
posts {
nodes{
id
title
}
}
}
query GetPostsSlug {
posts {
nodes{
id
title
slug
}
}
}
",
"queryId": "multiple-query-get-posts"
}
```

The GET request for the saved query specifying operation name looks like this,

https://domain.example/graphql?queryId=multiple-query-get-posts&operationName=GetPostsSlug

And if your query is multiple operations as well as variables, combine all of it together in your saved query and use the correct name/value parameters on the GET query requests.

## Not Found Error

If the queryId is not found in the system an error message will be returned in the response payload. A HTTP code of 200 is returned.

```
{
"errors": [
{
"message": "Query Not Found get-post-with-slug",
"extensions": {
"category": "request"
}
}
],
}
```

## Enable caching results

Log into wp-admin for the WP service.

Select the GraphQL Settings tab.

![Settings tab](./docs/images/wp-graphql-settings.png).
-
Check the box to enable results caching.

![The checkbox to enable the results cache](./docs/images/wp-graphql-smart-cache-settings-cache.png).
# WP GraphQL Smart Cache - BETA USERS

If you've been contacted to beta test this plugin, you can access the docs here: https://docs.google.com/document/d/16n2LxJB5POBkkWF6OIC9et1BogLMiRf6qZwL7ofBT5k/edit?usp=sharing
2 changes: 1 addition & 1 deletion readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ WPGraphQL Persisted Queries for WPGraphQL, a plugin that provides an extendable

= 0.1.1 =

Initial release for beta testers and feedback collection
- Initial release to beta users
54 changes: 27 additions & 27 deletions src/Admin/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,8 @@ function () {
register_graphql_settings_section(
'graphql_persisted_queries_section',
[
'title' => __( 'Network Cache', 'wp-graphql-smart-cache' ),
'desc' => __( 'These settings apply to GraphQL queries coming over HTTP requests.', 'wp-graphql-smart-cache' ),
]
);

register_graphql_settings_field(
'graphql_persisted_queries_section',
[
'name' => 'global_max_age',
'label' => __( 'Access-Control-Max-Age Header', 'wp-graphql-smart-cache' ),
'desc' => __( 'Global Max-Age HTTP header. Integer value, greater or equal to zero.', 'wp-graphql-smart-cache' ),
'type' => 'number',
'sanitize_callback' => function ( $value ) {
if ( $value < 0 || ! is_numeric( $value ) ) {
return 0;
}
return intval( $value );
},
'title' => __( 'Saved Queries', 'wp-graphql-smart-cache' ),
'desc' => __( 'Saved/Persisted GraphQL Queries', 'wp-graphql-smart-cache' ),
]
);

Expand Down Expand Up @@ -99,8 +83,8 @@ function () {
'graphql_persisted_queries_section',
[
'name' => 'editor_display',
'label' => __( 'Display saved queries in admin editor', 'wp-graphql-smart-cache' ),
'desc' => __( 'Toggle to show saved queries in wp-admin left side menu', 'wp-graphql-smart-cache' ),
'label' => __( 'Display saved query documents in admin editor', 'wp-graphql-smart-cache' ),
'desc' => __( 'Toggle to show saved query documents in the wp-admin left side menu', 'wp-graphql-smart-cache' ),
'type' => 'checkbox',
'default' => 'off',
]
Expand All @@ -110,17 +94,33 @@ function () {
register_graphql_settings_section(
'graphql_cache_section',
[
'title' => __( 'Object Cache', 'wp-graphql-smart-cache' ),
'desc' => __( 'Use local object or transient cache to save entire GraphQL query results, for improved speed and performance.', 'wp-graphql-smart-cache' ),
'title' => __( 'Cache', 'wp-graphql-smart-cache' ),
'desc' => __( 'Caching and other settings related to improved performance of GraphQL queries.', 'wp-graphql-smart-cache' ),
]
);

register_graphql_settings_field(
'graphql_cache_section',
[
'name' => 'global_max_age',
'label' => __( 'Access-Control-Max-Age Header', 'wp-graphql-smart-cache' ),
'desc' => __( 'Global Max-Age HTTP header. Integer value, greater or equal to zero.', 'wp-graphql-smart-cache' ),
'type' => 'number',
'sanitize_callback' => function ( $value ) {
if ( $value < 0 || ! is_numeric( $value ) ) {
return 0;
}
return (int) $value;
},
]
);

register_graphql_settings_field(
'graphql_cache_section',
[
'name' => 'cache_toggle',
'label' => __( 'GraphQL Object Cache', 'wp-graphql-smart-cache' ),
'desc' => __( 'Store and return results of GraphQL Queries in the Object cache until they have expired (see below) or a related action has evicted the cached response.', 'wp-graphql-smart-cache' ),
'label' => __( 'Use Object Cache', 'wp-graphql-smart-cache' ),
'desc' => __( 'Use local object or transient cache to save entire GraphQL query results, for improved speed and performance. Store and return results of GraphQL Queries in the Object cache until they have expired (see below) or a related action has evicted the cached response.', 'wp-graphql-smart-cache' ),
'type' => 'checkbox',
'default' => 'off',
]
Expand All @@ -138,7 +138,7 @@ function () {
if ( $value < 0 || ! is_numeric( $value ) ) {
return null;
}
return intval( $value );
return (int) $value;
},
]
);
Expand All @@ -147,8 +147,8 @@ function () {
'graphql_cache_section',
[
'name' => 'purge_all',
'label' => __( 'Purge GraphQL Object Cache', 'wp-graphql-smart-cache' ),
'desc' => __( 'Select this box and click the save button to purge all responses stored in the GraphQL Object Cache.', 'wp-graphql-smart-cache' ),
'label' => __( 'Purge Now!', 'wp-graphql-smart-cache' ),
'desc' => __( 'Purge GraphQL Cache. Select this box and click the save button to purge all responses stored in the GraphQL Cache.', 'wp-graphql-smart-cache' ),
'type' => 'checkbox',
'default' => 'off',
'sanitize_callback' => function ( $value ) {
Expand Down
54 changes: 51 additions & 3 deletions src/Cache/Results.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,27 @@ class Results extends Query {

const GLOBAL_DEFAULT_TTL = 600;

/**
* The cache key for the executed GraphQL Document
*
* @var string
*/
protected $cache_key = '';

/**
* The cached response of a GraphQL Query execution. False if it doesn't exist.
*
* @var mixed|bool|array|object
*/
protected $cached_result;

public function init() {
$this->cached_result = false;

add_filter( 'pre_graphql_execute_request', [ $this, 'get_query_results_from_cache_cb' ], 10, 2 );
add_action( 'graphql_return_response', [ $this, 'save_query_results_to_cache_cb' ], 10, 7 );
add_action( 'wpgraphql_cache_purge_nodes', [ $this, 'purge_nodes_cb' ], 10, 2 );
add_filter( 'graphql_request_results', [ $this, 'add_cache_key_to_response_extensions' ], 10, 1 );

parent::init();
}
Expand All @@ -31,7 +48,37 @@ public function init() {
* @return string|false unique id for this request or false if query not provided
*/
public function the_results_key( $query_id, $query, $variables = null, $operation = null ) {
return $this->build_key( $query_id, $query, $variables, $operation );
$this->cache_key = $this->build_key( $query_id, $query, $variables, $operation );
return $this->cache_key;
}


/**
* Add a message to the extensions when a GraphQL request is returned from the GraphQL Object Cache
*
* @param mixed|array|object $response The response of the GraphQL Request
*
* @return array|mixed
*/
public function add_cache_key_to_response_extensions( $response ) {
$message = [];

// if there's no cache key, or there is no cached_result return the response as-is
if ( ! empty( $this->cache_key ) && ! empty( $this->cached_result ) ) {
$message = [
'message' => __( 'This response was not executed at run-time but has been returned from the GraphQL Object Cache', 'wp-graphql-smart-cache' ),
'cacheKey' => $this->cache_key,
];
}

if ( is_array( $response ) ) {
$response['extensions']['graphqlSmartCache']['graphqlObjectCache'] = $message;
} if ( is_object( $response ) ) {
$response->extensions['graphqlSmartCache']['graphqlObjectCache'] = $message;
}

// return the modified response with the graphqlSmartCache message in the extensions output
return $response;
}

/**
Expand All @@ -56,8 +103,9 @@ public function get_query_results_from_cache_cb( $result, $request ) {
return null;
}

$cached_result = $this->get( $key );
return ( false === $cached_result ) ? null : $cached_result;
$this->cached_result = $this->get( $key );

return ( false === $this->cached_result ) ? null : $this->cached_result;
}

/**
Expand Down
7 changes: 3 additions & 4 deletions src/Document.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,12 @@ public function init() {
register_post_type(
self::TYPE_NAME,
[
'description' => __( 'Saved GraphQL queries', 'wp-graphql-smart-cache' ),
'description' => __( 'Saved GraphQL Documents', 'wp-graphql-smart-cache' ),
'labels' => [
'name' => __( 'GraphQLQueries', 'wp-graphql-smart-cache' ),
'singular_name' => __( 'GraphQLQuery', 'wp-graphql-smart-cache' ),
'name' => __( 'GraphQL Documents', 'wp-graphql-smart-cache' ),
'singular_name' => __( 'GraphQL Document', 'wp-graphql-smart-cache' ),
],
'public' => false,
'publicly_queryable' => true,
'show_ui' => Settings::show_in_admin(),
'taxonomies' => [
self::ALIAS_TAXONOMY_NAME,
Expand Down
2 changes: 1 addition & 1 deletion src/Document/MaxAge.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public function http_headers_cb( $headers ) {

if ( null === $age ) {
// If not, use a global max-age setting if set.
$age = get_graphql_setting( 'global_max_age', null, 'graphql_persisted_queries_section' );
$age = get_graphql_setting( 'global_max_age', null, 'graphql_cache_section' );
}

// Access-Control-Max-Age header should be zero or positive integer, no decimals.
Expand Down
10 changes: 5 additions & 5 deletions tests/functional/AdminSettingsMaxAgeCest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@
class AdminSettingsMaxAgeCest
{
public function _after( FunctionalTester $I ) {
$I->dontHaveOptionInDatabase( 'graphql_persisted_queries_section' );
$I->dontHaveOptionInDatabase( 'graphql_cache_section' );
}

public function saveMaxAgeSettingsTest( FunctionalTester $I ) {
$I->loginAsAdmin();

$I->amOnPage('/wp-admin/admin.php?page=graphql-settings#graphql_persisted_queries_section');
$I->seeInField(['name' => 'graphql_persisted_queries_section[global_max_age]'], null);
$I->fillField(['name' => 'graphql_persisted_queries_section[global_max_age]'], '30');
$I->amOnPage('/wp-admin/admin.php?page=graphql-settings#graphql_cache_section');
$I->seeInField(['name' => 'graphql_cache_section[global_max_age]'], null);
$I->fillField(['name' => 'graphql_cache_section[global_max_age]'], '30');

// Save and see the selection after form submit
$I->click('Save Changes');
$I->seeInField(['name' => 'graphql_persisted_queries_section[global_max_age]'], '30');
$I->seeInField(['name' => 'graphql_cache_section[global_max_age]'], '30');
}

}
Loading

0 comments on commit 6a24257

Please sign in to comment.