Skip to content

Commit

Permalink
Merge pull request #193 from wp-graphql/fix/172-cloning-group-fields
Browse files Browse the repository at this point in the history
fix: cloning group fields
  • Loading branch information
jasonbahl committed Apr 24, 2024
2 parents d44413e + 054a010 commit 9a81fa1
Show file tree
Hide file tree
Showing 18 changed files with 65,147 additions and 312 deletions.
493 changes: 248 additions & 245 deletions composer.lock

Large diffs are not rendered by default.

36 changes: 27 additions & 9 deletions docker/app.setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ ACF_VERSION=${ACF_VERSION-"latest"}
ACF_PRO=${ACF_PRO-false}
WPGRAPHQL_CONTENT_BLOCKS=${WPGRAPHQL_CONTENT_BLOCKS-false}
WPGRAPHQL_CONTENT_BLOCKS_VERSION=${WPGRAPHQL_CONTENT_BLOCKS_VERSION-"latest"}
WPGRAPHQL_GIT_REPO=${WPGRAPHQL_GIT_REPO-}
WPGRAPHQL_GIT_BRANCH=${WPGRAPHQL_GIT_BRANCH-"develop"}

#// fallback to hello.php as a hack. dont love this, but we have to pass a slug.
export WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_SLUG=${WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_SLUG-'hello.php'}
Expand All @@ -36,15 +38,31 @@ apt-get -y update
apt-get -y install jq

if [ ! -f "${PLUGINS_DIR}/wp-graphql/wp-graphql.php" ]; then
# WPGRAPHQL_VERSION in format like v1.2.3 or latest
echo "Install wp-graphql version (${WPGRAPHQL_VERSION})"
if [[ -z ${WPGRAPHQL_VERSION} || "${WPGRAPHQL_VERSION}" == "latest" ]]; then
echo "Installing latest WPGraphQL from WordPress.org"
wp plugin install wp-graphql --activate --allow-root
else
echo "Installing WPGraphQL from Github"
wp plugin install "https://downloads.wordpress.org/plugin/wp-graphql.${WPGRAPHQL_VERSION-1.4.3}.zip" --allow-root --activate
fi


# if WPGRAPHQL_GIT_REPO is set, we'll install from the repo
if [[ -n ${WPGRAPHQL_GIT_REPO} ]]; then
echo "Installing WPGraphQL from GitHub repo ${WPGRAPHQL_GIT_REPO}"
# Clone the repository
git clone -b ${WPGRAPHQL_GIT_BRANCH} ${WPGRAPHQL_GIT_REPO} "${PLUGINS_DIR}/wp-graphql"
# Navigate to the plugin directory
cd "${PLUGINS_DIR}/wp-graphql"
# Install dependencies with Composer
composer install --no-dev
# Optionally activate the plugin using wp-cli
wp plugin activate wp-graphql --allow-root
else
# WPGRAPHQL_VERSION in format like v1.2.3 or latest
echo "Install wp-graphql version (${WPGRAPHQL_VERSION})"
if [[ -z ${WPGRAPHQL_VERSION} || "${WPGRAPHQL_VERSION}" == "latest" ]]; then
echo "Installing latest WPGraphQL from WordPress.org"
wp plugin install wp-graphql --activate --allow-root
else
echo "Installing WPGraphQL from Github"
wp plugin install "https://downloads.wordpress.org/plugin/wp-graphql.${WPGRAPHQL_VERSION-1.4.3}.zip" --allow-root --activate
fi
fi

fi

# Activate the plugin
Expand Down
3 changes: 0 additions & 3 deletions phpstan/constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
* Constants defined in this file are to help phpstan analyze code where constants outside the plugin (WordPress core constants, etc) are being used
*/

