Skip to content

Instantly share code, notes, and snippets.

@izzygld
Created December 4, 2019 14:16
Show Gist options
  • Save izzygld/b7a2acf4e7d9af2be371c69b63f1d226 to your computer and use it in GitHub Desktop.
Save izzygld/b7a2acf4e7d9af2be371c69b63f1d226 to your computer and use it in GitHub Desktop.
acf wpgraphql types meta
<?php
/**
* Config for WPGraphQL ACF
*
* @package wp-graphql-acf
*/
namespace WPGraphQL\ACF;
use WPGraphQL\Data\DataSource;
use WPGraphQL\Model\Comment;
use WPGraphQL\Model\Menu;
use WPGraphQL\Model\MenuItem;
use WPGraphQL\Model\Post;
use WPGraphQL\Model\Term;
use WPGraphQL\TypeRegistry;
use WPGraphQL\Types;
/**
* Config class.
*/
class Config {
/**
* Initialize WPGraphQL to ACF
*/
public function init() {
/**
* Add ACF Fields to GraphQL Types
*/
$this->add_acf_fields_to_post_object_types();
$this->add_acf_fields_to_term_objects();
$this->add_acf_fields_to_comments();
$this->add_acf_fields_to_menus();
$this->add_acf_fields_to_menu_items();
$this->add_acf_fields_to_media_items();
$this->add_acf_fields_to_individual_posts();
}
/**
* 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( $field_group ) {
/**
* By default, field groups will not be exposed to GraphQL.
*/
$show = false;
/**
* If
*/
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.
*
* @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 );
}
/**
* Undocumented function
*
* @todo: This may be a good utility to add to WPGraphQL Core? May even have something already?
*
* @param string $str Unknown.
* @param array $no_strip Unknown.
*
* @return mixed|null|string|string[]
*/
public static function camel_case( $str, array $no_strip = [] ) {
// non-alpha and non-numeric characters become spaces.
$str = preg_replace( '/[^a-z0-9' . implode( '', $no_strip ) . ']+/i', ' ', $str );
$str = trim( $str );
// Lowercase the string
$str = strtolower( $str );
// uppercase the first character of each word.
$str = ucwords( $str );
// Replace spaces
$str = str_replace( ' ', '', $str );
// Lowecase first letter
$str = lcfirst( $str );
return $str;
}
/**
* Add ACF Fields to Post Object Types.
*
* This gets the Post Types that are configured to show_in_graphql and iterates
* over them to expose ACF Fields to their Type in the GraphQL Schema.
*/
protected function add_acf_fields_to_post_object_types() {
/**
* Get a list of post types that have been registered to show in graphql
*/
$graphql_post_types = get_post_types(['show_in_graphql' => true]);
/**
* If there are no post types exposed to GraphQL, bail
*/
if ( empty( $graphql_post_types ) || ! is_array( $graphql_post_types ) ) {
return;
}
/**
* Loop over the post types exposed to GraphQL
*/
foreach ( $graphql_post_types as $post_type ) {
/**
* Get the field groups associated with the post type
*/
$field_groups = acf_get_field_groups(
[
'post_type' => $post_type,
]
);
/**
* If there are no field groups for this post type, move on to the next one.
*/
if ( empty( $field_groups ) || ! is_array( $field_groups ) ) {
continue;
}
/**
* Get the post_type_object
*/
$post_type_object = get_post_type_object( $post_type );
/**
* Loop over the field groups for this post type
*/
foreach ( $field_groups as $field_group ) {
$field_name = isset( $field_group['graphql_field_name'] ) ? $field_group['graphql_field_name'] : Config::camel_case( $field_group['title'] );
$field_group['type'] = 'group';
$field_group['name'] = $field_name;
$config = [
'name' => $field_name,
'description' => $field_group['description'],
'acf_field' => $field_group,
'acf_field_group' => null,
'resolve' => function( $root ) use ( $field_group ) {
return isset( $root ) ? $root : null;
}
];
$this->register_graphql_field( $post_type_object->graphql_single_name, $field_name, $config );
}
}
}
/**
* Undocumented function
*
* @param [type] $root Undocumented.
* @param [type] $acf_field Undocumented.
*
* @return mixed
*/
protected function get_acf_field_value( $root, $acf_field ) {
$value = null;
if ( is_array( $root ) ) {
if ( isset( $root[ $acf_field['key'] ] ) ) {
$value = $root[ $acf_field['key'] ];
if ( 'wysiwyg' === $acf_field['type'] ) {
$value = apply_filters( 'the_content', $value );
}
}
} else {
switch (true) {
case $root instanceof Term:
$id = acf_get_term_post_id( $root->taxonomyName, $root->term_id );
break;
case $root instanceof Post:
$id = absint( $root->ID );
break;
case $root instanceof MenuItem:
$id = absint( $root->menuItemId );
break;
case $root instanceof Menu:
$id = acf_get_term_post_id( 'nav_menu', $root->menuId );
break;
case $root instanceof Comment:
$id = 'comment_' . absint( $root->comment_ID );
break;
default:
$id = null;
break;
}
if ( empty( $id ) ) {
return null;
}
$format = false;
if ( 'wysiwyg' === $acf_field['type'] ) {
$format = true;
}
$field_value = get_field( $acf_field['key'], $id, $format );
$value = ! empty( $field_value ) ? $field_value : null;
}
return $value;
}
/**
* Get a list of supported fields 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 static function get_supported_fields() {
$supported_fields = [
'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'
];
/**
* filter the supported fields
*
* @param array $supported_fields
*/
return apply_filters( 'wpgraphql_acf_supported_fields', $supported_fields );
}
/**
* Undocumented function
*
* @param [type] $type_name Undocumented.
* @param [type] $field_name Undocumented.
* @param [type] $config Undocumented.
*
* @return mixed
*/
protected function register_graphql_field( $type_name, $field_name, $config ) {
$acf_field = isset( $config['acf_field'] ) ? $config['acf_field'] : null;
$acf_type = isset( $acf_field['type'] ) ? $acf_field['type'] : null;
if ( empty( $acf_type ) ) {
return false;
}
$field_config = [
'type' => null,
'resolve' => isset( $config['resolve'] ) && is_callable( $config['resolve'] ) ? $config['resolve'] : function( $root, $args, $context, $info ) use ( $acf_field ) {
$value = $this->get_acf_field_value( $root, $acf_field );
return ! empty( $value ) ? $value : null;
},
];
switch ( $acf_type ) {
case 'button_group':
case 'color_picker':
case 'email':
case 'textarea':
case 'text':
case 'message':
case 'oembed':
case 'password':
case 'wysiwyg':
case 'url':
// Even though Selects and Radios in ACF can _technically_ be an integer
// we're chosing to always cast as a string because with
// GraphQL we can't return different types
case 'select':
case 'radio':
$field_config['type'] = 'String';
break;
case 'range':
$field_config['type'] = 'Integer';
break;
case 'number':
$field_config['type'] = 'Float';
break;
case 'true_false':
$field_config['type'] = 'Boolean';
break;
case 'date_picker':
case 'time_picker':
case 'date_time_picker':
$field_config = [
'type' => 'String',
'resolve' => function( $root, $args, $context, $info ) use ( $acf_field ) {
return isset( $root->ID ) ? get_field( $acf_field['key'], $root->ID, true ) : null;
},
];
break;
case 'relationship':
if ( isset( $acf_field['post_type'] ) && is_array( $acf_field['post_type'] ) ) {
$field_type_name = $type_name . '_' . ucfirst( self::camel_case( $acf_field['name'] ) );
if ( TypeRegistry::get_type( $field_type_name ) == $field_type_name ) {
$type = $field_type_name;
} else {
$type_names = [];
foreach ( $acf_field['post_type'] as $post_type ) {
if ( in_array( $post_type, \WPGraphQL::$allowed_post_types, true ) ) {
$type_names[ $post_type ] = get_post_type_object( $post_type )->graphql_single_name;
}
}
if ( empty( $type_names ) ) {
$field_config['type'] = null;
break;
}
register_graphql_union_type( $field_type_name, [
'typeNames' => $type_names,
'resolveType' => function( $value ) use ( $type_names ) {
return ! empty( $value->post_type ) ? Types::post_object( $value->post_type ) : null;
}
] );
$type = $field_type_name;
}
} else {
$type = 'PostObjectUnion';
}
$field_config = [
'type' => [ 'list_of' => $type ],
'resolve' => function( $root, $args, $context, $info ) use ( $acf_field ) {
$relationship = [];
$value = $this->get_acf_field_value( $root, $acf_field );
if ( ! empty( $value ) && is_array( $value ) ) {
foreach ( $value as $post_id ) {
$post_object = get_post( $post_id );
if ( $post_object instanceof \WP_Post ) {
$post_model = new Post( $post_object );
$relationship[] = $post_model;
}
}
}
return isset( $value ) ? $relationship : null;
},
];
break;
case 'page_link':
case 'post_object':
if ( isset( $acf_field['post_type'] ) && is_array( $acf_field['post_type'] ) ) {
$field_type_name = $type_name . '_' . ucfirst( self::camel_case( $acf_field['name'] ) );
if ( TypeRegistry::get_type( $field_type_name ) == $field_type_name ) {
$type = $field_type_name;
} else {
$type_names = [];
foreach ( $acf_field['post_type'] as $post_type ) {
if ( in_array( $post_type, \WPGraphQL::$allowed_post_types, true ) ) {
$type_names[ $post_type ] = get_post_type_object( $post_type )->graphql_single_name;
}
}
if ( empty( $type_names ) ) {
$field_config['type'] = null;
break;
}
register_graphql_union_type( $field_type_name, [
'typeNames' => $type_names,
'resolveType' => function( $value ) use ( $type_names ) {
return ! empty( $value->post_type ) ? Types::post_object( $value->post_type ) : null;
}
] );
$type = $field_type_name;
}
} else {
$type = 'PostObjectUnion';
}
$field_config = [
'type' => $type,
'resolve' => function( $root, $args, $context, $info ) use ( $acf_field ) {
$value = $this->get_acf_field_value( $root, $acf_field );
if ( $value instanceof \WP_Post ) {
return new Post( $value );
}
return absint( $value ) ? DataSource::resolve_post_object( (int) $value, $context ) : null;
},
];
break;
case 'link':
$field_type_name = 'ACF_Link';
if ( TypeRegistry::get_type( $field_type_name ) == $field_type_name ) {
$field_config['type'] = $field_type_name;
break;
}
register_graphql_object_type(
$field_type_name,
[
'description' => __( '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' ),
],
],
]
);
$field_config['type'] = $field_type_name;
break;
case 'image':
case 'file':
$field_config = [
'type' => 'MediaItem',
'resolve' => function( $root, $args, $context, $info ) use ( $acf_field ) {
$value = $this->get_acf_field_value( $root, $acf_field );
return DataSource::resolve_post_object( (int) $value, $context );
},
];
break;
case 'checkbox':
$field_config = [
'type' => [ 'list_of' => 'String' ],
'resolve' => function( $root, $args, $context, $info ) use ( $acf_field ) {
$value = $this->get_acf_field_value( $root, $acf_field );
return is_array( $value ) ? $value : null;
},
];
break;
case 'gallery':
$field_config = [
'type' => [ 'list_of' => 'MediaItem' ],
'resolve' => function( $root, $args, $context, $info ) use ( $acf_field ) {
$value = $this->get_acf_field_value( $root, $acf_field );
$gallery = [];
if ( ! empty( $value ) && is_array( $value ) ) {
foreach ( $value as $image ) {
$post_object = get_post( (int) $image );
if ( $post_object instanceof \WP_Post ) {
$post_model = new Post( $post_object );
$gallery[] = $post_model;
}
}
}
return isset( $value ) ? $gallery : null;
},
];
break;
case 'user':
$field_config = [
'type' => 'User',
'resolve' => function( $root, $args, $context, $info ) use ( $acf_field ) {
$value = $this->get_acf_field_value( $root, $acf_field );
return DataSource::resolve_user( (int) $value, $context );
},
];
break;
case 'taxonomy':
$field_config = [
'type' => [ 'list_of' => 'TermObjectUnion' ],
'resolve' => function( $root, $args, $context, $info ) use ( $acf_field ) {
$value = $this->get_acf_field_value( $root, $acf_field );
$terms = [];
if ( ! empty( $value ) && is_array( $value ) ) {
foreach ( $value as $term ) {
$terms[] = DataSource::resolve_term_object( (int) $term, $context );
}
}
return $terms;
},
];
break;
// Accordions are not represented in the GraphQL Schema.
case 'accordion':
$field_config = null;
break;
case 'group':
$field_type_name = $type_name . '_' . ucfirst( self::camel_case( $acf_field['name'] ) );
if ( TypeRegistry::get_type( $field_type_name ) ) {
$field_config['type'] = $field_type_name;
break;
}
register_graphql_object_type(
$field_type_name,
[
'description' => __( 'Field Group', 'wp-graphql-acf' ),
'fields' => [
'fieldGroupName' => [
'type' => 'String',
'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 );
$field_config['type'] = $field_type_name;
break;
case 'google_map':
$field_type_name = 'ACF_GoogleMap';
if ( TypeRegistry::get_type( $field_type_name ) == $field_type_name ) {
$field_config['type'] = $field_type_name;
break;
}
register_graphql_object_type(
$field_type_name,
[
'description' => __( 'Google Map field', '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;
},
],
],
]
);
$field_config['type'] = $field_type_name;
break;
case 'repeater':
$field_type_name = $type_name . '_' . self::camel_case( $acf_field['name'] );
if ( TypeRegistry::get_type( $field_type_name ) ) {
$field_config['type'] = $field_type_name;
break;
}
register_graphql_object_type(
$field_type_name,
[
'description' => __( 'Field Group', 'wp-graphql-acf' ),
'fields' => [
'fieldGroupName' => [
'type' => 'String',
'resolve' => function( $source ) use ( $acf_field ) {
return ! empty( $acf_field['name'] ) ? $acf_field['name'] : null;
},
],
],
'resolve' => function( $source ) use ( $acf_field ) {
$repeater = $this->get_acf_field_value( $source, $acf_field );
return ! empty( $repeater ) ? $repeater : [];
},
]
);
$this->add_field_group_fields( $acf_field, $field_type_name );
$field_config['type'] = [ 'list_of' => $field_type_name ];
break;
/**
* Flexible content fields should return a Union of the Layouts that can be configured.
*
*
* Example Query of a flex field with the name "flex_field" and 2 groups
*
* {
* post {
* flexField {
* ...on GroupOne {
* textField
* textAreaField
* }
* ...on GroupTwo {
* imageField {
* id
* title
* }
* }
* }
* }
* }
*
*/
case 'flexible_content':
$field_config = null;
$field_type_name = $type_name . '_' . ucfirst( self::camel_case( $acf_field['name'] ) );
if ( TypeRegistry::get_type( $field_type_name ) ) {
$field_config['type'] = $field_type_name;
break;
}
if ( ! empty( $acf_field['layouts'] ) && is_array( $acf_field['layouts'] ) ) {
$union_types = [];
foreach ( $acf_field['layouts'] as $layout ) {
$flex_field_layout_name = ! empty( $layout['name'] ) ? ucfirst( self::camel_case( $layout['name'] ) ) : null;
$flex_field_layout_name = ! empty( $flex_field_layout_name ) ? $field_type_name . '_' . $flex_field_layout_name : null;
$layout_type = TypeRegistry::get_type( $flex_field_layout_name );
if ( $layout_type ) {
$union_types[ $layout['name'] ] = $layout_type;
} else {
register_graphql_object_type( $flex_field_layout_name, [
'description' => __( 'Group within the flex field', 'wp-graphql-acf' ),
'fields' => [
'fieldGroupName' => [
'type' => 'String',
'resolve' => function( $source ) use ( $flex_field_layout_name ) {
return ! empty( $flex_field_layout_name ) ? $flex_field_layout_name : null;
},
],
],
] );
$layout_type = TypeRegistry::get_type( $flex_field_layout_name );
$union_types[ $layout['name'] ] = $layout_type;
$layout['parent'] = $acf_field;
$layout['show_in_graphql'] = isset( $acf_field['show_in_graphql'] ) ? (bool) $acf_field['show_in_graphql'] : true;
$this->add_field_group_fields( $layout, $flex_field_layout_name );
}
}
register_graphql_union_type( $field_type_name, [
'types' => $union_types,
'resolveType' => function( $value ) use ( $union_types ) {
return isset( $union_types[ $value['acf_fc_layout'] ] ) ? $union_types[ $value['acf_fc_layout'] ] : null;
}
] );
$field_config['type'] = [ 'list_of' => $field_type_name ];
$field_config['resolve'] = function( $root, $args, $context, $info ) use ( $acf_field ) {
$value = $this->get_acf_field_value( $root, $acf_field );
return ! empty( $value ) ? $value : [];
};
}
break;
default:
break;
}
if ( empty( $field_config ) || empty( $field_config['type'] ) ) {
return null;
}
$config = array_merge( $config, $field_config );
return register_graphql_field( $type_name, $field_name, $config );
}
/**
* Given a field group array, this adds the fields to the specified Type in the Schema
*
* @param array $field_group The group to add to the Schema.
* @param string $type_name The Type name in the GraphQL Schema to add fields to.
*/
protected function add_field_group_fields( $field_group, $type_name ) {
/**
* If the field group has the show_in_graphql setting configured, respect it's setting
* otherwise default to true (for nested fields)
*/
$field_group['show_in_graphql'] = isset( $field_group['show_in_graphql'] ) ? (boolean) $field_group['show_in_graphql'] : true;
/**
* Determine if the field group should be exposed
* to graphql
*/
if ( ! $this->should_field_group_show_in_graphql( $field_group ) ) {
return;
}
/**
* Get the fields in the group.
*/
$acf_fields = ! empty( $field_group['sub_fields'] ) ? $field_group['sub_fields'] : acf_get_fields( $field_group );
/**
* If there are no fields, bail
*/
if ( empty( $acf_fields ) || ! is_array( $acf_fields ) ) {
return;
}
/**
* Loop over the fields and register them to the Schema
*/
foreach ( $acf_fields as $acf_field ) {
/**
* Setup data for register_graphql_field
*/
$name = ! empty( $acf_field['name'] ) ? self::camel_case( $acf_field['name'] ) : null;
$show_in_graphql = isset( $acf_field['show_in_graphql'] ) ? (bool) $acf_field['show_in_graphql'] : true;
$description = isset( $acf_field['instructions'] ) ? $acf_field['instructions'] : __( 'ACF Field added to the Schema by WPGraphQL ACF' );
/**
* If the field is missing a name or a type,
* we can't add it to the Schema.
*/
if (
empty( $name ) ||
true != $show_in_graphql
) {
/**
* Uncomment line below to determine what fields are not going to be output
* in the Schema.
*/
continue;
}
$config = [
'name' => $name,
'description' => $description,
'acf_field' => $acf_field,
'acf_field_group' => $field_group,
];
$this->register_graphql_field( $type_name, $name, $config );
}
}
/**
* Add field groups to Taxonomies
*
* @return void
*/
protected function add_acf_fields_to_term_objects() {
/**
* Get a list of taxonomies that have been registered to show in graphql
*/
$graphql_taxonomies = \WPGraphQL::get_allowed_taxonomies();
/**
* If there are no taxonomies exposed to GraphQL, bail
*/
if ( empty( $graphql_taxonomies ) || ! is_array( $graphql_taxonomies ) ) {
return;
}
/**
* Loop over the taxonomies exposed to GraphQL
*/
foreach ( $graphql_taxonomies as $taxonomy ) {
/**
* Get the field groups associated with the taxonomy
*/
$field_groups = acf_get_field_groups(
[
'taxonomy' => $taxonomy,
]
);
/**
* If there are no field groups for this taxonomy, move on to the next one.
*/
if ( empty( $field_groups ) || ! is_array( $field_groups ) ) {
continue;
}
/**
* Get the Taxonomy object
*/
$tax_object = get_taxonomy( $taxonomy );
/**
* Loop over the field groups for this post type
*/
foreach ( $field_groups as $field_group ) {
$field_name = isset( $field_group['graphql_field_name'] ) ? $field_group['graphql_field_name'] : Config::camel_case( $field_group['title'] );
$field_group['type'] = 'group';
$field_group['name'] = $field_name;
$description = $field_group['description'] ? $field_group['description'] . ' | ' : '';
$config = [
'name' => $field_name,
'description' => $description . sprintf( __( 'Added to the GraphQL Schema because the ACF Field Group "%1$s" was assigned to the "%2$s" taxonomy', 'wp-graphql-acf' ), $field_group['title'], $tax_object->name ),
'acf_field' => $field_group,
'acf_field_group' => null,
'resolve' => function( $root ) use ( $field_group ) {
return isset( $root ) ? $root : null;
}
];
$this->register_graphql_field( $tax_object->graphql_single_name, $field_name, $config );
}
}
}
/**
* Add ACF Fields to comments
*
* @return void
*/
protected function add_acf_fields_to_comments() {
$comment_field_groups = [];
/**
* Get the field groups associated with the taxonomy
*/
$field_groups = acf_get_field_groups();
foreach( $field_groups as $field_group ) {
if ( ! empty( $field_group['location'] ) && is_array( $field_group['location'] ) ) {
foreach ( $field_group['location'] as $locations ) {
if ( ! empty( $locations ) && is_array( $locations ) ) {
foreach ( $locations as $location ) {
if ( 'comment' === $location['param'] && '!=' === $location['operator'] ) {
continue;
}
if ( 'comment' === $location['param'] && '==' === $location['operator'] ) {
$comment_field_groups[] = $field_group;
}
}
}
}
}
}
if ( empty( $comment_field_groups ) ) {
return;
}
/**
* Loop over the field groups for this post type
*/
foreach ( $comment_field_groups as $field_group ) {
$field_name = isset( $field_group['graphql_field_name'] ) ? $field_group['graphql_field_name'] : Config::camel_case( $field_group['title'] );
$field_group['type'] = 'group';
$field_group['name'] = $field_name;
$description = $field_group['description'] ? $field_group['description'] . ' | ' : '';
$config = [
'name' => $field_name,
'description' => $description . sprintf( __( 'Added to the GraphQL Schema because the ACF Field Group "%s" was assigned to Comments', 'wp-graphql-acf' ), $field_group['title'] ),
'acf_field' => $field_group,
'acf_field_group' => null,
'resolve' => function( $root ) use ( $field_group ) {
return isset( $root ) ? $root : null;
}
];
$this->register_graphql_field( 'Comment', $field_name, $config );
}
}
/**
* Add Fields to Menus in the GraphQL Schema
*
* @return void
*/
protected function add_acf_fields_to_menus() {
$menu_field_groups = [];
/**
* Get the field groups associated with the taxonomy
*/
$field_groups = acf_get_field_groups();
foreach( $field_groups as $field_group ) {
if ( ! empty( $field_group['location'] ) && is_array( $field_group['location'] ) ) {
foreach ( $field_group['location'] as $locations ) {
if ( ! empty( $locations ) && is_array( $locations ) ) {
foreach ( $locations as $location ) {
if ( 'nav_menu' === $location['param'] && '!=' === $location['operator'] ) {
continue;
}
if ( 'nav_menu' === $location['param'] && '==' === $location['operator'] ) {
$menu_field_groups[] = $field_group;
break;
}
}
}
}
}
}
if ( empty( $menu_field_groups ) ) {
return;
}
/**
* Loop over the field groups for this post type
*/
foreach ( $menu_field_groups as $field_group ) {
$field_name = isset( $field_group['graphql_field_name'] ) ? $field_group['graphql_field_name'] : Config::camel_case( $field_group['title'] );
$field_group['type'] = 'group';
$field_group['name'] = $field_name;
$description = $field_group['description'] ? $field_group['description'] . ' | ' : '';
$config = [
'name' => $field_name,
'description' => $description . sprintf( __( 'Added to the GraphQL Schema because the ACF Field Group "%s" was assigned to Menus', 'wp-graphql-acf' ), $field_group['title'] ),
'acf_field' => $field_group,
'acf_field_group' => null,
'resolve' => function( $root ) use ( $field_group ) {
return isset( $root ) ? $root : null;
}
];
$this->register_graphql_field( 'Menu', $field_name, $config );
}
}
/**
* Add ACF Field Groups to Menu Items
*
* @return void
*/
protected function add_acf_fields_to_menu_items() {
$menu_item_field_groups = [];
/**
* Get the field groups associated with the taxonomy
*/
$field_groups = acf_get_field_groups();
foreach( $field_groups as $field_group ) {
if ( ! empty( $field_group['location'] ) && is_array( $field_group['location'] ) ) {
foreach ( $field_group['location'] as $locations ) {
if ( ! empty( $locations ) && is_array( $locations ) ) {
foreach ( $locations as $location ) {
if ( 'nav_menu_item' === $location['param'] && '!=' === $location['operator'] ) {
continue;
}
if ( 'nav_menu_item' === $location['param'] && '==' === $location['operator'] ) {
$menu_item_field_groups[] = $field_group;
}
}
}
}
}
}
if ( empty( $menu_item_field_groups ) ) {
return;
}
/**
* Loop over the field groups for this post type
*/
foreach ( $menu_item_field_groups as $field_group ) {
$field_name = isset( $field_group['graphql_field_name'] ) ? $field_group['graphql_field_name'] : Config::camel_case( $field_group['title'] );
$field_group['type'] = 'group';
$field_group['name'] = $field_name;
$description = $field_group['description'] ? $field_group['description'] . ' | ' : '';
$config = [
'name' => $field_name,
'description' => $description . sprintf( __( 'Added to the GraphQL Schema because the ACF Field Group "%s" was assigned to Menu Items', 'wp-graphql-acf' ), $field_group['title'] ),
'acf_field' => $field_group,
'acf_field_group' => null,
'resolve' => function( $root ) use ( $field_group ) {
return isset( $root ) ? $root : null;
}
];
$this->register_graphql_field( 'MenuItem', $field_name, $config );
}
}
/**
* Add ACF Field Groups to Media Items (attachments)
*
* @return void
*/
protected function add_acf_fields_to_media_items() {
$media_item_field_groups = [];
/**
* Get the field groups associated with the taxonomy
*/
$field_groups = acf_get_field_groups();
foreach( $field_groups as $field_group ) {
if ( ! empty( $field_group['location'] ) && is_array( $field_group['location'] ) ) {
foreach ( $field_group['location'] as $locations ) {
if ( ! empty( $locations ) && is_array( $locations ) ) {
foreach ( $locations as $location ) {
if ( 'attachment' === $location['param'] && '!=' === $location['operator'] ) {
continue;
}
if ( 'attachment' === $location['param'] && '==' === $location['operator'] ) {
$media_item_field_groups[] = $field_group;
}
}
}
}
}
}
if ( empty( $media_item_field_groups ) ) {
return;
}
/**
* Loop over the field groups for this post type
*/
foreach ( $media_item_field_groups as $field_group ) {
$field_name = isset( $field_group['graphql_field_name'] ) ? $field_group['graphql_field_name'] : Config::camel_case( $field_group['title'] );
$field_group['type'] = 'group';
$field_group['name'] = $field_name;
$description = $field_group['description'] ? $field_group['description'] . ' | ' : '';
$config = [
'name' => $field_name,
'description' => $description . sprintf( __( 'Added to the GraphQL Schema because the ACF Field Group "%s" was assigned to attachments', 'wp-graphql-acf' ), $field_group['title'] ),
'acf_field' => $field_group,
'acf_field_group' => null,
'resolve' => function( $root ) use ( $field_group ) {
return isset( $root ) ? $root : null;
}
];
$this->register_graphql_field( 'MediaItem', $field_name, $config );
}
}
protected function add_acf_fields_to_individual_posts() {
$post_field_groups = [];
/**
* Get the field groups associated with the taxonomy
*/
$field_groups = acf_get_field_groups();
foreach( $field_groups as $field_group ) {
if ( ! empty( $field_group['location'] ) && is_array( $field_group['location'] ) ) {
foreach ( $field_group['location'] as $locations ) {
if ( ! empty( $locations ) && is_array( $locations ) ) {
foreach ( $locations as $location ) {
/**
* If the operator is not equal to, we don't need to do anything,
* so we can just continue
*/
if ( '!=' === $location['operator'] ) {
continue;
}
/**
* If the param (the post_type) is in the array of allowed_post_types
*/
if ( 'post' === $location['param'] && '==' === $location['operator'] ) {
$post_field_groups[] = [
'field_group' => $field_group,
'post_id' => $location['value']
];
}
}
}
}
}
}
/**
* If no field groups are assigned to a specific post, we don't need to modify the Schema
*/
if ( empty( $post_field_groups ) ) {
return;
}
$allowed_post_types = get_post_types([
'show_ui' => true,
'show_in_graphql' => true
]);
/**
* Remove the `attachment` post_type, as it's treated special and we don't
* want to add field groups in the same way we do for other post types
*/
unset( $allowed_post_types['attachment'] );
/**
* Loop over the field groups assigned to a specific post
* and register them to the Schema
*/
foreach ( $post_field_groups as $key => $group ) {
if ( empty( $group['field_group'] ) || ! is_array( $group['field_group'] ) ) {
continue;
}
$post_object = get_post( (int) $group['post_id'] );
if ( ! $post_object instanceof \WP_Post ) {
continue;
}
$field_group = $group['field_group'];
$post_type = get_post_type_object( $post_object->post_type );
$field_name = isset( $field_group['graphql_field_name'] ) ? $field_group['graphql_field_name'] : Config::camel_case( $field_group['title'] );
$field_group['type'] = 'group';
$field_group['name'] = $field_name;
$description = $field_group['description'] ? $field_group['description'] . ' | ' : '';
$config = [
'name' => $field_name,
'description' => $description . sprintf( __( 'Added to the GraphQL Schema because the ACF Field Group "%1$s" was assigned to an individual post of the post_type: "%2$s". The group will be present in the Schema for the "%3$s" Type, but will only resolve if the entity has content saved.', 'wp-graphql-acf' ), $field_group['title'], $post_type->name, $post_type->graphql_plural_name ),
'acf_field' => $field_group,
'acf_field_group' => null,
'resolve' => function( $root ) use ( $field_group ) {
return isset( $root ) ? $root : null;
}
];
$this->register_graphql_field( $post_type->graphql_single_name, $field_name, $config );
}
}
protected function add_acf_fields_to_options_pages() {
// @todo: Coming soon
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment