ACF multiple select field type
-
Hello,
Thanks for your work on this plugin.
I saw this could be a related ticket: https://ww.wp.xz.cn/support/topic/import-user-meta-acf/Actually, I have an ACF field configured as “select” type but with “multiple” option being false. This ensures we can only select a single value from the list, and it’s stored as a string, not as an (serialized) array in the DB.
Unfortunately, when I add a value in a column and import that, it is stored as an array with a single value, serialized.
I can see this is due to ACUI_ACF::import method only checking if the field type is “select” to determine if this is a “multiple” field type. It would be great if it also checked the “multiple” configuration inside this field.
Don’t hesitate if you need further information, or even an updated code from ACUI_ACF class for this particular case.
Best regards.
-
This would be great:
an updated code from ACUI_ACF class for this particular case
Or tell me how we can reproduce the problem and we will fix it.
Hello @carazo,
Thanks for your quick reply. Since I cannot upload any file here, I will paste the code directly.
The corresponding git patch:From dc1f839aa1ca913ad5455af07a26ea4b12181d85 Mon Sep 17 00:00:00 2001 From: Lionel Pointet <[email protected]> Date: Wed, 10 Mar 2021 08:38:22 +0100 Subject: [PATCH] Fix ACUI_ACF class for multiple select ACF fields --- .../addons/advanced-custom-fields.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/wp-content/plugins/import-users-from-csv-with-meta/addons/advanced-custom-fields.php b/wp-content/plugins/import-users-from-csv-with-meta/addons/advanced-custom-fields.php index 4bd0272..e02af36 100644 --- a/wp-content/plugins/import-users-from-csv-with-meta/addons/advanced-custom-fields.php +++ b/wp-content/plugins/import-users-from-csv-with-meta/addons/advanced-custom-fields.php @@ -43,7 +43,6 @@ class ACUI_ACF{ function import( $headers, $row, $user_id ){ $fields_positions = array(); $types = $this->get_user_fields_types(); - $types_multiple = array( 'select', 'checkbox', 'radio', 'button_group' ); foreach ( $types as $key => $type ) { $pos = array_search( $key, $headers ); @@ -62,14 +61,14 @@ class ACUI_ACF{ }*/ // slugs in relationship - if( $types[ $key ] == 'relationship' && (string)(int)$data[0] != $data[0] ){ + if( $types[ $key ][ 'type' ] == 'relationship' && (string)(int)$data[0] != $data[0] ){ // @todo $data is undefined here, maybe $row was meant instead? $data = explode( ',', $row[ $pos ] ); foreach ( $data as $it => $slug ) { $data[ $it ] = $this->get_post_id_by_slug( $slug ); } } - elseif( in_array( $types[ $key ], $types_multiple ) ){ + elseif( $types[ $key ][ 'multiple' ] ){ $data = explode( ',', $row[ $pos ] ); array_filter( $data, function( $value ){ return $value !== ''; } ); } @@ -123,13 +122,18 @@ class ACUI_ACF{ function get_user_fields_types(){ $fields = $this->get_user_fields(); $fields_keys = array(); + $types_multiple = array( 'select', 'checkbox', 'radio', 'button_group' ); if( empty( $fields ) ) return array(); foreach ( $fields as $group => $fields_of_group ){ foreach ( $fields_of_group as $field ){ - $fields_keys[ $field['name'] ] = $field['type']; + $fields_keys[ $field['name'] ] = [ + 'type' => $field['type'], + // 'select' type has a 'multiple' key which can be 0 or 1 + 'multiple' => !empty( $field['multiple'] ) || ( !isset( $field['multiple'] ) && in_array( $field['type'], $types_multiple ) ), + ]; } } @@ -172,6 +176,7 @@ class ACUI_ACF{ if ( 0 == $p->post_parent && count( $revparts ) == $count + 1 && $p->post_name == $revparts[ $count ] ) { $foundid = $page->ID; + // @todo $post_type is undefined here if ( $page->post_type == $post_type ) { break; } -- 2.28.0.windows.1And the complete file:
<?php if ( ! defined( 'ABSPATH' ) ) exit; if( !is_plugin_active( 'advanced-custom-fields-pro/acf.php' ) && !is_plugin_active( 'advanced-custom-fields/acf.php' ) ){ return; } class ACUI_ACF{ function __construct(){ add_filter( 'acui_restricted_fields', array( $this, 'restricted_fields' ), 10, 1 ); add_filter( 'acui_not_meta_fields', array( $this, 'restricted_fields' ), 10, 1 ); add_action( 'acui_documentation_after_plugins_activated', array( $this, 'documentation' ) ); add_action( 'post_acui_import_single_user', array( $this, 'import' ), 10, 3 ); } function restricted_fields( $acui_restricted_fields ){ return array_merge( $acui_restricted_fields, $this->get_user_fields_keys() ); } function documentation(){ $fields = $this->get_user_fields(); ?> <tr valign="top"> <th scope="row"><?php _e( "Advaced Custom Fields is activated", 'import-users-from-csv-with-meta' ); ?></th> <td> <?php _e( "You can import those fields, look at every group which fields you can import using the column names shown below.", 'import-users-from-csv-with-meta' ); ?>. <ul style="list-style:disc outside none; margin-left:2em;"> <?php foreach ( $this->get_user_fields() as $group => $fields ): ?> <li><?php _e( "Group name", 'import-users-from-csv-with-meta' ); ?>: <em><?php echo $group; ?></em></li> <ul style="list-style:square inside none; margin-left:2em;"> <?php foreach ( $fields as $field ): ?> <li><?php echo $field['label']; ?> <em>(type: <?php echo $field['type']; ?>)</em> - Column name in the CSV: <strong><?php echo $field['name']; ?></strong></li> <?php endforeach; ?> </ul> <?php endforeach; ?> </ul> </td> </tr> <?php } function import( $headers, $row, $user_id ){ $fields_positions = array(); $types = $this->get_user_fields_types(); foreach ( $types as $key => $type ) { $pos = array_search( $key, $headers ); if( $pos === FALSE ) continue; $fields_positions[ $pos ] = $key; } foreach ( $fields_positions as $pos => $key ) { /*$preexisting_values = get_field( $key, "user_" . $user_id ); if( !empty( $preexisting_values ) ){ $data = array_unique( array_merge( $preexisting_values, $data ) ); $data = array_filter( $data, function( $value ) { return !is_null( $value ) && $value !== '' && $value != 0; } ); }*/ // slugs in relationship if( $types[ $key ][ 'type' ] == 'relationship' && (string)(int)$data[0] != $data[0] ){ // @todo $data is undefined here, maybe $row was meant instead? $data = explode( ',', $row[ $pos ] ); foreach ( $data as $it => $slug ) { $data[ $it ] = $this->get_post_id_by_slug( $slug ); } } elseif( $types[ $key ][ 'multiple' ] ){ $data = explode( ',', $row[ $pos ] ); array_filter( $data, function( $value ){ return $value !== ''; } ); } else{ $data = $row[ $pos ]; } update_field( $key, $data, "user_" . $user_id ); } } function get_user_fields(){ $post_id = "user_new"; $fields = array(); $args = array( 'user_id' => 'new', 'user_form' => '#your-profile' ); $field_groups = acf_get_field_groups( array( 'user_id' => 'new', 'user_form' => '#your-profile' ) ); if( empty($field_groups) ) return; acf_form_data( array( 'post_id' => "user_new", 'nonce' => 'user' ) ); foreach( $field_groups as $field_group ) { $fields[ $field_group['title'] ] = acf_get_fields( $field_group ); } return $fields; } function get_user_fields_keys(){ $fields = $this->get_user_fields(); $fields_keys = array(); if( empty( $fields ) ) return array(); foreach ( $fields as $group => $fields_of_group ){ foreach ( $fields_of_group as $field ){ $fields_keys[] = $field['name']; } } return $fields_keys; } function get_user_fields_types(){ $fields = $this->get_user_fields(); $fields_keys = array(); $types_multiple = array( 'select', 'checkbox', 'radio', 'button_group' ); if( empty( $fields ) ) return array(); foreach ( $fields as $group => $fields_of_group ){ foreach ( $fields_of_group as $field ){ $fields_keys[ $field['name'] ] = [ 'type' => $field['type'], // 'select' type has a 'multiple' key which can be 0 or 1 'multiple' => !empty( $field['multiple'] ) || ( !isset( $field['multiple'] ) && in_array( $field['type'], $types_multiple ) ), ]; } } return $fields_keys; } function get_post_id_by_slug( $slug ){ global $wpdb; $page_path = rawurlencode( urldecode( $slug ) ); $page_path = str_replace( '%2F', '/', $page_path ); $page_path = str_replace( '%20', ' ', $page_path ); $parts = explode( '/', trim( $page_path, '/' ) ); $parts = array_map( 'sanitize_title_for_query', $parts ); $escaped_parts = esc_sql( $parts ); $in_string = "'" . implode( "','", $escaped_parts ) . "'"; $sql = "SELECT ID, post_name, post_parent, post_type FROM $wpdb->posts WHERE post_name IN ($in_string)"; $pages = $wpdb->get_results( $sql, OBJECT_K ); $revparts = array_reverse( $parts ); $foundid = 0; foreach ( (array) $pages as $page ) { if ( $page->post_name == $revparts[0] ) { $count = 0; $p = $page; while ( 0 != $p->post_parent && isset( $pages[ $p->post_parent ] ) ) { $count++; $parent = $pages[ $p->post_parent ]; if ( ! isset( $revparts[ $count ] ) || $parent->post_name != $revparts[ $count ] ) { break; } $p = $parent; } if ( 0 == $p->post_parent && count( $revparts ) == $count + 1 && $p->post_name == $revparts[ $count ] ) { $foundid = $page->ID; // @todo $post_type is undefined here if ( $page->post_type == $post_type ) { break; } } } } return $foundid; } } new ACUI_ACF();FYI, I added 2 “@todo” comments in places where some variables are undefined, I’m not sure what were the use cases and it was not part of mine anyway.
I’m using a workaround before you fix this issue by filtering the value before ACF updates the value:
/** * Ensure we import correctly data from ACF field groups. * Import users and customers with meta plugin incorrectly stores serialized arrays for non-multiple select field type values. * * @param mixed $value * @param string|int $post_id * @param array $field * * @return mixed */ function multiple_select_acf_values( $value, $post_id, $field ) { if( 'select' === $field['type'] && !$field['multiple'] && is_array( $value ) ) { $value = array_shift( $value ); } return $value; } add_filter( 'acf/update_value', 'multiple_select_acf_values', 10, 3 );Don’t hesitate to contact me if you need.
Thanks for your help! You are great.
Respect to todos:
1) data seems to be useful when I used preexisting value, now it seems it is not useful
2) $post_type would need to be $p->post_type (anyway I have moved this function to the class where it should be).I have just included it and I am going to make the update.
Please check and tell me if all works as it should.
Hi,
Thank you for this update. It works as expected!
I can see the “get_post_id_by_slug” method has been moved but its call from ACUI_ACF class hasn’t been updated though.
I guess$this->get_post_id_by_slug( $slug );should beACUI_Helper::get_post_id_by_slug( $slug );on line 68.Thanks anyway for your prompt responses.
Yes I know, I did not change all the trunk.
Sorry, I will include in next version. We are so busy that sometimes we do not take care enough.
The topic ‘ACF multiple select field type’ is closed to new replies.