$attributes Attribute names (labels) and selected values. */ public static function line( array $attributes ): string { $parts = array(); foreach ( $attributes as $name => $value ) { $name = self::clean( (string) $name ); $value = self::clean( (string) $value ); if ( '' === $name || '' === $value || self::is_size( $name ) ) { continue; } $parts[] = $name . ': ' . $value; if ( count( $parts ) >= self::MAX_ATTRIBUTES ) { break; } } if ( array() === $parts ) { return ''; } return 'The shopper selected this variant of the product: ' . implode( '; ', $parts ) . '. Show the product in this variant, even if image 2 shows another one.'; } /** * Letters, digits, spaces, hyphens, apostrophes, ampersands and slashes only; shortened. * * @param string $text Name or value. */ private static function clean( string $text ): string { $text = (string) preg_replace( "/[^\\p{L}\\p{N}\\-'&\\/ ]+/u", ' ', $text ); $text = trim( (string) preg_replace( '/\s+/u', ' ', $text ) ); return trim( function_exists( 'mb_substr' ) ? mb_substr( $text, 0, self::MAX_LENGTH ) : substr( $text, 0, self::MAX_LENGTH ) ); } /** * Whether an attribute name means size. * * @param string $name Cleaned name. */ private static function is_size( string $name ): bool { $lower = function_exists( 'mb_strtolower' ) ? mb_strtolower( $name ) : strtolower( $name ); foreach ( (array) preg_split( "/[\\s\\-'\\/&]+/u", $lower ) as $word ) { if ( in_array( $word, self::SIZE_WORDS, true ) ) { return true; } } return false; } }