{"id":18328120,"url":"https://github.com/wpengine/wp-graphql-content-blocks","last_synced_at":"2025-04-05T02:08:27.625Z","repository":{"id":79319744,"uuid":"563478036","full_name":"wpengine/wp-graphql-content-blocks","owner":"wpengine","description":"Plugin that extends WPGraphQL to support querying (Gutenberg) Blocks as data","archived":false,"fork":false,"pushed_at":"2025-03-18T11:49:21.000Z","size":3520,"stargazers_count":123,"open_issues_count":15,"forks_count":15,"subscribers_count":43,"default_branch":"main","last_synced_at":"2025-03-29T01:08:07.174Z","etag":null,"topics":["graphql","wordpress","wordpress-plugin","wp-plugin","wpgraphql"],"latest_commit_sha":null,"homepage":"https://faustjs.org/docs/how-to/rendering-blocks/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wpengine.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-08T17:40:53.000Z","updated_at":"2025-03-17T20:02:14.000Z","dependencies_parsed_at":"2023-10-13T03:48:55.618Z","dependency_job_id":"cb62e2f3-5799-4eb2-92c9-e84090f8eec9","html_url":"https://github.com/wpengine/wp-graphql-content-blocks","commit_stats":{"total_commits":391,"total_committers":21,"mean_commits":18.61904761904762,"dds":0.8260869565217391,"last_synced_commit":"c09aeb754927fadfaedae473557465c3b1a74a8d"},"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wpengine%2Fwp-graphql-content-blocks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wpengine%2Fwp-graphql-content-blocks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wpengine%2Fwp-graphql-content-blocks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wpengine%2Fwp-graphql-content-blocks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wpengine","download_url":"https://codeload.github.com/wpengine/wp-graphql-content-blocks/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247276164,"owners_count":20912288,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graphql","wordpress","wordpress-plugin","wp-plugin","wpgraphql"],"created_at":"2024-11-05T19:13:11.796Z","updated_at":"2025-04-05T02:08:27.598Z","avatar_url":"https://github.com/wpengine.png","language":"PHP","readme":"# WPGraphQL Content Blocks\n\n[![Test Plugin](https://github.com/wpengine/wp-graphql-content-blocks/actions/workflows/test-plugin.yml/badge.svg)](https://github.com/wpengine/wp-graphql-content-blocks/actions/workflows/test-plugin.yml)\n\n[![Download Latest Version](https://img.shields.io/github/package-json/version/wpengine/wp-graphql-content-blocks?label=Download%20Latest%20Version)](https://github.com/wpengine/wp-graphql-content-blocks/releases/latest/download/wp-graphql-content-blocks.zip)\n\nWordPress plugin that extends WPGraphQL to support querying (Gutenberg) Blocks as data.\n\n## How to Install\n\nThis plugin is an extension of [`wp-graphql`](https://www.wpgraphql.com/), so make sure you have it installed first.\n\n1. Download the [latest .zip version of the plugin](https://github.com/wpengine/wp-graphql-content-blocks/releases/latest/download/wp-graphql-content-blocks.zip)\n2. Upload the plugin .zip to your WordPress site\n3. Activate the plugin within WordPress plugins page.\n\nThere is no other configuration needed once you install the plugin.\n\n## Getting started\n\nOnce the plugin is installed, head over to the GraphiQL IDE and you should be able to perform queries for the block data (This plugin is an extension of [wp-graphql](https://www.wpgraphql.com/), so make sure you have it installed first.).\nThere is a new field added in the Post and Page models called `editorBlocks`.\nThis represents a list of available blocks for that content type:\n\n```graphql\n{\n  posts {\n    nodes {\n      # editorBlocks field represents array of Block data\n      editorBlocks(flat: false) {\n        # fields from the interface\n        renderedHtml\n        __typename\n        # expand the Paragraph block attributes\n        ... on CoreParagraph {\n          attributes {\n            content\n          }\n        }\n        # expand a Custom block attributes\n        ... on CreateBlockMyFirstBlock {\n          attributes {\n            title\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n## How do I query block data?\n\nTo query specific block data you need to define that data in the `editorBlocks` as the appropriate type.\nFor example, to use `CoreParagraph` attributes you need to use the following query:\n\n```graphql\n{\n  posts {\n    nodes {\n      editorBlocks(flat: false) {\n        __typename\n        name\n        ... on CoreParagraph {\n          attributes {\n            content\n            className\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nIf the resolved block has values for those fields, it will return them, otherwise it will return `null`.\n\n```json\n{\n  \"__typename\": \"CoreParagraph\",\n  \"name\": \"core/paragraph\",\n  \"attributes\": {\n    \"content\": \"Hello world\",\n    \"className\": null\n  }\n}\n```\n\n## What about innerBlocks?\n\nIn order to facilitate querying `innerBlocks` fields more efficiently you want to use `editorBlocks(flat: true)` instead of `editorBlocks`.\nBy passing this argument, all the blocks available (both blocks and innerBlocks) will be returned all flattened in the same list.\n\nFor example, given the following HTML Content:\n\n```html\n\u003ccolumns\u003e\n  \u003ccolumn\u003e\n    \u003cp\u003eExample paragraph in Column\u003c/p\u003e\n    \u003cp\u003e\u003c/p\n  \u003e\u003c/column\u003e\n\n  \u003ccolumn\u003e\u003c/column\n\u003e\u003c/columns\u003e\n```\n\nIt will return the following blocks:\n\n```json\n[\n  {\n    \"__typename\": \"CoreColumns\",\n    \"name\": \"core/columns\",\n    \"id\": \"63dbec9abcf9d\",\n    \"parentClientId\": null\n  },\n  {\n    \"__typename\": \"CoreColumn\",\n    \"name\": \"core/column\",\n    \"id\": \"63dbec9abcfa6\",\n    \"parentClientId\": \"63dbec9abcf9d\"\n  },\n  {\n    \"__typename\": \"CoreParagraph\",\n    \"name\": \"core/paragraph\",\n    \"id\": \"63dbec9abcfa9\",\n    \"parentClientId\": \"63dbec9abcfa6\",\n    \"attributes\": {\n      \"content\": \"Example paragraph in Column 1\",\n      \"className\": null\n    }\n  }\n]\n```\n\nThe `CoreColumns` contains one or more `CoreColumn` block, and each `CoreColumn` contains a `CoreParagraph`.\n\nGiven the flattened list of blocks though, how can you put it back? Well that's where you use the \\`\\` and `parentId` fields to assign temporary unique ids for each block.\n\nThe `clientId` field assigns a temporary unique id for a specific block and the `parentClientId` will\nbe assigned only if the current block has a parent. If the current block does have a parent, it will get the parent's `clientId` value.\n\nSo in order to put everything back in the Headless site, you want to use the `flatListToHierarchical` function as mentioned in the [WPGraphQL docs](https://www.wpgraphql.com/docs/menus#hierarchical-data).\n\n### Note\n\n\u003e Currently the `clientId` field is only unique per request and is not persisted anywhere. If you perform another request each block will be assigned a new `clientId` each time.\n\n---\n\n## Querying Object-Type Block Attributes in WPGraphQL\n\n### Overview\nWith 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**.\n\n### How It Works\nThe `typed_object_attributes` is a **filterable** array that defines the expected **typed structure** for object-type block attributes.\n\n- The **keys** in `typed_object_attributes` correspond to **object attribute names** in the block.\n- Each value is an **associative array**, where:\n    - The key represents the **property name** inside the object.\n    - The value defines the **WPGraphQL type** (e.g., `string`, `integer`, `object`, etc.).\n- If a block attribute has a specified **typed structure**, only the properties listed within it will be processed.\n\n### Defining Typed Object Attributes\nTyped object attributes can be **defined in two ways**:\n\n#### 1. In a Child Class (`typed_object_attributes` property)\nDevelopers can extend the `Block` class and specify **typed properties** directly:\n\n```php\nclass CustomMovieBlock extends Block {\n\t/**\n\t * {@inheritDoc}\n\t *\n\t * @var array\u003cstring, array\u003cstring, \"array\"|\"boolean\"|\"number\"|\"integer\"|\"object\"|\"rich-text\"|\"string\"\u003e\u003e\n\t */\n\tprotected array $typed_object_attributes = [\n\t\t'film' =\u003e [\n\t\t\t'id'         =\u003e 'integer',\n\t\t\t'title'      =\u003e 'string',\n\t\t\t'director'   =\u003e 'string',\n\t\t\t'soundtrack' =\u003e 'object',\n\t\t],\n\t\t'soundtrack' =\u003e [\n\t\t\t'title'  =\u003e 'string',\n\t\t\t'artist' =\u003e 'string'\n\t\t],\n\t];\n}\n```\n\n#### 2. Via WordPress Filter\nYou can also define **typed structures dynamically** using a WordPress filter.\n\n```php\nadd_filter(\n    'wpgraphql_content_blocks_object_typing_my-custom-plugin_movie-block',\n    function () {\n        return [\n            'film'       =\u003e [\n                'id'         =\u003e 'integer',\n                'title'      =\u003e 'string',\n                'director'   =\u003e 'string',\n                'soundtrack' =\u003e 'object',\n            ],\n            'soundtrack' =\u003e [\n                'title'  =\u003e 'string',\n                'artist' =\u003e 'string'\n            ],\n        ];\n    }\n);\n```\n\n### Filter Naming Convention\nTo apply custom typing via a filter, use the following format:\n\n```\nwpgraphql_content_blocks_object_typing_{block-name}\n```\n- Replace `/` in the block name with `-`.\n- Example:\n    - **Block name**: `my-custom-plugin/movie-block`\n    - **Filter name**: `wpgraphql_content_blocks_object_typing_my-custom-plugin_movie-block`\n\n### Example:\n\n\n#### Example `block.json` Definition\nIf the block has attributes defined as **objects**, like this:\n\n```json\n\"attributes\": {\n    \"film\": {\n      \"type\": \"object\",\n      \"default\": {\n        \"id\": 1,\n        \"title\": \"The Matrix\",\n        \"director\": \"Director Name\"\n      }\n    },\n    \"soundtrack\": {\n      \"type\": \"object\",\n      \"default\": {\n        \"title\": \"The Matrix Revolutions...\",\n        \"artist\": \"Artist Name\"\n      }\n    }\n}\n```\nThis means:\n- The `film` attribute contains `id`, `title`, `director`.\n- The `soundtrack` attribute contains `title` and `artist`.\n\n### WPGraphQL Query Example\nOnce the typed object attributes are **defined**, you can query them **individually** in WPGraphQL.\n\n```graphql\nfragment Movie on MyCustomPluginMovieBlock {\n    attributes {\n        film {\n            id\n            title\n            director\n            soundtrack {\n                title\n            }\n        }\n        soundtrack {\n            title\n            artist\n        }\n    }\n}\n\nquery GetAllPostsWhichSupportBlockEditor {\n    posts {\n        edges {\n            node {\n                editorBlocks {\n                    __typename\n                    name\n                    ...Movie\n                }\n            }\n        }\n    }\n}\n```\n---\n\n### Contributor License Agreement\n\nAll external contributors to WP Engine products must have a signed Contributor License Agreement (CLA) in place before the contribution may be accepted into any WP Engine codebase.\n\n1. [Submit your name and email](https://wpeng.in/cla/)\n2. 📝 Sign the CLA emailed to you\n3. 📥 Receive copy of signed CLA\n\n❤️ Thank you for helping us fulfill our legal obligations in order to continue empowering builders through headless WordPress.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwpengine%2Fwp-graphql-content-blocks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwpengine%2Fwp-graphql-content-blocks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwpengine%2Fwp-graphql-content-blocks/lists"}