| @@ -80,12 +80,35 @@ | ||
| 80 | 80 | ) |
| 81 | 81 | ); |
| 82 | 82 | |
| 83 | 83 | foreach ( $fields as $field ) { |
| 84 | - // old code | |
| 85 | - // $options['acf_fields_' . $field->post_name] = DropDown::prepare_filters( $field->post_title ); | |
| 86 | - // new code | |
| 87 | - $options['acf_fields_' . $field->post_excerpt] = DropDown::prepare_filters( $field->post_title ); | |
| 84 | + // The field name, not the field key: that is what the value is | |
| 85 | + // stored under, and so what Product::get_product_meta() reads. | |
| 86 | + $key = 'acf_fields_' . $field->post_excerpt; | |
| 87 | + $choices = self::get_acf_field_choices( $field ); | |
| 88 | + | |
| 89 | + /** | |
| 90 | + * A field with a fixed set of choices (checkbox, select, radio) | |
| 91 | + * is matched against that set, so it gets the list conditions | |
| 92 | + * and a dropdown of its own options. Free text fields have no | |
| 93 | + * options to offer and keep the string conditions. | |
| 94 | + */ | |
| 95 | + if ( empty( $choices ) ) { | |
| 96 | + $options[ $key ] = DropDown::prepare_filters( $field->post_title ); | |
| 97 | + | |
| 98 | + continue; | |
| 99 | + } | |
| 100 | + | |
| 101 | + $options[ $key ] = DropDown::prepare_filters( | |
| 102 | + $field->post_title, | |
| 103 | + 'select', | |
| 104 | + array( | |
| 105 | + 'type' => 'select', | |
| 106 | + 'option_type' => 'manual', | |
| 107 | + 'multiple' => true, | |
| 108 | + 'options' => $choices, | |
| 109 | + ) | |
| 110 | + ); | |
| 88 | 111 | } |
| 89 | 112 | } |
| 90 | 113 | } |
| 91 | 114 | |
| @@ -100,7 +123,37 @@ | ||
| 100 | 123 | 'optionGroup' => esc_html__( 'Advance Custom Fields (ACF)', 'disco' ), |
| 101 | 124 | 'options' => $options, |
| 102 | 125 | 'disabled' => !Disco::is_pro(), // Disable if not pro. |
| 103 | 126 | ); |
| 127 | + } | |
| 128 | + | |
| 129 | + /** | |
| 130 | + * The choices an ACF field offers, keyed by the value that gets stored. | |
| 131 | + * | |
| 132 | + * Read from the field post's own settings rather than through the ACF API: | |
| 133 | + * acf_get_fields() is avoided here because it misbehaves with repeaters and | |
| 134 | + * returns trashed fields, and the settings blob carries everything needed. | |
| 135 | + * | |
| 136 | + * @param \WP_Post $field ACF field post. | |
| 137 | + * @return array<string, string> Stored value => label, empty when the field has no fixed choices. | |
| 138 | + */ | |
| 139 | + private static function get_acf_field_choices( $field ): array { | |
| 140 | + $settings = maybe_unserialize( $field->post_content ); | |
| 141 | + | |
| 142 | + if ( ! is_array( $settings ) || empty( $settings['choices'] ) || ! is_array( $settings['choices'] ) ) { | |
| 143 | + return array(); | |
| 144 | + } | |
| 145 | + | |
| 146 | + $choices = array(); | |
| 147 | + | |
| 148 | + foreach ( $settings['choices'] as $value => $label ) { | |
| 149 | + if ( ! is_scalar( $label ) ) { | |
| 150 | + continue; | |
| 151 | + } | |
| 152 | + | |
| 153 | + $choices[ (string) $value ] = (string) $label; | |
| 154 | + } | |
| 155 | + | |
| 156 | + return $choices; | |
| 104 | 157 | } |
| 105 | 158 | |
| 106 | 159 | } |