define( 'WP_LANG_DIR', true );
define( 'SAVEQUERIES', true );
define( 'WPGRAPHQL_PLUGIN_URL', true );
define( 'WP_CONTENT_DIR', true );
define( 'WP_PLUGIN_DIR', true );
define( 'PHPSTAN', true );
24 changes: 15 additions & 9 deletions src/Admin/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,39 +139,45 @@ function ( $acf_field ) use ( $field_type ) {
* Handle the AJAX callback for converting ACF Location settings to GraphQL Types
*/
public function graphql_types_ajax_callback(): void {
if ( ! isset( $_POST['data'] ) ) {
if ( ! isset( $_REQUEST['data'] ) ) {
echo esc_html( __( 'No location rules were found', 'wpgraphql-acf' ) );

/** @noinspection ForgottenDebugOutputInspection */
wp_die();
}

if ( empty( $_REQUEST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( $_REQUEST['nonce'] ), 'wp_graphql_acf' ) ) {
wp_send_json_error();
}

$form_data = [];
$sanitized_post_data = wp_strip_all_tags( $_POST['data'] );
$sanitized_post_data = wp_strip_all_tags( $_REQUEST['data'] );

parse_str( $sanitized_post_data, $form_data );

if ( empty( $form_data ) || ! isset( $form_data['acf_field_group'] ) ) {
if ( empty( $form_data ) ) {
wp_send_json( __( 'No form data.', 'wpgraphql-acf' ) );
}

if ( empty( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( $_POST['nonce'] ), 'wp_graphql_acf' ) ) {
wp_send_json_error();
if ( empty( $form_data['acf_field_group']['location'] ) ) {
wp_send_json( __( 'No field group locations found.', 'wpgraphql-acf' ) );
}

$field_group = $form_data['acf_field_group'];
$rules = new LocationRules( [ $field_group ] );

$rules = new LocationRules( [ $field_group ] );
$rules->determine_location_rules();

$group_title = $field_group['title'] ?? '';
$group_title = $form_data['post_title'] ?? '';
$group_name = $field_group['graphql_field_name'] ?? $group_title;
$group_name = \WPGraphQL\Utils\Utils::format_field_name( $group_name, true );

$all_rules = $rules->get_rules();
if ( isset( $all_rules[ $group_name ] ) ) {

if ( isset( $all_rules[ strtolower( $group_name ) ] ) ) {
wp_send_json(
[
'graphql_types' => array_values( $all_rules[ $group_name ] ),
'graphql_types' => array_values( $all_rules[ strtolower( $group_name ) ] ),
]
);
}
Expand Down
11 changes: 8 additions & 3 deletions src/FieldConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ public function get_parent_graphql_type_name( array $acf_field, ?string $prepend
} elseif ( ! empty( $parent_group ) ) {
$type_name = $this->registry->get_field_group_graphql_type_name( $parent_group );
$type_name = $this->get_parent_graphql_type_name( $parent_group, $type_name );
} else {
$type_name = $this->get_parent_graphql_type_name( $acf_field, '' );
}
}

Expand Down Expand Up @@ -411,6 +409,11 @@ public function resolve_field( $root, array $args, AppContext $context, ResolveI
return $this->prepare_acf_field_value( $root[ $field_config['__key'] ], $node, $node_id, $field_config );
}

// Else check if the values are being passed down via the name
if ( isset( $field_config['name'] ) && ! empty( $root[ '_' . $field_config['name'] ] ) ) {
return $this->prepare_acf_field_value( $root[ '_' . $field_config['name'] ], $node, $node_id, $field_config );
}

// Else check if the values are being passed down via the name
if ( isset( $field_config['name'] ) && ! empty( $root[ $field_config['name'] ] ) ) {
return $this->prepare_acf_field_value( $root[ $field_config['name'] ], $node, $node_id, $field_config );
Expand Down Expand Up @@ -603,7 +606,9 @@ public function register_graphql_connections( array $config ): void {
}

// Register the connection to the Field Group Type
register_graphql_connection( $connection_config );
if ( defined( 'WPGRAPHQL_VERSION' ) && version_compare( WPGRAPHQL_VERSION, '1.23.0', '<=' ) ) {
register_graphql_connection( $connection_config );
}

// Register the connection to the Field Group Fields Interface
register_graphql_connection( array_merge( $connection_config, [ 'fromType' => $type_name . '_Fields' ] ) );
Expand Down
40 changes: 13 additions & 27 deletions src/FieldType/CloneField.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,20 @@ public static function register_field_type(): void {
'clone',
[
'graphql_type' => static function ( FieldConfig $field_config, AcfGraphQLFieldType $acf_field_type ) {

$sub_field_group = $field_config->get_raw_acf_field();
$parent_type = $field_config->get_parent_graphql_type_name( $sub_field_group );
$field_name = $field_config->get_graphql_field_name();
$registry = $field_config->get_registry();
$type_name = Utils::format_type_name( $parent_type . ' ' . $field_name );
$prefix_name = $sub_field_group['prefix_name'] ?? false;

// If the "Clone" field has not set a "prefix_name",
// return NULL to prevent registering a new type
// The cloned
if ( ! $prefix_name ) {
return 'NULL';
}

$cloned_fields = array_filter(
array_map(
static function ( $cloned ) {
Expand All @@ -45,37 +52,16 @@ static function ( $cloned ) use ( $field_config ) {
);

if ( ! empty( $cloned_group_interfaces ) ) {
if ( ! $prefix_name ) {
register_graphql_interfaces_to_types( $cloned_group_interfaces, [ $parent_type ] );
} else {
$type_name = self::register_prefixed_clone_field_type( $type_name, $sub_field_group, $cloned_fields, $field_config );
register_graphql_interfaces_to_types( $cloned_group_interfaces, [ $type_name ] );
return $type_name;
}
$type_name = self::register_prefixed_clone_field_type( $type_name, $sub_field_group, $cloned_fields, $field_config );
register_graphql_interfaces_to_types( $cloned_group_interfaces, [ $type_name ] );
return $type_name;
}


// If the "Clone" field has cloned individual fields
if ( ! empty( $cloned_fields ) ) {

// If the clone field is NOT set to use "prefix_name"
if ( ! $prefix_name ) {

// Map over the cloned fields and register them to the parent type
foreach ( $cloned_fields as $cloned_field ) {
$field_config = $registry->map_acf_field_to_graphql( $cloned_field, $sub_field_group );
if ( ! empty( $field_config['name'] ) ) {
register_graphql_field( $parent_type, $field_config['name'], $field_config );
}
}

// If the Clone field is set to use "prefix_name"
// Register a new Object Type with the cloned fields, and return
// the new type.
} else {
return self::register_prefixed_clone_field_type( $type_name, $sub_field_group, $cloned_fields, $field_config );
}
return self::register_prefixed_clone_field_type( $type_name, $sub_field_group, $cloned_fields, $field_config );
}

// Bail by returning a NULL type
return 'NULL';
},
Expand Down
2 changes: 1 addition & 1 deletion src/FieldType/FlexibleContent.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ static function ( $field ) use ( $layout ) {

return isset( $field['parent_layout'] ) && $layout['key'] === $field['parent_layout'] ? $field : null;
},
acf_get_raw_fields( $layout['key'] )
acf_get_fields( $layout['key'] )
)
);

Expand Down
53 changes: 53 additions & 0 deletions src/FieldType/Group.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,59 @@ public static function register_field_type(): void {
$sub_field_group['graphql_field_name'] = $type_name;
$sub_field_group['parent'] = $sub_field_group['key'];

// Determine if the group is a clone field
$cloned_type = null;

// if the field group is actually a cloned field group, we
// can return the GraphQL Type of the cloned field group
if ( isset( $sub_field_group['_clone'] ) ) {
$cloned_from = acf_get_field( $sub_field_group['_clone'] );

if ( ! empty( $cloned_from['clone'] ) && is_array( $cloned_from['clone'] ) ) {
foreach ( $cloned_from['clone'] as $clone_field ) {
$cloned_group = acf_get_field_group( $clone_field );

// if there is no cloned group, continue to the next clone field
if ( ! $cloned_group ) {
continue;
}

// if the cloned group is not an ACF field group, continue to the next clone field
if ( ! acf_is_field_group( $cloned_group ) ) {
continue;
}

// if the cloned group should not show in GraphQL, continue to the next clone field
if ( ! $field_config->get_registry()->should_field_group_show_in_graphql( $cloned_group ) ) {
continue;
}

// determine the GraphQL Type of the cloned field group
$cloned_type = $field_config->get_registry()->get_field_group_graphql_type_name( $cloned_group );
break;
}
}
}

// If the group is a clone field, return the cloned type instead of registering
// another Type in the registry
if ( $cloned_type ) {
$cloned_type_name = Utils::format_type_name( $cloned_type . ' ' . $field_name );
if ( $field_config->get_registry()->has_registered_field_group( $cloned_type_name ) ) {
return $cloned_type_name;
}

$sub_field_group['graphql_type_name'] = $cloned_type_name;
$sub_field_group['graphql_field_name'] = $cloned_type_name;
$field_config->get_registry()->register_acf_field_groups_to_graphql(
[
$sub_field_group,
]
);

return $cloned_type_name;
}

$field_config->get_registry()->register_acf_field_groups_to_graphql(
[
$sub_field_group,
Expand Down
35 changes: 29 additions & 6 deletions src/FieldType/Repeater.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,38 @@ public static function register_field_type(): void {
$sub_field_group['graphql_field_name'] = $type_name;
$sub_field_group['locations'] = null;

if ( ! empty( $sub_field_group['__key'] ) ) {
$cloned_from = acf_get_field( $sub_field_group['__key'] );
$cloned_parent = ! empty( $cloned_from ) ? $field_config->get_parent_graphql_type_name( $cloned_from ) : null;
if ( ! empty( $cloned_parent ) ) {
$type_name = Utils::format_type_name( $cloned_parent . ' ' . $field_name );
return [ 'list_of' => $type_name ];
// Determine if the group is a clone field
$cloned_type = null;

// if the field group is actually a cloned field group, we
// can return the GraphQL Type of the cloned field group
if ( isset( $sub_field_group['_clone'] ) ) {
$cloned_from = acf_get_field( $sub_field_group['_clone'] );

if ( ! empty( $cloned_from['clone'] ) && is_array( $cloned_from['clone'] ) ) {
foreach ( $cloned_from['clone'] as $clone_field ) {
$cloned_group = acf_get_field_group( $clone_field );

if ( ! $cloned_group ) {
continue;
}

if ( ! $field_config->get_registry()->should_field_group_show_in_graphql( $cloned_group ) ) {
continue;
}

$cloned_type = $field_config->get_registry()->get_field_group_graphql_type_name( $cloned_group );
break;
}
}
}

// If the group is a clone field, return the cloned type instead of registering
// another Type in the registry
if ( $cloned_type ) {
return [ 'list_of' => Utils::format_type_name( $cloned_type . ' ' . $field_name ) ];
}


$field_config->get_registry()->register_acf_field_groups_to_graphql(
[
Expand Down

0 comments on commit 9a81fa1

Please sign in to comment.