Skip to content
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

feat: Adds property typing for an object attribute #338

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

whoami-pwd
Copy link
Contributor

@whoami-pwd whoami-pwd commented Feb 4, 2025

Description

Related Issue: #222

This PR introduces refactoring of the get_attribute_type method, new functionality for creating typed attribute objects by specifying either in child class or via WP filter.

The previous related PR is here. Comparing with the previous one the current approach is not based on the block.json but on the typed_object_attributes protected property and WP filter.


Querying Object-Type Block Attributes in WPGraphQL

Overview

With this update, you can now query object-type block attributes with each property individually, provided that the typed structure is defined in the class typed_object_attributes property or through a WordPress filter.

How It Works

The typed_object_attributes is a filterable array that defines the expected typed structure for object-type block attributes.

  • The keys in typed_object_attributes correspond to object attribute names in the block.
  • Each value is an associative array, where:
    • The key represents the property name inside the object.
    • The value defines the WPGraphQL type (e.g., string, integer, object, etc.).
  • If a block attribute has a specified typed structure, only the properties listed within it will be processed.

Defining Typed Object Attributes

Typed object attributes can be defined in two ways:

1. In a Child Class (typed_object_attributes property)

Developers can extend the Block class and specify typed properties directly:

class CustomMovieBlock extends Block {
	/**
	 * {@inheritDoc}
	 *
	 * @var array<string, array<string, "array"|"boolean"|"number"|"integer"|"object"|"rich-text"|"string">>
	 */
	protected array $typed_object_attributes = [
		'film' => [
			'id'         => 'integer',
			'title'      => 'string',
			'director'   => 'string',
			'soundtrack' => 'object',
		],
		'soundtrack' => [
			'title'  => 'string',
			'artist' => 'string'
		],
	];
}

2. Via WordPress Filter

You can also define typed structures dynamically using a WordPress filter.

add_filter(
    'wpgraphql_content_blocks_object_typing_my-custom-plugin_movie-block',
    function () {
        return [
            'film'       => [
                'id'         => 'integer',
                'title'      => 'string',
                'director'   => 'string',
                'soundtrack' => 'object',
            ],
            'soundtrack' => [
                'title'  => 'string',
                'artist' => 'string'
            ],
        ];
    }
);

Filter Naming Convention

To apply custom typing via a filter, use the following format:

wpgraphql_content_blocks_object_typing_{block-name}
  • Replace / in the block name with -.
  • Example:
    • Block name: my-custom-plugin/movie-block
    • Filter name: wpgraphql_content_blocks_object_typing_my-custom-plugin_movie-block

Example:

Example block.json Definition

If the block has attributes defined as objects, like this:

"attributes": {
    "film": {
      "type": "object",
      "default": {
        "id": 1,
        "title": "The Matrix",
        "director": "Director Name"
      }
    },
    "soundtrack": {
      "type": "object",
      "default": {
        "title": "The Matrix Revolutions...",
        "artist": "Artist Name"
      }
    }
}

This means:

  • The film attribute contains id, title, director.
  • The soundtrack attribute contains title and artist.

WPGraphQL Query Example

Once the typed object attributes are defined, you can query them individually in WPGraphQL.

fragment Movie on MyCustomPluginMovieBlock {
    attributes {
        film {
            id
            title
            director
            soundtrack {
                title
            }
        }
        soundtrack {
            title
            artist
        }
    }
}

query GetAllPostsWhichSupportBlockEditor {
    posts {
        edges {
            node {
                editorBlocks {
                    __typename
                    name
                    ...Movie
                }
            }
        }
    }
}

…ity by eliminating unnecessary if-else structures within the switch statement.
…ibutes of the block with the help of an associative array, where keys are block attributes of type object and values for the keys are associative arrays of property name and type. Provides protected property to store such array along with filter to fill it outside child classes.
Copy link

changeset-bot bot commented Feb 4, 2025

🦋 Changeset detected

Latest commit: 742f18a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@wpengine/wp-graphql-content-blocks Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

theodesp
theodesp previously approved these changes Feb 5, 2025
Copy link
Member

@theodesp theodesp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@theodesp
Copy link
Member

theodesp commented Feb 5, 2025

@whoami-pwd can you add a changeset release as well please?

@whoami-pwd whoami-pwd marked this pull request as ready for review February 6, 2025 16:58
@whoami-pwd whoami-pwd requested a review from a team as a code owner February 6, 2025 16:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants