get_attributes(); if ( empty( $attributes ) ) { return $proposals; } foreach ( $attributes as $key => $attribute ) { if ( ! $attribute instanceof WC_Product_Attribute ) { continue; } // Only custom/local attributes have a normalizable text name + options. if ( $attribute->is_taxonomy() ) { continue; } $old_name = (string) $attribute->get_name(); $new_name = $this->normalize_name( $old_name ); $old_options = array_map( 'strval', (array) $attribute->get_options() ); $new_options = $this->normalize_options( $old_options ); $name_changed = ( $new_name !== $old_name ); $option_changed = ( $new_options !== $old_options ); if ( ! $name_changed && ! $option_changed ) { continue; } $proposals[] = array( 'field' => (string) $key, 'label' => $old_name, 'before' => $old_name . ': ' . implode( ' | ', $old_options ), 'after' => $new_name . ': ' . implode( ' | ', $new_options ), 'needs_input' => false, 'auto' => true, 'note' => '', ); } return $proposals; } /** * {@inheritDoc} */ public function apply( WC_Product $product, array $input ) { unset( $input ); $result = $this->result(); $attributes = $product->get_attributes(); if ( empty( $attributes ) ) { return $result; } $changed = false; foreach ( $attributes as $key => $attribute ) { if ( ! $attribute instanceof WC_Product_Attribute || $attribute->is_taxonomy() ) { continue; } $old_name = (string) $attribute->get_name(); $new_name = $this->normalize_name( $old_name ); $old_options = array_map( 'strval', (array) $attribute->get_options() ); $new_options = $this->normalize_options( $old_options ); if ( $new_name === $old_name && $new_options === $old_options ) { continue; } $attribute->set_name( $new_name ); $attribute->set_options( $new_options ); $attributes[ $key ] = $attribute; $changed = true; $result->add_change( (string) $key, $old_name, $old_name . ': ' . implode( ' | ', $old_options ), $new_name . ': ' . implode( ' | ', $new_options ) ); } if ( $changed ) { $product->set_attributes( $attributes ); $product->save(); } return $result; } /** * Normalize a custom attribute display name: trim, collapse spaces, Title Case. * * @param string $name Raw name. * @return string */ protected function normalize_name( $name ) { $name = trim( preg_replace( '/\s+/', ' ', (string) $name ) ); if ( '' === $name ) { return $name; } if ( function_exists( 'mb_convert_case' ) ) { return mb_convert_case( $name, MB_CASE_TITLE, 'UTF-8' ); } return ucwords( strtolower( $name ) ); } /** * Normalize a list of attribute option values: trim, collapse whitespace, * drop empties, de-duplicate (case-insensitively, keeping first spelling). * * @param string[] $options Raw options. * @return string[] */ protected function normalize_options( array $options ) { $clean = array(); $seen = array(); foreach ( $options as $value ) { $value = trim( preg_replace( '/\s+/', ' ', (string) $value ) ); if ( '' === $value ) { continue; } $fold = function_exists( 'mb_strtolower' ) ? mb_strtolower( $value, 'UTF-8' ) : strtolower( $value ); if ( isset( $seen[ $fold ] ) ) { continue; } $seen[ $fold ] = true; $clean[] = $value; } return $clean; } }