diff --git a/.gitignore b/.gitignore
index e6c29ad..c24e35e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,3 +17,4 @@ vendor/composer/installed.json
vendor/composer/*/
composer.lock
.log
+local
diff --git a/README.md b/README.md
index f231b0f..1ad8cba 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# WPGraphQL for Advanced Custom Fields
-WPGraphQL for Advanced Custom Fields automatically exposes your ACF fields to the WPGraphQL Schema.
+WPGraphQL for Advanced Custom Fields automatically exposes your ACF fields to the WPGraphQL Schema.
- [Install and Activate](#install-and-activate)
- [Installing from Github](#install-from-github)
@@ -8,51 +8,51 @@ WPGraphQL for Advanced Custom Fields automatically exposes your ACF fields to th
- [Dependencies](#dependencies)
- [Adding Fields to the WPGraphQL Schema](#adding-fields-to-wpgraphql)
- [Supported Fields](#supported-fields)
- - [Text](#text-field)
- - [Text Area](#text-area-field)
- - [Number](#number-field)
- - [Range](#range-field)
- - [Email](#email-field)
- - [URL](#url-field)
- - [Password](#password-field)
- - [Image](#image-field)
- - [File](#file-field)
- - [WYSIWYG Editor](#wysiwyg-field)
- - [oEmbed](#oembed-field)
- - [Gallery](#gallery-field)
- - [Select](#select-field)
- - [Checkbox](#checkbox-field)
- - [Radio Button](#radio-button-field)
- - [Button Group](#button-group-field)
- - [True/False](#true-false-field)
- - [Link](#link-field)
- - [Post Object](#post-object-field)
- - [Page Link](#page-link-field)
- - [Relationship](#relationship-field)
- - [Taxonomy](#taxonomy-field)
- - [User](#user-field)
- - [Google Map](#google-map-field)
- - [Date Picker](#date-picker-field)
- - [Date/Time Picker](#date-time-picker-field)
- - [Time Picker](#time-picker-field)
- - [Color Picker](#color-picker-field)
- - [Message](#message-field)
- - [Accordion](#accordion-field)
- - [Tab](#tab-field)
- - [Group](#group-field)
- - [Repeater](#repeater-field)
- - [Flexible Content](#flexible-content-field)
- - [Clone](#clone-field)
+ - [Accordion](./docs/fields/accordion.md)
+ - [Button Group](./docs/fields/button-group.md)
+ - [Checkbox](./docs/fields/checkbox.md)
+ - [Clone](./docs/fields/clone.md)
+ - [Color Picker](./docs/fields/color-picker.md)
+ - [Date Picker](./docs/fields/date-picker.md)
+ - [Date/Time Picker](./docs/fields/date-time-picker.md)
+ - [Email](./docs/fields/email.md)
+ - [File](./docs/fields/file.md)
+ - [Flexible Content](./docs/fields/flexible-content.md)
+ - [Gallery](./docs/fields/gallery.md)
+ - [Google Map](./docs/fields/google-map.md)
+ - [Group](./docs/fields/group.md)
+ - [Image](./docs/fields/image.md)
+ - [Link](./docs/fields/link.md)
+ - [Message](./docs/fields/message.md)
+ - [Number](./docs/fields/number.md)
+ - [Oembed](./docs/fields/oembed.md)
+ - [Page Link](./docs/fields/page-link.md)
+ - [Password](./docs/fields/password.md)
+ - [Post Object](./docs/fields/post-object.md)
+ - [Radio](./docs/fields/radio.md)
+ - [Range](./docs/fields/range.md)
+ - [Relationship](./docs/fields/relationship.md)
+ - [Repeater](./docs/fields/repeater.md)
+ - [Select](./docs/fields/select.md)
+ - [Tab](./docs/fields/tab.md)
+ - [Taxonomy](./docs/fields/taxonomy.md)
+ - [Text](./docs/fields/text.md)
+ - [Text Area](./docs/fields/text-area.md)
+ - [Time Picker](./docs/fields/time-picker.md)
+ - [True/False](./docs/fields/true-false.md)
+ - [Url](./docs/fields/url.md)
+ - [User](./docs/fields/user.md)
+ - [WYSIWYG](./docs/fields/wysiwyg.md)
- [Options Pages](#options-pages)
- [Location Rules](#location-rules)
## Install and Activate
-WPGraphQL for Advanced Custom Fields is not currently available on the WordPress.org repository, so you must download it from Github, or Composer.
+WPGraphQL for Advanced Custom Fields is not currently available on the WordPress.org repository, so you must download it from Github, or Composer.
### Installing From Github
-To install the plugin from Github, you can [download the latest release zip file](https://github.com/wp-graphql/wp-graphql-acf/archive/master.zip), upload the Zip file to your WordPress install, and activate the plugin.
+To install the plugin from Github, you can [download the latest release zip file](https://github.com/wp-graphql/wp-graphql-acf/archive/master.zip), upload the Zip file to your WordPress install, and activate the plugin.
[Click here](https://wordpress.org/support/article/managing-plugins/) to learn more about installing WordPress plugins from a Zip file.
@@ -62,19 +62,19 @@ To install the plugin from Github, you can [download the latest release zip file
## Dependencies
-In order to use WPGraphQL for Advanced Custom Fields, you must have [WPGraphQL](https://github.com/wp-graphql/wp-graphql) and [Advanced Custom Fields](https://advancedcustomfields.com) (free or pro) installed and activated.
+In order to use WPGraphQL for Advanced Custom Fields, you must have [WPGraphQL](https://github.com/wp-graphql/wp-graphql) and [Advanced Custom Fields](https://advancedcustomfields.com) (free or pro) installed and activated.
## Adding Fields to the WPGraphQL Schema
**TL;DR:** [Here's a video](https://www.youtube.com/watch?v=rIg4MHc8elg) showing an overview of usage.
-Advanced Custom Fields, or ACF for short, enables users to add Field Groups, either using a [Graphical User Interface](https://www.advancedcustomfields.com/resources/creating-a-field-group/), [PHP code](https://www.advancedcustomfields.com/resources/register-fields-via-php/), or [local JSON](https://www.advancedcustomfields.com/resources/local-json/) to various screens in the WordPress dashboard, such as (but not limited to) the Edit Post, Edit User and Edit Term screens.
+Advanced Custom Fields, or ACF for short, enables users to add Field Groups, either using a [Graphical User Interface](https://www.advancedcustomfields.com/resources/creating-a-field-group/), [PHP code](https://www.advancedcustomfields.com/resources/register-fields-via-php/), or [local JSON](https://www.advancedcustomfields.com/resources/local-json/) to various screens in the WordPress dashboard, such as (but not limited to) the Edit Post, Edit User and Edit Term screens.
-Whatever method you use to register ACF fields to your WordPress site should work with WPGraphQL for Advanced Custom Fields. For the sake of simplicity, the documentation below will _primarily_ use the Graphic User Interface for examples.
+Whatever method you use to register ACF fields to your WordPress site should work with WPGraphQL for Advanced Custom Fields. For the sake of simplicity, the documentation below will _primarily_ use the Graphic User Interface for examples.
### Add ACF Fields to the WPGraphQL Schema
-The first step in using Advanced Custom Fields with WPGraphQL is to [create an ACF Field Group](https://www.advancedcustomfields.com/resources/creating-a-field-group/).
+The first step in using Advanced Custom Fields with WPGraphQL is to [create an ACF Field Group](https://www.advancedcustomfields.com/resources/creating-a-field-group/).
By default, field groups are _not_ exposed to WPGraphQL. You must opt-in to expose your ACF Field Groups and fields to the WPGraphQL Schema as some information managed by your ACF fields may not be intended for exposure in a queryable API like WPGraphQL.
@@ -96,7 +96,7 @@ When registering ACF Fields in PHP, you need to add `show_in_graphql` and `graph
```
function my_acf_add_local_field_groups() {
-
+
acf_add_local_field_group(array(
'key' => 'group_1',
'title' => 'My Group',
@@ -120,7 +120,7 @@ function my_acf_add_local_field_groups() {
),
),
));
-
+
}
add_action('acf/init', 'my_acf_add_local_field_groups');
@@ -130,7 +130,7 @@ Each individual field will inherit its GraphQL name from the supplied `name` tag
## Supported Fields
-In order to document interacting with the fields in GraphQL, an example field group has been created with one field of each type.
+In order to document interacting with the fields in GraphQL, an example field group has been created with one field of each type.
To replicate the same field group documented here you can download the [example field group](https://github.com/wp-graphql/wp-graphql-acf/blob/master/docs/field-group-examples-export.json) and [import it](https://support.advancedcustomfields.com/forums/topic/importing-exporting-acf-settings/) into your environment.
@@ -138,1565 +138,6 @@ For the sake of documentation, this example field group has the [location rule](

-### Text Field
-
-Text fields are added to the WPGraphQL Schema as a field with the Type `String`.
-
-Text fields can be queried and a String will be returned.
-
-Here, we have a Text field named `text` on the Post Edit screen within the "ACF Docs" Field Group.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post( id: "acf-example-test" idType: URI ) {
- acfDocs {
- text
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "text": "Text Value"
- }
- }
- }
-}
-```
-
-### Text Area Field
-
-Text Area fields are added to the WPGraphQL Schema as a field with the Type `String`.
-
-Text Area fields can be queried and a String will be returned.
-
-Here, we have a Text Area field named `text_area` on the Post Edit screen within the "ACF Docs" Field Group.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post( id: "acf-example-test" idType: URI ) {
- acfDocs {
- textArea
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "textArea": "Text value"
- }
- }
- }
-}
-```
-
-### Number Field
-
-Number fields are added to the WPGraphQL Schema as a field with the Type `Float`.
-
-Number fields can be queried and a Float will be returned.
-
-Here, we have a Number field named `number` on the Post Edit screen within the "ACF Docs" Field Group.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post( id: "acf-example-test" idType: URI ) {
- acfDocs {
- number
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "number": 5
- }
- }
- }
-}
-```
-
-### Range Field
-
-Range fields are added to the WPGraphQL Schema as a field with the Type `Float`.
-
-Range fields can be queried and a Float will be returned.
-
-Here, we have a Range field named `range` on the Post Edit screen within the "ACF Docs" Field Group.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post( id: "acf-example-test" idType: URI ) {
- acfDocs {
- range
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "range": 5
- }
- }
- }
-}
-```
-
-### Email Field
-
-Email fields are added to the WPGraphQL Schema as a field with the Type `String`.
-
-Email fields can be queried and a String will be returned.
-
-Here, we have an Email field named `email` on the Post Edit screen within the "ACF Docs" Field Group.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post( id: "acf-example-test" idType: URI ) {
- acfDocs {
- email
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "email": "test@example.com"
- }
- }
- }
-}
-```
-
-### URL Field
-
-Url fields are added to the WPGraphQL Schema as a field with the Type `String`.
-
-Url fields can be queried and a String will be returned.
-
-Here, we have a URL field named `url` on the Post Edit screen within the "ACF Docs" Field Group.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post( id: "acf-example-test" idType: URI ) {
- acfDocs {
- url
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "url": "https://wpgraphql.com"
- }
- }
- }
-}
-```
-
-### Password Field
-
-Password fields are added to the WPGraphQL Schema as a field with the Type `String`.
-
-Password fields can be queried and a String will be returned.
-
-Here, we have a Password field named `password` on the Post Edit screen within the "ACF Docs" Field Group.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post( id: "acf-example-test" idType: URI ) {
- acfDocs {
- password
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "password": "123456"
- }
- }
- }
-}
-```
-
-### Image Field
-
-Image fields are added to the WPGraphQL Schema as a field with the Type `MediaItem`.
-
-Image fields can be queried and a MediaItem will be returned.
-
-The `MediaItem` type is an Object type that has it's own fields that can be selected. So, instead of _just_ getting the Image ID returned and having to ask for the MediaItem object in a follow-up request, we can ask for fields available on the MediaItem Type. For this example, we ask for the `id` and `sourceUrl`.
-
-Here, we have an Image field named `image` on the Post Edit screen within the "ACF Docs" Field Group.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post( id: "acf-example-test" idType: URI ) {
- acfDocs {
- image {
- id
- sourceUrl(size: MEDIUM)
- }
- }
- }
-}
-```
-
-And the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "image": {
- "id": "YXR0YWNobWVudDozMjM=",
- "sourceUrl": "http://wpgraphql.local/wp-content/uploads/2020/03/babe-ruth-300x169.jpg"
- }
- }
- }
- }
-}
-```
-
-### File Field
-
-File fields are added to the WPGraphQL Schema as a field with the Type `MediaItem`.
-
-File fields can be queried and a MediaItem will be returned.
-
-The `MediaItem` type is an Object type that has it's own fields that can be selected. So, instead of _just_ getting the File ID returned and having to ask for the MediaItem object in a follow-up request, we can ask for fields available on the MediaItem Type. For this example, we ask for the `id` and `mediaItemUrl`.
-
-Here, we have a File field named `file` on the Post Edit screen within the "ACF Docs" Field Group.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- file {
- id
- mediaItemUrl
- }
- }
- }
-}
-```
-
-And the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "file": {
- "id": "YXR0YWNobWVudDozMjQ=",
- "mediaItemUrl": "http://acf2.local/wp-content/uploads/2020/03/little-ceasars-receipt-01282020.pdf"
- }
- }
- }
- }
-}
-```
-
-### WYSIWYG Editor Field
-
-WYSIWYG fields are added to the WPGraphQL Schema as a field with the Type `String`.
-
-WYSIWYG fields can be queried and a String will be returned.
-
-Here, we have a WYSIWYG field named `wysiwyg` on the Post Edit screen within the "ACF Docs" Field Group.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post( id: "acf-example-test" idType: URI ) {
- acfDocs {
- wysiwyg
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "wysiwyg": "
Some content in a WYSIWYG field
\n"
- }
- }
- }
-}
-```
-
-### oEmbed Field
-
-oEmbed fields are added to the WPGraphQL Schema as a field with the Type `String`.
-
-oEmbed fields can be queried and a String will be returned.
-
-Here, we have a oEmbed field named `oembed` on the Post Edit screen within the "ACF Docs" Field Group.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- oembed
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "oembed": "https://www.youtube.com/watch?v=ZEytXfaWwcc"
- }
- }
- }
-}
-```
-
-### Gallery Field
-
-Gallery fields are added to the WPGraphQL Schema as a field with the Type of `['list_of' => 'MediaItem']`.
-
-Gallery fields can be queried and a list of MediaItem types will be returned.
-
-Since the type is a list, we can expect an array to be returned. And since the Type within the list is `MediaItem`, we can ask for fields we want returned for each `MediaItem` in the list. In this case, let's say we want to ask for the `id` of each image and the `sourceUrl`, (size large).
-
-Here, we have a Gallery field named `gallery` on the Post Edit screen within the "ACF Docs" Field Group.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- gallery {
- id
- sourceUrl(size: LARGE)
- }
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "gallery": [
- {
- "id": "YXR0YWNobWVudDoyNTY=",
- "sourceUrl": "http://wpgraphql.local/wp-content/uploads/2020/02/babe-ruth.jpg"
- },
- {
- "id": "YXR0YWNobWVudDoyNTU=",
- "sourceUrl": "http://wpgraphql.local/wp-content/uploads/2020/02/babe-ruth-baseball-986x1024.jpg"
- }
- ]
- }
- }
- }
-}
-```
-
-### Select Field
-
-Select fields (when configured to _not_ allow mutliple selections) are added to the WPGraphQL Schema as a field with the Type `String`.
-
-Select fields, without multiple selections allowed, can be queried and a String will be returned.
-
-Here, we have a Select field named `select` on the Post Edit screen within the "ACF Docs" Field Group, and "Choice 1" is selected.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- select
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "select": "choice_1"
- }
- }
- }
-}
-```
-
-### Checkbox Field
-
-Checkbox fields are added to the WPGraphQL Schema as a field with the Type `[ 'list_of' => 'String' ]`.
-
-Checkbox fields can be queried and a list (array) of Strings (the selected values) will be returned.
-
-Here, we have a Checkbox field named `checkbox` on the Post Edit screen within the "ACF Docs" Field Group, and "Choice 1" is selected.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- checkbox
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "checkbox": [
- "choice_1"
- ]
- }
- }
- }
-}
-```
-
-### Radio Button Field
-
-Radio Button fields are added to the WPGraphQL Schema as a field with the Type `String`.
-
-Radio Button fields can be queried and a String will be returned.
-
-Here, we have a Radio Button field named `radio_button` on the Post Edit screen within the "ACF Docs" Field Group, and "Choice 2" is selected.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- radioButton
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "radioButton": "choice_2"
- }
- }
- }
-}
-```
-
-### Button Group Field
-
-Button Group fields are added to the WPGraphQL Schema as a field with the Type `String`.
-
-Button Group fields can be queried and a String will be returned.
-
-Here, we have a Button Group field named `button_group` on the Post Edit screen within the "ACF Docs" Field Group, and "Choice 2" is selected.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- buttonGroup
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "buttonGroup": "choice_2"
- }
- }
- }
-}
-```
-
-### True/False Field
-
-True/False fields are added to the WPGraphQL Schema as a field with the Type `Boolean`.
-
-True/False fields can be queried and a Boolean will be returned.
-
-Here, we have a True/False field named `true_false` on the Post Edit screen within the "ACF Docs" Field Group, and "true" is selected.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- trueFalse
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "trueFalse": true
- }
- }
- }
-}
-```
-
-### Link Field
-
-Link fields are added to the WPGraphQL Schema as a field with the Type `ACF_Link`.
-
-Link fields can be queried and a `ACF_Link` will be returned. The ACF Link is an object with fields that can be selected.
-
-The available fields on the `ACF_Link` Type are:
-
-- **target** (String): The target of the link
-- **title** (String): The target of the link
-- **url** (String): The url of the link
-
-Here, we have a Link field named `link` on the Post Edit screen within the "ACF Docs" Field Group.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- link {
- target
- title
- url
- }
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "link": {
- "target": "",
- "title": "Hello world!",
- "url": "http://acf2.local/hello-world/"
- }
- }
- }
- }
-}
-```
-
-### Post Object Field
-
-Post Object fields are added to the WPGraphQL Schema as a field with a [Union](https://graphql.org/learn/schema/#union-types) of Possible Types the field is configured to allow.
-
-If the field is configured to allow multiple selections, it will be added to the Schema as a List Of the Union Type.
-
-Since Post Object fields can be configured to be limited to certain Post Types, the Union will represent those Types.
-
-For example, if the Post Object field is configured to allow Posts of the `post` and `page` types to be selected:
-
-
-
-Then the Union type for the field will allow `Post` and `Page` types to be returned, as seen in the Schema via GraphiQL:
-
-
-
-Here, we have a Post Object field named `post_object` on the Post Edit screen within the "ACF Docs" Field Group, configured with the Post "Hello World!".
-
-
-
-As a GraphQL consumer, we don't know in advance if the value is going to be a Page or a Post.
-
-So we can specify, via GraphQL fragment, what fields we want if the object is a Post, or if it is a Page.
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- postObject {
- __typename
- ... on Post {
- id
- title
- date
- }
- ... on Page {
- id
- title
- }
- }
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "postObject": {
- "__typename": "Post",
- "id": "cG9zdDox",
- "title": "Hello world!",
- "date": "2020-02-20T23:12:21"
- }
- }
- }
- }
-}
-```
-
-If the input of the field was saved as a Page, instead of a Post, like so:
-
-
-
-Then the same query above, would return the following results:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "postObject": {
- "__typename": "Page",
- "id": "cGFnZToy",
- "title": "Sample Page"
- }
- }
- }
- }
-}
-```
-
-Now, if the field were configured to allow multiple values, the field would be added to the Schema as a `listOf`, returning an Array of the Union.
-
-If the field were set with a value of one Page, and one Post, like so:
-
-
-
-Then the results of the same query as above would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "postObject": [
- {
- "__typename": "Page",
- "id": "cGFnZToy",
- "title": "Sample Page"
- },
- {
- "__typename": "Post",
- "id": "cG9zdDox",
- "title": "Hello world!",
- "date": "2020-02-20T23:12:21"
- }
- ]
- }
- }
- }
-}
-```
-
-### Page Link Field
-
-Page Link fields are added to the WPGraphQL Schema as a field with a [Union](https://graphql.org/learn/schema/#union-types) of Possible Types the field is configured to allow.
-
-Since Page Link fields can be configured to be limited to certain Post Types, the Union will represent those Types.
-
-For example, if the Post Object field is configured to allow Posts of the `post` and `page` types to be selected:
-
-
-
-Then the Union type for the field will allow `Post` and `Page` types to be returned, as seen in the Schema via GraphiQL:
-
-
-
-Here, we have a Page Link field named `page_link` on the Post Edit screen within the "ACF Docs" Field Group, and the value is set to the "Sample Page" page.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- pageLink {
- __typename
- ... on Post {
- id
- title
- date
- }
- ... on Page {
- id
- title
- }
- }
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "pageLink": {
- "__typename": "Page",
- "id": "cGFnZToy",
- "title": "Sample Page"
- }
- }
- }
- }
-}
-```
-
-Here, we set the value to the "Hello World" Post:
-
-
-
-And the results of the same query are now:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "pageLink": {
- "__typename": "Post",
- "id": "cG9zdDox",
- "title": "Hello world!",
- "date": "2020-02-20T23:12:21"
- }
- }
- }
- }
-}
-```
-
-### Relationship Field
-
-Relationship fields are added to the WPGraphQL Schema as a field with a [Union](https://graphql.org/learn/schema/#union-types) of Possible Types the field is configured to allow.
-
-Since Relationship fields can be configured to be limited to certain Post Types, the Union will represent those Types.
-
-For example, if the Post Object field is configured to allow Posts of the `post` and `page` types to be selected:
-
-
-
-Then the Union type for the field will allow `Post` and `Page` types to be returned, as seen in the Schema via GraphiQL:
-
-
-
-Here, we have a Relationship field named `relationship` on the Post Edit screen within the "ACF Docs" Field Group, and the value is set to "Hello World!" post, and the "Sample Page" page.
-
-
-
-This field can be Queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- relationship {
- __typename
- ... on Post {
- id
- title
- date
- }
- ... on Page {
- id
- title
- }
- }
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "relationship": [
- {
- "__typename": "Post",
- "id": "cG9zdDox",
- "title": "Hello world!",
- "date": "2020-02-20T23:12:21"
- },
- {
- "__typename": "Page",
- "id": "cGFnZToy",
- "title": "Sample Page"
- }
- ]
- }
- }
- }
-}
-```
-
-### Taxonomy Field
-
-The Taxonomy field is added to the GraphQL Schema as a List Of the Taxonomy Type.
-
-For example, if the field is configured to the "Category" taxonomy, then the field in the Schema will be a List of the Category type.
-
-
-
-Here, we have a Taxonomy field named `taxonomy` on the Post Edit screen within the "ACF Docs" Field Group, configured with the Category "Test Category".
-
-
-
-This field can be queried like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- taxonomy {
- __typename
- id
- name
- }
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "taxonomy": [
- {
- "__typename": "Category",
- "id": "Y2F0ZWdvcnk6Mg==",
- "name": "Test Category"
- }
- ]
- }
- }
- }
-}
-```
-
-### User Field
-
-User fields are added to the WPGraphQL Schema as a field with a User type.
-
-Here, we have a User field named `user` on the Post Edit screen within the "ACF Docs" Field Group, set with the User "jasonbahl" as the value.
-
-
-
-This field can be queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- user {
- id
- username
- firstName
- lastName
- }
- }
- }
-}
-```
-
-and the response would look like:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "user": {
- "id": "dXNlcjox",
- "username": "jasonbahl",
- "firstName": "Jason",
- "lastName": "Bahl"
- }
- }
- }
- }
-}
-```
-
-If the field is configured to allow multiple selections, it's added to the Schema as a List Of the User type.
-
-Here, we have a User field named `user` on the Post Edit screen within the "ACF Docs" Field Group, set with the User "jasonbahl" and "WPGraphQL" as the value.
-
-
-
-and the response to the same query would look like:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "user": [
- {
- "id": "dXNlcjox",
- "username": "jasonbahl",
- "firstName": "Jason",
- "lastName": "Bahl"
- },
- {
- "id": "dXNlcjoy",
- "username": "WPGraphQL",
- "firstName": "WP",
- "lastName": "GraphQL"
- }
- ]
- }
- }
- }
-}
-```
-
-### Google Map Field
-
-Google Map fields are added to the WPGraphQL Schema as the `ACF_GoogleMap` Type.
-
-The `ACF_GoogleMap` Type has fields that expose location data. The available fields are:
-
-- **city** (String): The city associated with the location
-- **country** (String): The country associated with the location
-- **countryShort** (String): The country abbreviation associated with the location
-- **latitude** (String): The latitude associated with the location
-- **longitude** (String): The longitude associated with the location
-- **placeId** (String): Place IDs uniquely identify a place in the Google Places database and on Google Maps.
-- **postCode** (String): The post code associated with the location
-- **state** (String): The state associated with the location
-- **stateShort** (String): The state abbreviation associated with the location
-- **streetAddress** (String): The street address associated with the location
-- **streetName** (String): The street name associated with the location
-- **streetNumber** (String): The street number associated with the location
-- **zoom** (String): The zoom defined with the location
-
-Here, we have a Google Map field named `google_map` on the Post Edit screen within the "ACF Docs" Field Group, set with the Address "1 Infinite Loop, Cupertino, CA 95014, USA" as the value.
-
-
-
-This field can be queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- googleMap {
- streetAddress
- streetNumber
- streetName
- city
- state
- postCode
- countryShort
- }
- }
- }
-}
-```
-
-and the response would look like:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "googleMap": {
- "streetAddress": "1 Infinite Loop, Cupertino, CA 95014, USA",
- "streetNumber": "1",
- "streetName": "Infinite Loop",
- "city": "Cupertino",
- "state": "California",
- "postCode": "95014",
- "placeId": "ChIJHTRqF7e1j4ARzZ_Fv8VA4Eo",
- "countryShort": "US"
- }
- }
- }
- }
-}
-```
-
-### Date Picker Field
-
-The Date Picker field is added to the WPGraphQL Schema as field with the Type `String`.
-
-Date Picker fields can be queried and a String will be returned.
-
-Here, we have a Date Picker field named `date_picker` on the Post Edit screen within the "ACF Docs" Field Group, and "13/03/2020" is the date set.
-
-
-
-This field can be queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- datePicker
- }
- }
-}
-```
-
-and the result of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "datePicker": "13/03/2020"
- }
- }
- }
-}
-```
-
-### Date/Time Picker Field
-
-The Date/Time Picker field is added to the WPGraphQL Schema as field with the Type `String`.
-
-Date/Time Picker fields can be queried and a String will be returned.
-
-Here, we have a Date/Time Picker field named `date_time_picker` on the Post Edit screen within the "ACF Docs" Field Group, and "20/03/2020 8:15 am" is the value.
-
-
-
-This field can be queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- dateTimePicker
- }
- }
-}
-```
-
-and the result of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "dateTimePicker": "20/03/2020 8:15 am"
- }
- }
- }
-}
-```
-
-### Time Picker Field
-
-The Time Picker field is added to the WPGraphQL Schema as field with the Type `String`.
-
-Time Picker fields can be queried and a String will be returned.
-
-Here, we have a Time Picker field named `time_picker` on the Post Edit screen within the "ACF Docs" Field Group, and "12:30 am" is the value.
-
-
-
-This field can be queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- timePicker
- }
- }
-}
-```
-
-and the result of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "timePicker": "12:30 am"
- }
- }
- }
-}
-```
-
-### Color Picker Field
-
-The Color Picker field is added to the WPGraphQL Schema as field with the Type `String`.
-
-Color Picker fields can be queried and a String will be returned.
-
-Here, we have a Color Picker field named `color_picker` on the Post Edit screen within the "ACF Docs" Field Group, and "#dd3333" is the value.
-
-
-
-This field can be queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- colorPicker
- }
- }
-}
-```
-
-and the result of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "colorPicker": "12:30 am"
- }
- }
- }
-}
-```
-
-### Message Field
-
-Message fields are not currently supported.
-
-### Accordion Field
-
-Accordion Fields are not currently supported.
-
-### Tab Field
-
-Tab fields are not currently supported.
-
-### Group Field
-
-Group Fields are added to the WPGraphQL Schema as fields resolving to an Object Type named after the Group.
-
-Here, we have a Group field named `group` on the Post Edit screen within the "ACF Docs" Field Group. Within the "group" field, we have a Text Field named `text_field_in_group` and a Text Area field named `text_area_field_in_group`
-
-
-
-We can query the fields within the group like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- group {
- textFieldInGroup
- textAreaFieldInGroup
- }
- }
- }
-}
-```
-
-And the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "group": {
- "textFieldInGroup": "Text value, in group",
- "textAreaFieldInGroup": "Text are value, in group"
- }
- }
- }
- }
-}
-```
-
-### Repeater Field
-
-Repeater Fields are added to the Schema as a List Of the Type of group that makes up the fields.
-
-For example, we've created a Repeater Field that has a Text Field named `text_field_in_repeater` and an Image Field named `image_field_in_repeater`.
-
-Here, the Repeater Field is populated with 2 rows:
-- Row 1:
- - Text Field: Text Value 1
- - Image: 256
-- Row 2:
- - Text Field: Text Value 2
- - Image: 255
-
-
-
-This field can be queried in GraphQL like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- repeater {
- textFieldInRepeater
- imageFieldInRepeater {
- databaseId
- id
- sourceUrl
- }
- }
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "repeater": [
- {
- "textFieldInRepeater": "Text Value 1",
- "imageFieldInRepeater": {
- "id": "YXR0YWNobWVudDoyNTY=",
- "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth.jpg"
- }
- },
- {
- "textFieldInRepeater": "Text Value 2",
- "imageFieldInRepeater": {
- "id": "YXR0YWNobWVudDoyNTU=",
- "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth-baseball-scaled.jpg"
- }
- }
- ]
- }
- }
- }
-}
-```
-
-### Flexible Content Field
-
-The Flexible Content is a powerful ACF field that allows for groups of fields to be organized into "Layouts".
-
-These Layouts can be made up of other types of fields, and can be added and arranged in any order.
-
-Flexible Content Fields are added to the WPGraphQL Schema as a List Of [Unions](https://graphql.org/learn/schema/#union-types).
-
-The Union for a Flex Field is made up of each Layout in the Flex Field as the possible Types.
-
-In our example, we've created a Flex Field with 3 layouts named "Layout One", "Layout Two" and "Layout Three". In the Schema, we can see the Flex Field Union's Possible Types are these 3 layouts.
-
-
-
-Each of these Layout types will contain the fields defined for the layout and can be queried like fields in any other Group.
-
-Here's an example of a Flex Field named `flexible_content`, with 3 layouts:
-
-- Layout One
- - Text field named "text"
- - Text field named "another_text_field"
-- Layout Two
- - Image field named "image"
-- Layout Three
- - Gallery field named "gallery"
-
-Above are the possible layouts and their fields. These layouts can be added and arranged in any order. While we, as a GraphQL consumer, don't know ahead of time what order they will be in, we _do_ know what the possibilities are.
-
-Here's an example of a Flex Field named `flexible_content` with the values saved as "Layout One", "Layout Two" and "Layout Three", in that order, all populated with their respective fields.
-
-
-
-We can query this field like so:
-
-```graphql
-{
- post(id: "acf-example-test", idType: URI) {
- acfDocs {
- flexibleContent {
- __typename
- ... on Post_Acfdocs_FlexibleContent_LayoutOne {
- text
- anotherTextField
- }
- ... on Post_Acfdocs_FlexibleContent_LayoutTwo {
- image {
- id
- sourceUrl(size: MEDIUM)
- }
- }
- ... on Post_Acfdocs_FlexibleContent_LayoutThree {
- gallery {
- id
- sourceUrl(size: MEDIUM)
- }
- }
- }
- }
- }
-}
-```
-
-and the results of the query would be:
-
-```json
-{
- "data": {
- "post": {
- "acfDocs": {
- "flexibleContent": [
- {
- "__typename": "Post_Acfdocs_FlexibleContent_LayoutOne",
- "text": "Text Value One",
- "anotherTextField": "Another Text Value"
- },
- {
- "__typename": "Post_Acfdocs_FlexibleContent_LayoutTwo",
- "image": {
- "id": "YXR0YWNobWVudDoyNTY=",
- "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth-300x169.jpg"
- }
- },
- {
- "__typename": "Post_Acfdocs_FlexibleContent_LayoutThree",
- "gallery": [
- {
- "id": "YXR0YWNobWVudDoyNTY=",
- "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth-300x169.jpg"
- },
- {
- "id": "YXR0YWNobWVudDoyNTU=",
- "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth-baseball-289x300.jpg"
- }
- ]
- }
- ]
- }
- }
- }
-}
-```
-
-If we were to re-arrange the layouts, so that the order was "Layout Three", "Layout One", "Layout Two", the results of the query would be:
-
-```json
-"data": {
- "post": {
- "acfDocs": {
- "flexibleContent": [
- {
- "__typename": "Post_Acfdocs_FlexibleContent_LayoutThree",
- "gallery": [
- {
- "id": "YXR0YWNobWVudDoyNTY=",
- "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth-300x169.jpg"
- },
- {
- "id": "YXR0YWNobWVudDoyNTU=",
- "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth-baseball-289x300.jpg"
- }
- ]
- }
- {
- "__typename": "Post_Acfdocs_FlexibleContent_LayoutOne",
- "text": "Text Value One",
- "anotherTextField": "Another Text Value"
- },
- {
- "__typename": "Post_Acfdocs_FlexibleContent_LayoutTwo",
- "image": {
- "id": "YXR0YWNobWVudDoyNTY=",
- "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth-300x169.jpg"
- }
- },
- ]
- }
- }
- }
-```
-
-### Clone Field
-
-The clone field is not fully supported (yet). We plan to support it in the future.
-
## Options Pages
**Reference**: https://www.advancedcustomfields.com/add-ons/options-page/
@@ -1738,11 +179,11 @@ Alternatively, it's you can check the Fields API Reference to learn about exposi
## Location Rules
-Advanced Custom Fields field groups are added to the WordPress dashboard by being assigned "Location Rules".
+Advanced Custom Fields field groups are added to the WordPress dashboard by being assigned "Location Rules".
-WPGraphQL for Advanced Custom Fields uses the Location Rules to determine where in the GraphQL Schema the field groups/fields should be added to the Schema.
+WPGraphQL for Advanced Custom Fields uses the Location Rules to determine where in the GraphQL Schema the field groups/fields should be added to the Schema.
-For example, if a Field Group were assigned to "Post Type is equal to Post", then the field group would show in the WPGraphQL Schema on the `Post` type, allowing you to query for ACF fields of the Post, anywhere you can interact with the `Post` type in the Schema.
+For example, if a Field Group were assigned to "Post Type is equal to Post", then the field group would show in the WPGraphQL Schema on the `Post` type, allowing you to query for ACF fields of the Post, anywhere you can interact with the `Post` type in the Schema.
### Supported Locations
@@ -1750,10 +191,10 @@ For example, if a Field Group were assigned to "Post Type is equal to Post", the
### Why aren't all location rules supported?
-You might notice that some location rules don't add fields to the Schema. This is because some location rules are based on context that doesn't exist when the GraphQL Schema is generated.
+You might notice that some location rules don't add fields to the Schema. This is because some location rules are based on context that doesn't exist when the GraphQL Schema is generated.
-For example, if you have a location rule to show a field group only on a specific page, how would that be exposed the the Schema? There's no Type in the Schema for just one specific page.
+For example, if you have a location rule to show a field group only on a specific page, how would that be exposed the the Schema? There's no Type in the Schema for just one specific page.
-If you're not seeing a field group in the Schema, look at the location rules, and think about _how_ the field group would be added to a Schema that isn't aware of context like which admin page you're on, what category a Post is assigned to, etc.
+If you're not seeing a field group in the Schema, look at the location rules, and think about _how_ the field group would be added to a Schema that isn't aware of context like which admin page you're on, what category a Post is assigned to, etc.
If you have ideas on how these specific contextual rules should be handled in WPGraphQL, submit an issue so we can consider how to best support it!
diff --git a/composer.json b/composer.json
index a5fcb29..04e77bd 100644
--- a/composer.json
+++ b/composer.json
@@ -19,6 +19,38 @@
"src/"
]
},
+ "repositories": [
+ {
+ "type": "package",
+ "package": {
+ "name": "wp-graphql/acf-pro",
+ "version": "5.8.7",
+ "type": "wordpress-plugin",
+ "source": {
+ "url": "git@github.com:wp-graphql/acf-pro.git",
+ "type": "git",
+ "reference": "master"
+ }
+ }
+ },
+ {
+ "type": "package",
+ "package": {
+ "name": "hoppinger/advanced-custom-fields-wpcli",
+ "version": "5.8.7",
+ "type": "wordpress-plugin",
+ "source": {
+ "url": "git@github.com:hoppinger/advanced-custom-fields-wpcli.git",
+ "type": "git",
+ "reference": "master"
+ }
+ }
+ },
+ {
+ "type":"composer",
+ "url":"https://wpackagist.org"
+ }
+ ],
"scripts": {
"install-test-env": "bash bin/install-test-env.sh",
"docker-build": "bash bin/run-docker.sh build",
@@ -45,7 +77,7 @@
"phpstan": ["phpstan analyze --ansi --memory-limit=1G"]
},
"require": {
- "php": "^7"
+ "php": "^7.1 || ^8.0"
},
"require-dev": {
"lucatume/wp-browser": "^2.4",
@@ -57,15 +89,27 @@
"codeception/module-cli": "^1.0",
"codeception/util-universalframework": "^1.0",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.1",
+ "composer/installers": "~1.0",
"wp-coding-standards/wpcs": "2.1.1",
"phpcompatibility/phpcompatibility-wp": "2.1.0",
- "squizlabs/php_codesniffer": "3.5.4",
+ "squizlabs/php_codesniffer": "^3.5.7",
"phpstan/phpstan": "^0.12.64",
"szepeviktor/phpstan-wordpress": "^0.7.1",
"codeception/module-rest": "^1.2",
- "wp-graphql/wp-graphql-testcase": "^1.0",
- "phpunit/phpunit": "9.4.1",
+ "wp-graphql/wp-graphql-testcase": "~2.1",
+ "phpunit/phpunit": "^8.5",
"simpod/php-coveralls-mirror": "^3.0",
- "phpstan/extension-installer": "^1.1"
+ "phpstan/extension-installer": "^1.1",
+ "wp-graphql/wp-graphql": "^v1.5",
+ "wp-graphql/acf-pro": "^5.8",
+ "hoppinger/advanced-custom-fields-wpcli": "^3.2"
+ },
+ "extra": {
+ "wordpress-install-dir": "local/public",
+ "installer-paths": {
+ "local/public/wp-content/plugins/{$name}/": ["type:wordpress-plugin"],
+ "local/public/wp-content/mu-plugins/{$name}/": ["type:wordpress-muplugin"],
+ "local/public/wp-content/themes/{$name}/": ["type:wordpress-theme"]
+ }
}
}
diff --git a/docs/fields/accordion.md b/docs/fields/accordion.md
new file mode 100644
index 0000000..d5aa667
--- /dev/null
+++ b/docs/fields/accordion.md
@@ -0,0 +1,10 @@
+# Accordion
+
+The Accordion Field in Advanced Custom Fields that lets users separate other fields in collapsible
+sections.
+
+This field is for administrative display purposes and is not exposed in WPGraphQL.
+
+----
+
+- **Next Field:** [Button Group](./button-group.md)
diff --git a/docs/fields/button-group.md b/docs/fields/button-group.md
new file mode 100644
index 0000000..b4a387d
--- /dev/null
+++ b/docs/fields/button-group.md
@@ -0,0 +1,40 @@
+# Button Group Field
+
+Button Group fields are added to the WPGraphQL Schema as a field with the Type `String`.
+
+Button Group fields can be queried and a String will be returned.
+
+Here, we have a Button Group field named `button_group` on the Post Edit screen within the "ACF Docs" Field Group, and "Choice 2" is selected.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ buttonGroup
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "buttonGroup": "choice_2"
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Accordion](./accordion.md)
+- **Next Field:** [Checkbox](./checkbox.md)
diff --git a/docs/fields/checkbox.md b/docs/fields/checkbox.md
new file mode 100644
index 0000000..c95c0c9
--- /dev/null
+++ b/docs/fields/checkbox.md
@@ -0,0 +1,43 @@
+# Checkbox Field
+
+Checkbox fields are added to the WPGraphQL Schema as a field with the Type `[ 'list_of' => 'String' ]`.
+
+Checkbox fields can be queried and a list (array) of Strings (the selected values) will be returned.
+
+Here, we have a Checkbox field named `checkbox` on the Post Edit screen within the "ACF Docs" Field Group, and "Choice 1" is selected.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ checkbox
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "checkbox": [
+ "choice_1"
+ ]
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Button Group](./button-group.md)
+- **Next Field:** [Clone](./clone.md)
+
diff --git a/docs/fields/clone.md b/docs/fields/clone.md
new file mode 100644
index 0000000..93ff021
--- /dev/null
+++ b/docs/fields/clone.md
@@ -0,0 +1,9 @@
+# Clone Field
+
+The clone field is not fully supported (yet). We plan to support it in the future.
+
+----
+
+- **Previous Field:** [Checkbox](./checkbox.md)
+- **Next Field:** [Color Picker](./color-picker.md)
+
diff --git a/docs/fields/color-picker.md b/docs/fields/color-picker.md
new file mode 100644
index 0000000..73fee41
--- /dev/null
+++ b/docs/fields/color-picker.md
@@ -0,0 +1,40 @@
+# Color Picker Field
+
+The Color Picker field is added to the WPGraphQL Schema as field with the Type `String`.
+
+Color Picker fields can be queried and a String will be returned.
+
+Here, we have a Color Picker field named `color_picker` on the Post Edit screen within the "ACF Docs" Field Group, and "#dd3333" is the value.
+
+
+
+This field can be queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ colorPicker
+ }
+ }
+}
+```
+
+and the result of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "colorPicker": "12:30 am"
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Clone](./clone.md)
+- **Next Field:** [Date Picker](./date-picker.md)
diff --git a/docs/fields/date-picker.md b/docs/fields/date-picker.md
new file mode 100644
index 0000000..4ac098c
--- /dev/null
+++ b/docs/fields/date-picker.md
@@ -0,0 +1,40 @@
+# Date Picker Field
+
+The Date Picker field is added to the WPGraphQL Schema as field with the Type `String`.
+
+Date Picker fields can be queried and a String will be returned.
+
+Here, we have a Date Picker field named `date_picker` on the Post Edit screen within the "ACF Docs" Field Group, and "13/03/2020" is the date set.
+
+
+
+This field can be queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ datePicker
+ }
+ }
+}
+```
+
+and the result of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "datePicker": "13/03/2020"
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Color Picker](./color-picker.md)
+- **Next Field:** [Date/Time Picker](./date-time-picker.md)
diff --git a/docs/fields/date-time-picker.md b/docs/fields/date-time-picker.md
new file mode 100644
index 0000000..5188ff4
--- /dev/null
+++ b/docs/fields/date-time-picker.md
@@ -0,0 +1,40 @@
+# Date/Time Picker Field
+
+The Date/Time Picker field is added to the WPGraphQL Schema as field with the Type `String`.
+
+Date/Time Picker fields can be queried, and a String will be returned.
+
+Here, we have a Date/Time Picker field named `date_time_picker` on the Post Edit screen within the "ACF Docs" Field Group, and "20/03/2020 8:15 am" is the value.
+
+
+
+This field can be queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ dateTimePicker
+ }
+ }
+}
+```
+
+and the result of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "dateTimePicker": "20/03/2020 8:15 am"
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Date Picker](./date-picker.md)
+- **Next Field:** [Email](./email.md)
diff --git a/docs/fields/email.md b/docs/fields/email.md
new file mode 100644
index 0000000..112b167
--- /dev/null
+++ b/docs/fields/email.md
@@ -0,0 +1,40 @@
+# Email Field
+
+Email fields are added to the WPGraphQL Schema as a field with the Type `String`.
+
+Email fields can be queried and a String will be returned.
+
+Here, we have an Email field named `email` on the Post Edit screen within the "ACF Docs" Field Group.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post( id: "acf-example-test" idType: URI ) {
+ acfDocs {
+ email
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "email": "test@example.com"
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Date/Time Picker](./date-time-picker.md)
+- **Next Field:** [File](./file.md)
diff --git a/docs/fields/file.md b/docs/fields/file.md
new file mode 100644
index 0000000..4010a14
--- /dev/null
+++ b/docs/fields/file.md
@@ -0,0 +1,48 @@
+# File Field
+
+File fields are added to the WPGraphQL Schema as a field with the Type `MediaItem`.
+
+File fields can be queried and a MediaItem will be returned.
+
+The `MediaItem` type is an Object type that has it's own fields that can be selected. So, instead of _just_ getting the File ID returned and having to ask for the MediaItem object in a follow-up request, we can ask for fields available on the MediaItem Type. For this example, we ask for the `id` and `mediaItemUrl`.
+
+Here, we have a File field named `file` on the Post Edit screen within the "ACF Docs" Field Group.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ file {
+ id
+ mediaItemUrl
+ }
+ }
+ }
+}
+```
+
+And the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "file": {
+ "id": "YXR0YWNobWVudDozMjQ=",
+ "mediaItemUrl": "http://acf2.local/wp-content/uploads/2020/03/little-ceasars-receipt-01282020.pdf"
+ }
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Email](./email.md)
+- **Next Field:** [Flexible Content](./flexible-content.md)
diff --git a/docs/fields/flexible-content.md b/docs/fields/flexible-content.md
new file mode 100644
index 0000000..8c90d07
--- /dev/null
+++ b/docs/fields/flexible-content.md
@@ -0,0 +1,144 @@
+# Flexible Content Field
+
+The Flexible Content is a powerful ACF field that allows for groups of fields to be organized into "Layouts".
+
+These Layouts can be made up of other types of fields, and can be added and arranged in any order.
+
+Flexible Content Fields are added to the WPGraphQL Schema as a List Of [Unions](https://graphql.org/learn/schema/#union-types).
+
+The Union for a Flex Field is made up of each Layout in the Flex Field as the possible Types.
+
+In our example, we've created a Flex Field with 3 layouts named "Layout One", "Layout Two" and "Layout Three". In the Schema, we can see the Flex Field Union's Possible Types are these 3 layouts.
+
+
+
+Each of these Layout types will contain the fields defined for the layout and can be queried like fields in any other Group.
+
+Here's an example of a Flex Field named `flexible_content`, with 3 layouts:
+
+- Layout One
+ - Text field named "text"
+ - Text field named "another_text_field"
+- Layout Two
+ - Image field named "image"
+- Layout Three
+ - Gallery field named "gallery"
+
+Above are the possible layouts and their fields. These layouts can be added and arranged in any order. While we, as a GraphQL consumer, don't know ahead of time what order they will be in, we _do_ know what the possibilities are.
+
+Here's an example of a Flex Field named `flexible_content` with the values saved as "Layout One", "Layout Two" and "Layout Three", in that order, all populated with their respective fields.
+
+
+
+We can query this field like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ flexibleContent {
+ __typename
+ ... on Post_Acfdocs_FlexibleContent_LayoutOne {
+ text
+ anotherTextField
+ }
+ ... on Post_Acfdocs_FlexibleContent_LayoutTwo {
+ image {
+ id
+ sourceUrl(size: MEDIUM)
+ }
+ }
+ ... on Post_Acfdocs_FlexibleContent_LayoutThree {
+ gallery {
+ id
+ sourceUrl(size: MEDIUM)
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "flexibleContent": [
+ {
+ "__typename": "Post_Acfdocs_FlexibleContent_LayoutOne",
+ "text": "Text Value One",
+ "anotherTextField": "Another Text Value"
+ },
+ {
+ "__typename": "Post_Acfdocs_FlexibleContent_LayoutTwo",
+ "image": {
+ "id": "YXR0YWNobWVudDoyNTY=",
+ "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth-300x169.jpg"
+ }
+ },
+ {
+ "__typename": "Post_Acfdocs_FlexibleContent_LayoutThree",
+ "gallery": [
+ {
+ "id": "YXR0YWNobWVudDoyNTY=",
+ "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth-300x169.jpg"
+ },
+ {
+ "id": "YXR0YWNobWVudDoyNTU=",
+ "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth-baseball-289x300.jpg"
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
+```
+
+If we were to re-arrange the layouts, so that the order was "Layout Three", "Layout One", "Layout Two", the results of the query would be:
+
+```json
+"data": {
+ "post": {
+ "acfDocs": {
+ "flexibleContent": [
+ {
+ "__typename": "Post_Acfdocs_FlexibleContent_LayoutThree",
+ "gallery": [
+ {
+ "id": "YXR0YWNobWVudDoyNTY=",
+ "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth-300x169.jpg"
+ },
+ {
+ "id": "YXR0YWNobWVudDoyNTU=",
+ "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth-baseball-289x300.jpg"
+ }
+ ]
+ }
+ {
+ "__typename": "Post_Acfdocs_FlexibleContent_LayoutOne",
+ "text": "Text Value One",
+ "anotherTextField": "Another Text Value"
+ },
+ {
+ "__typename": "Post_Acfdocs_FlexibleContent_LayoutTwo",
+ "image": {
+ "id": "YXR0YWNobWVudDoyNTY=",
+ "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth-300x169.jpg"
+ }
+ },
+ ]
+ }
+ }
+ }
+```
+
+----
+
+- **Previous Field:** [File](./file.md)
+- **Next Field:** [Gallery](./gallery.md)
diff --git a/docs/fields/gallery.md b/docs/fields/gallery.md
new file mode 100644
index 0000000..2eb3cd7
--- /dev/null
+++ b/docs/fields/gallery.md
@@ -0,0 +1,55 @@
+# Gallery Field
+
+Gallery fields are added to the WPGraphQL Schema as a field with the Type of `['list_of' => 'MediaItem']`.
+
+Gallery fields can be queried and a list of MediaItem types will be returned.
+
+Since the type is a list, we can expect an array to be returned. And since the Type within the list is `MediaItem`, we can ask for fields we want returned for each `MediaItem` in the list. In this case, let's say we want to ask for the `id` of each image and the `sourceUrl`, (size large).
+
+Here, we have a Gallery field named `gallery` on the Post Edit screen within the "ACF Docs" Field Group.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ gallery {
+ id
+ sourceUrl(size: LARGE)
+ }
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "gallery": [
+ {
+ "id": "YXR0YWNobWVudDoyNTY=",
+ "sourceUrl": "http://wpgraphql.local/wp-content/uploads/2020/02/babe-ruth.jpg"
+ },
+ {
+ "id": "YXR0YWNobWVudDoyNTU=",
+ "sourceUrl": "http://wpgraphql.local/wp-content/uploads/2020/02/babe-ruth-baseball-986x1024.jpg"
+ }
+ ]
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Flexible Content](./flexible-content.md)
+- **Next Field:** [Google Map](./google-map.md)
+
diff --git a/docs/fields/google-map.md b/docs/fields/google-map.md
new file mode 100644
index 0000000..f99b8fc
--- /dev/null
+++ b/docs/fields/google-map.md
@@ -0,0 +1,71 @@
+# Google Map Field
+
+Google Map fields are added to the WPGraphQL Schema as the `ACF_GoogleMap` Type.
+
+The `ACF_GoogleMap` Type has fields that expose location data. The available fields are:
+
+- **city** (String): The city associated with the location
+- **country** (String): The country associated with the location
+- **countryShort** (String): The country abbreviation associated with the location
+- **latitude** (String): The latitude associated with the location
+- **longitude** (String): The longitude associated with the location
+- **placeId** (String): Place IDs uniquely identify a place in the Google Places database and on Google Maps.
+- **postCode** (String): The post code associated with the location
+- **state** (String): The state associated with the location
+- **stateShort** (String): The state abbreviation associated with the location
+- **streetAddress** (String): The street address associated with the location
+- **streetName** (String): The street name associated with the location
+- **streetNumber** (String): The street number associated with the location
+- **zoom** (String): The zoom defined with the location
+
+Here, we have a Google Map field named `google_map` on the Post Edit screen within the "ACF Docs" Field Group, set with the Address "1 Infinite Loop, Cupertino, CA 95014, USA" as the value.
+
+
+
+This field can be queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ googleMap {
+ streetAddress
+ streetNumber
+ streetName
+ city
+ state
+ postCode
+ countryShort
+ }
+ }
+ }
+}
+```
+
+and the response would look like:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "googleMap": {
+ "streetAddress": "1 Infinite Loop, Cupertino, CA 95014, USA",
+ "streetNumber": "1",
+ "streetName": "Infinite Loop",
+ "city": "Cupertino",
+ "state": "California",
+ "postCode": "95014",
+ "placeId": "ChIJHTRqF7e1j4ARzZ_Fv8VA4Eo",
+ "countryShort": "US"
+ }
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Gallery](./gallery.md)
+- **Next Field:** [Group](./group.md)
diff --git a/docs/fields/group.md b/docs/fields/group.md
new file mode 100644
index 0000000..8e38227
--- /dev/null
+++ b/docs/fields/group.md
@@ -0,0 +1,44 @@
+# Group Field
+
+Group Fields are added to the WPGraphQL Schema as fields resolving to an Object Type named after the Group.
+
+Here, we have a Group field named `group` on the Post Edit screen within the "ACF Docs" Field Group. Within the "group" field, we have a Text Field named `text_field_in_group` and a Text Area field named `text_area_field_in_group`
+
+
+
+We can query the fields within the group like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ group {
+ textFieldInGroup
+ textAreaFieldInGroup
+ }
+ }
+ }
+}
+```
+
+And the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "group": {
+ "textFieldInGroup": "Text value, in group",
+ "textAreaFieldInGroup": "Text are value, in group"
+ }
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Google Map](./google-map.md)
+- **Next Field:** [image](./image.md)
diff --git a/docs/fields/image.md b/docs/fields/image.md
new file mode 100644
index 0000000..4f34999
--- /dev/null
+++ b/docs/fields/image.md
@@ -0,0 +1,48 @@
+# Image Field
+
+Image fields are added to the WPGraphQL Schema as a field with the Type `MediaItem`.
+
+Image fields can be queried and a MediaItem will be returned.
+
+The `MediaItem` type is an Object type that has it's own fields that can be selected. So, instead of _just_ getting the Image ID returned and having to ask for the MediaItem object in a follow-up request, we can ask for fields available on the MediaItem Type. For this example, we ask for the `id` and `sourceUrl`.
+
+Here, we have an Image field named `image` on the Post Edit screen within the "ACF Docs" Field Group.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post( id: "acf-example-test" idType: URI ) {
+ acfDocs {
+ image {
+ id
+ sourceUrl(size: MEDIUM)
+ }
+ }
+ }
+}
+```
+
+And the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "image": {
+ "id": "YXR0YWNobWVudDozMjM=",
+ "sourceUrl": "http://wpgraphql.local/wp-content/uploads/2020/03/babe-ruth-300x169.jpg"
+ }
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Group](./group.md)
+- **Next Field:** [Link](./link.md)
diff --git a/docs/fields/link.md b/docs/fields/link.md
new file mode 100644
index 0000000..fa6ab5e
--- /dev/null
+++ b/docs/fields/link.md
@@ -0,0 +1,55 @@
+# Link Field
+
+Link fields are added to the WPGraphQL Schema as a field with the Type `ACF_Link`.
+
+Link fields can be queried and a `ACF_Link` will be returned. The ACF Link is an object with fields that can be selected.
+
+The available fields on the `ACF_Link` Type are:
+
+- **target** (String): The target of the link
+- **title** (String): The target of the link
+- **url** (String): The url of the link
+
+Here, we have a Link field named `link` on the Post Edit screen within the "ACF Docs" Field Group.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ link {
+ target
+ title
+ url
+ }
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "link": {
+ "target": "",
+ "title": "Hello world!",
+ "url": "http://acf2.local/hello-world/"
+ }
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Image](./image.md)
+- **Next Field:** [Message](./message.md)
+
diff --git a/docs/fields/message.md b/docs/fields/message.md
new file mode 100644
index 0000000..bbefeab
--- /dev/null
+++ b/docs/fields/message.md
@@ -0,0 +1,8 @@
+# Message Field
+
+Message fields are not currently supported.
+
+----
+
+- **Previous Field:** [Link](./link.md)
+- **Next Field:** [Number](./number.md)
diff --git a/docs/fields/number.md b/docs/fields/number.md
new file mode 100644
index 0000000..71e4d99
--- /dev/null
+++ b/docs/fields/number.md
@@ -0,0 +1,40 @@
+# Number Field
+
+Number fields are added to the WPGraphQL Schema as a field with the Type `Float`.
+
+Number fields can be queried, and a Float will be returned.
+
+Here, we have a Number field named `number` on the Post Edit screen within the "ACF Docs" Field Group.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post( id: "acf-example-test" idType: URI ) {
+ acfDocs {
+ number
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "number": 5
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Message](./message.md)
+- **Next Field:** [Oembed](./oembed.md)
diff --git a/docs/fields/oembed.md b/docs/fields/oembed.md
new file mode 100644
index 0000000..07604c2
--- /dev/null
+++ b/docs/fields/oembed.md
@@ -0,0 +1,41 @@
+# oEmbed Field
+
+oEmbed fields are added to the WPGraphQL Schema as a field with the Type `String`.
+
+oEmbed fields can be queried, and a String will be returned.
+
+Here, we have a oEmbed field named `oembed` on the Post Edit screen within the "ACF Docs" Field Group.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ oembed
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "oembed": "https://www.youtube.com/watch?v=ZEytXfaWwcc"
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Number](./number.md)
+- **Next Field:** [Page Link](./page-link.md)
+
diff --git a/docs/fields/page-link.md b/docs/fields/page-link.md
new file mode 100644
index 0000000..49a3747
--- /dev/null
+++ b/docs/fields/page-link.md
@@ -0,0 +1,87 @@
+# Page Link Field
+
+Page Link fields are added to the WPGraphQL Schema as a field with a [Union](https://graphql.org/learn/schema/#union-types) of Possible Types the field is configured to allow.
+
+Since Page Link fields can be configured to be limited to certain Post Types, the Union will represent those Types.
+
+For example, if the Post Object field is configured to allow Posts of the `post` and `page` types to be selected:
+
+
+
+Then the Union type for the field will allow `Post` and `Page` types to be returned, as seen in the Schema via GraphiQL:
+
+
+
+Here, we have a Page Link field named `page_link` on the Post Edit screen within the "ACF Docs" Field Group, and the value is set to the "Sample Page" page.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ pageLink {
+ __typename
+ ... on Post {
+ id
+ title
+ date
+ }
+ ... on Page {
+ id
+ title
+ }
+ }
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "pageLink": {
+ "__typename": "Page",
+ "id": "cGFnZToy",
+ "title": "Sample Page"
+ }
+ }
+ }
+ }
+}
+```
+
+Here, we set the value to the "Hello World" Post:
+
+
+
+And the results of the same query are now:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "pageLink": {
+ "__typename": "Post",
+ "id": "cG9zdDox",
+ "title": "Hello world!",
+ "date": "2020-02-20T23:12:21"
+ }
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Oembed](./oembed.md)
+- **Next Field:** [Checkbox](./password.md)
+
diff --git a/docs/fields/password.md b/docs/fields/password.md
new file mode 100644
index 0000000..8b89f7b
--- /dev/null
+++ b/docs/fields/password.md
@@ -0,0 +1,40 @@
+# Password Field
+
+Password fields are added to the WPGraphQL Schema as a field with the Type `String`.
+
+Password fields can be queried, and a String will be returned.
+
+Here, we have a Password field named `password` on the Post Edit screen within the "ACF Docs" Field Group.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post( id: "acf-example-test" idType: URI ) {
+ acfDocs {
+ password
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "password": "123456"
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Page Link](./page-link.md)
+- **Next Field:** [Post Object](./post-object.md)
diff --git a/docs/fields/post-object.md b/docs/fields/post-object.md
new file mode 100644
index 0000000..deed218
--- /dev/null
+++ b/docs/fields/post-object.md
@@ -0,0 +1,125 @@
+# Post Object Field
+
+Post Object fields are added to the WPGraphQL Schema as a field with a [Union](https://graphql.org/learn/schema/#union-types) of Possible Types the field is configured to allow.
+
+If the field is configured to allow multiple selections, it will be added to the Schema as a List Of the Union Type.
+
+Since Post Object fields can be configured to be limited to certain Post Types, the Union will represent those Types.
+
+For example, if the Post Object field is configured to allow Posts of the `post` and `page` types to be selected:
+
+
+
+Then the Union type for the field will allow `Post` and `Page` types to be returned, as seen in the Schema via GraphiQL:
+
+
+
+Here, we have a Post Object field named `post_object` on the Post Edit screen within the "ACF Docs" Field Group, configured with the Post "Hello World!".
+
+
+
+As a GraphQL consumer, we don't know in advance if the value is going to be a Page or a Post.
+
+So we can specify, via GraphQL fragment, what fields we want if the object is a Post, or if it is a Page.
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ postObject {
+ __typename
+ ... on Post {
+ id
+ title
+ date
+ }
+ ... on Page {
+ id
+ title
+ }
+ }
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "postObject": {
+ "__typename": "Post",
+ "id": "cG9zdDox",
+ "title": "Hello world!",
+ "date": "2020-02-20T23:12:21"
+ }
+ }
+ }
+ }
+}
+```
+
+If the input of the field was saved as a Page, instead of a Post, like so:
+
+
+
+Then the same query above, would return the following results:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "postObject": {
+ "__typename": "Page",
+ "id": "cGFnZToy",
+ "title": "Sample Page"
+ }
+ }
+ }
+ }
+}
+```
+
+Now, if the field were configured to allow multiple values, the field would be added to the Schema as a `listOf`, returning an Array of the Union.
+
+If the field were set with a value of one Page, and one Post, like so:
+
+
+
+Then the results of the same query as above would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "postObject": [
+ {
+ "__typename": "Page",
+ "id": "cGFnZToy",
+ "title": "Sample Page"
+ },
+ {
+ "__typename": "Post",
+ "id": "cG9zdDox",
+ "title": "Hello world!",
+ "date": "2020-02-20T23:12:21"
+ }
+ ]
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Password](./password.md)
+- **Next Field:** [Radio](./radio.md)
+
diff --git a/docs/fields/radio.md b/docs/fields/radio.md
new file mode 100644
index 0000000..a11d9b5
--- /dev/null
+++ b/docs/fields/radio.md
@@ -0,0 +1,40 @@
+# Radio Button Field
+
+Radio Button fields are added to the WPGraphQL Schema as a field with the Type `String`.
+
+Radio Button fields can be queried and a String will be returned.
+
+Here, we have a Radio Button field named `radio_button` on the Post Edit screen within the "ACF Docs" Field Group, and "Choice 2" is selected.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ radioButton
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "radioButton": "choice_2"
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Post Object](./post-object.md)
+- **Next Field:** [Range](./range.md)
diff --git a/docs/fields/range.md b/docs/fields/range.md
new file mode 100644
index 0000000..2768acd
--- /dev/null
+++ b/docs/fields/range.md
@@ -0,0 +1,40 @@
+# Range Field
+
+Range fields are added to the WPGraphQL Schema as a field with the Type `Float`.
+
+Range fields can be queried, and a Float will be returned.
+
+Here, we have a Range field named `range` on the Post Edit screen within the "ACF Docs" Field Group.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post( id: "acf-example-test" idType: URI ) {
+ acfDocs {
+ range
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "range": 5
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Radio](./radio.md)
+- **Next Field:** [Relationship](./relationship.md)
diff --git a/docs/fields/relationship.md b/docs/fields/relationship.md
new file mode 100644
index 0000000..5c0fb30
--- /dev/null
+++ b/docs/fields/relationship.md
@@ -0,0 +1,72 @@
+# Relationship Field
+
+Relationship fields are added to the WPGraphQL Schema as a field with a [Union](https://graphql.org/learn/schema/#union-types) of Possible Types the field is configured to allow.
+
+Since Relationship fields can be configured to be limited to certain Post Types, the Union will represent those Types.
+
+For example, if the Post Object field is configured to allow Posts of the `post` and `page` types to be selected:
+
+
+
+Then the Union type for the field will allow `Post` and `Page` types to be returned, as seen in the Schema via GraphiQL:
+
+
+
+Here, we have a Relationship field named `relationship` on the Post Edit screen within the "ACF Docs" Field Group, and the value is set to "Hello World!" post, and the "Sample Page" page.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ relationship {
+ __typename
+ ... on Post {
+ id
+ title
+ date
+ }
+ ... on Page {
+ id
+ title
+ }
+ }
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "relationship": [
+ {
+ "__typename": "Post",
+ "id": "cG9zdDox",
+ "title": "Hello world!",
+ "date": "2020-02-20T23:12:21"
+ },
+ {
+ "__typename": "Page",
+ "id": "cGFnZToy",
+ "title": "Sample Page"
+ }
+ ]
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Range](./range.md)
+- **Next Field:** [Repeater](./repeater.md)
+
diff --git a/docs/fields/repeater.md b/docs/fields/repeater.md
new file mode 100644
index 0000000..f57d5bb
--- /dev/null
+++ b/docs/fields/repeater.md
@@ -0,0 +1,68 @@
+# Repeater Field
+
+Repeater Fields are added to the Schema as a List Of the Type of group that makes up the fields.
+
+For example, we've created a Repeater Field that has a Text Field named `text_field_in_repeater` and an Image Field named `image_field_in_repeater`.
+
+Here, the Repeater Field is populated with 2 rows:
+- Row 1:
+ - Text Field: Text Value 1
+ - Image: 256
+- Row 2:
+ - Text Field: Text Value 2
+ - Image: 255
+
+
+
+This field can be queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ repeater {
+ textFieldInRepeater
+ imageFieldInRepeater {
+ databaseId
+ id
+ sourceUrl
+ }
+ }
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "repeater": [
+ {
+ "textFieldInRepeater": "Text Value 1",
+ "imageFieldInRepeater": {
+ "id": "YXR0YWNobWVudDoyNTY=",
+ "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth.jpg"
+ }
+ },
+ {
+ "textFieldInRepeater": "Text Value 2",
+ "imageFieldInRepeater": {
+ "id": "YXR0YWNobWVudDoyNTU=",
+ "sourceUrl": "http://acf2.local/wp-content/uploads/2020/02/babe-ruth-baseball-scaled.jpg"
+ }
+ }
+ ]
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Relationship](./relationship.md)
+- **Next Field:** [Select](./select.md)
diff --git a/docs/fields/select.md b/docs/fields/select.md
new file mode 100644
index 0000000..cf3b566
--- /dev/null
+++ b/docs/fields/select.md
@@ -0,0 +1,40 @@
+# Select Field
+
+Select fields (when configured to _not_ allow mutliple selections) are added to the WPGraphQL Schema as a field with the Type `String`.
+
+Select fields, without multiple selections allowed, can be queried and a String will be returned.
+
+Here, we have a Select field named `select` on the Post Edit screen within the "ACF Docs" Field Group, and "Choice 1" is selected.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ select
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "select": "choice_1"
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Repeater](./repeater.md)
+- **Next Field:** [Tab](./tab.md)
diff --git a/docs/fields/tab.md b/docs/fields/tab.md
new file mode 100644
index 0000000..481486b
--- /dev/null
+++ b/docs/fields/tab.md
@@ -0,0 +1,8 @@
+# Tab Field
+
+Tab fields are not currently supported.
+
+----
+
+- **Previous Field:** [Select](./select.md)
+- **Next Field:** [Taxonomy](./taxonomy.md)
diff --git a/docs/fields/taxonomy.md b/docs/fields/taxonomy.md
new file mode 100644
index 0000000..69593c1
--- /dev/null
+++ b/docs/fields/taxonomy.md
@@ -0,0 +1,53 @@
+# Taxonomy Field
+
+The Taxonomy field is added to the GraphQL Schema as a List Of the Taxonomy Type.
+
+For example, if the field is configured to the "Category" taxonomy, then the field in the Schema will be a List of the Category type.
+
+
+
+Here, we have a Taxonomy field named `taxonomy` on the Post Edit screen within the "ACF Docs" Field Group, configured with the Category "Test Category".
+
+
+
+This field can be queried like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ taxonomy {
+ __typename
+ id
+ name
+ }
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "taxonomy": [
+ {
+ "__typename": "Category",
+ "id": "Y2F0ZWdvcnk6Mg==",
+ "name": "Test Category"
+ }
+ ]
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Tab](./tab.md)
+- **Next Field:** [Text](./text.md)
+
diff --git a/docs/fields/text-area.md b/docs/fields/text-area.md
new file mode 100644
index 0000000..c3b20a5
--- /dev/null
+++ b/docs/fields/text-area.md
@@ -0,0 +1,41 @@
+# Text Area Field
+
+Text Area fields are added to the WPGraphQL Schema as a field with the Type `String`.
+
+Text Area fields can be queried and a String will be returned.
+
+Here, we have a Text Area field named `text_area` on the Post Edit screen within the "ACF Docs" Field Group.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post( id: "acf-example-test" idType: URI ) {
+ acfDocs {
+ textArea
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "textArea": "Text value"
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Text](./text.md)
+- **Next Field:** [Time Picker](./time-picker.md)
+
diff --git a/docs/fields/text.md b/docs/fields/text.md
new file mode 100644
index 0000000..824cd08
--- /dev/null
+++ b/docs/fields/text.md
@@ -0,0 +1,40 @@
+# Text Field
+
+Text fields are added to the WPGraphQL Schema as a field with the Type `String`.
+
+Text fields can be queried and a String will be returned.
+
+Here, we have a Text field named `text` on the Post Edit screen within the "ACF Docs" Field Group.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post( id: "acf-example-test" idType: URI ) {
+ acfDocs {
+ text
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "text": "Text Value"
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Taxonomy](./taxonomy.md)
+- **Next Field:** [Text Area](./text-area.md)
diff --git a/docs/fields/time-picker.md b/docs/fields/time-picker.md
new file mode 100644
index 0000000..4f9ada3
--- /dev/null
+++ b/docs/fields/time-picker.md
@@ -0,0 +1,41 @@
+# Time Picker Field
+
+The Time Picker field is added to the WPGraphQL Schema as field with the Type `String`.
+
+Time Picker fields can be queried and a String will be returned.
+
+Here, we have a Time Picker field named `time_picker` on the Post Edit screen within the "ACF Docs" Field Group, and "12:30 am" is the value.
+
+
+
+This field can be queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ timePicker
+ }
+ }
+}
+```
+
+and the result of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "timePicker": "12:30 am"
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Text Area](text-area.md)
+- **Next Field:** [True/False](true-false.md)
+
diff --git a/docs/fields/true-false.md b/docs/fields/true-false.md
new file mode 100644
index 0000000..887f556
--- /dev/null
+++ b/docs/fields/true-false.md
@@ -0,0 +1,41 @@
+# True/False Field
+
+True/False fields are added to the WPGraphQL Schema as a field with the Type `Boolean`.
+
+True/False fields can be queried and a Boolean will be returned.
+
+Here, we have a True/False field named `true_false` on the Post Edit screen within the "ACF Docs" Field Group, and "true" is selected.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ trueFalse
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "trueFalse": true
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Time Picker](./time-picker.md)
+- **Next Field:** [url](./url.md)
+
diff --git a/docs/fields/url.md b/docs/fields/url.md
new file mode 100644
index 0000000..1290924
--- /dev/null
+++ b/docs/fields/url.md
@@ -0,0 +1,41 @@
+# URL Field
+
+Url fields are added to the WPGraphQL Schema as a field with the Type `String`.
+
+Url fields can be queried and a String will be returned.
+
+Here, we have a URL field named `url` on the Post Edit screen within the "ACF Docs" Field Group.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post( id: "acf-example-test" idType: URI ) {
+ acfDocs {
+ url
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "url": "https://wpgraphql.com"
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [True/False](./true-false.md)
+- **Next Field:** [User](./user.md)
+
diff --git a/docs/fields/user.md b/docs/fields/user.md
new file mode 100644
index 0000000..3fa00fe
--- /dev/null
+++ b/docs/fields/user.md
@@ -0,0 +1,81 @@
+# User Field
+
+User fields are added to the WPGraphQL Schema as a field with a User type.
+
+Here, we have a User field named `user` on the Post Edit screen within the "ACF Docs" Field Group, set with the User "jasonbahl" as the value.
+
+
+
+This field can be queried in GraphQL like so:
+
+```graphql
+{
+ post(id: "acf-example-test", idType: URI) {
+ acfDocs {
+ user {
+ id
+ username
+ firstName
+ lastName
+ }
+ }
+ }
+}
+```
+
+and the response would look like:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "user": {
+ "id": "dXNlcjox",
+ "username": "jasonbahl",
+ "firstName": "Jason",
+ "lastName": "Bahl"
+ }
+ }
+ }
+ }
+}
+```
+
+If the field is configured to allow multiple selections, it's added to the Schema as a List Of the User type.
+
+Here, we have a User field named `user` on the Post Edit screen within the "ACF Docs" Field Group, set with the User "jasonbahl" and "WPGraphQL" as the value.
+
+
+
+and the response to the same query would look like:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "user": [
+ {
+ "id": "dXNlcjox",
+ "username": "jasonbahl",
+ "firstName": "Jason",
+ "lastName": "Bahl"
+ },
+ {
+ "id": "dXNlcjoy",
+ "username": "WPGraphQL",
+ "firstName": "WP",
+ "lastName": "GraphQL"
+ }
+ ]
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [Url](./url.md)
+- **Next Field:** [WYSIWYG](./wysiwyg.md)
diff --git a/docs/fields/wysiwyg.md b/docs/fields/wysiwyg.md
new file mode 100644
index 0000000..d9742fb
--- /dev/null
+++ b/docs/fields/wysiwyg.md
@@ -0,0 +1,39 @@
+# WYSIWYG Editor Field
+
+WYSIWYG fields are added to the WPGraphQL Schema as a field with the Type `String`.
+
+WYSIWYG fields can be queried and a String will be returned.
+
+Here, we have a WYSIWYG field named `wysiwyg` on the Post Edit screen within the "ACF Docs" Field Group.
+
+
+
+This field can be Queried in GraphQL like so:
+
+```graphql
+{
+ post( id: "acf-example-test" idType: URI ) {
+ acfDocs {
+ wysiwyg
+ }
+ }
+}
+```
+
+and the results of the query would be:
+
+```json
+{
+ "data": {
+ "post": {
+ "acfDocs": {
+ "wysiwyg": "Some content in a WYSIWYG field
\n"
+ }
+ }
+ }
+}
+```
+
+----
+
+- **Previous Field:** [User](./user.md)
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
new file mode 100644
index 0000000..6030bb5
--- /dev/null
+++ b/phpstan.neon.dist
@@ -0,0 +1,22 @@
+parameters:
+ level: 8
+ inferPrivatePropertyTypeFromConstructor: true
+ checkMissingIterableValueType: false
+ stubFiles:
+ # Simulate added properties
+ - phpstan/class-wp-post-type.stub
+ - phpstan/class-wp-taxonomy.stub
+ scanDirectories:
+ - local/public/wp-content/plugins/advanced-custom-fields-pro
+ - local/public/wp-content/plugins/wp-graphql
+ bootstrapFiles:
+ - phpstan/constants.php
+ - wp-graphql-acf.php
+ paths:
+ - wp-graphql-acf.php
+ - src/
+ excludePaths:
+ - src/deprecated-class-config.php
+ ignoreErrors:
+ # Ignore any filters that are applied with more than 2 paramaters
+ - '#^Function apply_filters(_ref_array)? invoked with ([1-9]|1[0-2]) parameters, 2 required\.$#'
diff --git a/phpstan/class-wp-post-type.stub b/phpstan/class-wp-post-type.stub
new file mode 100644
index 0000000..33a7209
--- /dev/null
+++ b/phpstan/class-wp-post-type.stub
@@ -0,0 +1,9 @@
+setup_constants();
self::$instance->includes();
self::$instance->actions();
@@ -41,7 +41,7 @@ public static function instance() {
/**
* Fire off init action
*
- * @param ACF $instance The instance of the WPGraphQL\ACF class
+ * @param Acf $instance The instance of the WPGraphQL\Acf class
*/
do_action( 'graphql_acf_init', self::$instance );
@@ -119,6 +119,8 @@ private function includes() {
/**
* Sets up actions to run at certain spots throughout WordPress and the WPGraphQL execution
* cycle
+ *
+ * @return void
*/
private function actions() {
@@ -126,6 +128,8 @@ private function actions() {
/**
* Setup filters
+ *
+ * @return void
*/
private function filters() {
@@ -146,13 +150,15 @@ private function filters() {
/**
* Initialize
+ *
+ * @return void
*/
private function init() {
- $config = new Config();
- add_action( 'graphql_register_types', [ $config, 'init' ], 10, 1 );
+ $registry = new Registry();
+ add_action( 'graphql_register_types', [ $registry, 'init' ], 10, 1 );
- $acf_settings = new ACF_Settings();
+ $acf_settings = new AcfSettings();
$acf_settings->init();
}
diff --git a/src/class-acfsettings.php b/src/AcfSettings.php
similarity index 50%
rename from src/class-acfsettings.php
rename to src/AcfSettings.php
index ff8292e..92aa665 100644
--- a/src/class-acfsettings.php
+++ b/src/AcfSettings.php
@@ -7,12 +7,15 @@
namespace WPGraphQL\ACF;
+use Exception;
+use WPGraphQL\Utils\Utils;
+
/**
* Class ACF_Settings
*
* @package WPGraphQL\ACF
*/
-class ACF_Settings {
+class AcfSettings {
/**
* Initialize ACF Settings for the plugin
@@ -40,6 +43,272 @@ public function init() {
*/
add_action( 'wp_ajax_get_acf_field_group_graphql_types', [ $this, 'ajax_callback' ] );
+ add_filter( 'manage_acf-field-group_posts_columns', [ $this, 'admin_table_columns' ], 15, 1 );
+ add_action( 'manage_acf-field-group_posts_custom_column', [ $this, 'admin_table_columns_html' ], 15, 2 );
+
+ }
+
+ public function admin_table_columns_html( $column_name, $post_id ) {
+
+
+
+ $field_group = acf_get_field_group( $post_id );
+ $location_rules = new LocationRules( [ $field_group ] );
+ $location_rules->determine_location_rules();
+ $rules = $location_rules->get_rules();
+
+ $group_name = $field_group['graphql_field_name'] ?? $field_group['title'];
+ $group_name = $location_rules->format_field_name( $group_name );
+
+ $show_in_graphql = isset( $field_group['show_in_graphql'] ) && true === (bool) $field_group['show_in_graphql'];
+
+ switch( $column_name ) {
+ case 'graphql_types':
+ echo isset( $rules[ $group_name ] ) ? implode( ', ', $rules[ $group_name ] ) : '';
+ break;
+ case 'graphql_field_name':
+ $field_name = ! empty( $group_name ) ? $group_name : '';
+ echo $show_in_graphql ? $field_name : '';
+ break;
+ case 'graphql_type_name':
+ // @todo: add link to open fragment in GraphiQL
+ // I think a good way to do this would be to generate some sort of ID that is passed
+ // in the query params
+ // and when GraphiQL is loaded, the ID signals that the "default query" for
+ // GraphiQL should be the fragment for this, that way
+ // we don't have to do introspection in the WP List Table for all field groups
+ // and generate the fragment in the WP-Admin, we can generate it from
+ // GraphiQL when asked
+ echo $show_in_graphql ? Utils::format_type_name( $group_name ) : __( 'This Field Group is set to NOT show in the GraphQL Schema', 'wp-graphql-acf' );
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ /**
+ * Returns the query used to generate the Fragment for the Field Group
+ *
+ * @return string
+ */
+ public function get_graphql_fragment_query() {
+ return '
+ query getType($name: String!) {
+ __type(name: $name) {
+ ...TypeRef
+ fields {
+ ...FieldRef
+ type {
+ ...TypeRef
+ fields {
+ ...FieldRef
+ type {
+ ...TypeRef
+ fields {
+ ...FieldRef
+ type {
+ ...TypeRef
+ fields {
+ ...FieldRef
+ type {
+ ...TypeRef
+ fields {
+ ...FieldRef
+ type {
+ ...TypeRef
+ fields {
+ ...FieldRef
+ type {
+ ...TypeRef
+ fields {
+ ...FieldRef
+ type {
+ ...TypeRef
+ fields {
+ ...FieldRef
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fragment FieldRef on __Field {
+ __typename
+ name
+ }
+
+ fragment TypeRef on __Type {
+ kind
+ name
+ ofType {
+ kind
+ name
+ ofType {
+ kind
+ name
+ ofType {
+ kind
+ name
+ ofType {
+ kind
+ name
+ ofType {
+ kind
+ name
+ ofType {
+ kind
+ name
+ ofType {
+ kind
+ name
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ';
+ }
+
+ /**
+ * Given an array of fields from introspection, this maps over and returns the field name or
+ * recursively maps again until leaf fields are determined
+ *
+ * @param array $fields Fields from introspection
+ *
+ * @return string[]
+ */
+ public function map_fields_to_query( array $fields ) {
+
+ // Map over the fields and return the field name, or continue mapping the nested fields
+ return array_map( function( $field ) {
+
+ $excluded_names = [ 'pageInfo', 'edges' ];
+
+ if ( in_array( $field['name'], $excluded_names, true ) ) {
+ return null;
+ }
+
+ if ( isset( $field['type']['fields'] ) && ! empty( $field['type']['fields'] ) ) {
+
+ $mapped = $this->map_fields_to_query( $field['type']['fields'] );
+ $mapped = array_filter( $mapped );
+
+ if ( empty( $mapped ) || ! is_array( $mapped ) ) {
+ $mapped = '__typename';
+ }
+
+ if ( is_array( $mapped ) && ! empty( $mapped ) ) {
+ $mapped = implode( ' ', $mapped );
+ } else {
+ return null;
+ }
+ return $field['name'] . ' { ' . $mapped . ' } ';
+
+ }
+
+ if (
+ ( isset( $field['type']['kind'] ) && 'SCALAR' === $field['type']['kind'] ) ||
+ ( isset( $field['type']['ofType']['kind'] ) && 'SCALAR' === $field['type']['ofType']['kind'] )
+ ) {
+ return $field['name'] . ' ';
+ }
+
+ }, $fields );
+
+ }
+
+ /**
+ * Given a GraphQL Type, this builds a Fragment for the Type
+ *
+ * @param string $type
+ *
+ * @return string
+ */
+ public function build_fragment_from_introspection( array $type ) {
+
+ $type_name = $type['name'];
+ $mapped = implode( ' ', $this->map_fields_to_query( $type['fields'] ) );
+
+ return "fragment {$type_name}_Fields on {$type_name} {
+ __typename
+ {$mapped}
+ }";
+
+ }
+
+ /**
+ * Given a GraphQL TypeName, the Type is returned from Introspection
+ *
+ * @param string $type_name The name of the Type in the Schema to introspect
+ *
+ * @return mixed|array|null
+ * @throws Exception
+ */
+ public function get_graphql_type_from_introspection( string $type_name ) {
+
+ $get_type = graphql([
+ 'query' => $this->get_graphql_fragment_query(),
+ 'variables' => [
+ 'name' => $type_name
+ ]
+ ]);
+
+ return $get_type['data']['__type'] ?? null;
+
+ }
+
+ public function get_fragment_from_type_name( $type_name ) {
+
+ $type = $this->get_graphql_type_from_introspection( $type_name );
+
+ if ( empty( $type ) ) {
+ return '';
+ }
+
+ // Build the fragment
+ return $this->build_fragment_from_introspection( $type );
+
+ }
+
+ /**
+ * Given a GraphQL Type Name, this creates a Fragment for it with several levels of nested fields
+ *
+ * @param string $type_name The name of the Type to generate a Fragment link for
+ *
+ * @return string
+ * @throws Exception
+ */
+ public function get_graphiql_link( string $type_name ) {
+
+ $fragment = $this->get_fragment_from_type_name( $type_name );
+
+ // Return the URL
+ return '/wp-admin/admin.php?page=graphiql-ide&explorerIsOpen=true&query=' . urlencode( wp_strip_all_tags( $fragment, null ) );
+
+ }
+
+ public function admin_table_columns( $columns ) {
+ $columns['graphql_types'] = __( 'GraphQL Schema Location', 'wp-graphql-acf' );
+ $columns['graphql_field_name'] = __( 'GraphQL Field Name', 'wp-graphql-acf' );
+ $columns['graphql_type_name'] = __( 'GraphQL Type Name', 'wp-graphql-acf' );
+ return $columns;
+
}
/**
@@ -59,11 +328,11 @@ public function ajax_callback() {
wp_send_json( __( 'No form data.', 'wp-graphql-acf' ) );
}
- $field_group = isset( $form_data['acf_field_group'] ) ? $form_data['acf_field_group'] : [];
+ $field_group = $form_data['acf_field_group'] ?? [];
$rules = new LocationRules( [ $field_group ] );
$rules->determine_location_rules();
- $group_name = isset( $field_group['graphql_field_name'] ) ? $field_group['graphql_field_name'] : $field_group['title'];
+ $group_name = $field_group['graphql_field_name'] ?? $field_group['title'];
$group_name = $rules->format_field_name( $group_name );
$all_rules = $rules->get_rules();
@@ -98,9 +367,7 @@ public function display_metabox( $field_group_post_object ) {
global $field_group;
- /**
- * Render a field in the Field Group settings to allow for a Field Group to be shown in GraphQL.
- */
+ // Render a field in the Field Group settings to allow for a Field Group to be shown in GraphQL.
acf_render_field_wrap(
[
'label' => __( 'Show in GraphQL', 'acf' ),
@@ -219,7 +486,7 @@ public function enqueue_graphql_acf_scripts( string $screen ) {
if ( $screen == 'post-new.php' || $screen == 'post.php' ) {
if ( 'acf-field-group' === $post->post_type ) {
- wp_enqueue_script( 'graphql-acf', plugins_url( 'src/js/main.js', dirname( __FILE__ ) ), array(
+ wp_enqueue_script( 'graphql-acf', plugins_url( 'src/admin/js/main.js', dirname( __FILE__ ) ), array(
'jquery',
'acf-input',
'acf-field-group'
diff --git a/src/Fields/AcfField.php b/src/Fields/AcfField.php
new file mode 100644
index 0000000..0d9cff3
--- /dev/null
+++ b/src/Fields/AcfField.php
@@ -0,0 +1,366 @@
+registry = $registry;
+ $this->field_group = $field_group;
+ $this->field_config = $field;
+ $this->should_format = false;
+ $this->field_name = isset( $this->field_config['graphql_field_name'] ) ? Utils::format_field_name( $this->field_config['graphql_field_name'] ) : Utils::format_field_name( $this->field_config['name'] );
+ $this->field_type = $this->field_config['type'];
+ return $this;
+ }
+
+ /**
+ * Get the field name for the GraphQL Field mapped to the schema
+ *
+ * @return string
+ */
+ public function get_field_name() {
+ return $this->field_name;
+ }
+
+ /**
+ * Given a node and an ACF Field Config, this determines the ID to use to resolve the field
+ *
+ * @param mixed $node The node the field belongs to
+ * @param array $acf_field The ACF Field config
+ *
+ * @return int|mixed|string
+ */
+ public function get_acf_node_id( $node, array $acf_field ) {
+
+ if ( is_array( $node ) && isset( $node['node'] ) && isset( $node['node']->ID ) ) {
+ return absint( $node['node']->ID );
+ }
+
+ switch ( true ) {
+ case $node instanceof Term:
+ $id = 'term_' . $node->term_id;
+ break;
+ case $node instanceof Post:
+ $id = absint( $node->databaseId );
+ break;
+ case $node instanceof MenuItem:
+ $id = absint( $node->menuItemId );
+ break;
+ case $node instanceof Menu:
+ $id = 'term_' . $node->menuId;
+ break;
+ case $node instanceof User:
+ $id = 'user_' . absint( $node->userId );
+ break;
+ case $node instanceof Comment:
+ $id = 'comment_' . absint( $node->databaseId );
+ break;
+ case is_array( $node ) && isset ( $node['post_id'] ) && 'options' === $node['post_id']:
+ $id = $node['post_id'];
+ break;
+ default:
+ $id = 0;
+ break;
+ }
+
+ return $id;
+
+ }
+
+ /**
+ * Returns the GraphQL Type of the parent field group
+ *
+ * @return string
+ */
+ public function get_parent_type() {
+ return $this->registry->get_field_group_type_name( $this->field_group );
+ }
+
+ /**
+ * Returns the name of the Parent Type's fields Interface
+ *
+ * @return mixed|string|null
+ */
+ public function get_parent_type_fields_interface() {
+ return ! empty( $this->get_parent_type() ) ? 'With_' . $this->get_parent_type() . '_Fields' : null;
+ }
+
+ /**
+ * Returns the config array for the ACF Field
+ *
+ * @return array
+ */
+ public function get_field_config() {
+ return $this->field_config;
+ }
+
+ /**
+ * Determine if the field should ask ACF to format the response when retrieving
+ * the field using get_field()
+ *
+ * @return bool
+ */
+ public function should_format_field_value() {
+
+ if ( 'wysiwyg' === $this->field_type || 'select' === $this->field_type ) {
+ $this->should_format = true;
+ }
+
+ return $this->should_format;
+ }
+
+ /**
+ * Get the GraphQL Type to return for the field
+ *
+ * @return string|string[]
+ */
+ public function get_graphql_type() {
+
+ switch ( $this->field_config['type'] ) {
+ case 'number':
+ case 'range':
+ $type = 'float';
+ break;
+ case 'true_false':
+ $type = 'boolean';
+ break;
+ case 'link':
+ $type = 'AcfLink';
+ break;
+ case 'checkbox':
+ $type = [ 'list_of' => 'String' ];
+ break;
+ case 'gallery':
+ case 'date_picker':
+ case 'time_picker':
+ case 'date_time_picker':
+ case 'button_group':
+ case 'color_picker':
+ case 'email':
+ case 'text':
+ case 'message':
+ case 'oembed':
+ case 'password':
+ case 'wysiwyg':
+ case 'url':
+ case 'textarea':
+ case 'radio':
+ default:
+ $type = 'String';
+ break;
+ }
+
+ return $type;
+ }
+
+ /**
+ * Extending classes must implement this function
+ *
+ * @param mixed $node The node the field being resolved is connected with
+ * @param array $args The arguments passed to the field in the GraphQL query
+ * @param AppContext $context The AppContext passed down to all resolvers
+ * @param ResolveInfo $info The ResolveInfo passed down to all resolvers
+ *
+ * @return mixed
+ */
+ public function resolve( $node, array $args, AppContext $context, ResolveInfo $info ) {
+
+ // If the node is an array, and the type is options page, return the value early
+ // 🤔 This seems fragile 🤔
+ if ( is_array( $node ) && ! ( ! empty( $node['type'] ) && 'options_page' === $node['type'] ) ) {
+
+ if ( isset( $node[ $this->field_config['key'] ] ) ) {
+ $value = $node[ $this->field_config['key'] ];
+
+ if ( 'wysiwyg' === $this->field_config['type'] ) {
+ return apply_filters( 'the_content', $value );
+ }
+
+ }
+ }
+
+ $node_id = $this->get_acf_node_id( $node, $this->field_config );
+ $value = null;
+
+ if ( is_array( $node ) && isset( $node[ $this->field_config['key'] ] ) ) {
+ return $this->prepare_acf_field_value( $node[ $this->field_config['key'] ], $node, $node_id );
+ }
+
+ if ( empty( $node_id ) ) {
+ return null;
+ }
+
+ /**
+ * Filter the field value before resolving.
+ *
+ * @param mixed $value The value of the ACF Field stored on the node
+ * @param mixed $node The object the field is connected to
+ * @param mixed|string|int $node_id The ACF ID of the node to resolve the field with
+ * @param array $acf_field The ACF Field config
+ * @param bool $format Whether to apply formatting to the field
+ */
+ $value = apply_filters( 'graphql_acf_pre_resolve_acf_field', $value, $node, $node_id, $this->get_field_config(), $this->should_format_field_value() );
+
+ if ( empty( $value ) ) {
+
+ /**
+ * Check if cloned field and retrieve the key accordingly.
+ */
+ if ( ! empty( $this->field_config['_clone'] ) ) {
+ $key = $this->field_config['__key'];
+ } else {
+ $key = $this->field_config['key'];
+ }
+
+ $value = get_field( $key, $node_id, $this->should_format_field_value() );
+
+ }
+
+ $value = $this->prepare_acf_field_value( $value, $node, $node_id );
+
+ /**
+ * Filters the returned ACF field value
+ *
+ * @param mixed $value The resolved ACF field value
+ * @param array $acf_field The ACF field config
+ * @param mixed $node The node being resolved. The ID is typically a property of this object.
+ * @param int $node_id The ID of the node
+ */
+ return apply_filters( 'graphql_acf_field_value', $value, $this->field_config, $node, $node_id );
+
+ }
+
+ /**
+ * Prepares the ACF Field Value to be returned.
+ *
+ * @param mixed $value The value of the ACF field to return
+ * @param mixed $node The node the field belongs to
+ * @param mixed|string|int $node_id The ID of the node the field belongs to
+ *
+ * @return mixed
+ */
+ public function prepare_acf_field_value( $value, $node, $node_id ) {
+
+ if ( isset( $this->field_config['new_lines'] ) ) {
+ if ( 'wpautop' === $this->field_config['new_lines'] ) {
+ $value = wpautop( $value );
+ }
+ if ( 'br' === $this->field_config['new_lines'] ) {
+ $value = nl2br( $value );
+ }
+ }
+
+ // @todo: This was ported over, but I'm not 💯 sure what this is solving and
+ // why it's only applied on options pages and not other pages 🤔
+ if ( is_array( $node ) && ! ( ! empty( $node['type'] ) && 'options_page' === $node['type'] ) ) {
+
+ if ( isset( $root[ $this->field_config['key'] ] ) ) {
+ $value = $root[ $this->field_config['key'] ];
+ if ( 'wysiwyg' === $this->field_config['type'] ) {
+ $value = apply_filters( 'the_content', $value );
+ }
+
+ }
+ }
+
+ if ( in_array( $this->field_type, [
+ 'date_picker',
+ 'time_picker',
+ 'date_time_picker'
+ ], true ) ) {
+
+ if ( ! empty( $value ) && isset( $this->field_config['return_format'] ) && ! empty( $this->field_config['return_format'] ) ) {
+ $value = date( $this->field_config['return_format'], strtotime( $value ) );
+ }
+ }
+
+ if ( in_array( $this->field_type, [ 'number', 'range' ], true ) ) {
+ return (float) $value ?: null;
+ }
+
+ return $value;
+ }
+
+ /**
+ * Registers a field to the WPGraphQL Schema
+ *
+ * @return array
+ */
+ public function get_graphql_field_config() {
+
+ if ( ! empty( $this->get_graphql_type() ) ) {
+
+ return [
+ 'type' => $this->get_graphql_type(),
+ 'resolve' => function( $source, $args, $context, $info ) {
+ return $this->resolve( $source, $args, $context, $info );
+ }
+ ];
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/Fields/File.php b/src/Fields/File.php
new file mode 100644
index 0000000..b4bd100
--- /dev/null
+++ b/src/Fields/File.php
@@ -0,0 +1,60 @@
+get_parent_type_fields_interface();
+
+ $type_registry = $this->registry->get_type_registry();
+
+ $connection_name = ucfirst( $type_name ) . 'ToSingleMediaItemConnection';
+
+ // If the connection already exists, don't register it again
+ if ( $type_registry->get_type( $connection_name ) ) {
+ return $connection_name;
+ }
+
+ $type_registry->register_connection([
+ 'fromType' => $type_name,
+ 'toType' => 'MediaItem',
+ 'fromFieldName' => $this->field_name,
+ 'connectionTypeName' => $connection_name,
+ 'oneToOne' => true,
+ 'resolve' => function( $root, $args, AppContext $context, $info ) {
+
+ $value = $this->resolve( $root, $args, $context, $info );
+
+ if ( empty( $value ) || ! absint( $value ) ) {
+ return null;
+ }
+
+ $resolver = new PostObjectConnectionResolver( $root, $args, $context, $info, 'attachment' );
+ return $resolver
+ ->one_to_one()
+ ->set_query_arg( 'p', absint( $value ) )
+ ->get_connection();
+ }
+ ]);
+
+ return null;
+
+ }
+
+}
diff --git a/src/Fields/FlexibleContent.php b/src/Fields/FlexibleContent.php
new file mode 100644
index 0000000..d21c48f
--- /dev/null
+++ b/src/Fields/FlexibleContent.php
@@ -0,0 +1,83 @@
+field_config['layouts'] ) && is_array( $this->field_config['layouts'] ) ) {
+ $layouts = array_map( function( $layout ) {
+ $layout['parent'] = $this->field_config['key'];
+ $graphql_field_name = $layout['graphql_field_name'] ?? $layout['name'];
+ $graphql_field_name = $this->get_parent_type() . '_' . Utils::format_type_name( $this->field_name ) . '_' . Utils::format_type_name( $graphql_field_name );
+ $layout['graphql_field_name'] = $graphql_field_name;
+ $layout['graphql_types'] = [ $this->get_parent_type() ];
+ $layout['isFlexLayout'] = true;
+ return $layout;
+ }, $this->field_config['layouts'] );
+ }
+
+ if ( empty( $layouts ) ) {
+ return null;
+ }
+
+ $parent_type = $this->get_parent_type();
+ $type_name = $parent_type . '_' . Utils::format_type_name( $this->field_config['name'] );
+ $layout_interface_name = $type_name . '_Layout';
+
+ if ( ! $this->registry->get_registered_field_group_interface( $this->field_config['key'] ) ) {
+
+ $this->registry->get_type_registry()->register_interface_type( $layout_interface_name, [
+ 'description' => sprintf( __( 'Layouts of the %s Flexible Field Type', 'wp-graphql-acf' ), $layout_interface_name ),
+ 'fields' => [
+ 'layoutName' => [
+ 'type' => 'String',
+ 'description' => __( 'The name of the flexible field layout', 'wp-graphql-acf' ),
+ ],
+ ],
+ 'resolveType' => function( $object ) use ( $layouts, $type_name ) {
+ return $type_name . '_' . Utils::format_type_name( $object['acf_fc_layout'] );
+ }
+ ] );
+
+ $this->registry->add_registered_field_group_interface( $this->field_config['key'], $layout_interface_name );
+
+ }
+
+ $registered = [];
+ foreach ( $layouts as $layout ) {
+ $registered[] = $this->registry->add_acf_field_group_to_graphql( $layout, [], [ $layout_interface_name ] );
+ }
+
+ if ( ! empty( $registered ) ) {
+ register_graphql_interfaces_to_types( $layout_interface_name, $registered );
+ }
+
+ return [ 'list_of' => $layout_interface_name ];
+
+ }
+
+ public function resolve( $node, array $args, AppContext $context, ResolveInfo $info ) {
+ $value = parent::resolve( $node, $args, $context, $info );
+ return ! empty( $value ) && is_array( $value ) ? $value : [];
+ }
+
+}
diff --git a/src/Fields/Gallery.php b/src/Fields/Gallery.php
new file mode 100644
index 0000000..b27e82d
--- /dev/null
+++ b/src/Fields/Gallery.php
@@ -0,0 +1,50 @@
+get_parent_type_fields_interface();
+
+ $type_registry = $this->registry->get_type_registry();
+
+ $connection_name = $this->registry->get_connection_name( $type_name, 'MediaItem', $this->field_name );
+
+ // If the connection already exists, don't register it again
+ if ( null !== $type_registry->get_type( $connection_name ) ) {
+ return $type_registry->get_type( $connection_name );
+ }
+
+ $type_registry->register_connection([
+ 'fromType' => $type_name,
+ 'toType' => 'MediaItem',
+ 'fromFieldName' => $this->field_name,
+ 'oneToOne' => false,
+ 'resolve' => function( $root, $args, AppContext $context, $info ) {
+ $value = $this->resolve( $root, $args, $context, $info );
+
+ if ( empty( $value ) || ! is_array( $value ) ) {
+ return null;
+ }
+
+ $value = array_map(function( $id ) {
+ return absint( $id );
+ }, $value );
+
+ $resolver = new PostObjectConnectionResolver( $root, $args, $context, $info, 'attachment' );
+ return $resolver
+ ->set_query_arg( 'post__in', $value )
+ ->set_query_arg( 'orderby', 'post__in' )
+ ->get_connection();
+ }
+ ]);
+
+
+ return null;
+ }
+
+}
diff --git a/src/Fields/Group.php b/src/Fields/Group.php
new file mode 100644
index 0000000..2a9afc5
--- /dev/null
+++ b/src/Fields/Group.php
@@ -0,0 +1,30 @@
+get_parent_type();
+ $title = $this->field_config['title'] ?? ( isset( $this->field_config['label'] ) ? $this->field_config['label'] : 'no label or title' );
+ $this->field_config['graphql_field_name'] = $parent_type . '_' . Utils::format_type_name( $title );
+
+ $type_name = $this->registry->add_acf_field_group_to_graphql( $this->field_config );
+ return ! empty( $type_name ) ? $type_name : null;
+ }
+
+}
diff --git a/src/Fields/Image.php b/src/Fields/Image.php
new file mode 100644
index 0000000..e2c3b5d
--- /dev/null
+++ b/src/Fields/Image.php
@@ -0,0 +1,4 @@
+get_parent_type_fields_interface();
+
+ $type_registry = $this->registry->get_type_registry();
+
+ $connection_name = $this->registry->get_connection_name( $type_name, 'ContentNode', $this->field_name );
+
+ $connection_config = [
+ 'fromType' => $type_name,
+ 'toType' => 'ContentNode',
+ 'fromFieldName' => $this->field_name,
+ 'resolve' => function( $root, $args, AppContext $context, $info ) {
+ $value = $this->resolve( $root, $args, $context, $info );
+
+ if ( empty( $value ) || ! is_array( $value ) ) {
+ return null;
+ }
+
+ $value = array_map(function( $id ) {
+ return absint( $id );
+ }, $value );
+
+ $resolver = new PostObjectConnectionResolver( $root, $args, $context, $info, 'any' );
+ return $resolver
+ ->set_query_arg( 'post__in', $value )
+ ->set_query_arg( 'orderby', 'post__in' )
+ ->get_connection();
+ }
+ ];
+
+ if ( ! isset( $this->field_config['multiple'] ) || true !== (bool) $this->field_config['multiple'] ) {
+ $connection_name = ucfirst( $type_name ) . 'ToSingleContentNodeConnection';
+ $connection_config['connectionTypeName'] = $connection_name;
+ $connection_config['oneToOne'] = true;
+ $connection_config['resolve'] = function( $root, $args, AppContext $context, $info ) {
+ $value = $this->resolve( $root, $args, $context, $info );
+
+ if ( empty( $value ) || ! absint( $value ) ) {
+ return null;
+ }
+
+ $resolver = new PostObjectConnectionResolver( $root, $args, $context, $info, 'any' );
+ return $resolver
+ ->one_to_one()
+ ->set_query_arg( 'p', absint( $value ) )
+ ->get_connection();
+ };
+ }
+
+ // If the connection already exists, don't register it again
+ if ( null !== $type_registry->get_type( $connection_name ) ) {
+ return $type_registry->get_type( $connection_name );
+ }
+
+ $type_registry->register_connection( $connection_config );
+ return null;
+ }
+
+}
diff --git a/src/Fields/Relationship.php b/src/Fields/Relationship.php
new file mode 100644
index 0000000..31004f0
--- /dev/null
+++ b/src/Fields/Relationship.php
@@ -0,0 +1,49 @@
+get_parent_type_fields_interface();
+
+ $type_registry = $this->registry->get_type_registry();
+
+ $connection_config = [
+ 'fromType' => $type_name,
+ 'toType' => 'ContentNode',
+ 'fromFieldName' => $this->field_name,
+ 'resolve' => function( $root, $args, AppContext $context, $info ) {
+ $value = $this->resolve( $root, $args, $context, $info );
+
+ if ( empty( $value ) || ! is_array( $value ) ) {
+ return null;
+ }
+
+ $value = array_map(function( $id ) {
+ return absint( $id );
+ }, $value );
+
+ $resolver = new PostObjectConnectionResolver( $root, $args, $context, $info, 'any' );
+ return $resolver
+ ->set_query_arg( 'post__in', $value )
+ ->set_query_arg( 'orderby', 'post__in' )
+ ->get_connection();
+ }
+ ];
+
+ $connection_name = $this->registry->get_connection_name( $type_name, 'ContentNode', $this->field_name );
+
+ // If the connection already exists, don't register it again
+ if ( null !== $type_registry->get_type( $connection_name ) ) {
+ return null;
+ }
+ $type_registry->register_connection( $connection_config );
+ return null;
+
+ }
+
+}
diff --git a/src/Fields/Repeater.php b/src/Fields/Repeater.php
new file mode 100644
index 0000000..2f0376a
--- /dev/null
+++ b/src/Fields/Repeater.php
@@ -0,0 +1,44 @@
+get_parent_type();
+ $title = $this->field_config['title'] ?? ( $this->field_config['label'] ?? 'no label or title' );
+ $this->field_config['graphql_field_name'] = $parent_type . Utils::format_type_name( $title );
+ $type_name = $this->registry->add_acf_field_group_to_graphql( $this->field_config, [ $parent_type ] );
+ return [ 'non_null' => [ 'list_of' => $type_name ] ];
+ }
+
+ /**
+ * @param mixed $node The parent node the repeater field belongs to
+ * @param array $args The args passed to the field
+ * @param AppContext $context The AppContext passed down the resolve tree
+ * @param ResolveInfo $info The ResolveInfo for the field
+ *
+ * @return array
+ */
+ public function resolve( $node, array $args, AppContext $context, ResolveInfo $info ) {
+ $value = parent::resolve( $node, $args, $context, $info );
+
+ return ! empty( $value ) && is_array( $value ) ? $value : [];
+ }
+
+}
diff --git a/src/Fields/Select.php b/src/Fields/Select.php
new file mode 100644
index 0000000..2877ed7
--- /dev/null
+++ b/src/Fields/Select.php
@@ -0,0 +1,48 @@
+field_config['multiple'] ) && true === (bool) $this->field_config['multiple'] ) {
+ return [ 'list_of' => 'String' ];
+ }
+
+ return 'String';
+ }
+
+ /**
+ * Return the value different based on single or multiple selection allowed
+ *
+ * @param mixed $node The node the field belongs to
+ * @param array $args The field arguments
+ * @param AppContext $context The AppContext passed down the resolve tree
+ * @param ResolveInfo $info The ResolveInfo passed down the resolve tree
+ *
+ * @return array|mixed|null
+ */
+ public function resolve( $node, array $args, AppContext $context, ResolveInfo $info ) {
+ $value = parent::resolve( $node, $args, $context, $info );
+ if ( isset( $this->field_config['multiple'] ) && true === (bool) $this->field_config['multiple'] ) {
+ return ! empty( $value ) && is_array( $value ) ? $value : null;
+ }
+
+ return $value;
+ }
+
+}
diff --git a/src/Fields/Taxonomy.php b/src/Fields/Taxonomy.php
new file mode 100644
index 0000000..415ab05
--- /dev/null
+++ b/src/Fields/Taxonomy.php
@@ -0,0 +1,61 @@
+get_parent_type_fields_interface();
+
+ $type_registry = $this->registry->get_type_registry();
+
+ $connection_config = [
+ 'fromType' => $type_name,
+ 'toType' => 'TermNode',
+ 'fromFieldName' => $this->field_name,
+ 'resolve' => function( $root, $args, AppContext $context, $info ) {
+ $value = $this->resolve( $root, $args, $context, $info );
+
+ if ( empty( $value ) || ! is_array( $value ) ) {
+ return null;
+ }
+
+ $value = array_map(function( $id ) {
+ return absint( $id );
+ }, $value );
+
+ $resolver = new TermObjectConnectionResolver( $root, $args, $context, $info );
+ return $resolver
+ ->set_query_arg( 'include', $value )
+ ->set_query_arg( 'orderby', 'include' )
+ ->get_connection();
+ }
+ ];
+
+ $connection_name = $this->registry->get_connection_name( $type_name, 'TermNode', $this->field_name );
+
+ // If the connection already exists, don't register it again
+ if ( null !== $type_registry->get_type( $connection_name ) ) {
+ return $type_registry->get_type( $connection_name );
+ }
+
+ $type_registry->register_connection( $connection_config );
+
+ }
+
+}
diff --git a/src/Fields/User.php b/src/Fields/User.php
new file mode 100644
index 0000000..e581da4
--- /dev/null
+++ b/src/Fields/User.php
@@ -0,0 +1,79 @@
+get_parent_type_fields_interface();
+ $type_registry = $this->registry->get_type_registry();
+ $connection_name = $this->registry->get_connection_name( $type_name, 'User', $this->field_name );
+
+ $connection_config = [
+ 'fromType' => $type_name,
+ 'toType' => 'User',
+ 'fromFieldName' => $this->field_name,
+ 'resolve' => function( $root, $args, AppContext $context, $info ) {
+ $value = $this->resolve( $root, $args, $context, $info );
+
+ if ( empty( $value ) || ! is_array( $value ) ) {
+ return null;
+ }
+
+ $value = array_map(function( $id ) {
+ return absint( $id );
+ }, $value );
+
+ $resolver = new UserConnectionResolver( $root, $args, $context, $info );
+ return $resolver
+ ->set_query_arg( 'include', $value )
+ ->set_query_arg( 'orderby', 'include' )
+ ->get_connection();
+ }
+ ];
+
+
+ if ( ! isset( $this->field_config['multiple'] ) || true !== (bool) $this->field_config['multiple'] ) {
+ $connection_name = ucfirst( $type_name ) . 'ToSingleUserConnection';
+ $connection_config['connectionTypeName'] = $connection_name;
+ $connection_config['oneToOne'] = true;
+ $connection_config['resolve'] = function( $root, $args, AppContext $context, $info ) {
+ $value = $this->resolve( $root, $args, $context, $info );
+
+ if ( empty( $value ) || ! absint( $value ) ) {
+ return null;
+ }
+
+ $resolver = new UserConnectionResolver( $root, $args, $context, $info );
+ return $resolver
+ ->one_to_one()
+ ->set_query_arg( 'include', absint( $value ) )
+ ->get_connection();
+ };
+ }
+
+ // If the connection already exists, don't register it again
+ if ( null !== $type_registry->get_type( $connection_name ) ) {
+ return $connection_name;
+ }
+
+ $type_registry->register_connection( $connection_config );
+
+ }
+
+}
diff --git a/src/location-rules.php b/src/LocationRules.php
similarity index 99%
rename from src/location-rules.php
rename to src/LocationRules.php
index af6f678..d951116 100644
--- a/src/location-rules.php
+++ b/src/LocationRules.php
@@ -390,6 +390,10 @@ public function determine_location_rules() {
$field_group_name = isset( $field_group['graphql_field_name'] ) ? $field_group['graphql_field_name'] : $field_group['title'];
+ if ( ! isset( $field_group['active'] ) || false === (bool) $field_group['active'] ) {
+ continue;
+ }
+
if ( ! empty( $field_group['location'] ) && is_array( $field_group['location'] ) ) {
foreach ( $field_group['location'] as $location_rule_group ) {
@@ -950,7 +954,9 @@ public function determine_options_rules( string $field_group_name, string $param
if ( ! isset( $options_page['show_in_graphql'] ) || false === (bool) $options_page['show_in_graphql'] ) {
return;
}
+
$type_name = isset( $options_page['graphql_field_name'] ) ? Utils::format_type_name( $options_page['graphql_field_name'] ) : Utils::format_type_name( $options_page['menu_slug'] );
+
$this->set_graphql_type( $field_group_name, $type_name );
}
diff --git a/src/Registry.php b/src/Registry.php
new file mode 100644
index 0000000..87fb766
--- /dev/null
+++ b/src/Registry.php
@@ -0,0 +1,811 @@
+type_registry = $type_registry;
+
+ // Get all ACF Field Groups
+ $this->acf_field_groups = acf_get_field_groups();
+
+ // Instantiate the field groups array
+ $this->registered_field_groups = [];
+ $this->registered_field_group_interfaces = [];
+ $this->registered_field_group_fields_interfaces = [];
+
+ // If there are no ACF Field Groups, don't proceed
+ if ( empty( $this->acf_field_groups ) || ! is_array( $this->acf_field_groups ) ) {
+ return;
+ }
+
+ // Filters GraphQL meta resolvers for preview support of ACF Fields
+ add_filter( 'graphql_resolve_revision_meta_from_parent', [
+ $this,
+ 'resolve_meta_from_parent'
+ ], 10, 4 );
+
+ // Register types
+ $this->map_acf_to_graphql();
+ }
+
+ /**
+ * Determines if a field group has already been registered
+ *
+ * @param string $key
+ *
+ * @return mixed|string|null
+ */
+ public function get_registered_field_group( string $key ) {
+ return $this->registered_field_groups[ $key ] ?? null;
+ }
+
+ /**
+ *
+ *
+ * @param string string $key The key the field group is registered under
+ * @param string $type_name $type_name The GraphQL Type name
+ *
+ * @return string
+ */
+ public function add_registered_field_group( string $key, string $type_name ) {
+ $this->registered_field_groups[ $key ] = $type_name;
+ return $type_name;
+ }
+
+ /**
+ * @param $key
+ *
+ * @return mixed
+ */
+ public function get_registered_field_group_interface( string $key ) {
+ return $this->registered_field_group_interfaces[ $key ] ?? null;
+ }
+
+ /**
+ * @param $key
+ * @param $interface_name
+ * @return string
+ */
+ public function add_registered_field_group_interface( string $key, string $interface_name ) {
+ $this->registered_field_group_interfaces[ $key ] = $interface_name;
+ return $interface_name;
+ }
+
+ /**
+ * @param $key
+ *
+ * @return mixed
+ */
+ public function get_registered_field_group_fields_interface( string $key ) {
+ return $this->registered_field_group_fields_interfaces[ $key ] ?? null;
+ }
+
+ /**
+ * @param $key
+ * @param $interface_name
+ * @return string
+ */
+ public function add_registered_field_group_fields_interface( string $key, string $interface_name ) {
+ $this->registered_field_group_fields_interfaces[ $key ] = $interface_name;
+ return $interface_name;
+ }
+
+ /**
+ * Given a from Type, to Type and from field name, a connection name is returned
+ *
+ * @param string $from_type The Type name the connection is coming from
+ * @param string $to_type The Type name the connection is going to
+ * @param string $from_field_name The name of the field the connection resolves from
+ *
+ * @return string
+ */
+ public function get_connection_name( string $from_type, string $to_type, string $from_field_name ) {
+ // Create connection name using $from_type + To + $to_type + Connection.
+ $connection_name = ucfirst( $from_type ) . 'To' . ucfirst( $to_type ) . 'Connection';
+
+ // If connection type already exists with that connection name. Set connection name using
+ // $from_field_name + To + $to_type + Connection.
+ if ( ! empty( $this->type_registry->get_type( $connection_name ) ) ) {
+ $connection_name = ucfirst( $from_type ) . 'To' . ucfirst( $from_field_name ) . 'Connection';
+ }
+
+ return $connection_name;
+ }
+
+ /**
+ * @return TypeRegistry
+ */
+ public function get_type_registry() {
+ return $this->type_registry;
+ }
+
+ /**
+ * Determines whether meta should resolve from the requested object or the parent. This
+ * aids with previews.
+ *
+ * @param bool $should Whether the meta should resolve from the parent or not.
+ * @param mixed $object_id The ID of the object the field belongs to
+ * @param string $meta_key The name of the field
+ * @param bool $single Whether it's a singular field or a group
+ *
+ * @return bool
+ */
+ public function resolve_meta_from_parent( bool $should, $object_id, string $meta_key, bool $single ) {
+
+ if ( empty( $this->registered_field_names ) || ! is_array( $this->registered_field_names ) ) {
+ return $should;
+ }
+
+ $matches = null;
+
+ // Iterate over all field names
+ foreach ( $this->registered_field_names as $field_name ) {
+
+ // If the field name is an exact match with the $meta_key, the ACF field should
+ // resolve from the revision meta, so we can return false here, so that meta can
+ // resolve from the revision instead of the parent
+ if ( $field_name === $meta_key ) {
+ return false;
+ }
+
+ // For flex fields/repeaters, the meta keys are structured a bit funky.
+ // This checks to see if the $meta_key starts with the same string as one of the
+ // acf fields (a flex/repeater field) and then checks if it's preceeded by an underscore and a number.
+ if ( $field_name === substr( $meta_key, 0, strlen( $field_name ) ) ) {
+ // match any string that starts with the field name, followed by an underscore, followed by a number, followed by another string
+ // ex my_flex_field_0_text_field or some_repeater_field_12_25MostPopularDogToys
+ $pattern = '/' . $field_name . '_\d+_\w+/m';
+ preg_match( $pattern, $meta_key, $matches );
+ }
+
+ // If the meta key matches the pattern, treat it as a sub-field of an ACF Field Group
+ if ( null !== $matches ) {
+ return false;
+ }
+
+ }
+
+ return $should;
+
+ }
+
+ /**
+ * Register Types to the WPGraphQL Schema
+ *
+ * @return void
+ * @throws Exception
+ */
+ protected function map_acf_to_graphql() {
+
+ // Register initial pre-defined types
+ $this->register_initial_types();
+ $this->register_options_pages();
+
+ // Map User created Field Groups to the Schema
+ $this->map_acf_field_groups_to_types();
+
+ }
+
+ /**
+ * Register ACF Options pages to the GraphQL Schema.
+ *
+ * @return void
+ * @throws Exception
+ */
+ public function register_options_pages() {
+
+ $options_pages = acf_get_options_pages();
+ if ( empty( $options_pages ) || ! is_array( $options_pages ) ) {
+ return;
+ }
+
+ foreach ( $options_pages as $options_page ) {
+
+ if ( ! isset( $options_page['show_in_graphql'] ) || false === (bool) $options_page['show_in_graphql'] ) {
+ continue;
+ }
+
+ $page_title = $options_page['page_title'];
+ $page_slug = $options_page['menu_slug'];
+ $type_name = isset( $options_page['graphql_field_name'] ) ? Utils::format_type_name( $options_page['graphql_field_name'] ) : Utils::format_type_name( $options_page['menu_slug'] );
+
+ if ( null !== $this->type_registry->get_type( $type_name ) ) {
+ return;
+ }
+
+ register_graphql_object_type( $type_name, [
+ 'description' => sprintf( __( '%s options. Registered as an ACF Options page.', 'wp-graphql-acf' ), $page_title ),
+ 'fields' => [
+ 'pageTitle' => [
+ 'type' => 'String',
+ 'resolve' => function( $source ) use ( $page_title ) {
+ return ! empty( $page_title ) ? $page_title : null;
+ },
+ ],
+ 'pageSlug' => [
+ 'type' => 'String',
+ 'resolve' => function( $source ) use ( $page_slug ) {
+ return ! empty( $page_slug ) ? $page_slug : null;
+ },
+ ],
+ ],
+ ] );
+
+ $field_name = Utils::format_field_name( $type_name );
+
+ register_graphql_field(
+ 'RootQuery',
+ $field_name,
+ [
+ 'type' => $type_name,
+ 'description' => sprintf( __( '%s options.', 'wp-graphql-acf' ), $page_title ),
+ 'resolve' => function() use ( $options_page ) {
+ return ! empty( $options_page ) ? $options_page : null;
+ }
+ ]
+ );
+
+
+ }
+
+ }
+
+ /**
+ * Register initial types to the Schema
+ *
+ * @return void
+ *
+ * @throws Exception
+ */
+ public function register_initial_types() {
+
+ // Interfaces
+ AcfFieldGroupInterface::register_type( $this );
+
+ // Object Types
+ AcfLink::register_type();
+ AcfGoogleMap::register_type();
+ AcfFieldGroupConfig::register_type();
+
+ /**
+ * Registers a RootQuery entry for fetching
+ * an individual FieldGroup by ID
+ */
+ $this->type_registry->register_field( 'RootQuery', 'acfFieldGroup', [
+ 'description' => __( 'ACF Field Group', 'wp-graphql-acf' ),
+ 'type' => 'AcfFieldGroup',
+ 'args' => [
+ 'id' => [
+ 'type' => [ 'non_null' => 'ID' ],
+ ],
+ ],
+ 'resolve' => function( $root, $args, $context, $info ) {
+
+ $id_parts = Relay::fromGlobalId( $args['id'] );
+ $field_group = isset( $id_parts['id'] ) ? acf_get_field_group( $id_parts['id'] ) : null;
+
+ if ( empty( $field_group ) ) {
+ return null;
+ }
+
+ return [
+ 'fieldGroupName' => isset( $field_group['title'] ) ? $field_group['title'] : null,
+ '_fieldGroupConfig' => $field_group,
+ ];
+
+ }
+ ] );
+
+ }
+
+ /**
+ * Map ACF field groups to the Schema
+ *
+ * @return void
+ * @throws Exception
+ */
+ public function map_acf_field_groups_to_types() {
+
+ if ( empty( $this->acf_field_groups ) || ! is_array( $this->acf_field_groups ) ) {
+ return;
+ }
+
+ foreach ( $this->acf_field_groups as $field_group ) {
+ $this->add_acf_field_group_to_graphql( $field_group );
+ }
+ }
+
+ /**
+ * Adds an ACF Field Group to the GraphQL Schema by determining the GraphQL Types the
+ * field group should show on.
+ *
+ * @param array $field_group The ACF Field Group config to add to the Schema
+ * @param array $graphql_types The GraphQL Types the field group should show on
+ * @param array $interfaces Interfaces to apply to the Types
+ *
+ * @return mixed|string|void
+ *
+ * @throws Exception
+ */
+ public function add_acf_field_group_to_graphql( array $field_group, array $graphql_types = [], $interfaces = [] ) {
+
+ // If the field group has already been registered, return the registered Type
+ if ( isset( $field_group['key'] ) && $this->get_registered_field_group( $field_group['key'] ) ) {
+ return $this->get_registered_field_group( $field_group['key'] );
+ }
+
+ if ( ! $this->should_field_group_show_in_graphql( $field_group ) ) {
+ return;
+ }
+
+ $field_group_name = '';
+
+ if ( isset( $field_group['graphql_field_name'] ) ) {
+ $field_group_name = $field_group['graphql_field_name'];
+ } else if ( isset( $field_group['title'] ) ) {
+ $field_group_name = $field_group['title'];
+ } else if ( isset( $field_group['label'] ) ) {
+ $field_group_name = $field_group['label'];
+ } else if ( isset( $field_group['name'] ) ) {
+ $field_group_name = $field_group['name'];
+ }
+
+ if ( empty( $field_group_name ) ) {
+ graphql_debug( __( 'No name could be determined for the field group', 'wp-graphql-acf'), [ 'fieldGroup' => $field_group ] );
+ return;
+ }
+
+ $type_name = $this->get_field_group_type_name( $field_group );
+ $interface_name = 'With_' . $type_name;
+ $fields_interface_name = 'With_' . $type_name . '_Fields';
+
+ $this->type_registry->register_interface_type( $interface_name, [
+ 'description' => sprintf( __( 'Fields of the %s ACF Field Group', 'wp-graphql-acf' ), $field_group_name ),
+ 'fields' => [
+ lcfirst( $type_name ) => [
+ 'type' => $type_name,
+ 'description' => sprintf( __( 'Types that support the %s field group', 'wp-graphql' ), $field_group_name ),
+ 'resolve' => function( $root ) use ( $field_group ) {
+ return ! empty( $root ) ? $root : $field_group;
+ }
+ ],
+ ],
+ ] );
+
+ $fields = [
+ 'fieldGroupName' => [
+ 'type' => 'String',
+ 'resolve' => function() use ( $type_name ) {
+ return lcfirst( $type_name );
+ }
+ ]
+ ];
+
+ $mapped_fields = $this->map_acf_fields_to_field_group( $field_group );
+ $mapped_fields = ! empty( $mapped_fields ) ? array_merge( $fields, $mapped_fields ) : $fields;
+
+ $this->type_registry->register_interface_type( $fields_interface_name, [
+ 'description' => sprintf( __( 'Field Groups with fields of the %s ACF Field Group', 'wp-graphql-acf' ), $field_group_name ),
+ 'fields' => $mapped_fields
+ ]);
+
+ $layout_interfaces = [ 'AcfFieldGroup', $fields_interface_name ];
+
+ if ( ! empty( $interfaces ) ) {
+ $interfaces = array_merge( $layout_interfaces, $interfaces );
+ } else {
+ $interfaces = $layout_interfaces;
+ }
+
+ $this->type_registry->register_object_type( $type_name, [
+ 'interfaces' => $interfaces,
+ 'fields' => $mapped_fields
+ ]);
+
+ $is_flex_layout = false;
+
+ if ( isset( $field_group['isFlexLayout'] ) && true === $field_group['isFlexLayout'] ) {
+ $is_flex_layout = true;
+ }
+
+ // For flex layouts we want to leave the GraphQL Types empty
+ // As they don't need to be added as fields in the Schema independently
+ if ( empty( $graphql_types ) && ! $is_flex_layout ) {
+ $graphql_types = $this->get_graphql_types_for_field_group( $field_group );
+ }
+
+ if ( ! empty( $graphql_types ) ) {
+ register_graphql_interfaces_to_types( $interface_name, $graphql_types );
+ }
+
+
+ // Add the interfaces to a Registry, so they can be identified by field group key
+ $this->add_registered_field_group_interface( $field_group['key'], $interface_name );
+ $this->add_registered_field_group_fields_interface( $field_group['key'], $fields_interface_name );
+
+ // Add the field group to the list of registered field groups
+ return $this->add_registered_field_group( $field_group['key'], $type_name );
+
+ }
+
+ /**
+ * Get the GraphQL Types a Field Group should be registered to show on
+ *
+ * @param array $field_group The ACF Field Group config to determine the Types for
+ *
+ * @return array
+ *
+ * @return array
+ */
+ public function get_graphql_types_for_field_group( array $field_group ) {
+
+ $graphql_types = $field_group['graphql_types'] ?? [];
+
+ $field_group_name = $field_group['graphql_field_name'] ?? $field_group['title'];
+ $field_group_name = Utils::format_field_name( $field_group_name );
+
+ $manually_set_graphql_types = isset( $field_group['map_graphql_types_from_location_rules'] ) ? (bool) $field_group['map_graphql_types_from_location_rules'] : false;
+
+ if ( false === $manually_set_graphql_types || empty( $graphql_types ) ) {
+ if ( ! isset( $field_group['graphql_types'] ) || empty( $field_group['graphql_types'] ) ) {
+ $location_rules = $this->get_location_rules();
+ if ( isset( $location_rules[ $field_group_name ] ) ) {
+ $graphql_types = $location_rules[ $field_group_name ];
+ }
+ }
+ }
+
+ return ! empty( $graphql_types ) && is_array( $graphql_types ) ? array_unique( array_filter( $graphql_types ) ) : [];
+
+ }
+
+ /**
+ * Gets the location rules
+ *
+ * @return array
+ */
+ protected function get_location_rules() {
+
+ $field_groups = $this->acf_field_groups;
+ $rules = [];
+
+ // Each field group that doesn't have GraphQL Types explicitly set should get the location
+ // rules interpreted.
+ foreach ( $field_groups as $field_group ) {
+ if ( ! isset( $field_group['graphql_types'] ) || ! is_array( $field_group['graphql_types'] ) ) {
+ $rules[] = $field_group;
+ }
+ }
+
+ if ( empty( $rules ) ) {
+ return [];
+ }
+
+ // If there are field groups with no graphql_types field set, inherit the rules from
+ // ACF Location Rules
+ $rules = new LocationRules();
+ $rules->determine_location_rules();
+
+ return $rules->get_rules();
+ }
+
+ /**
+ * Determines whether a field group should be exposed to the GraphQL Schema. By default, field
+ * groups will not be exposed to GraphQL.
+ *
+ * @param array $field_group Undocumented.
+ *
+ * @return bool
+ */
+ protected function should_field_group_show_in_graphql( array $field_group ) {
+
+ /**
+ * By default, field groups will not be exposed to GraphQL.
+ */
+ $show = false;
+
+ /**
+ * If the field group is set to show_in_graphql, show it
+ */
+ if ( isset( $field_group['show_in_graphql'] ) && true === (bool) $field_group['show_in_graphql'] ) {
+ $show = true;
+ }
+
+ if ( isset( $field_group['parent'] ) && ! empty( $field_group['parent'] ) ) {
+ $show = true;
+ }
+
+ /**
+ * Whether a field group should show in GraphQL.
+ *
+ * @var boolean $show Whether the field group should show in the GraphQL Schema
+ * @var array $field_group The ACF Field Group
+ * @var Config $this The Config for the ACF Plugin
+ */
+ return apply_filters( 'wpgraphql_acf_should_field_group_show_in_graphql', $show, $field_group, $this );
+
+ }
+
+ /**
+ * Given a field group config array, returns the Type name to be used in the graph
+ *
+ * @param array $field_group The ACF Field Group config array
+ *
+ * @return string
+ */
+ public function get_field_group_type_name( array $field_group ) {
+ $type_name = $field_group['graphql_field_name'] ?? $field_group['title'];
+ $type_name = ucfirst( $type_name );
+
+ return $type_name;
+ }
+
+ /**
+ * Get a list of supported field types that WPGraphQL for ACF supports.
+ *
+ * This is helpful for determining whether UI should be output for the field, and whether
+ * the field should be added to the Schema.
+ *
+ * Some fields, such as "Accordion" are not supported currently.
+ *
+ * @return array
+ */
+ public function get_supported_field_types() {
+
+ $supported_field_types = [
+ 'text',
+ 'textarea',
+ 'number',
+ 'range',
+ 'email',
+ 'url',
+ 'password',
+ 'image',
+ 'file',
+ 'wysiwyg',
+ 'oembed',
+ 'gallery',
+ 'select',
+ 'checkbox',
+ 'radio',
+ 'button_group',
+ 'true_false',
+ 'link',
+ 'post_object',
+ 'page_link',
+ 'relationship',
+ 'taxonomy',
+ 'user',
+ 'google_map',
+ 'date_picker',
+ 'date_time_picker',
+ 'time_picker',
+ 'color_picker',
+ 'group',
+ 'repeater',
+ 'flexible_content',
+ 'clone'
+ ];
+
+ /**
+ * filter the supported fields to allow 3rd party extensions to hook in and
+ * add support for their fields.
+ *
+ * @param array $supported_fields
+ */
+ return apply_filters( 'wpgraphql_acf_supported_fields', $supported_field_types );
+
+ }
+
+ /**
+ * Map Fields to the Field Groups in the Schema
+ *
+ * @param array $field_group
+ *
+ * @return array
+ */
+ public function map_acf_fields_to_field_group( array $field_group ) {
+
+ // Get the ACF Fields for the specified field group
+ $fields = isset( $field_group['sub_fields'] ) && is_array( $field_group['sub_fields'] ) ? $field_group['sub_fields'] : acf_get_fields( $field_group );
+
+ // If there are no for the field group, do nothing.
+ if ( empty( $fields ) || ! is_array( $fields ) ) {
+ return [];
+ }
+
+ $cloned_groups = [];
+
+ foreach ( $fields as $field ) {
+
+ if ( ! isset( $field['_clone'] ) ) {
+ continue;
+ }
+
+ $field_config = acf_get_field( $field['_clone'] );
+
+ if ( ! isset( $field_config['clone'] ) || ! is_array( $field_config['clone' ] ) ) {
+ continue;
+ }
+
+ foreach ( $field_config['clone'] as $cloned ) {
+ if ( 0 !== strpos( $cloned, 'group_' ) ) {
+ continue;
+ }
+
+ if ( isset( $groups[ $cloned ] ) ) {
+ continue;
+ }
+
+ $cloned_field_group = acf_get_field_group( $cloned );
+ $cloned_groups[ $cloned ] = 'With_' . $this->get_field_group_type_name( $cloned_field_group ) . '_Fields';
+
+ }
+
+ }
+
+ if ( ! empty( $cloned_groups ) ) {
+
+ graphql_debug( [
+ 'register_graphql_interfaces_to_types',
+ array_values( $cloned_groups ),
+ $this->get_field_group_type_name( $field_group )
+ ]);
+
+ register_graphql_interfaces_to_types( array_values( $cloned_groups ), [ $this->get_field_group_type_name( $field_group ) ]);
+ // graphql_debug( [ $this->get_field_group_type_name( $field_group ), $cloned_groups ] );
+ }
+
+ $mapped_fields = [];
+
+ // Store a list of field keys that have been registered
+ // to help avoid registering the same field twice on one
+ // field group. This occasionally happens with clone fields.
+ $registered_field_keys = [];
+
+ foreach ( $fields as $field ) {
+
+ // If a field is empty or not an array, it's not valid
+ if ( empty( $field ) || ! is_array( $field ) ) {
+ continue;
+ }
+
+ // If a field doesn't have a name or key, it's not valid
+ if ( ! isset( $field['name'], $field['key'] ) ) {
+ continue;
+ }
+
+ // If a field is specifically set to not show in GraphQL, don't proceed
+ if ( isset( $field['show_in_graphql'] ) && false === $field['show_in_graphql'] ) {
+ continue;
+ }
+
+ // Prevent duplicate cloned fields from being registered to the same field group
+ if ( in_array( $field['key'], $registered_field_keys, true ) ) {
+ continue;
+ }
+
+ // If the ACF Field Type is not a supported field type, don't add it to the Schema.
+ // For example, Accordion and Tab types, and various extension types
+ // are not supported natively, but can be filtered in!
+ if ( ! in_array( $field['type'], $this->get_supported_field_types(), true ) ) {
+ continue;
+ }
+
+ $mapped_field = $this->map_graphql_field( $field, $field_group );
+
+ if ( $mapped_field instanceof AcfField && null !== $mapped_field->get_graphql_field_config() ) {
+ $mapped_fields[ $mapped_field->get_field_name() ] = $mapped_field->get_graphql_field_config();
+ }
+
+ }
+
+ return $mapped_fields;
+
+ }
+
+ /**
+ * @param array $field The ACF Field config
+ * @param array $field_group The ACF Field Group Config
+ *
+ * @return AcfField
+ */
+ public function map_graphql_field( array $field, array $field_group ) {
+
+ $field_type = $field['type'] ?? null;
+
+ $class_name = Utils::format_type_name( $field_type );
+ $class_name = '\\WPGraphQL\\ACF\Fields\\' . $class_name;
+
+ /**
+ * This allows 3rd party extensions to hook and and provide
+ * a path to their class for registering a field to the Schema
+ */
+ $class_name = apply_filters( 'graphql_acf_field_class', $class_name, $field, $field_group, $this );
+
+ if ( class_exists( $class_name ) ) {
+ $field = new $class_name( $field, $field_group, $this );
+ if ( $field instanceof AcfField ) {
+ return $field;
+ }
+
+ return new AcfField( $field, $field_group, $this );
+ }
+
+ return new AcfField( $field, $field_group, $this );
+
+ }
+
+}
diff --git a/src/Types/InterfaceType/AcfFieldGroupInterface.php b/src/Types/InterfaceType/AcfFieldGroupInterface.php
new file mode 100644
index 0000000..3005cf0
--- /dev/null
+++ b/src/Types/InterfaceType/AcfFieldGroupInterface.php
@@ -0,0 +1,50 @@
+ __( 'A Field Group registered by ACF', 'wp-graphql-acf' ),
+ 'fields' => [
+ 'fieldGroupName' => [
+ 'description' => __( 'The name of the ACF Field Group', 'wp-graphql-acf' ),
+ 'deprecationReason' => __( 'Deprecated in favor of "_fieldGroupConfig"', 'wp-graphql-acf' ),
+ 'type' => 'String',
+ ],
+ '_fieldGroupConfig' => [
+ 'type' => 'AcfFieldGroupConfig',
+ 'description' => __( 'Configuration settings of an ACF Field Group', 'wp-graphql' ),
+ ]
+ ],
+ 'resolveType' => function( $field_group ) use ( $registry ) {
+ if ( ! empty( $field_group['_fieldGroupConfig'] ) ) {
+ $field_group = $field_group['_fieldGroupConfig'];
+ return $registry->get_field_group_type_name( $field_group );
+ }
+ return null;
+ }
+ ]
+ );
+ }
+}
diff --git a/src/Types/ObjectType/AcfFieldGroupConfig.php b/src/Types/ObjectType/AcfFieldGroupConfig.php
new file mode 100644
index 0000000..18571ab
--- /dev/null
+++ b/src/Types/ObjectType/AcfFieldGroupConfig.php
@@ -0,0 +1,36 @@
+ __( 'Configuration settings of an ACF Field Group.', 'wp-graphql' ),
+ 'fields' => [
+ 'databaseId' => [
+ 'type' => 'Int',
+ 'resolve' => function( $field_group ) {
+ return $field_group['ID'];
+ }
+ ],
+ 'key' => [
+ 'type' => 'String',
+ ],
+ ],
+ ] );
+
+ }
+
+}
diff --git a/src/Types/ObjectType/AcfGoogleMap.php b/src/Types/ObjectType/AcfGoogleMap.php
new file mode 100644
index 0000000..d622e11
--- /dev/null
+++ b/src/Types/ObjectType/AcfGoogleMap.php
@@ -0,0 +1,118 @@
+ __( 'A group of fields representing a Google Map', 'wp-graphql-acf' ),
+ 'fields' => [
+ 'streetAddress' => [
+ 'type' => 'String',
+ 'description' => __( 'The street address associated with the map', 'wp-graphql-acf' ),
+ 'resolve' => function( $root ) {
+ return isset( $root['address'] ) ? $root['address'] : null;
+ },
+ ],
+ 'latitude' => [
+ 'type' => 'Float',
+ 'description' => __( 'The latitude associated with the map', 'wp-graphql-acf' ),
+ 'resolve' => function( $root ) {
+ return isset( $root['lat'] ) ? $root['lat'] : null;
+ },
+ ],
+ 'longitude' => [
+ 'type' => 'Float',
+ 'description' => __( 'The longitude associated with the map', 'wp-graphql-acf' ),
+ 'resolve' => function( $root ) {
+ return isset( $root['lng'] ) ? $root['lng'] : null;
+ },
+ ],
+ 'streetName' => [
+ 'type' => 'String',
+ 'description' => __( 'The street name associated with the map', 'wp-graphql-acf' ),
+ 'resolve' => function( $root ) {
+ return isset( $root['street_name'] ) ? $root['street_name'] : null;
+ },
+ ],
+ 'streetNumber' => [
+ 'type' => 'String',
+ 'description' => __( 'The street number associated with the map', 'wp-graphql-acf' ),
+ 'resolve' => function( $root ) {
+ return isset( $root['street_number'] ) ? $root['street_number'] : null;
+ },
+ ],
+ 'city' => [
+ 'type' => 'String',
+ 'description' => __( 'The city associated with the map', 'wp-graphql-acf' ),
+ 'resolve' => function( $root ) {
+ return isset( $root['city'] ) ? $root['city'] : null;
+ },
+ ],
+ 'state' => [
+ 'type' => 'String',
+ 'description' => __( 'The state associated with the map', 'wp-graphql-acf' ),
+ 'resolve' => function( $root ) {
+ return isset( $root['state'] ) ? $root['state'] : null;
+ },
+ ],
+ 'stateShort' => [
+ 'type' => 'String',
+ 'description' => __( 'The state abbreviation associated with the map', 'wp-graphql-acf' ),
+ 'resolve' => function( $root ) {
+ return isset( $root['state_short'] ) ? $root['state_short'] : null;
+ },
+ ],
+ 'postCode' => [
+ 'type' => 'String',
+ 'description' => __( 'The post code associated with the map', 'wp-graphql-acf' ),
+ 'resolve' => function( $root ) {
+ return isset( $root['post_code'] ) ? $root['post_code'] : null;
+ },
+ ],
+ 'country' => [
+ 'type' => 'String',
+ 'description' => __( 'The country associated with the map', 'wp-graphql-acf' ),
+ 'resolve' => function( $root ) {
+ return isset( $root['country'] ) ? $root['country'] : null;
+ },
+ ],
+ 'countryShort' => [
+ 'type' => 'String',
+ 'description' => __( 'The country abbreviation associated with the map', 'wp-graphql-acf' ),
+ 'resolve' => function( $root ) {
+ return isset( $root['country_short'] ) ? $root['country_short'] : null;
+ },
+ ],
+ 'placeId' => [
+ 'type' => 'String',
+ 'description' => __( 'The country associated with the map', 'wp-graphql-acf' ),
+ 'resolve' => function( $root ) {
+ return isset( $root['place_id'] ) ? $root['place_id'] : null;
+ },
+ ],
+ 'zoom' => [
+ 'type' => 'String',
+ 'description' => __( 'The zoom defined with the map', 'wp-graphql-acf' ),
+ 'resolve' => function( $root ) {
+ return isset( $root['zoom'] ) ? $root['zoom'] : null;
+ },
+ ],
+ ]
+ ] );
+
+ }
+
+}
diff --git a/src/Types/ObjectType/AcfLink.php b/src/Types/ObjectType/AcfLink.php
new file mode 100644
index 0000000..1652eb0
--- /dev/null
+++ b/src/Types/ObjectType/AcfLink.php
@@ -0,0 +1,37 @@
+ __( 'ACF Link field', 'wp-graphql-acf' ),
+ 'fields' => [
+ 'url' => [
+ 'type' => 'String',
+ 'description' => __( 'The url of the link', 'wp-graphql-acf' ),
+ ],
+ 'title' => [
+ 'type' => 'String',
+ 'description' => __( 'The title of the link', 'wp-graphql-acf' ),
+ ],
+ 'target' => [
+ 'type' => 'String',
+ 'description' => __( 'The target of the link (_blank, etc)', 'wp-graphql-acf' ),
+ ],
+ ],
+ ] );
+ }
+
+}
diff --git a/src/js/main.js b/src/admin/js/main.js
similarity index 100%
rename from src/js/main.js
rename to src/admin/js/main.js
diff --git a/src/class-config.php b/src/deprecated-class-config.php
similarity index 86%
rename from src/class-config.php
rename to src/deprecated-class-config.php
index 927f2b3..b213f85 100644
--- a/src/class-config.php
+++ b/src/deprecated-class-config.php
@@ -61,15 +61,6 @@ public function init( TypeRegistry $type_registry ) {
$this->type_registry = $type_registry;
$this->register_initial_types();
- /**
- * Gets the location rules for backward compatibility.
- *
- * This allows for ACF Field Groups that were registered before the "graphql_types"
- * field was respected can still work with the old GraphQL Schema rules that mapped
- * from the ACF Location rules.
- */
- $this->location_rules = $this->get_location_rules();
-
/**
* Add ACF Fields to GraphQL Types
*/
@@ -304,25 +295,12 @@ protected function should_field_group_show_in_graphql( $field_group ) {
$show = false;
/**
- * If
+ * If the field group is set to show_in_graphql, show it
*/
if ( isset( $field_group['show_in_graphql'] ) && true === (bool) $field_group['show_in_graphql'] ) {
$show = true;
}
- /**
- * Determine conditions where the GraphQL Schema should NOT be shown in GraphQL for
- * root groups, not nested groups with parent.
- */
- if ( ! isset( $field_group['parent'] ) ) {
- if (
- ( isset( $field_group['active'] ) && true != $field_group['active'] ) ||
- ( empty( $field_group['location'] ) || ! is_array( $field_group['location'] ) )
- ) {
- $show = false;
- }
- }
-
/**
* Whether a field group should show in GraphQL.
*
@@ -547,8 +525,9 @@ protected function register_graphql_field( string $type_name, string $field_name
*/
$field_config = apply_filters( 'wpgraphql_acf_register_graphql_field', [
'type' => null,
- 'resolve' => isset( $config['resolve'] ) && is_callable( $config['resolve'] ) ? $config['resolve'] : function( $root, $args, $context, $info ) use ( $acf_field ) {
+ 'resolve' => isset( $config['resolve'] ) && is_callable( $config['resolve'] ) ? $config['resolve'] : function( $root, $args, $context, $info ) use ( $acf_field, $acf_type ) {
$value = $this->get_acf_field_value( $root, $acf_field );
+
return ! empty( $value ) ? $value : null;
},
], $type_name, $field_name, $config );
@@ -921,22 +900,39 @@ protected function register_graphql_field( string $type_name, string $field_name
if ( null !== $this->type_registry->get_type( $field_type_name ) ) {
$field_config['type'] = $field_type_name;
break;
- }
+ } else {
- $this->type_registry->register_object_type(
- $field_type_name,
- [
- 'description' => __( 'Field Group', 'wp-graphql-acf' ),
- 'interfaces' => [ 'AcfFieldGroup' ],
- 'fields' => [
- 'fieldGroupName' => [
- 'resolve' => function( $source ) use ( $acf_field ) {
- return ! empty( $acf_field['name'] ) ? $acf_field['name'] : null;
- },
+ if ( isset( $acf_field['parent'] ) && ! empty( $acf_field['parent'] ) ) {
+
+ $parent_group = acf_get_field_group( $acf_field['parent'] );
+
+
+ if ( isset( $parent_group['graphql_field_name' ] ) ) {
+ if ( $this->type_registry->get_type( strtolower( $parent_group['graphql_field_name' ] ) ) ) {
+ $field_config['type'] = $parent_group['graphql_field_name' ];
+ break;
+ }
+ }
+
+ $field_type_name = $type_name . '_' . Utils::format_type_name( $acf_field['name'] );
+ }
+
+ $this->type_registry->register_object_type(
+ $field_type_name,
+ [
+ 'description' => __( 'Field Group', 'wp-graphql-acf' ),
+ 'interfaces' => [ 'AcfFieldGroup' ],
+ 'fields' => [
+ 'fieldGroupName' => [
+ 'resolve' => function( $source ) use ( $acf_field ) {
+ return ! empty( $acf_field['name'] ) ? $acf_field['name'] : null;
+ },
+ ],
],
- ],
- ]
- );
+ ]
+ );
+
+ }
$this->add_field_group_fields( $acf_field, $field_type_name );
@@ -946,119 +942,6 @@ protected function register_graphql_field( string $type_name, string $field_name
case 'google_map':
$field_type_name = 'ACF_GoogleMap';
- if ( $this->type_registry->get_type( $field_type_name ) == $field_type_name ) {
- $field_config['type'] = $field_type_name;
- break;
- }
-
- $fields = [
- 'streetAddress' => [
- 'type' => 'String',
- 'description' => __( 'The street address associated with the map', 'wp-graphql-acf' ),
- 'resolve' => function( $root ) {
- return isset( $root['address'] ) ? $root['address'] : null;
- },
- ],
- 'latitude' => [
- 'type' => 'Float',
- 'description' => __( 'The latitude associated with the map', 'wp-graphql-acf' ),
- 'resolve' => function( $root ) {
- return isset( $root['lat'] ) ? $root['lat'] : null;
- },
- ],
- 'longitude' => [
- 'type' => 'Float',
- 'description' => __( 'The longitude associated with the map', 'wp-graphql-acf' ),
- 'resolve' => function( $root ) {
- return isset( $root['lng'] ) ? $root['lng'] : null;
- },
- ],
- ];
-
- // ACF 5.8.6 added more data to Google Maps field value
- // https://www.advancedcustomfields.com/changelog/
- if ( \acf_version_compare(acf_get_db_version(), '>=', '5.8.6' ) ) {
- $fields += [
- 'streetName' => [
- 'type' => 'String',
- 'description' => __( 'The street name associated with the map', 'wp-graphql-acf' ),
- 'resolve' => function( $root ) {
- return isset( $root['street_name'] ) ? $root['street_name'] : null;
- },
- ],
- 'streetNumber' => [
- 'type' => 'String',
- 'description' => __( 'The street number associated with the map', 'wp-graphql-acf' ),
- 'resolve' => function( $root ) {
- return isset( $root['street_number'] ) ? $root['street_number'] : null;
- },
- ],
- 'city' => [
- 'type' => 'String',
- 'description' => __( 'The city associated with the map', 'wp-graphql-acf' ),
- 'resolve' => function( $root ) {
- return isset( $root['city'] ) ? $root['city'] : null;
- },
- ],
- 'state' => [
- 'type' => 'String',
- 'description' => __( 'The state associated with the map', 'wp-graphql-acf' ),
- 'resolve' => function( $root ) {
- return isset( $root['state'] ) ? $root['state'] : null;
- },
- ],
- 'stateShort' => [
- 'type' => 'String',
- 'description' => __( 'The state abbreviation associated with the map', 'wp-graphql-acf' ),
- 'resolve' => function( $root ) {
- return isset( $root['state_short'] ) ? $root['state_short'] : null;
- },
- ],
- 'postCode' => [
- 'type' => 'String',
- 'description' => __( 'The post code associated with the map', 'wp-graphql-acf' ),
- 'resolve' => function( $root ) {
- return isset( $root['post_code'] ) ? $root['post_code'] : null;
- },
- ],
- 'country' => [
- 'type' => 'String',
- 'description' => __( 'The country associated with the map', 'wp-graphql-acf' ),
- 'resolve' => function( $root ) {
- return isset( $root['country'] ) ? $root['country'] : null;
- },
- ],
- 'countryShort' => [
- 'type' => 'String',
- 'description' => __( 'The country abbreviation associated with the map', 'wp-graphql-acf' ),
- 'resolve' => function( $root ) {
- return isset( $root['country_short'] ) ? $root['country_short'] : null;
- },
- ],
- 'placeId' => [
- 'type' => 'String',
- 'description' => __( 'The country associated with the map', 'wp-graphql-acf' ),
- 'resolve' => function( $root ) {
- return isset( $root['place_id'] ) ? $root['place_id'] : null;
- },
- ],
- 'zoom' => [
- 'type' => 'String',
- 'description' => __( 'The zoom defined with the map', 'wp-graphql-acf' ),
- 'resolve' => function( $root ) {
- return isset( $root['zoom'] ) ? $root['zoom'] : null;
- },
- ],
- ];
- }
-
- $this->type_registry->register_object_type(
- $field_type_name,
- [
- 'description' => __( 'Google Map field', 'wp-graphql-acf' ),
- 'fields' => $fields,
- ]
- );
$field_config['type'] = $field_type_name;
break;
case 'repeater':
@@ -1195,7 +1078,8 @@ protected function register_graphql_field( string $type_name, string $field_name
$config = array_merge( $config, $field_config );
$this->registered_field_names[] = $acf_field['name'];
- return $this->type_registry->register_field( $type_name, $field_name, $config );
+
+ $this->type_registry->register_field( $type_name, $field_name, $config );
}
/**
@@ -1450,10 +1334,6 @@ protected function add_acf_fields_to_graphql_types() {
}
}
- if ( ! is_array( $field_group['graphql_types'] ) || empty( $field_group['graphql_types'] ) ) {
- continue;
- }
-
/**
* Determine if the field group should be exposed
* to graphql
@@ -1483,12 +1363,60 @@ protected function add_acf_fields_to_graphql_types() {
$qualifier = sprintf( __( 'Added to the GraphQL Schema because the ACF Field Group "%1$s" was set to Show in GraphQL.', 'wp-graphql-acf' ), $field_group['title'] );
$config['description'] = $field_group['description'] ? $field_group['description'] . ' | ' . $qualifier : $qualifier;
- /**
- * Loop over the GraphQL types for this field group on
- */
- foreach ( $graphql_types as $graphql_type ) {
- $this->register_graphql_field( $graphql_type, $field_name, $config );
+ $field_type_name = $field_name;
+ $interface_name = 'With' . ucfirst( $field_type_name );
+
+ if ( ! $this->type_registry->get_type( $field_type_name ) ) {
+
+ $this->type_registry->register_object_type(
+ $field_type_name,
+ [
+ 'description' => __( 'Field Group', 'wp-graphql-acf' ),
+ 'interfaces' => [ 'AcfFieldGroup' ],
+ 'fields' => [
+ 'fieldGroupName' => [
+ 'resolve' => function( $source ) use ( $config ) {
+ return ! empty( $config['name'] ) ? $config['name'] : null;
+ },
+ ],
+ ],
+ ]
+ );
+
+ $this->add_field_group_fields( $field_group, $field_type_name );
+
+ }
+
+ if ( ! $this->type_registry->get_type( strtolower( $interface_name ) ) && ! empty( $graphql_types ) ) {
+
+ $explicit_name = ! empty( $field_group['graphql_field_name'] ) ? $field_group['graphql_field_name'] : null;
+ $name = empty( $explicit_name ) && ! empty( $field_group['name'] ) ? self::camel_case( $field_group['name'] ) : $explicit_name;
+
+ $this->type_registry->register_interface_type( $interface_name, [
+ 'description' => sprintf( __( 'A node that can have fields of the "%s" Field Group.', 'wp-graphql-acf' ), $field_type_name ),
+ 'fields' => [
+ $name => [
+ 'type' => $field_type_name,
+ 'description' => sprintf( __( 'Fields of the "%s" Field Group.', 'wp-graphql' ), $field_type_name ),
+ 'resolve' => function( $root ) use ( $field_group ) {
+ return $root;
+ }
+ ],
+ ],
+
+ ] );
+
+ register_graphql_interfaces_to_types( [ $interface_name ], $graphql_types );
+
+ /**
+ * Loop over the GraphQL types for this field group on
+ */
+ foreach ( $graphql_types as $graphql_type ) {
+ $this->register_graphql_field( $graphql_type, $field_name, $config );
+ }
+
}
+
}
}
diff --git a/tests/_data/field-group-exports/complex-field-group/acf-export.json b/tests/_data/field-group-exports/complex-field-group/acf-export.json
new file mode 100644
index 0000000..7fe35c4
--- /dev/null
+++ b/tests/_data/field-group-exports/complex-field-group/acf-export.json
@@ -0,0 +1,3896 @@
+[
+ {
+ "key": "group_5fedf8bf735af",
+ "title": "Project Details",
+ "fields": [
+ {
+ "key": "field_5fedf8dddd6f8",
+ "label": "Details",
+ "name": "details",
+ "type": "repeater",
+ "instructions": "Add pertinent details about the project",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "collapsed": "field_5fedf8eedd6f9",
+ "min": 0,
+ "max": 0,
+ "layout": "block",
+ "button_label": "Add Detail",
+ "sub_fields": [
+ {
+ "key": "field_5fedf8eedd6f9",
+ "label": "Title",
+ "name": "title",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_5fedf8f8dd6fa",
+ "label": "Content",
+ "name": "content",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ }
+ ]
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "project"
+ }
+ ]
+ ],
+ "menu_order": -1,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": [
+ "the_content",
+ "excerpt",
+ "discussion",
+ "comments",
+ "revisions",
+ "slug",
+ "author",
+ "format",
+ "page_attributes",
+ "featured_image",
+ "categories",
+ "tags",
+ "send-trackbacks"
+ ],
+ "active": false,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfProjectDetails"
+ },
+ {
+ "key": "group_5fce88119bcf2",
+ "title": "Background Image with Content",
+ "fields": [
+ {
+ "key": "field_5fce884513772",
+ "label": "Background Image",
+ "name": "background_image",
+ "type": "image",
+ "instructions": "Upload or select image for use as section background. If link is included below, image will change to full color on hover, so be sure to upload a color image.",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array",
+ "preview_size": "thumbnail",
+ "library": "all",
+ "min_width": "",
+ "min_height": "",
+ "min_size": "",
+ "max_width": "",
+ "max_height": "",
+ "max_size": "",
+ "mime_types": ""
+ },
+ {
+ "key": "field_5fea57ad0007a",
+ "label": "Section Headline",
+ "name": "section_headline",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_5fce887313773",
+ "label": "Section Content",
+ "name": "section_content",
+ "type": "textarea",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "maxlength": "",
+ "rows": 4,
+ "new_lines": ""
+ },
+ {
+ "key": "field_5fce889a13774",
+ "label": "Section Link",
+ "name": "section_link",
+ "type": "link",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array"
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "post"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": [
+ "permalink",
+ "the_content",
+ "excerpt",
+ "discussion",
+ "comments",
+ "revisions",
+ "slug",
+ "author",
+ "format",
+ "page_attributes",
+ "featured_image",
+ "categories",
+ "tags",
+ "send-trackbacks"
+ ],
+ "active": false,
+ "description": "Full width image section with text overlay",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfFullImageComponent"
+ },
+ {
+ "key": "group_5fecf293ca9b2",
+ "title": "Background Shade",
+ "fields": [
+ {
+ "key": "field_5fecf2c91082e",
+ "label": "Shade",
+ "name": "shade",
+ "type": "true_false",
+ "instructions": "Add light gray background to section.",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "message": "Add background shade?",
+ "default_value": 0,
+ "ui": 0,
+ "ui_on_text": "",
+ "ui_off_text": ""
+ },
+ {
+ "key": "field_60198deb9dc35",
+ "label": "Component Padding",
+ "name": "padding",
+ "type": "group",
+ "instructions": "Provide vertical padding for section interior when needed.",
+ "required": 0,
+ "conditional_logic": [
+ [
+ {
+ "field": "field_5fecf2c91082e",
+ "operator": "==",
+ "value": "1"
+ }
+ ]
+ ],
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "layout": "block",
+ "sub_fields": [
+ {
+ "key": "field_60198e089dc36",
+ "label": "Padding Top",
+ "name": "padding_top",
+ "type": "button_group",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "choices": {
+ "default": "Default (50px)",
+ "pt0": "0px",
+ "pt2": "25px"
+ },
+ "allow_null": 0,
+ "default_value": "default",
+ "layout": "horizontal",
+ "return_format": "value"
+ },
+ {
+ "key": "field_60198e3f9dc37",
+ "label": "Padding Bottom",
+ "name": "padding_bottom",
+ "type": "button_group",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "choices": {
+ "default": "Default (50px)",
+ "pb0": "0px",
+ "pb2": "25px"
+ },
+ "allow_null": 0,
+ "default_value": "default",
+ "layout": "horizontal",
+ "return_format": "value"
+ }
+ ]
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "post"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": "",
+ "active": false,
+ "description": "Boolean for displaying background shade",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfBackgroundShade"
+ },
+ {
+ "key": "group_5feb58ee935c4",
+ "title": "Circular Image Row",
+ "fields": [
+ {
+ "key": "field_5feb591cf9a69",
+ "label": "Items",
+ "name": "row_items",
+ "type": "repeater",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "collapsed": "field_5feb598ef9a6b",
+ "min": 2,
+ "max": 0,
+ "layout": "block",
+ "button_label": "Add Item",
+ "sub_fields": [
+ {
+ "key": "field_5feb597ef9a6a",
+ "label": "Image",
+ "name": "image",
+ "type": "image",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "33",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array",
+ "preview_size": "thumbnail",
+ "library": "all",
+ "min_width": "",
+ "min_height": "",
+ "min_size": "",
+ "max_width": "",
+ "max_height": "",
+ "max_size": "",
+ "mime_types": ""
+ },
+ {
+ "key": "field_5feb598ef9a6b",
+ "label": "Headline",
+ "name": "headline",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "33",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_5feb599ef9a6c",
+ "label": "Sub Headline",
+ "name": "subheadline",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "33",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_5feb59b1f9a6d",
+ "label": "Item Content",
+ "name": "item_content",
+ "type": "textarea",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "maxlength": "",
+ "rows": 4,
+ "new_lines": ""
+ }
+ ]
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "post"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": "",
+ "active": false,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfCircleRowComponent"
+ },
+ {
+ "key": "group_6023fa60f3606",
+ "title": "Contact Page",
+ "fields": [
+ {
+ "key": "field_6023fa85e6ecb",
+ "label": "Headline",
+ "name": "headline",
+ "type": "textarea",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "maxlength": "",
+ "rows": 3,
+ "new_lines": "br"
+ },
+ {
+ "key": "field_6023fab4e6ecc",
+ "label": "Locations",
+ "name": "locations",
+ "type": "group",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "layout": "block",
+ "sub_fields": [
+ {
+ "key": "field_6023fae0e6ecd",
+ "label": "Headline",
+ "name": "headline",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_6023faf8e6ece",
+ "label": "Facility",
+ "name": "facility",
+ "type": "repeater",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "collapsed": "",
+ "min": 0,
+ "max": 0,
+ "layout": "table",
+ "button_label": "",
+ "sub_fields": [
+ {
+ "key": "field_6023fb08e6ecf",
+ "label": "Title",
+ "name": "title",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_6023fb14e6ed0",
+ "label": "Address",
+ "name": "address",
+ "type": "wysiwyg",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "tabs": "all",
+ "toolbar": "basic",
+ "media_upload": 0,
+ "delay": 0
+ },
+ {
+ "key": "field_6023fb49e6ed2",
+ "label": "Phone",
+ "name": "phone",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_6023fb51e6ed3",
+ "label": "Fax",
+ "name": "fax",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "key": "field_6023fb93e6ed4",
+ "label": "Contacts",
+ "name": "contacts",
+ "type": "group",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "layout": "block",
+ "sub_fields": [
+ {
+ "key": "field_6023fba1e6ed5",
+ "label": "Headline",
+ "name": "headline",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_6023fbb0e6ed6",
+ "label": "Contact",
+ "name": "contact",
+ "type": "repeater",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "collapsed": "field_6023fbb9e6ed7",
+ "min": 0,
+ "max": 0,
+ "layout": "table",
+ "button_label": "",
+ "sub_fields": [
+ {
+ "key": "field_6023fbb9e6ed7",
+ "label": "Title",
+ "name": "title",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_6023fbc1e6ed8",
+ "label": "Email",
+ "name": "email",
+ "type": "email",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": ""
+ }
+ ]
+ },
+ {
+ "key": "field_6023fbe1e6ed9",
+ "label": "Social",
+ "name": "social",
+ "type": "repeater",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "collapsed": "field_6023fc45e6edb",
+ "min": 0,
+ "max": 0,
+ "layout": "table",
+ "button_label": "Add Social Icon",
+ "sub_fields": [
+ {
+ "key": "field_6023fc36e6eda",
+ "label": "Icon",
+ "name": "icon",
+ "type": "image",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array",
+ "preview_size": "thumbnail",
+ "library": "all",
+ "min_width": "",
+ "min_height": "",
+ "min_size": "",
+ "max_width": "",
+ "max_height": "",
+ "max_size": "",
+ "mime_types": ""
+ },
+ {
+ "key": "field_6023fc45e6edb",
+ "label": "Link",
+ "name": "link",
+ "type": "url",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": ""
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "page",
+ "operator": "==",
+ "value": "36"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": "",
+ "active": false,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfContactPage"
+ },
+ {
+ "key": "group_5fce89c5b3912",
+ "title": "Content Component",
+ "fields": [
+ {
+ "key": "field_5fce89ed0825f",
+ "label": "Headline",
+ "name": "headline",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_5fce89f808260",
+ "label": "Content",
+ "name": "content",
+ "type": "wysiwyg",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "tabs": "all",
+ "toolbar": "basic",
+ "media_upload": 0,
+ "delay": 0
+ },
+ {
+ "key": "field_6032c5cbdf717",
+ "label": "Columns",
+ "name": "list_columns",
+ "type": "true_false",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "message": "Display list items in columns",
+ "default_value": 0,
+ "ui": 0,
+ "ui_on_text": "",
+ "ui_off_text": ""
+ },
+ {
+ "key": "field_5fce8a1508261",
+ "label": "Section Link",
+ "name": "section_link",
+ "type": "link",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array"
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "post"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": [
+ "permalink",
+ "the_content",
+ "excerpt",
+ "discussion",
+ "comments",
+ "revisions",
+ "slug",
+ "author",
+ "format",
+ "page_attributes",
+ "featured_image",
+ "categories",
+ "tags",
+ "send-trackbacks"
+ ],
+ "active": false,
+ "description": "Headline + copy section",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfContentComponent"
+ },
+ {
+ "key": "group_5f7cbbc9a7b58",
+ "title": "Global Settings",
+ "fields": [
+ {
+ "key": "field_5f7cbbf28b673",
+ "label": "Logo",
+ "name": "logo",
+ "type": "image",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array",
+ "preview_size": "medium",
+ "library": "all",
+ "min_width": "",
+ "min_height": "",
+ "min_size": "",
+ "max_width": "",
+ "max_height": "",
+ "max_size": "",
+ "mime_types": ""
+ },
+ {
+ "key": "field_5fda2666e2179",
+ "label": "Login Link",
+ "name": "login_link",
+ "type": "link",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array"
+ },
+ {
+ "key": "field_5fda2618e2178",
+ "label": "Address",
+ "name": "address",
+ "type": "textarea",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "maxlength": "",
+ "rows": 4,
+ "new_lines": ""
+ },
+ {
+ "key": "field_6026dbc62e47f",
+ "label": "Fallback Meta Image",
+ "name": "fallback_meta_image",
+ "type": "image",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array",
+ "preview_size": "thumbnail",
+ "library": "all",
+ "min_width": "",
+ "min_height": "",
+ "min_size": "",
+ "max_width": "",
+ "max_height": "",
+ "max_size": "",
+ "mime_types": ""
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "options_page",
+ "operator": "==",
+ "value": "global-settings"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": [
+ "permalink",
+ "the_content",
+ "excerpt",
+ "discussion",
+ "comments",
+ "revisions",
+ "slug",
+ "author",
+ "format",
+ "page_attributes",
+ "featured_image",
+ "categories",
+ "tags",
+ "send-trackbacks"
+ ],
+ "active": true,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "globalSettings"
+ },
+ {
+ "key": "group_5f7e16238aedf",
+ "title": "Hero",
+ "fields": [
+ {
+ "key": "field_5f7e1632abb71",
+ "label": "Hero Image",
+ "name": "hero_image",
+ "type": "image",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array",
+ "preview_size": "medium",
+ "library": "all",
+ "min_width": "",
+ "min_height": "",
+ "min_size": "",
+ "max_width": "",
+ "max_height": "",
+ "max_size": "",
+ "mime_types": ""
+ },
+ {
+ "key": "field_5f7e1666abb72",
+ "label": "Hero Headline",
+ "name": "hero_headline",
+ "type": "text",
+ "instructions": "Add headline. You can wrap word(s) in <span class=\"yellow\"> to color them with LeJeune yellow",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_5fc7cc6579e9e",
+ "label": "Hero Sub Headline",
+ "name": "hero_sub_headline",
+ "type": "textarea",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "maxlength": "",
+ "rows": 4,
+ "new_lines": ""
+ },
+ {
+ "key": "field_5fc7cf6948369",
+ "label": "Has CTA",
+ "name": "has_cta",
+ "type": "true_false",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "33",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "message": "Include CTA?",
+ "default_value": 0,
+ "ui": 0,
+ "ui_on_text": "",
+ "ui_off_text": ""
+ },
+ {
+ "key": "field_5fce92774b177",
+ "label": "CTA Type",
+ "name": "cta_type",
+ "type": "select",
+ "instructions": "Choose Type of CTA",
+ "required": 0,
+ "conditional_logic": [
+ [
+ {
+ "field": "field_5fc7cf6948369",
+ "operator": "==",
+ "value": "1"
+ }
+ ]
+ ],
+ "wrapper": {
+ "width": "33",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "choices": {
+ "link": "Link",
+ "video": "Video"
+ },
+ "default_value": false,
+ "allow_null": 1,
+ "multiple": 0,
+ "ui": 0,
+ "return_format": "value",
+ "ajax": 0,
+ "placeholder": ""
+ },
+ {
+ "key": "field_5fc7cf874836a",
+ "label": "Hero Link",
+ "name": "link",
+ "type": "link",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": [
+ [
+ {
+ "field": "field_5fc7cf6948369",
+ "operator": "==",
+ "value": "1"
+ },
+ {
+ "field": "field_5fce92774b177",
+ "operator": "==",
+ "value": "link"
+ }
+ ]
+ ],
+ "wrapper": {
+ "width": "33",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array"
+ },
+ {
+ "key": "field_603e8b5421811",
+ "label": "Hero Video",
+ "name": "hero_video",
+ "type": "text",
+ "instructions": "Enter URL for hosted video",
+ "required": 0,
+ "conditional_logic": [
+ [
+ {
+ "field": "field_5fc7cf6948369",
+ "operator": "==",
+ "value": "1"
+ },
+ {
+ "field": "field_5fce92774b177",
+ "operator": "==",
+ "value": "video"
+ }
+ ]
+ ],
+ "wrapper": {
+ "width": "33",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "post"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": [
+ "permalink",
+ "the_content",
+ "excerpt",
+ "discussion",
+ "comments",
+ "revisions",
+ "slug",
+ "author",
+ "format",
+ "page_attributes",
+ "featured_image",
+ "categories",
+ "tags",
+ "send-trackbacks"
+ ],
+ "active": false,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfHero"
+ },
+ {
+ "key": "group_5fce85b420cd6",
+ "title": "Icons Component",
+ "fields": [
+ {
+ "key": "field_5fce864a0e510",
+ "label": "Headline",
+ "name": "headline",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_5fce865f0e511",
+ "label": "Icon Repeater",
+ "name": "icon_repeater",
+ "type": "repeater",
+ "instructions": "Create row of icons. IMPORTANT: Front-end only accepts SVG file type for output, so make sure to upload SVGs below.",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "collapsed": "field_5fce86860e512",
+ "min": 0,
+ "max": 0,
+ "layout": "block",
+ "button_label": "Add Icon",
+ "sub_fields": [
+ {
+ "key": "field_5fce869a0e513",
+ "label": "Icon",
+ "name": "icon",
+ "type": "image",
+ "instructions": "Upload an SVG",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "33.33",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array",
+ "preview_size": "thumbnail",
+ "library": "all",
+ "min_width": "",
+ "min_height": "",
+ "min_size": "",
+ "max_width": "",
+ "max_height": "",
+ "max_size": "",
+ "mime_types": "svg"
+ },
+ {
+ "key": "field_5fce86860e512",
+ "label": "Icon Title",
+ "name": "icon_title",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_lofgic": 0,
+ "wrapper": {
+ "width": "33.33",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_5fce86b60e514",
+ "label": "Icon Link",
+ "name": "icon_link",
+ "type": "link",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "33.33",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array"
+ }
+ ]
+ },
+ {
+ "key": "field_5fce86fd0e515",
+ "label": "Link Elsewhere",
+ "name": "link_elsewhere",
+ "type": "true_false",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "message": "Link to Another Page?",
+ "default_value": 0,
+ "ui": 0,
+ "ui_on_text": "",
+ "ui_off_text": ""
+ },
+ {
+ "key": "field_5fce87310e516",
+ "label": "Section Link",
+ "name": "section_link",
+ "type": "link",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": [
+ [
+ {
+ "field": "field_5fce86fd0e515",
+ "operator": "==",
+ "value": "1"
+ }
+ ]
+ ],
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array"
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "post"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": [
+ "permalink",
+ "the_content",
+ "excerpt",
+ "discussion",
+ "comments",
+ "revisions",
+ "slug",
+ "author",
+ "format",
+ "page_attributes",
+ "featured_image",
+ "categories",
+ "tags",
+ "send-trackbacks"
+ ],
+ "active": false,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfIconsComponent"
+ },
+ {
+ "key": "group_5fce9442d5581",
+ "title": "Multi Column Component",
+ "fields": [
+ {
+ "key": "field_5fcfb69aa763a",
+ "label": "Section Headline",
+ "name": "section_headline",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_5fce987f8d53c",
+ "label": "Section Link",
+ "name": "section_link",
+ "type": "link",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array"
+ },
+ {
+ "key": "field_5fcfb51507336",
+ "label": "Columns",
+ "name": "columns",
+ "type": "repeater",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "collapsed": "field_5fcfb56c07338",
+ "min": 2,
+ "max": 4,
+ "layout": "block",
+ "button_label": "Add Column",
+ "sub_fields": [
+ {
+ "key": "field_5fcfb55807337",
+ "label": "Image",
+ "name": "column_image",
+ "type": "image",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "33.33",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array",
+ "preview_size": "thumbnail",
+ "library": "all",
+ "min_width": "",
+ "min_height": "",
+ "min_size": "",
+ "max_width": "",
+ "max_height": "",
+ "max_size": "",
+ "mime_types": ""
+ },
+ {
+ "key": "field_5fcfb56c07338",
+ "label": "Title",
+ "name": "column_title",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "33.33",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_5fcfb5910733a",
+ "label": "Link",
+ "name": "column_link",
+ "type": "link",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "33.33",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array"
+ },
+ {
+ "key": "field_5fcfb57a07339",
+ "label": "Content",
+ "name": "column_content",
+ "type": "textarea",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "maxlength": "",
+ "rows": 4,
+ "new_lines": ""
+ }
+ ]
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "post"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": [
+ "permalink",
+ "the_content",
+ "excerpt",
+ "discussion",
+ "comments",
+ "revisions",
+ "slug",
+ "author",
+ "format",
+ "page_attributes",
+ "featured_image",
+ "categories",
+ "tags",
+ "send-trackbacks"
+ ],
+ "active": false,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfMultiColumnComponent"
+ },
+ {
+ "key": "group_5f7e17665ae67",
+ "title": "Page Builder",
+ "fields": [
+ {
+ "key": "field_5f7e1791756e9",
+ "label": "Components",
+ "name": "components",
+ "type": "flexible_content",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "layouts": {
+ "layout_5f7e1809d7739": {
+ "key": "layout_5f7e1809d7739",
+ "name": "hero",
+ "label": "Hero",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_5f7e182b756ea",
+ "label": "Hero",
+ "name": "hero",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5f7e16238aedf"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_5fce8a3da96a4": {
+ "key": "layout_5fce8a3da96a4",
+ "name": "content_section",
+ "label": "Content Section",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_60199058e70b6",
+ "label": "Layout and Style",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "placement": "top",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5fecf4118fd25",
+ "label": "Shade",
+ "name": "shade",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5fecf293ca9b2"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ },
+ {
+ "key": "field_60199109ec139",
+ "label": "Margins",
+ "name": "margins",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_60197b43a8abc"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ },
+ {
+ "key": "field_6019906ae70b7",
+ "label": "Content",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "placement": "top",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5fce8a47a96a5",
+ "label": "Content Section",
+ "name": "content_section",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "clone": [
+ "group_5fce89c5b3912"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_5fc7d1fe93bb2": {
+ "key": "layout_5fc7d1fe93bb2",
+ "name": "image_with_content",
+ "label": "Image with Content",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_60199078e70b8",
+ "label": "Layout and Style",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "placement": "top",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5fecf4c382f55",
+ "label": "Shade",
+ "name": "shade",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5fecf293ca9b2"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ },
+ {
+ "key": "field_60199132ec13a",
+ "label": "Margins",
+ "name": "margins",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_60197b43a8abc"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ },
+ {
+ "key": "field_6019908ae70b9",
+ "label": "Content",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "placement": "top",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5fc7d20a93bb3",
+ "label": "Image with Content",
+ "name": "imgWithContent",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "clone": [
+ "group_5fc7ca09bcb0f"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_5fce87677d38a": {
+ "key": "layout_5fce87677d38a",
+ "name": "icons_component",
+ "label": "Icons Component",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_60199094e70ba",
+ "label": "Layout and Style",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "placement": "top",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5fecf47082f52",
+ "label": "Shade",
+ "name": "shade",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5fecf293ca9b2"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ },
+ {
+ "key": "field_60199149ec13b",
+ "label": "Margins",
+ "name": "margins",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_60197b43a8abc"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ },
+ {
+ "key": "field_6019909fe70bb",
+ "label": "Content",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "placement": "top",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5fce87757d38b",
+ "label": "Icons Component",
+ "name": "iconsComponent",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5fce85b420cd6"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_5fce88d2e8d9e": {
+ "key": "layout_5fce88d2e8d9e",
+ "name": "background_image_with_text",
+ "label": "Background Image with Text",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_5fce88e6e8d9f",
+ "label": "Full Width Image",
+ "name": "full_width_image",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5fce88119bcf2"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_5fce96a2784f7": {
+ "key": "layout_5fce96a2784f7",
+ "name": "multi_column",
+ "label": "Multi Column with Image",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_60198fa3fa2be",
+ "label": "Layout and Style",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "placement": "top",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5fecf49782f53",
+ "label": "Shade",
+ "name": "shade",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5fecf293ca9b2"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ },
+ {
+ "key": "field_60197c263cffe",
+ "label": "Margins",
+ "name": "margins",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "clone": [
+ "group_60197b43a8abc"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ },
+ {
+ "key": "field_60198fc2fa2bf",
+ "label": "Content",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "placement": "top",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5fce96ad784f8",
+ "label": "Three Column",
+ "name": "three_column",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5fce9442d5581"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_5ff4c73f6860b": {
+ "key": "layout_5ff4c73f6860b",
+ "name": "multi_column_content",
+ "label": "Multi Column Content Only",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_601990b0e70bc",
+ "label": "Layout and Style",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "placement": "top",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5ff4c75b6860c",
+ "label": "Shade",
+ "name": "shade",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5fecf293ca9b2"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ },
+ {
+ "key": "field_60199171ec13c",
+ "label": "Margins",
+ "name": "margins",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_60197b43a8abc"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ },
+ {
+ "key": "field_601990b9e70bd",
+ "label": "Content",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "placement": "top",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5ff4c77c6860d",
+ "label": "Multi Column Content Only",
+ "name": "multi_column_content",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5ff4c66dc6cc3"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_5fea4e74f8566": {
+ "key": "layout_5fea4e74f8566",
+ "name": "stat_component",
+ "label": "Stat Component",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_601990c8e70be",
+ "label": "Layout and Style",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "placement": "top",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5fecf4ac82f54",
+ "label": "Shade",
+ "name": "shade",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5fecf293ca9b2"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ },
+ {
+ "key": "field_60199195ec13d",
+ "label": "Margins",
+ "name": "margins",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_60197b43a8abc"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ },
+ {
+ "key": "field_601990d2e70bf",
+ "label": "Content",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "placement": "top",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5fea4e84f8567",
+ "label": "Stat Component",
+ "name": "stat_component",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5fea4d8beff77"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_5feb5a68ccd5e": {
+ "key": "layout_5feb5a68ccd5e",
+ "name": "circular_image_row",
+ "label": "Circular Image Row",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_5feb5a89ccd5f",
+ "label": "Circular Image Row",
+ "name": "circular_image_row",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5feb58ee935c4"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_5ff369e0f7468": {
+ "key": "layout_5ff369e0f7468",
+ "name": "project_carousel_pages",
+ "label": "Project Carousel",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_5ff369edf7469",
+ "label": "Project Carousel",
+ "name": "project_carousel_pages",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5ff36850095be"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_60099d9bc9235": {
+ "key": "layout_60099d9bc9235",
+ "name": "projects",
+ "label": "Projects",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_60099dacc9236",
+ "label": "Projects",
+ "name": "projects",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5ff88c842f967"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_6023fc981cca3": {
+ "key": "layout_6023fc981cca3",
+ "name": "contact_page",
+ "label": "Contact Page",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_6023fca11cca4",
+ "label": "Contact Page",
+ "name": "contact_page",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_6023fa60f3606"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ }
+ },
+ "button_label": "Add Component",
+ "min": "",
+ "max": ""
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "page"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": [
+ "the_content",
+ "excerpt",
+ "discussion",
+ "comments",
+ "revisions",
+ "slug",
+ "author",
+ "format",
+ "featured_image",
+ "categories",
+ "tags",
+ "send-trackbacks"
+ ],
+ "active": true,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfPageBuilder"
+ },
+ {
+ "key": "group_60d109596e399",
+ "title": "Post Fields",
+ "fields": [
+ {
+ "key": "field_60d1096121224",
+ "label": "text",
+ "name": "text",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_60d1096821225",
+ "label": "image",
+ "name": "image",
+ "type": "image",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array",
+ "preview_size": "medium",
+ "library": "all",
+ "min_width": "",
+ "min_height": "",
+ "min_size": "",
+ "max_width": "",
+ "max_height": "",
+ "max_size": "",
+ "mime_types": ""
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "post"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": "",
+ "active": true,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "postFields",
+ "map_graphql_types_from_location_rules": 0,
+ "graphql_types": ""
+ },
+ {
+ "key": "group_5ff343799f06b",
+ "title": "Project Carousel",
+ "fields": [
+ {
+ "key": "field_5ff343ce9d131",
+ "label": "Project Name",
+ "name": "project_name",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_5ff349269bfb6",
+ "label": "Images",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 0,
+ "placement": "left",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5ff347be9d132",
+ "label": "Project Images",
+ "name": "project_images",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5fedf9c87fca8"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ },
+ {
+ "key": "field_5ff3493d9bfb7",
+ "label": "Details",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 0,
+ "placement": "left",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5ff347db9d133",
+ "label": "Project Details",
+ "name": "project_details",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5fedf8bf735af"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "post"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": "",
+ "active": false,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfProjectCarousel"
+ },
+ {
+ "key": "group_5ff36850095be",
+ "title": "Project Carousel for Pages",
+ "fields": [
+ {
+ "key": "field_5ffe15c033d7f",
+ "label": "Headline",
+ "name": "headline",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_5ff3687f3e1d6",
+ "label": "Featured Projects",
+ "name": "featured_projects",
+ "type": "relationship",
+ "instructions": "Select up to 5 projects to feature in carousel.",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "post_type": [
+ "project"
+ ],
+ "taxonomy": "",
+ "filters": [
+ "search",
+ "taxonomy"
+ ],
+ "elements": "",
+ "min": 1,
+ "max": 5,
+ "return_format": "object"
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "page"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": "",
+ "active": false,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfProjectCarouselPages"
+ },
+ {
+ "key": "group_5ff88c842f967",
+ "title": "Project Vertical",
+ "fields": [
+ {
+ "key": "field_60099e0ce46fa",
+ "label": "Title",
+ "name": "title",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_5ff88e7ecffd2",
+ "label": "Projects",
+ "name": "projects",
+ "type": "relationship",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "post_type": [
+ "project"
+ ],
+ "taxonomy": "",
+ "filters": [
+ "search",
+ "taxonomy"
+ ],
+ "elements": "",
+ "min": "",
+ "max": "",
+ "return_format": "object"
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "page"
+ },
+ {
+ "param": "page",
+ "operator": "==",
+ "value": "28"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": "",
+ "active": false,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfProjectVertical"
+ },
+ {
+ "key": "group_5fedfb4b1eadb",
+ "title": "Related Projects",
+ "fields": [
+ {
+ "key": "field_5fedfb5c0084c",
+ "label": "Related Projects",
+ "name": "related_projects",
+ "type": "relationship",
+ "instructions": "Choose up to six related projects",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "post_type": [
+ "project"
+ ],
+ "taxonomy": "",
+ "filters": [
+ "search",
+ "taxonomy"
+ ],
+ "elements": "",
+ "min": "",
+ "max": 2,
+ "return_format": "object"
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "project"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": "",
+ "active": false,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfRelatedProjects"
+ },
+ {
+ "key": "group_60087adf59a40",
+ "title": "Resource Builder",
+ "fields": [
+ {
+ "key": "field_60087b1fe0236",
+ "label": "Resource Builder",
+ "name": "resource_builder",
+ "type": "flexible_content",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "layouts": {
+ "layout_60087db2dd04c": {
+ "key": "layout_60087db2dd04c",
+ "name": "content",
+ "label": "Content",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_60087dbadd04d",
+ "label": "Content",
+ "name": "content",
+ "type": "wysiwyg",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "tabs": "all",
+ "toolbar": "full",
+ "media_upload": 1,
+ "delay": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_60087dd0dd04e": {
+ "key": "layout_60087dd0dd04e",
+ "name": "full_width_image",
+ "label": "Full Width Image",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_60087dd8dd04f",
+ "label": "Full Width Image",
+ "name": "full_width_image",
+ "type": "image",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array",
+ "preview_size": "thumbnail",
+ "library": "all",
+ "min_width": "",
+ "min_height": "",
+ "min_size": "",
+ "max_width": "",
+ "max_height": "",
+ "max_size": "",
+ "mime_types": ""
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_60087deedd050": {
+ "key": "layout_60087deedd050",
+ "name": "button",
+ "label": "Button",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_60087e19dd051",
+ "label": "Link Type",
+ "name": "link_type",
+ "type": "radio",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "choices": {
+ "link": "Link",
+ "file": "File"
+ },
+ "allow_null": 0,
+ "other_choice": 0,
+ "default_value": "",
+ "layout": "horizontal",
+ "return_format": "value",
+ "save_other_choice": 0
+ },
+ {
+ "key": "field_60087e57dd052",
+ "label": "Link",
+ "name": "link",
+ "type": "link",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": [
+ [
+ {
+ "field": "field_60087e19dd051",
+ "operator": "==",
+ "value": "link"
+ }
+ ]
+ ],
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array"
+ },
+ {
+ "key": "field_60087e65dd053",
+ "label": "File",
+ "name": "file",
+ "type": "file",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": [
+ [
+ {
+ "field": "field_60087e19dd051",
+ "operator": "==",
+ "value": "file"
+ }
+ ]
+ ],
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array",
+ "library": "all",
+ "min_size": "",
+ "max_size": "",
+ "mime_types": ""
+ },
+ {
+ "key": "field_60087e7bdd054",
+ "label": "Button Text",
+ "name": "button_text",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": [
+ [
+ {
+ "field": "field_60087e19dd051",
+ "operator": "==",
+ "value": "file"
+ }
+ ]
+ ],
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_60087f280d16c": {
+ "key": "layout_60087f280d16c",
+ "name": "related_resources",
+ "label": "Related Resources",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_60119f2dd43e3",
+ "label": "Headline",
+ "name": "headline",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_60087f320d16d",
+ "label": "Related Resources",
+ "name": "related_resources",
+ "type": "relationship",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "post_type": [
+ "resource"
+ ],
+ "taxonomy": "",
+ "filters": [
+ "search",
+ "taxonomy"
+ ],
+ "elements": "",
+ "min": "",
+ "max": 2,
+ "return_format": "object"
+ }
+ ],
+ "min": "",
+ "max": "1"
+ }
+ },
+ "button_label": "Add Component",
+ "min": "",
+ "max": ""
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "resource"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": [
+ "the_content",
+ "excerpt",
+ "discussion",
+ "comments",
+ "revisions",
+ "slug",
+ "author",
+ "format",
+ "featured_image",
+ "send-trackbacks"
+ ],
+ "active": true,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfResourceBuilder"
+ },
+ {
+ "key": "group_5fc7ca09bcb0f",
+ "title": "Side-by-Side Image\/Content",
+ "fields": [
+ {
+ "key": "field_5fc7ca1ff4fbc",
+ "label": "Image Upload",
+ "name": "image_upload",
+ "type": "image",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array",
+ "preview_size": "thumbnail",
+ "library": "all",
+ "min_width": "",
+ "min_height": "",
+ "min_size": "",
+ "max_width": "",
+ "max_height": "",
+ "max_size": "",
+ "mime_types": ""
+ },
+ {
+ "key": "field_5fc7ca9df4fbf",
+ "label": "Image Side",
+ "name": "image_side",
+ "type": "radio",
+ "instructions": "Choose which side the image will display",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "choices": {
+ "left": "Left",
+ "right": "Right"
+ },
+ "allow_null": 0,
+ "other_choice": 0,
+ "default_value": "left",
+ "layout": "horizontal",
+ "return_format": "value",
+ "save_other_choice": 0
+ },
+ {
+ "key": "field_5fc7ca67f4fbd",
+ "label": "Headline",
+ "name": "headline",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "Max 50 characters",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_5fc7ca85f4fbe",
+ "label": "Content",
+ "name": "content",
+ "type": "wysiwyg",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "tabs": "all",
+ "toolbar": "basic",
+ "media_upload": 0,
+ "delay": 0
+ },
+ {
+ "key": "field_5fc7d1452298a",
+ "label": "Link",
+ "name": "link",
+ "type": "link",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array"
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "post"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": "",
+ "active": false,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfImageContent"
+ },
+ {
+ "key": "group_5fea4d8beff77",
+ "title": "Stat Component",
+ "fields": [
+ {
+ "key": "field_5fea4daa5fd82",
+ "label": "Stats",
+ "name": "stats",
+ "type": "repeater",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "collapsed": "",
+ "min": 2,
+ "max": 4,
+ "layout": "table",
+ "button_label": "Add Stat",
+ "sub_fields": [
+ {
+ "key": "field_5fea4df55fd83",
+ "label": "Stat Count",
+ "name": "stat_count",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ },
+ {
+ "key": "field_5fea4e405fd84",
+ "label": "Stat Description",
+ "name": "stat_description",
+ "type": "text",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "default_value": "",
+ "placeholder": "",
+ "prepend": "",
+ "append": "",
+ "maxlength": ""
+ }
+ ]
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "page"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": "",
+ "active": false,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfStatComponent"
+ },
+ {
+ "key": "group_60197b43a8abc",
+ "title": "Vertical Margin",
+ "fields": [
+ {
+ "key": "field_60198a39174e9",
+ "label": "Margins",
+ "name": "margins",
+ "type": "group",
+ "instructions": "Provide vertical spacing outside section when needed.",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "layout": "block",
+ "sub_fields": [
+ {
+ "key": "field_60198a5d174ea",
+ "label": "Top Margin",
+ "name": "margin_top",
+ "type": "button_group",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "choices": {
+ "default": "Default (0px)",
+ "mt2": "25px",
+ "mt5": "50px",
+ "mt10": "100px"
+ },
+ "allow_null": 0,
+ "default_value": "default",
+ "layout": "horizontal",
+ "return_format": "value"
+ },
+ {
+ "key": "field_60198b26188a2",
+ "label": "Bottom Margin",
+ "name": "margin_bottom",
+ "type": "button_group",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "50",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "choices": {
+ "default": "Default (100px)",
+ "mb0": "0px",
+ "mb2": "25px",
+ "mb5": "50px"
+ },
+ "allow_null": 0,
+ "default_value": "default",
+ "layout": "horizontal",
+ "return_format": "value"
+ }
+ ]
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "post"
+ }
+ ]
+ ],
+ "menu_order": 0,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": "",
+ "active": false,
+ "description": "Options for vertical spacing",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfVerticalSpacing"
+ },
+ {
+ "key": "group_5fedf5817fcaa",
+ "title": "Project Builder",
+ "fields": [
+ {
+ "key": "field_5fedf5d16f777",
+ "label": "Components",
+ "name": "components",
+ "type": "flexible_content",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "layouts": {
+ "layout_5fedf5d9ecd19": {
+ "key": "layout_5fedf5d9ecd19",
+ "name": "hero",
+ "label": "Hero",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_5fedf5f56f778",
+ "label": "Hero",
+ "name": "hero",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5f7e16238aedf"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_5fedf6336f779": {
+ "key": "layout_5fedf6336f779",
+ "name": "content_section",
+ "label": "Content Section",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_601af7af227d7",
+ "label": "Layout and Style",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "placement": "top",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5fedf6416f77a",
+ "label": "Shade",
+ "name": "shade",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5fecf293ca9b2"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ },
+ {
+ "key": "field_601af7d5227d9",
+ "label": "Margins",
+ "name": "margins",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_60197b43a8abc"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ },
+ {
+ "key": "field_601af7bb227d8",
+ "label": "Content",
+ "name": "",
+ "type": "tab",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "placement": "top",
+ "endpoint": 0
+ },
+ {
+ "key": "field_5fedf6526f77b",
+ "label": "Content Section",
+ "name": "content_section",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5fce89c5b3912"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_5ff3480674076": {
+ "key": "layout_5ff3480674076",
+ "name": "project_carousel",
+ "label": "Project Carousel",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_5ff3480d74077",
+ "label": "Project Carousel",
+ "name": "project_carousel",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5ff343799f06b"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ },
+ "layout_5fedfc4d60e96": {
+ "key": "layout_5fedfc4d60e96",
+ "name": "related_projects",
+ "label": "Related Projects",
+ "display": "block",
+ "sub_fields": [
+ {
+ "key": "field_5fedfc5760e97",
+ "label": "Related Projects",
+ "name": "related_projects",
+ "type": "clone",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "clone": [
+ "group_5fedfb4b1eadb"
+ ],
+ "display": "seamless",
+ "layout": "block",
+ "prefix_label": 0,
+ "prefix_name": 0
+ }
+ ],
+ "min": "",
+ "max": ""
+ }
+ },
+ "button_label": "Add Component",
+ "min": "",
+ "max": ""
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "project"
+ }
+ ]
+ ],
+ "menu_order": 2,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": [
+ "the_content",
+ "excerpt",
+ "discussion",
+ "comments",
+ "revisions",
+ "slug",
+ "author",
+ "format",
+ "page_attributes",
+ "featured_image",
+ "categories",
+ "tags",
+ "send-trackbacks"
+ ],
+ "active": true,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfProjectBuilder"
+ },
+ {
+ "key": "group_5fedf9c87fca8",
+ "title": "Project Images",
+ "fields": [
+ {
+ "key": "field_5fedf9e086435",
+ "label": "Images",
+ "name": "images",
+ "type": "repeater",
+ "instructions": "Add images for project carousel",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "collapsed": "",
+ "min": 0,
+ "max": 0,
+ "layout": "row",
+ "button_label": "Add Image",
+ "sub_fields": [
+ {
+ "key": "field_5fedf9f286436",
+ "label": "Image",
+ "name": "image",
+ "type": "image",
+ "instructions": "",
+ "required": 0,
+ "conditional_logic": 0,
+ "wrapper": {
+ "width": "",
+ "class": "",
+ "id": ""
+ },
+ "show_in_graphql": 1,
+ "return_format": "array",
+ "preview_size": "thumbnail",
+ "library": "all",
+ "min_width": "",
+ "min_height": "",
+ "min_size": "",
+ "max_width": "",
+ "max_height": "",
+ "max_size": "",
+ "mime_types": ""
+ }
+ ]
+ }
+ ],
+ "location": [
+ [
+ {
+ "param": "post_type",
+ "operator": "==",
+ "value": "project"
+ }
+ ]
+ ],
+ "menu_order": 2,
+ "position": "normal",
+ "style": "default",
+ "label_placement": "top",
+ "instruction_placement": "label",
+ "hide_on_screen": "",
+ "active": false,
+ "description": "",
+ "show_in_graphql": 1,
+ "graphql_field_name": "acfProjectImages"
+ }
+]
diff --git a/tests/wpunit/AcfSettingsTest.php b/tests/wpunit/AcfSettingsTest.php
new file mode 100644
index 0000000..2b079f2
--- /dev/null
+++ b/tests/wpunit/AcfSettingsTest.php
@@ -0,0 +1,109 @@
+group_key = __CLASS__;
+ $this->clearSchema();
+ $this->register_acf_field_group();
+ parent::setUp();
+ // your set up methods here
+ }
+
+ public function tearDown(): void {
+ $this->deregister_acf_field_group();
+ // your tear down methods here
+ $this->clearSchema();
+ // then
+ parent::tearDown();
+ }
+
+ public function deregister_acf_field_group() {
+ acf_remove_local_field_group( $this->group_key );
+ }
+
+ public function register_acf_field_group( $config = [] ) {
+
+ $defaults = [
+ 'key' => $this->group_key,
+ 'title' => 'Post Object Fields',
+ 'fields' => [],
+ 'location' => [
+ [
+ [
+ 'param' => 'post_type',
+ 'operator' => '==',
+ 'value' => 'post',
+ ],
+ ],
+ ],
+ 'menu_order' => 0,
+ 'position' => 'normal',
+ 'style' => 'default',
+ 'label_placement' => 'top',
+ 'instruction_placement' => 'label',
+ 'hide_on_screen' => '',
+ 'active' => true,
+ 'description' => '',
+ 'show_in_graphql' => 1,
+ 'graphql_field_name' => 'postFieldsSettingsTest',
+ 'graphql_types' => [ 'Post' ]
+ ];
+
+ acf_add_local_field_group( array_merge( $defaults, $config ) );
+
+ }
+
+ public function register_acf_field( $config = [] ) {
+
+ $defaults = [
+ 'parent' => $this->group_key,
+ 'key' => 'field_5d7812ert5tg',
+ 'label' => 'Text',
+ 'name' => 'text',
+ 'type' => 'text',
+ 'instructions' => '',
+ 'required' => 0,
+ 'conditional_logic' => 0,
+ 'wrapper' => array(
+ 'width' => '',
+ 'class' => '',
+ 'id' => '',
+ ),
+ 'show_in_graphql' => 1,
+ 'default_value' => '',
+ 'placeholder' => '',
+ 'prepend' => '',
+ 'append' => '',
+ 'maxlength' => '',
+ ];
+
+ acf_add_local_field( array_merge( $defaults, $config ) );
+ }
+
+ public function testBuildFragmentFromIntrospection() {
+
+ $this->register_acf_field([
+ 'name' => 'textFieldTest',
+ 'type' => 'text',
+ ]);
+
+ $this->clearSchema();
+
+ $type_name = 'PostFieldsSettingsTest';
+ $settings = new \WPGraphQL\ACF\AcfSettings();
+ $fragment = $settings->get_graphql_type_from_introspection( $type_name );
+
+ codecept_debug( $fragment );
+
+ $this->assertSame( $type_name, $fragment['name'] );
+
+ }
+
+}
diff --git a/tests/wpunit/ClonedFieldsTest.php b/tests/wpunit/ClonedFieldsTest.php
new file mode 100644
index 0000000..da28fdf
--- /dev/null
+++ b/tests/wpunit/ClonedFieldsTest.php
@@ -0,0 +1,339 @@
+group_key = __CLASS__;
+ WPGraphQL::clear_schema();
+ $this->register_acf_field_group();
+
+ $this->post_id = $this->factory()->post->create( [
+ 'post_type' => 'post',
+ 'post_status' => 'publish',
+ 'post_title' => 'Test',
+ 'post_content' => 'test',
+ ] );
+
+ $this->test_image = dirname( __FILE__, 2 ) . '/_data/images/test.png';
+
+
+ }
+
+ public function tearDown(): void {
+
+ $this->deregister_acf_field_group();
+ WPGraphQL::clear_schema();
+ wp_delete_post( $this->post_id, true );
+ parent::tearDown(); // TODO: Change the autogenerated stub
+ }
+
+ public function deregister_acf_field_group() {
+ acf_remove_local_field_group( $this->group_key );
+ }
+
+ public function register_acf_field_group( $config = [] ) {
+
+ $defaults = [
+ 'key' => $this->group_key,
+ 'title' => 'Cloned Field Group',
+ 'fields' => [
+ [
+ 'key' => 'field_60abe262d31cd',
+ 'label' => 'text',
+ 'name' => 'text',
+ 'type' => 'text',
+ 'instructions' => '',
+ 'required' => 0,
+ 'conditional_logic' => 0,
+ 'wrapper' => [
+ 'width' => '',
+ 'class' => '',
+ 'id' => '',
+ ],
+ 'show_in_graphql' => 1,
+ 'default_value' => '',
+ 'placeholder' => '',
+ 'prepend' => '',
+ 'append' => '',
+ 'maxlength' => '',
+ ],
+ [
+ 'key' => 'field_60abe267d31ce',
+ 'label' => 'Image',
+ 'name' => 'image',
+ 'type' => 'image',
+ 'instructions' => '',
+ 'required' => 0,
+ 'conditional_logic' => 0,
+ 'wrapper' => [
+ 'width' => '',
+ 'class' => '',
+ 'id' => '',
+ ],
+ 'show_in_graphql' => 1,
+ 'return_format' => 'array',
+ 'preview_size' => 'medium',
+ 'library' => 'all',
+ 'min_width' => '',
+ 'min_height' => '',
+ 'min_size' => '',
+ 'max_width' => '',
+ 'max_height' => '',
+ 'max_size' => '',
+ 'mime_types' => '',
+ ],
+ [
+ 'key' => 'field_60abe26ed31cf',
+ 'label' => 'color',
+ 'name' => 'color',
+ 'type' => 'color_picker',
+ 'instructions' => '',
+ 'required' => 0,
+ 'conditional_logic' => 0,
+ 'wrapper' => [
+ 'width' => '',
+ 'class' => '',
+ 'id' => '',
+ ],
+ 'show_in_graphql' => 1,
+ 'default_value' => '',
+ ],
+ ],
+ 'location' => [
+ [
+ [
+ 'param' => 'post_type',
+ 'operator' => '==',
+ 'value' => 'post',
+ ],
+ ],
+ ],
+ 'menu_order' => 0,
+ 'position' => 'normal',
+ 'style' => 'default',
+ 'label_placement' => 'top',
+ 'instruction_placement' => 'label',
+ 'hide_on_screen' => '',
+ 'active' => false,
+ 'description' => '',
+ 'show_in_graphql' => 1,
+ 'graphql_field_name' => 'cloneGroup',
+ 'graphql_types' => '',
+ 'map_graphql_types_from_location_rules' => false,
+ ];
+
+ acf_add_local_field_group( array_merge( $defaults, $config ) );
+
+ }
+
+ public function register_acf_field( $config = [] ) {
+
+ $defaults = [
+ 'parent' => $this->group_key,
+ 'key' => 'field_5d7812fd000a4',
+ 'label' => 'Text',
+ 'name' => 'text',
+ 'type' => 'text',
+ 'instructions' => '',
+ 'required' => 0,
+ 'conditional_logic' => 0,
+ 'wrapper' => array(
+ 'width' => '',
+ 'class' => '',
+ 'id' => '',
+ ),
+ 'show_in_graphql' => 1,
+ 'default_value' => '',
+ 'placeholder' => '',
+ 'prepend' => '',
+ 'append' => '',
+ 'maxlength' => '',
+ ];
+
+ acf_add_local_field( array_merge( $defaults, $config ) );
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function testBasicQuery() {
+ $query = '{ posts { nodes { id } } }';
+ $actual = graphql( [ 'query' => $query ] );
+ $this->assertArrayNotHasKey( 'errors', $actual );
+ }
+
+ public function test_cloned_field_group_exists_in_schema() {
+
+ $this->register_acf_field([
+ 'name' => 'text_field_clone_test',
+ 'type' => 'text',
+ ]);
+
+ $query = '
+ query getType( $name: String! ){
+ __type(name: $name) {
+ name
+ kind
+ fields {
+ name
+ type {
+ kind
+ }
+ }
+ }
+ }
+ ';
+
+ $name = 'CloneGroup';
+
+ $actual = graphql([
+ 'query' => $query,
+ 'variables' => [
+ 'name' => $name
+ ]
+ ]);
+
+ codecept_debug( $actual );
+
+ $this->assertArrayNotHasKey( 'errors', $actual );
+ $this->assertSame( $name, $actual['data']['__type']['name'] );
+
+ }
+
+ public function testFieldGroupWithClonedFieldsIsQueryable() {
+
+ // Register a field to the clone field group
+ $this->register_acf_field([
+ 'name' => 'text_field_clone_test',
+ 'type' => 'text',
+ ]);
+
+ // Register a new field group, which sets it's fields
+ // as a clone of the clone field group
+ $this->register_acf_field_group([
+ 'key' => 'group_60abfd20a6b4e',
+ 'title' => 'Post Group With Clone Fields',
+ 'fields' => array(
+ array(
+ 'key' => 'field_60abfd2d03112',
+ 'label' => 'clone',
+ 'name' => 'clone',
+ 'type' => 'clone',
+ 'instructions' => '',
+ 'required' => 0,
+ 'conditional_logic' => 0,
+ 'wrapper' => array(
+ 'width' => '',
+ 'class' => '',
+ 'id' => '',
+ ),
+ 'show_in_graphql' => 1,
+ 'clone' => array(
+ 0 => $this->group_key,
+ ),
+ 'display' => 'seamless',
+ 'layout' => 'block',
+ 'prefix_label' => 0,
+ 'prefix_name' => 0,
+ ),
+ ),
+ 'location' => array(
+ array(
+ array(
+ 'param' => 'post_type',
+ 'operator' => '==',
+ 'value' => 'post',
+ ),
+ ),
+ ),
+ 'menu_order' => 0,
+ 'position' => 'normal',
+ 'style' => 'default',
+ 'label_placement' => 'top',
+ 'instruction_placement' => 'label',
+ 'hide_on_screen' => '',
+ 'active' => true,
+ 'description' => '',
+ 'show_in_graphql' => true,
+ 'graphql_field_name' => 'postGroupWithCloneFields',
+ 'map_graphql_types_from_location_rules' => 0,
+ 'graphql_types' => '',
+ ]);
+
+ // Query to make sure the field we registered to the clone field group
+ // shows in the Schema
+ $query = '
+ query getType( $name: String! ){
+ __type(name: $name) {
+ name
+ kind
+ fields {
+ name
+ type {
+ kind
+ }
+ }
+ }
+ }
+ ';
+
+ $name = 'PostGroupWithCloneFields';
+
+ $actual = graphql([
+ 'query' => $query,
+ 'variables' => [
+ 'name' => $name
+ ]
+ ]);
+
+ codecept_debug( $actual );
+
+ $this->assertArrayNotHasKey( 'errors', $actual );
+ $this->assertSame( $name, $actual['data']['__type']['name'] );
+ $field_names = wp_list_pluck( $actual['data']['__type']['fields'], 'name' );
+
+ // Test to make sure the field we just registered exists in the Schema on the `PostGroupWithCloneFields` type
+ $this->assertTrue( in_array( 'textFieldCloneTest', $field_names, true ) );
+
+ $query = '
+ query getPostById( $id: ID! ) {
+ post(id:$id idType:DATABASE_ID) {
+ databaseId
+ postGroupWithCloneFields {
+ textFieldCloneTest
+ }
+ }
+ }
+ ';
+
+ // Update the ACF field value
+ $value = 'test value';
+ update_field( 'text_field_clone_test', $value, $this->post_id );
+
+ // Query the field group that has cloned fields assigned to it
+ $actual = graphql([
+ 'query' => $query,
+ 'variables' => [
+ 'id' => $this->post_id,
+ ]
+ ]);
+
+ codecept_debug( $actual );
+
+ delete_field( 'text_field_clone_test', $this->post_id );
+
+ // Assert that the value of the clone field is returned
+ $this->assertArrayNotHasKey( 'errors', $actual );
+ $this->assertSame( $value, $actual['data']['post']['postGroupWithCloneFields']['textFieldCloneTest'] );
+
+ acf_remove_local_field_group( 'group_60abfd20a6b4e' );
+ }
+
+}
diff --git a/tests/wpunit/ComplexFlexAndCloneFieldsTest.php b/tests/wpunit/ComplexFlexAndCloneFieldsTest.php
new file mode 100644
index 0000000..2cc45e3
--- /dev/null
+++ b/tests/wpunit/ComplexFlexAndCloneFieldsTest.php
@@ -0,0 +1,232 @@
+import_field_groups( $this->import_file );
+
+ $this->group_key = __CLASS__;
+ WPGraphQL::clear_schema();
+
+ $this->post_id = $this->factory()->post->create( [
+ 'post_type' => 'post',
+ 'post_status' => 'publish',
+ 'post_title' => 'Test',
+ 'post_content' => 'test',
+ ] );
+
+ $this->page_id = $this->factory()->post->create( [
+ 'post_type' => 'page',
+ 'post_status' => 'publish',
+ 'post_title' => 'Test Page',
+ 'post_content' => 'test Page Content...',
+ ] );
+
+ $this->test_image = dirname( __FILE__, 2 ) . '/_data/images/test.png';
+
+
+ }
+
+ public function tearDown(): void {
+
+ $this->remove_imported_acf_field_groups();
+
+ WPGraphQL::clear_schema();
+ wp_delete_post( $this->post_id, true );
+ parent::tearDown(); // TODO: Change the autogenerated stub
+ }
+
+ public function remove_imported_acf_field_groups() {
+
+ if ( ! empty( $this->imported_group_ids ) ) {
+ foreach ( $this->imported_group_ids as $id ) {
+ acf_delete_field_group( $id );
+ }
+ }
+ }
+
+ public function import_field_groups( string $import_file ) {
+
+ $file = dirname( __FILE__, 2 ) . '/_data/field-group-exports/' . $import_file ;
+
+ $json = file_get_contents( $file );
+ $json = json_decode( $json, true );
+
+ if( ! $json || !is_array($json) ) {
+ codecept_debug( 'Cannot import ' . $file );
+ }
+
+ // Ensure $json is an array of groups.
+ if( isset($json['key']) ) {
+ $json = array( $json );
+ }
+
+ // Loop over json
+ foreach( $json as $field_group ) {
+
+ // Import field group.
+ $imported_field_group = acf_import_field_group( $field_group );
+
+ // append message
+ $this->imported_group_ids[] = $imported_field_group['ID'];
+ }
+
+ // Count number of imported field groups.
+ $total = count($this->imported_group_ids);
+
+ // Generate text.
+ $text = sprintf( _n( 'Imported 1 field group', 'Imported %s field groups', $total, 'acf' ), $total );
+ codecept_debug( $text );
+
+ }
+
+ public function deregister_acf_field_group() {
+ acf_delete_field_group( $this->group_key );
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function testBasicQuery() {
+ $query = '{ posts { nodes { id } } }';
+ $actual = graphql( [ 'query' => $query ] );
+ $this->assertArrayNotHasKey( 'errors', $actual );
+ }
+
+ public function testPageBuilderQuery() {
+
+ $hero_fragment = '
+ fragment Hero on With_AcfHero_Fields {
+ heroImage {
+ node {
+ databaseId
+ }
+ }
+ heroHeadline
+ heroSubHeadline
+ hasCta
+ ctaType
+ link {
+ url
+ }
+ heroVideo
+ }
+ ';
+
+ $shade_fragment = '
+ fragment Shade on With_AcfBackgroundShade_Fields {
+ shade
+ }
+ ';
+
+ $margins_fragment = '
+ fragment Margins on With_AcfVerticalSpacing_Fields {
+ margins {
+ marginTop
+ marginBottom
+ }
+ }
+ ';
+
+ $query = '
+ query GetPage( $id:ID! ) {
+ page(id: $id idType: DATABASE_ID) {
+ id
+ title
+ acfPageBuilder {
+ componentNames: components {
+ __typename
+ }
+ components {
+ __typename
+ ...Hero
+ ...Shade
+ ...Margins
+ }
+ }
+ }
+ }
+ ' . $hero_fragment . '
+ ' . $shade_fragment . '
+ ' . $margins_fragment . '
+ ';
+
+//
+// $margins_fragment = '
+// fragment Margins on With_AcfVerticalSpacing_Fields {
+// margins {
+// marginTop
+// marginBottom
+// }
+// }
+// ';
+//
+// $content_component_fragment = '
+// fragment Content on With_AcfContentComponent_Fields {
+// headline
+// content
+// listColumns
+// sectionLink {
+// url
+// }
+// }
+// ';
+//
+// $content_section_fragment = '
+// fragment ContentSection on AcfPageBuilderContentSection {
+// shade
+// ...Margins
+// ...Content
+// }
+// ';
+//
+// $page_builder_fragment = '
+// fragment PageBuilder on With_AcfPageBuilder {
+// pageBuilder {
+// components {
+// ...Hero
+// ...ContentSection
+// }
+// }
+// }
+// ';
+//
+// $query = '
+// {
+// page( id: $id idType: DATABASE_ID ) {
+// id
+// databaseId
+// ...PageBuilder
+// }
+// }
+// '. $page_builder_fragment .'
+// '. $content_section_fragment .'
+// '. $content_component_fragment .'
+// '. $margins_fragment .'
+// '. $hero_fragment .'
+// ';
+//
+ $actual = graphql([
+ 'query' => $query,
+ 'variables' => [
+ 'id' => $this->page_id,
+ ]
+ ]);
+
+ codecept_debug( $actual );
+
+ $this->assertArrayNotHasKey( 'errors', $actual );
+
+ }
+
+}
diff --git a/tests/wpunit/FieldGroupTest.php b/tests/wpunit/FieldGroupTest.php
new file mode 100644
index 0000000..443f8cd
--- /dev/null
+++ b/tests/wpunit/FieldGroupTest.php
@@ -0,0 +1,114 @@
+group_key = __CLASS__;
+ WPGraphQL::clear_schema();
+ $this->register_acf_field_group();
+
+ $this->post_id = $this->factory()->post->create( [
+ 'post_type' => 'post',
+ 'post_status' => 'publish',
+ 'post_title' => 'Test',
+ 'post_content' => 'test',
+ ] );
+
+ $this->test_image = dirname( __FILE__, 2 ) . '/_data/images/test.png';
+
+
+ }
+
+ public function tearDown(): void {
+
+ $this->deregister_acf_field_group();
+ WPGraphQL::clear_schema();
+ wp_delete_post( $this->post_id, true );
+ parent::tearDown(); // TODO: Change the autogenerated stub
+ }
+
+ public function deregister_acf_field_group() {
+ acf_remove_local_field_group( $this->group_key );
+ }
+
+ public function register_acf_field_group( $config = [] ) {
+
+ $defaults = [
+ 'key' => $this->group_key,
+ 'title' => 'Post Object Fields',
+ 'fields' => [],
+ 'location' => [
+ [
+ [
+ 'param' => 'post_type',
+ 'operator' => '==',
+ 'value' => 'post',
+ ],
+ ],
+ ],
+ 'menu_order' => 0,
+ 'position' => 'normal',
+ 'style' => 'default',
+ 'label_placement' => 'top',
+ 'instruction_placement' => 'label',
+ 'hide_on_screen' => '',
+ 'active' => true,
+ 'description' => '',
+ 'show_in_graphql' => 1,
+ 'graphql_field_name' => 'postFields',
+ 'graphql_types' => [ 'Post' ]
+ ];
+
+ acf_add_local_field_group( array_merge( $defaults, $config ) );
+
+ }
+
+ public function register_acf_field( $config = [] ) {
+
+ $defaults = [
+ 'parent' => $this->group_key,
+ 'key' => 'field_5d7812fd000a4',
+ 'label' => 'Text',
+ 'name' => 'text',
+ 'type' => 'text',
+ 'instructions' => '',
+ 'required' => 0,
+ 'conditional_logic' => 0,
+ 'wrapper' => array(
+ 'width' => '',
+ 'class' => '',
+ 'id' => '',
+ ),
+ 'show_in_graphql' => 1,
+ 'default_value' => '',
+ 'placeholder' => '',
+ 'prepend' => '',
+ 'append' => '',
+ 'maxlength' => '',
+ ];
+
+ acf_add_local_field( array_merge( $defaults, $config ) );
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function testBasicQuery() {
+ $query = '{ posts { nodes { id } } }';
+ $actual = graphql( [ 'query' => $query ] );
+ $this->assertArrayNotHasKey( 'errors', $actual );
+ }
+
+ public function test_query_flex_field_on_post() {
+
+ }
+
+}
diff --git a/tests/wpunit/FlexFieldsTest.php b/tests/wpunit/FlexFieldsTest.php
new file mode 100644
index 0000000..fa1dfba
--- /dev/null
+++ b/tests/wpunit/FlexFieldsTest.php
@@ -0,0 +1,298 @@
+group_key = __CLASS__;
+ WPGraphQL::clear_schema();
+ $this->register_acf_field_group();
+
+ $this->post_id = $this->factory()->post->create( [
+ 'post_type' => 'post',
+ 'post_status' => 'publish',
+ 'post_title' => 'Test',
+ 'post_content' => 'test',
+ ] );
+
+ $this->test_image = dirname( __FILE__, 2 ) . '/_data/images/test.png';
+
+
+ }
+
+ public function tearDown(): void {
+
+ $this->deregister_acf_field_group();
+ WPGraphQL::clear_schema();
+ wp_delete_post( $this->post_id, true );
+ parent::tearDown(); // TODO: Change the autogenerated stub
+ }
+
+ public function deregister_acf_field_group() {
+ acf_remove_local_field_group( $this->group_key );
+ }
+
+ public function register_acf_field_group( $config = [] ) {
+
+ $defaults = [
+ 'key' => $this->group_key,
+ 'title' => 'Post Object Fields',
+ 'fields' => [],
+ 'location' => [
+ [
+ [
+ 'param' => 'post_type',
+ 'operator' => '==',
+ 'value' => 'post',
+ ],
+ ],
+ ],
+ 'menu_order' => 0,
+ 'position' => 'normal',
+ 'style' => 'default',
+ 'label_placement' => 'top',
+ 'instruction_placement' => 'label',
+ 'hide_on_screen' => '',
+ 'active' => true,
+ 'description' => '',
+ 'show_in_graphql' => 1,
+ 'graphql_field_name' => 'postFields',
+ 'graphql_types' => [ 'Post' ]
+ ];
+
+ acf_add_local_field_group( array_merge( $defaults, $config ) );
+
+ }
+
+ public function register_acf_field( $config = [] ) {
+
+ $defaults = [
+ 'parent' => $this->group_key,
+ 'key' => 'field_5d7812fd0789678',
+ 'label' => 'Text',
+ 'name' => 'text',
+ 'type' => 'text',
+ 'instructions' => '',
+ 'required' => 0,
+ 'conditional_logic' => 0,
+ 'wrapper' => array(
+ 'width' => '',
+ 'class' => '',
+ 'id' => '',
+ ),
+ 'show_in_graphql' => 1,
+ 'default_value' => '',
+ 'placeholder' => '',
+ 'prepend' => '',
+ 'append' => '',
+ 'maxlength' => '',
+ ];
+
+ acf_add_local_field( array_merge( $defaults, $config ) );
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function testBasicQuery() {
+ $query = '{ posts { nodes { id } } }';
+ $actual = graphql( [ 'query' => $query ] );
+ $this->assertArrayNotHasKey( 'errors', $actual );
+ }
+
+ public function test_query_flex_field_on_post() {
+
+ $this->register_acf_field([
+ 'key' => 'field_flex_12345',
+ 'type' => 'flexible_content',
+ 'name' => 'flex_field',
+ 'layouts' => [
+ 'layout_60a6eec68967' => array(
+ 'key' => 'layout_60a6eec68967',
+ 'name' => 'layout_one',
+ 'label' => 'Layout One',
+ 'display' => 'block',
+ 'sub_fields' => array(
+ array(
+ 'key' => 'field_60a6eec4566',
+ 'label' => 'text',
+ 'name' => 'text',
+ 'type' => 'text',
+ 'instructions' => '',
+ 'required' => 0,
+ 'conditional_logic' => 0,
+ 'wrapper' => array(
+ 'width' => '',
+ 'class' => '',
+ 'id' => '',
+ ),
+ 'show_in_graphql' => 1,
+ 'default_value' => '',
+ 'placeholder' => '',
+ 'prepend' => '',
+ 'append' => '',
+ 'maxlength' => '',
+ ),
+ array(
+ 'key' => 'field_60a6eee67866',
+ 'label' => 'Image',
+ 'name' => 'image',
+ 'type' => 'image',
+ 'instructions' => '',
+ 'required' => 0,
+ 'conditional_logic' => 0,
+ 'wrapper' => array(
+ 'width' => '',
+ 'class' => '',
+ 'id' => '',
+ ),
+ 'show_in_graphql' => 1,
+ 'return_format' => 'array',
+ 'preview_size' => 'medium',
+ 'library' => 'all',
+ 'min_width' => '',
+ 'min_height' => '',
+ 'min_size' => '',
+ 'max_width' => '',
+ 'max_height' => '',
+ 'max_size' => '',
+ 'mime_types' => '',
+ ),
+ ),
+ 'min' => '',
+ 'max' => '',
+ ),
+ 'layout_60a6eee6567687' => [
+ 'key' => 'layout_60a6eee6567687',
+ 'name' => 'layout_two',
+ 'label' => 'Layout Two',
+ 'display' => 'block',
+ 'sub_fields' => [
+ [
+ 'key' => 'field_60a6eee345453',
+ 'label' => 'Gallery',
+ 'name' => 'gallery',
+ 'type' => 'gallery',
+ 'instructions' => '',
+ 'required' => 0,
+ 'conditional_logic' => 0,
+ 'wrapper' => [
+ 'width' => '',
+ 'class' => '',
+ 'id' => '',
+ ],
+ 'show_in_graphql' => 1,
+ 'return_format' => 'array',
+ 'preview_size' => 'medium',
+ 'insert' => 'append',
+ 'library' => 'all',
+ 'min' => '',
+ 'max' => '',
+ 'min_width' => '',
+ 'min_height' => '',
+ 'min_size' => '',
+ 'max_width' => '',
+ 'max_height' => '',
+ 'max_size' => '',
+ 'mime_types' => '',
+ ],
+ ],
+ 'min' => '',
+ 'max' => '',
+ ],
+ ],
+ 'button_label' => 'Add Row',
+ 'min' => '',
+ 'max' => '',
+ ]);
+
+ $query = '
+ query post($id: ID!) {
+ post(id: $id, idType: DATABASE_ID) {
+ id
+ databaseId
+ postFields {
+ flexField {
+ __typename
+ ...LayoutOne
+ ...LayoutTwo
+ }
+ }
+ }
+ }
+
+ fragment LayoutOne on PostFields_FlexField_LayoutOne {
+ text
+ image {
+ node {
+ __typename
+ databaseId
+ }
+ }
+ }
+
+ fragment LayoutTwo on PostFields_FlexField_LayoutTwo {
+ gallery {
+ nodes {
+ __typename
+ databaseId
+ }
+ }
+ }
+ ';
+
+ $gallery_ids = [];
+ $image_id = $this->factory()->attachment->create();
+ $gallery_ids[] = $this->factory()->attachment->create();
+ $gallery_ids[] = $this->factory()->attachment->create();
+
+ // Update the Flex Field data
+ update_field( 'flex_field', [
+ [
+ 'acf_fc_layout' => 'layout_one',
+ 'image' => $image_id,
+ 'text' => 'Some Example Text...'
+ ],
+ [
+ 'acf_fc_layout' => 'layout_two',
+ 'gallery' => $gallery_ids,
+ ]
+ ], $this->post_id );
+
+ codecept_debug( get_post_custom( $this->post_id ));
+
+ $actual = graphql([
+ 'query' => $query,
+ 'variables' => [
+ 'id' => $this->post_id,
+ ],
+ ]);
+
+ codecept_debug( $actual );
+
+ $this->assertArrayNotHasKey( 'errors', $actual );
+ $this->assertSame( $this->post_id, $actual['data']['post']['databaseId'] );
+
+ // Assert that there are 2 rows of flex fields
+ $this->assertSame( 2, count( $actual['data']['post']['postFields']['flexField'] ) );
+
+
+ // Assert the first layout values
+ $this->assertSame( 'Some Example Text...', $actual['data']['post']['postFields']['flexField'][0]['text'] );
+ $this->assertSame( $image_id, $actual['data']['post']['postFields']['flexField'][0]['image']['node']['databaseId'] );
+
+ // Assert the 2nd layout values
+ $this->assertSame( $gallery_ids[0], $actual['data']['post']['postFields']['flexField'][1]['gallery']['nodes'][0]['databaseId'] );
+ $this->assertSame( $gallery_ids[1], $actual['data']['post']['postFields']['flexField'][1]['gallery']['nodes'][1]['databaseId'] );
+
+
+ }
+
+}
diff --git a/tests/wpunit/LocationRulesTest.php b/tests/wpunit/LocationRulesTest.php
index 3a3b2fc..28589eb 100644
--- a/tests/wpunit/LocationRulesTest.php
+++ b/tests/wpunit/LocationRulesTest.php
@@ -799,7 +799,7 @@ public function testOnlyFieldGroupsSetToShowInGraphqlAreInTheSchema() {
// showInGraphqlTest should be queryable against the Post type in the Schema
$this->assertSame( $post_id, $actual['data']['post']['databaseId'] );
- $this->assertSame( 'Post_Showingraphqltest', $actual['data']['post']['showInGraphqlTest']['__typename'] );
+ $this->assertSame( 'ShowInGraphqlTest', $actual['data']['post']['showInGraphqlTest']['__typename'] );
acf_remove_local_field_group( 'doNotShowInGraphQL' );
acf_remove_local_field_group( 'showInGraphqlTest' );
diff --git a/tests/wpunit/PostObjectFieldsTest.php b/tests/wpunit/PostObjectFieldsTest.php
index 13d8d0e..d8fbb32 100644
--- a/tests/wpunit/PostObjectFieldsTest.php
+++ b/tests/wpunit/PostObjectFieldsTest.php
@@ -145,7 +145,6 @@ public function testAcfTextField() {
$this->assertSame( $expected_text_1, $actual['data']['postBy']['postFields']['textField'] );
-
}
/**
@@ -411,11 +410,13 @@ public function testQueryImageField() {
title
postFields {
imageField {
- mediaItemId
- thumbnail: sourceUrl(size: THUMBNAIL)
- medium: sourceUrl(size: MEDIUM)
- full: sourceUrl(size: LARGE)
- sourceUrl
+ node {
+ mediaItemId
+ thumbnail: sourceUrl(size: THUMBNAIL)
+ medium: sourceUrl(size: MEDIUM)
+ full: sourceUrl(size: LARGE)
+ sourceUrl
+ }
}
}
}
@@ -437,7 +438,7 @@ public function testQueryImageField() {
'medium' => wp_get_attachment_image_src( $img_id, 'medium' )[0],
'full' => wp_get_attachment_image_src( $img_id, 'full' )[0],
'sourceUrl' => wp_get_attachment_image_src( $img_id, 'full' )[0]
- ], $actual['data']['postBy']['postFields']['imageField'] );
+ ], $actual['data']['postBy']['postFields']['imageField']['node'] );
}
@@ -464,8 +465,10 @@ public function testQueryFileField() {
title
postFields {
fileField {
- mediaItemId
- sourceUrl
+ node {
+ mediaItemId
+ sourceUrl
+ }
}
}
}
@@ -484,7 +487,7 @@ public function testQueryFileField() {
$this->assertEquals( [
'mediaItemId' => $img_id,
'sourceUrl' => wp_get_attachment_image_src( $img_id, 'full' )[0]
- ], $actual['data']['postBy']['postFields']['fileField'] );
+ ], $actual['data']['postBy']['postFields']['fileField']['node'] );
}
@@ -603,8 +606,10 @@ public function testQueryGalleryField() {
title
postFields {
galleryField {
- mediaItemId
- sourceUrl
+ nodes {
+ mediaItemId
+ sourceUrl
+ }
}
}
}
@@ -628,8 +633,32 @@ public function testQueryGalleryField() {
[
'mediaItemId' => $img_id_2,
'sourceUrl' => wp_get_attachment_image_src( $img_id_2, 'full' )[0]
- ]
- ], $actual['data']['postBy']['postFields']['galleryField'] );
+ ],
+ ], $actual['data']['postBy']['postFields']['galleryField']['nodes'] );
+
+ $img_ids = [ $img_id_2, $img_id_1 ];
+ update_field( 'gallery_field', $img_ids, $this->post_id );
+
+ $actual = graphql([
+ 'query' => $query,
+ 'variables' => [
+ 'postId' => $this->post_id,
+ ],
+ ]);
+
+ codecept_debug( $actual );
+
+ $this->assertArrayNotHasKey( 'errors', $actual );
+ $this->assertSame( [
+ [
+ 'mediaItemId' => $img_id_2,
+ 'sourceUrl' => wp_get_attachment_image_src( $img_id_2, 'full' )[0]
+ ],
+ [
+ 'mediaItemId' => $img_id_1,
+ 'sourceUrl' => wp_get_attachment_image_src( $img_id_1, 'full' )[0]
+ ],
+ ], $actual['data']['postBy']['postFields']['galleryField']['nodes'] );
}
@@ -911,12 +940,14 @@ public function testQueryPostObjectField() {
title
postFields {
postObjectField {
- __typename
- ...on Post {
- postId
- }
- ...on Page {
- pageId
+ node {
+ __typename
+ ...on Post {
+ postId
+ }
+ ...on Page {
+ pageId
+ }
}
}
}
@@ -936,7 +967,7 @@ public function testQueryPostObjectField() {
$this->assertSame( [
'__typename' => 'Post',
'postId' => $post_id,
- ], $actual['data']['postBy']['postFields']['postObjectField'] );
+ ], $actual['data']['postBy']['postFields']['postObjectField']['node'] );
}
@@ -962,12 +993,14 @@ public function testQueryPostObjectFieldWithPage() {
title
postFields {
postObjectField {
- __typename
- ...on Post {
- postId
- }
- ...on Page {
- pageId
+ node {
+ __typename
+ ...on Post {
+ postId
+ }
+ ...on Page {
+ pageId
+ }
}
}
}
@@ -987,7 +1020,7 @@ public function testQueryPostObjectFieldWithPage() {
$this->assertSame( [
'__typename' => 'Page',
'pageId' => $page_id,
- ], $actual['data']['postBy']['postFields']['postObjectField'] );
+ ], $actual['data']['postBy']['postFields']['postObjectField']['node'] );
}
@@ -1017,9 +1050,11 @@ public function testQueryPageLinkField() {
title
postFields {
pageLinkField {
- __typename
- ...on Post {
- postId
+ node {
+ __typename
+ ...on Post {
+ postId
+ }
}
}
}
@@ -1039,7 +1074,7 @@ public function testQueryPageLinkField() {
$this->assertSame( [
'__typename' => 'Post',
'postId' => $id,
- ], $actual['data']['postBy']['postFields']['pageLinkField'] );
+ ], $actual['data']['postBy']['postFields']['pageLinkField']['node'] );
}
@@ -1202,7 +1237,7 @@ public function testQueryMultipleSelectFieldWithNoValueSet() {
codecept_debug( $actual );
- $this->assertSame( [], $actual['data']['postBy']['postFields']['selectMultiple'] );
+ $this->assertSame( null, $actual['data']['postBy']['postFields']['selectMultiple'] );
}
@@ -1253,7 +1288,7 @@ public function testQueryFieldOnCustomPostType() {
$query = '
{
- __type( name: "AcfTest_Acftestfields" ) {
+ __type( name: "AcfTestFields" ) {
name
description
fields {
@@ -1331,11 +1366,7 @@ public function testQueryRelationshipField() {
'post_title' => 'Test Page',
]);
- $filename = ( $this->test_image );
- $img_id = $this->factory()->attachment->create_upload_object( $filename );
-
-
- update_field( 'relationship_field', [ $post_id, $page_id, $img_id ], $this->post_id );
+ update_field( 'relationship_field', [ $post_id, $page_id ], $this->post_id );
$query = '
query GET_POST_WITH_ACF_FIELD( $postId: Int! ) {
@@ -1344,15 +1375,14 @@ public function testQueryRelationshipField() {
title
postFields {
relationshipField {
- __typename
- ...on Post {
- postId
- }
- ...on Page {
- pageId
- }
- ...on MediaItem {
- mediaItemId
+ nodes {
+ __typename
+ ...on Post {
+ postId
+ }
+ ...on Page {
+ pageId
+ }
}
}
}
@@ -1378,11 +1408,376 @@ public function testQueryRelationshipField() {
'__typename' => 'Page',
'pageId' => $page_id,
],
+ ], $actual['data']['postBy']['postFields']['relationshipField']['nodes'] );
+
+ }
+
+ public function test_relationship_field_with_draft_post_doesnt_cause_error() {
+
+ $this->register_acf_field([
+ 'type' => 'relationship',
+ 'name' => 'relationship_field',
+ 'post_type' => [
+ 'post',
+ 'page',
+ 'attachment'
+ ],
+ ]);
+
+ $page_id = $this->factory()->post->create([
+ 'post_type' => 'page',
+ 'post_status' => 'draft',
+ 'post_title' => 'Test Page',
+ ]);
+
+ // Set the value of the field to a draft post
+ update_field( 'relationship_field', [ $page_id ], $this->post_id );
+
+ $query = '
+ query GET_POST_WITH_ACF_FIELD( $postId: Int! ) {
+ postBy( postId: $postId ) {
+ id
+ title
+ postFields {
+ relationshipField {
+ nodes {
+ __typename
+ ...on Post {
+ postId
+ }
+ ...on Page {
+ pageId
+ }
+ }
+ }
+ }
+ }
+ }';
+
+ $actual = graphql([
+ 'query' => $query,
+ 'variables' => [
+ 'postId' => $this->post_id,
+ ],
+ ]);
+
+ codecept_debug( $actual );
+
+ $this->assertArrayNotHasKey( 'errors', $actual );
+
+ // Since the related post is a draft, we shouldn't get any node returned, and should
+ // also get no errors
+ $this->assertSame( [], $actual['data']['postBy']['postFields']['relationshipField']['nodes'] );
+
+ // Update the relationship to have one published Post ID and one Draft Page ID
+ update_field( 'relationship_field', [ $this->post_id, $page_id ], $this->post_id );
+
+ $actual = graphql([
+ 'query' => $query,
+ 'variables' => [
+ 'postId' => $this->post_id,
+ ],
+ ]);
+
+ codecept_debug( $actual );
+
+ $this->assertArrayNotHasKey( 'errors', $actual );
+
+ // Since the related post is published, but the related page is draft, we should
+ // get the post returned, but the draft page should not be in the response
+ $this->assertSame( [
[
- '__typename' => 'MediaItem',
- 'mediaItemId' => $img_id,
+ '__typename' => 'Post',
+ 'postId' => $this->post_id,
+ ],
+ ], $actual['data']['postBy']['postFields']['relationshipField']['nodes'] );
+
+ }
+
+ public function test_taxonomy_field_in_repeater_returns_terms() {
+
+ $this->register_acf_field([
+ 'type' => 'repeater',
+ 'name' => 'repeater_field',
+ 'sub_fields' => [
+ [
+ 'key' => 'field_609d76ed7dc3e',
+ 'label' => 'category',
+ 'name' => 'category',
+ 'type' => 'taxonomy',
+ 'instructions' => '',
+ 'required' => 0,
+ 'conditional_logic' => 0,
+ 'wrapper' => [
+ 'width' => '',
+ 'class' => '',
+ 'id' => '',
+ ],
+ 'show_in_graphql' => 1,
+ 'taxonomy' => 'category',
+ 'field_type' => 'checkbox',
+ 'add_term' => 1,
+ 'save_terms' => 0,
+ 'load_terms' => 0,
+ 'return_format' => 'id',
+ 'multiple' => 0,
+ 'allow_null' => 0,
+ ],
+ ],
+ ]);
+
+ $category_1 = $this->factory()->category->create([
+ 'name' => 'test one'
+ ]);
+ $category_2 = $this->factory()->category->create([
+ 'name' => 'test two',
+ 'parent' => $category_1,
+ ]);
+
+ update_field( 'repeater_field', [
+ [
+ 'field_609d76ed7dc3e' => [ $category_1 ]
+ ],
+ [
+ 'field_609d76ed7dc3e' => [ $category_2, $category_1 ]
+ ],
+ [
+ 'field_609d76ed7dc3e' => [ $category_2 ]
]
- ], $actual['data']['postBy']['postFields']['relationshipField'] );
+ ], $this->post_id );
+
+ codecept_debug( get_post_custom( $this->post_id ) );
+
+ $query = '
+ query GET_POST_WITH_ACF_FIELD( $postId: Int! ) {
+ postBy( postId: $postId ) {
+ id
+ title
+ postFields {
+ repeaterField {
+ category {
+ nodes {
+ __typename
+ databaseId
+ }
+ }
+ }
+ }
+ }
+ }';
+
+ $actual = graphql([
+ 'query' => $query,
+ 'variables' => [
+ 'postId' => $this->post_id,
+ ]
+ ]);
+
+ codecept_debug( $actual );
+
+ $this->assertArrayNotHasKey( 'errors', $actual );
+
+ // First repeater has just the parent category
+ $this->assertSame( [
+ [
+ '__typename' => 'Category',
+ 'databaseId' => $category_1,
+ ],
+ ], $actual['data']['postBy']['postFields']['repeaterField'][0]['category']['nodes'] );
+
+ // Next repeater has parent and child category, ordered with the child first, parent 2nd
+ $this->assertSame( [
+ [
+ '__typename' => 'Category',
+ 'databaseId' => $category_2,
+ ],
+ [
+ '__typename' => 'Category',
+ 'databaseId' => $category_1,
+ ],
+ ], $actual['data']['postBy']['postFields']['repeaterField'][1]['category']['nodes'] );
+
+ // Next repeater has just child category
+ $this->assertSame( [
+ [
+ '__typename' => 'Category',
+ 'databaseId' => $category_2,
+ ],
+ ], $actual['data']['postBy']['postFields']['repeaterField'][2]['category']['nodes'] );
+
+
+ }
+
+ public function test_repeater_field_with_no_values_returns_empty_array() {
+
+ $this->register_acf_field([
+ 'type' => 'repeater',
+ 'name' => 'repeater_test',
+ 'sub_fields' => [
+ [
+ 'key' => 'field_609d76easdfere',
+ 'label' => 'text',
+ 'name' => 'text',
+ 'type' => 'text',
+ 'instructions' => '',
+ 'required' => 0,
+ 'conditional_logic' => 0,
+ 'wrapper' => [
+ 'width' => '',
+ 'class' => '',
+ 'id' => '',
+ ],
+ 'show_in_graphql' => 1,
+ 'add_term' => 1,
+ 'save_terms' => 0,
+ 'load_terms' => 0,
+ 'multiple' => 0,
+ 'allow_null' => 0,
+ ],
+ ],
+ ]);
+
+ $query = '
+ query GET_POST_WITH_ACF_FIELD( $postId: Int! ) {
+ postBy( postId: $postId ) {
+ id
+ title
+ postFields {
+ repeaterTest {
+ text
+ }
+ }
+ }
+ }';
+
+ update_field( 'repeater_test', [], $this->post_id );
+
+ $actual = graphql([
+ 'query' => $query,
+ 'variables' => [
+ 'postId' => $this->post_id,
+ ]
+ ]);
+
+ codecept_debug( $actual );
+
+ $this->assertArrayNotHasKey( 'errors', $actual );
+
+ $this->assertEmpty( $actual['data']['postBy']['postFields']['repeaterTest'] );
+
+ update_field( 'repeater_test', [
+ [
+ 'field_609d76easdfere' => 'text one'
+ ],
+ [
+ 'field_609d76easdfere' => 'text two'
+ ],
+ [
+ 'field_609d76easdfere' => 'text three'
+ ]
+ ], $this->post_id );
+
+ $query = '
+ query GET_POST_WITH_ACF_FIELD( $postId: Int! ) {
+ postBy( postId: $postId ) {
+ id
+ title
+ postFields {
+ repeaterTest {
+ text
+ }
+ }
+ }
+ }';
+
+ $actual = graphql([
+ 'query' => $query,
+ 'variables' => [
+ 'postId' => $this->post_id,
+ ]
+ ]);
+
+ codecept_debug( $actual );
+
+ $this->assertArrayNotHasKey( 'errors', $actual );
+
+ $this->assertSame( 'text one', $actual['data']['postBy']['postFields']['repeaterTest'][0]['text'] );
+ $this->assertSame( 'text two', $actual['data']['postBy']['postFields']['repeaterTest'][1]['text'] );
+ $this->assertSame( 'text three', $actual['data']['postBy']['postFields']['repeaterTest'][2]['text'] );
+
+ }
+
+ public function test_flex_field_with_empty_layout_does_not_return_errors() {
+
+ // @todo: Write this test!!!
+ // Register Flex Field
+ // Query flex field, with no data saved to it
+ // Assert no errors
+ // Update field with empty layout
+ // Query field
+ // Assert no errors
+ // Update field with layout data
+ // Query Field
+ // Assert no errors
+
+// $this->register_acf_field([
+// 'key' => 'field_60a2eba592eca',
+// 'label' => 'FlexFieldWithEmptyLayout',
+// 'name' => 'flex_field_with_empty_layout',
+// 'type' => 'flexible_content',
+// 'instructions' => '',
+// 'required' => 0,
+// 'conditional_logic' => 0,
+// 'wrapper' => array(
+// 'width' => '',
+// 'class' => '',
+// 'id' => '',
+// ),
+// 'show_in_graphql' => 1,
+// 'layouts' => array(
+// 'layout_60a2ebb0ddd96' => array(
+// 'key' => 'layout_60a2ebb0ddd96',
+// 'name' => 'layout_one',
+// 'label' => 'Layout One',
+// 'display' => 'block',
+// 'sub_fields' => array(
+// // No subfields in the layout, intentionally
+// ),
+// 'min' => '',
+// 'max' => '',
+// ),
+// ),
+// 'button_label' => 'Add Row',
+// 'min' => '',
+// 'max' => '',
+// ]);
+//
+// $query = '
+// query GET_POST_WITH_ACF_FIELD( $postId: Int! ) {
+// postBy( postId: $postId ) {
+// id
+// title
+// postFields {
+// flexFieldWithEmptyLayout {
+// __typename
+// }
+// }
+// }
+// }';
+//
+// $actual = graphql([
+// 'query' => $query,
+// 'variables' => [
+// 'postId' => $this->post_id,
+// ]
+// ]);
+//
+// codecept_debug( $actual );
+//
+//
+// $this->assertArrayNotHasKey( 'errors', $actual );
+// $this->assertEmpty( $actual['data']['postBy']['postFields']['flexFieldWithEmptyLayout']);
+
}
diff --git a/vendor/autoload.php b/vendor/autoload.php
index f128e0f..7be413a 100644
--- a/vendor/autoload.php
+++ b/vendor/autoload.php
@@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
-return ComposerAutoloaderInit9e804fc6f45415f83dd03aeed86e33f0::getLoader();
+return ComposerAutoloaderInit5d3b6ccf12f2a55d6ca3051497f869df::getLoader();
diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php
index 6b5a555..9a89755 100644
--- a/vendor/composer/InstalledVersions.php
+++ b/vendor/composer/InstalledVersions.php
@@ -25,24 +25,24 @@ class InstalledVersions
private static $installed = array (
'root' =>
array (
- 'pretty_version' => 'dev-master',
- 'version' => 'dev-master',
+ 'pretty_version' => 'dev-develop',
+ 'version' => 'dev-develop',
'aliases' =>
array (
),
- 'reference' => 'dc5e83d190211baf88978a905ff44a9122fdaff8',
+ 'reference' => 'aa697aecfa118c71373cb8a5610d95b476a8fe68',
'name' => 'wp-graphql/wp-graphql-acf',
),
'versions' =>
array (
'wp-graphql/wp-graphql-acf' =>
array (
- 'pretty_version' => 'dev-master',
- 'version' => 'dev-master',
+ 'pretty_version' => 'dev-develop',
+ 'version' => 'dev-develop',
'aliases' =>
array (
),
- 'reference' => 'dc5e83d190211baf88978a905ff44a9122fdaff8',
+ 'reference' => 'aa697aecfa118c71373cb8a5610d95b476a8fe68',
),
),
);
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
index 7d3d8b2..3894f1e 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -7,8 +7,26 @@
return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
- 'WPGraphQL\\ACF\\ACF' => $baseDir . '/src/class-acf.php',
- 'WPGraphQL\\ACF\\ACF_Settings' => $baseDir . '/src/class-acfsettings.php',
- 'WPGraphQL\\ACF\\Config' => $baseDir . '/src/class-config.php',
- 'WPGraphQL\\ACF\\LocationRules' => $baseDir . '/src/location-rules.php',
+ 'WPGraphQL\\ACF\\Acf' => $baseDir . '/src/Acf.php',
+ 'WPGraphQL\\ACF\\AcfSettings' => $baseDir . '/src/AcfSettings.php',
+ 'WPGraphQL\\ACF\\Config' => $baseDir . '/src/deprecated-class-config.php',
+ 'WPGraphQL\\ACF\\Fields\\AcfField' => $baseDir . '/src/Fields/AcfField.php',
+ 'WPGraphQL\\ACF\\Fields\\File' => $baseDir . '/src/Fields/File.php',
+ 'WPGraphQL\\ACF\\Fields\\FlexibleContent' => $baseDir . '/src/Fields/FlexibleContent.php',
+ 'WPGraphQL\\ACF\\Fields\\Gallery' => $baseDir . '/src/Fields/Gallery.php',
+ 'WPGraphQL\\ACF\\Fields\\Group' => $baseDir . '/src/Fields/Group.php',
+ 'WPGraphQL\\ACF\\Fields\\Image' => $baseDir . '/src/Fields/Image.php',
+ 'WPGraphQL\\ACF\\Fields\\PageLink' => $baseDir . '/src/Fields/PageLink.php',
+ 'WPGraphQL\\ACF\\Fields\\PostObject' => $baseDir . '/src/Fields/PostObject.php',
+ 'WPGraphQL\\ACF\\Fields\\Relationship' => $baseDir . '/src/Fields/Relationship.php',
+ 'WPGraphQL\\ACF\\Fields\\Repeater' => $baseDir . '/src/Fields/Repeater.php',
+ 'WPGraphQL\\ACF\\Fields\\Select' => $baseDir . '/src/Fields/Select.php',
+ 'WPGraphQL\\ACF\\Fields\\Taxonomy' => $baseDir . '/src/Fields/Taxonomy.php',
+ 'WPGraphQL\\ACF\\Fields\\User' => $baseDir . '/src/Fields/User.php',
+ 'WPGraphQL\\ACF\\LocationRules' => $baseDir . '/src/LocationRules.php',
+ 'WPGraphQL\\ACF\\Registry' => $baseDir . '/src/Registry.php',
+ 'WPGraphQL\\ACF\\Types\\InterfaceType\\AcfFieldGroupInterface' => $baseDir . '/src/Types/InterfaceType/AcfFieldGroupInterface.php',
+ 'WPGraphQL\\ACF\\Types\\ObjectType\\AcfFieldGroupConfig' => $baseDir . '/src/Types/ObjectType/AcfFieldGroupConfig.php',
+ 'WPGraphQL\\ACF\\Types\\ObjectType\\AcfGoogleMap' => $baseDir . '/src/Types/ObjectType/AcfGoogleMap.php',
+ 'WPGraphQL\\ACF\\Types\\ObjectType\\AcfLink' => $baseDir . '/src/Types/ObjectType/AcfLink.php',
);
diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php
index 3be627f..222c33c 100644
--- a/vendor/composer/autoload_real.php
+++ b/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
-class ComposerAutoloaderInit9e804fc6f45415f83dd03aeed86e33f0
+class ComposerAutoloaderInit5d3b6ccf12f2a55d6ca3051497f869df
{
private static $loader;
@@ -24,15 +24,15 @@ public static function getLoader()
require __DIR__ . '/platform_check.php';
- spl_autoload_register(array('ComposerAutoloaderInit9e804fc6f45415f83dd03aeed86e33f0', 'loadClassLoader'), true, true);
+ spl_autoload_register(array('ComposerAutoloaderInit5d3b6ccf12f2a55d6ca3051497f869df', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
- spl_autoload_unregister(array('ComposerAutoloaderInit9e804fc6f45415f83dd03aeed86e33f0', 'loadClassLoader'));
+ spl_autoload_unregister(array('ComposerAutoloaderInit5d3b6ccf12f2a55d6ca3051497f869df', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
- call_user_func(\Composer\Autoload\ComposerStaticInit9e804fc6f45415f83dd03aeed86e33f0::getInitializer($loader));
+ call_user_func(\Composer\Autoload\ComposerStaticInit5d3b6ccf12f2a55d6ca3051497f869df::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index 23d10df..5c09178 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -4,7 +4,7 @@
namespace Composer\Autoload;
-class ComposerStaticInit9e804fc6f45415f83dd03aeed86e33f0
+class ComposerStaticInit5d3b6ccf12f2a55d6ca3051497f869df
{
public static $prefixLengthsPsr4 = array (
'W' =>
@@ -22,18 +22,36 @@ class ComposerStaticInit9e804fc6f45415f83dd03aeed86e33f0
public static $classMap = array (
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
- 'WPGraphQL\\ACF\\ACF' => __DIR__ . '/../..' . '/src/class-acf.php',
- 'WPGraphQL\\ACF\\ACF_Settings' => __DIR__ . '/../..' . '/src/class-acfsettings.php',
- 'WPGraphQL\\ACF\\Config' => __DIR__ . '/../..' . '/src/class-config.php',
- 'WPGraphQL\\ACF\\LocationRules' => __DIR__ . '/../..' . '/src/location-rules.php',
+ 'WPGraphQL\\ACF\\Acf' => __DIR__ . '/../..' . '/src/Acf.php',
+ 'WPGraphQL\\ACF\\AcfSettings' => __DIR__ . '/../..' . '/src/AcfSettings.php',
+ 'WPGraphQL\\ACF\\Config' => __DIR__ . '/../..' . '/src/deprecated-class-config.php',
+ 'WPGraphQL\\ACF\\Fields\\AcfField' => __DIR__ . '/../..' . '/src/Fields/AcfField.php',
+ 'WPGraphQL\\ACF\\Fields\\File' => __DIR__ . '/../..' . '/src/Fields/File.php',
+ 'WPGraphQL\\ACF\\Fields\\FlexibleContent' => __DIR__ . '/../..' . '/src/Fields/FlexibleContent.php',
+ 'WPGraphQL\\ACF\\Fields\\Gallery' => __DIR__ . '/../..' . '/src/Fields/Gallery.php',
+ 'WPGraphQL\\ACF\\Fields\\Group' => __DIR__ . '/../..' . '/src/Fields/Group.php',
+ 'WPGraphQL\\ACF\\Fields\\Image' => __DIR__ . '/../..' . '/src/Fields/Image.php',
+ 'WPGraphQL\\ACF\\Fields\\PageLink' => __DIR__ . '/../..' . '/src/Fields/PageLink.php',
+ 'WPGraphQL\\ACF\\Fields\\PostObject' => __DIR__ . '/../..' . '/src/Fields/PostObject.php',
+ 'WPGraphQL\\ACF\\Fields\\Relationship' => __DIR__ . '/../..' . '/src/Fields/Relationship.php',
+ 'WPGraphQL\\ACF\\Fields\\Repeater' => __DIR__ . '/../..' . '/src/Fields/Repeater.php',
+ 'WPGraphQL\\ACF\\Fields\\Select' => __DIR__ . '/../..' . '/src/Fields/Select.php',
+ 'WPGraphQL\\ACF\\Fields\\Taxonomy' => __DIR__ . '/../..' . '/src/Fields/Taxonomy.php',
+ 'WPGraphQL\\ACF\\Fields\\User' => __DIR__ . '/../..' . '/src/Fields/User.php',
+ 'WPGraphQL\\ACF\\LocationRules' => __DIR__ . '/../..' . '/src/LocationRules.php',
+ 'WPGraphQL\\ACF\\Registry' => __DIR__ . '/../..' . '/src/Registry.php',
+ 'WPGraphQL\\ACF\\Types\\InterfaceType\\AcfFieldGroupInterface' => __DIR__ . '/../..' . '/src/Types/InterfaceType/AcfFieldGroupInterface.php',
+ 'WPGraphQL\\ACF\\Types\\ObjectType\\AcfFieldGroupConfig' => __DIR__ . '/../..' . '/src/Types/ObjectType/AcfFieldGroupConfig.php',
+ 'WPGraphQL\\ACF\\Types\\ObjectType\\AcfGoogleMap' => __DIR__ . '/../..' . '/src/Types/ObjectType/AcfGoogleMap.php',
+ 'WPGraphQL\\ACF\\Types\\ObjectType\\AcfLink' => __DIR__ . '/../..' . '/src/Types/ObjectType/AcfLink.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
- $loader->prefixLengthsPsr4 = ComposerStaticInit9e804fc6f45415f83dd03aeed86e33f0::$prefixLengthsPsr4;
- $loader->prefixDirsPsr4 = ComposerStaticInit9e804fc6f45415f83dd03aeed86e33f0::$prefixDirsPsr4;
- $loader->classMap = ComposerStaticInit9e804fc6f45415f83dd03aeed86e33f0::$classMap;
+ $loader->prefixLengthsPsr4 = ComposerStaticInit5d3b6ccf12f2a55d6ca3051497f869df::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInit5d3b6ccf12f2a55d6ca3051497f869df::$prefixDirsPsr4;
+ $loader->classMap = ComposerStaticInit5d3b6ccf12f2a55d6ca3051497f869df::$classMap;
}, null, ClassLoader::class);
}
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
index 933c2e4..fd591e0 100644
--- a/vendor/composer/installed.php
+++ b/vendor/composer/installed.php
@@ -1,24 +1,24 @@
array (
- 'pretty_version' => 'dev-master',
- 'version' => 'dev-master',
+ 'pretty_version' => 'dev-develop',
+ 'version' => 'dev-develop',
'aliases' =>
array (
),
- 'reference' => 'dc5e83d190211baf88978a905ff44a9122fdaff8',
+ 'reference' => 'aa697aecfa118c71373cb8a5610d95b476a8fe68',
'name' => 'wp-graphql/wp-graphql-acf',
),
'versions' =>
array (
'wp-graphql/wp-graphql-acf' =>
array (
- 'pretty_version' => 'dev-master',
- 'version' => 'dev-master',
+ 'pretty_version' => 'dev-develop',
+ 'version' => 'dev-develop',
'aliases' =>
array (
),
- 'reference' => 'dc5e83d190211baf88978a905ff44a9122fdaff8',
+ 'reference' => 'aa697aecfa118c71373cb8a5610d95b476a8fe68',
),
),
);
diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php
index f79e574..6d3407d 100644
--- a/vendor/composer/platform_check.php
+++ b/vendor/composer/platform_check.php
@@ -4,8 +4,8 @@
$issues = array();
-if (!(PHP_VERSION_ID >= 70000)) {
- $issues[] = 'Your Composer dependencies require a PHP version ">= 7.0.0". You are running ' . PHP_VERSION . '.';
+if (!(PHP_VERSION_ID >= 70100)) {
+ $issues[] = 'Your Composer dependencies require a PHP version ">= 7.1.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
diff --git a/wp-graphql-acf.php b/wp-graphql-acf.php
index 7275d55..b39fa79 100644
--- a/wp-graphql-acf.php
+++ b/wp-graphql-acf.php
@@ -7,7 +7,7 @@
* Author URI: https://www.wpgraphql.com
* Text Domain: wp-graphql-acf
* Domain Path: /languages
- * Version: 0.5.2
+ * Version: 0.6.0
* Requires PHP: 7.0
* GitHub Plugin URI: https://github.com/wp-graphql/wp-graphql-acf
*
@@ -26,17 +26,17 @@
* Define constants
*/
const WPGRAPHQL_REQUIRED_MIN_VERSION = '0.4.0';
-const WPGRAPHQL_ACF_VERSION = '0.5.2';
+const WPGRAPHQL_ACF_VERSION = '0.6.0';
/**
* Initialize the plugin
*
- * @return ACF|void
+ * @return mixed|Acf|void
*/
function init() {
/**
- * If either ACF or WPGraphQL are not active, show the admin notice and bail
+ * If either Acf or WPGraphQL are not active, show the admin notice and bail
*/
if ( false === can_load_plugin() ) {
// Show the admin notice
@@ -49,16 +49,17 @@ function init() {
/**
* Return the instance of WPGraphQL\ACF
*/
- return ACF::instance();
+ return Acf::instance();
}
-add_action( 'init', '\WPGraphQL\ACF\init' );
+add_action( 'init', '\WPGraphQL\Acf\init' );
+
/**
* Show admin notice to admins if this plugin is active but either ACF and/or WPGraphQL
* are not active
*
- * @return bool
+ * @return void
*/
function show_admin_notice() {
@@ -66,7 +67,7 @@ function show_admin_notice() {
* For users with lower capabilities, don't show the notice
*/
if ( ! current_user_can( 'manage_options' ) ) {
- return false;
+ return;
}
add_action(
@@ -79,19 +80,21 @@ function() {