-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix "Array" values in GraphQL block array data #61
Conversation
src/graphql/graphql-api.php
Outdated
*/ | ||
public static function get_block_attribute_pair( $name, $value ) { | ||
// Unknown array types (table cells, for example) are encoded as JSON strings. | ||
if ( is_array( $value ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about using !is_scalar( $value )
instead?
$value = wp_json_encode( $value ); | ||
} | ||
|
||
return [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking if it would make sense to specify the actual type of $value
(which would be the best approach imo), or at least specifying that the content is encoded (we may run into performance issues by trying to decode every attribute in frontend)
Thanks a ton for your input, @Zamfi99! We just pushed a change that adds a Query query MyPostQuery {
post(id: $ID, idType: DATABASE_ID) {
blocksData {
blocks {
attributes {
name
value
isValueJsonEncoded " <-- New attribute "
}
id
name
innerBlocks {
attributes {
name
value
isValueJsonEncode " <-- New attribute "
}
id
name
parentId
}
}
}
}
} → Result {
"data": {
"post": {
"blocksData": {
"blocks": [
{
"attributes": [
{
"name": "hasFixedLayout",
"value": "",
"isValueJsonEncoded": false
},
{
"name": "head",
"value": "[{\"cells\":[{\"content\":\"Header A\",\"tag\":\"th\"},{\"content\":\"Header B\",\"tag\":\"th\"}]}]",
"isValueJsonEncoded": true
},
{
"name": "body",
"value": "[{\"cells\":[{\"content\":\"Value A\",\"tag\":\"td\"},{\"content\":\"Value B\",\"tag\":\"td\"}]},{\"cells\":[{\"content\":\"Value C\",\"tag\":\"td\"},{\"content\":\"Value D\",\"tag\":\"td\"}]}]",
"isValueJsonEncoded": true
},
{
"name": "foot",
"value": "[{\"cells\":[{\"content\":\"Footer A\",\"tag\":\"td\"},{\"content\":\"Footer B\",\"tag\":\"td\"}]}]",
"isValueJsonEncoded": true
}
],
"id": "QmxvY2tEYXRhOjQ1NTox",
"name": "core/table",
"innerBlocks": null
}
]
}
}
}
} We liked the idea of an opt-in
We also chose not to add the attribute's type as a queryable option, because we're actively trying to keep the GraphQL querying options simple. I also think it feels confusing to not use a "real" GraphQL type and specify a type another attribute instead. This is the same trade-off we made for original attribute typing as strings. I think the Let me know what you think! We're look to get this shipped out this week. Thank you for your input! |
@ingeniumed Would appreciate your review here as well, thank you! |
Forgot to mention that the plugin version should be bumped |
Description
See #53 for a description of the problem. In short, the code that maps block attributes into GraphQL types coerces the
value
property into a string:vip-block-data-api/src/graphql/graphql-api.php
Lines 93 to 102 in f89ed3c
This causes an
'Array'
string to replace the actual value, which makesarray
data inaccessible through WPGraphQL. Additionally, this coercion produces a notice:Why JSON?
The fix in this PR checks for arrays in the
value
property, and converts those to a JSON string representation. This was selected instead of per-block custom properties or union types.array
-source values can represent arbitrarily complex data which could require adding a new type for each block. For example, thehead
,body
, andfoot
of a table follow a structuredcell
-based pattern:That's because
core/table
uses aquery
with a known structure to fill those values.However, other uses of
array
values, like thetracks
attribute ofcore/video
use a freeform structure:If we tried to cover known core
array
types with custom types, this still wouldn't solve the problem for custom blocks. JSON representation will allow the GraphQL backend to model arbitrarily complex nested types without needing to know their structure beforehand.The primary downside is that consumers of the data will be required to know that the block contains JSON-encoded information for
array
-type values.However, that doesn't change the existing model for querying. All attribute values are already treated as
String
type as a trade-off for convenience. Also, given that array values were completely clobbered into an"Array"
string previously, this is an improvement.Steps to Test
A test using
core/table
was added intest_array_data_in_attribute()
. To run tests:wp-env start
composer install
composer run test
Fixes #53