<?php
declare(strict_types = 1);
namespace Automattic\WooCommerce\EmailEditor\Engine\Renderer\ContentRenderer\Postprocessors;
if (!defined('ABSPATH')) exit;
class Border_Style_Postprocessor implements Postprocessor {
 public function postprocess( string $html ): string {
 $processor = new \WP_HTML_Tag_Processor( $html );
 while ( $processor->next_tag() ) {
 $style = $processor->get_attribute( 'style' );
 if ( null !== $style && true !== $style ) {
 $processed_style = $this->process_style( $style );
 if ( $processed_style !== $style ) {
 $processor->set_attribute( 'style', $processed_style );
 }
 }
 }
 return $processor->get_updated_html();
 }
 private function process_style( string $style ): string {
 // Parse style into associative array.
 $styles = array();
 foreach ( explode( ';', $style ) as $declaration ) {
 if ( strpos( $declaration, ':' ) !== false ) {
 list( $prop, $value ) = array_map( 'trim', explode( ':', $declaration, 2 ) );
 $styles[ strtolower( $prop ) ] = $value;
 }
 }
 $should_update_style = false;
 // Collect border-widths and styles.
 $border_widths = array();
 $border_styles = array();
 foreach ( $styles as $prop => $value ) {
 if ( 'border' === $prop ) {
 $border_width = $this->extract_width_from_shorthand_value( $value );
 if ( $border_width ) {
 $border_widths['top'] = $border_width;
 $border_widths['right'] = $border_width;
 $border_widths['bottom'] = $border_width;
 $border_widths['left'] = $border_width;
 }
 $border_style = $this->extract_style_from_shorthand_value( $value );
 if ( $border_style ) {
 $border_styles['top'] = $border_style;
 $border_styles['right'] = $border_style;
 $border_styles['bottom'] = $border_style;
 $border_styles['left'] = $border_style;
 }
 }
 if ( preg_match( '/^border-(top|right|bottom|left)$/', $prop, $matches ) ) {
 $border_width = $this->extract_width_from_shorthand_value( $value );
 if ( $border_width ) {
 $border_widths[ $matches[1] ] = $border_width;
 }
 $border_style = $this->extract_style_from_shorthand_value( $value );
 if ( $border_style ) {
 $border_styles[ $matches[1] ] = $border_style;
 }
 }
 if ( 'border-width' === $prop ) {
 $border_widths = array_merge( $border_widths, $this->expand_shorthand_value( $value ) );
 }
 if ( preg_match( '/^border-(top|right|bottom|left)-width$/', $prop, $matches ) ) {
 $border_widths[ $matches[1] ] = $value;
 }
 if ( 'border-style' === $prop ) {
 $border_styles = array_merge( $border_styles, $this->expand_shorthand_value( $value ) );
 // Remove the original border style declaration, as it will be added later.
 unset( $styles[ $prop ] );
 $should_update_style = true;
 }
 if ( preg_match( '/^border-(top|right|bottom|left)-style$/', $prop, $matches ) ) {
 $border_styles[ $matches[1] ] = $value;
 // Remove the original border style declaration, as it will be added later.
 unset( $styles[ $prop ] );
 $should_update_style = true;
 }
 }
 if ( array_diff( array_keys( $border_widths ), array_keys( $border_styles ) ) ) {
 $should_update_style = true;
 }
 if ( ! $should_update_style ) {
 return $style;
 }
 $border_styles_declarations = array();
 foreach ( $border_widths as $side => $value ) {
 if ( $this->is_nonzero_width( $value ) ) {
 $border_styles_declarations[ "border-$side-style" ] = isset( $border_styles[ $side ] ) ? $border_styles[ $side ] : 'solid';
 }
 }
 // If border style declarations for all sides are present and have the same value, use shorthand syntax.
 if ( 4 === count( $border_styles_declarations ) && 1 === count( array_unique( $border_styles_declarations ) ) ) {
 $border_styles_declarations = array( 'border-style' => array_values( $border_styles_declarations )[0] );
 }
 $merged_styles = array_merge( $styles, $border_styles_declarations );
 $updated_style = '';
 foreach ( $merged_styles as $prop => $value ) {
 if ( '' !== $value ) {
 $updated_style .= $prop . ': ' . $value . '; ';
 }
 }
 return trim( $updated_style );
 }
 private function expand_shorthand_value( string $value ): array {
 $values = preg_split( '/\s+/', trim( $value ) );
 if ( ! is_array( $values ) ) {
 return array();
 }
 $count = count( $values );
 if ( 4 === $count ) {
 return array(
 'top' => $values[0] ?? '',
 'right' => $values[1] ?? '',
 'bottom' => $values[2] ?? '',
 'left' => $values[3] ?? '',
 );
 }
 if ( 3 === $count ) {
 return array(
 'top' => $values[0] ?? '',
 'right' => $values[1] ?? '',
 'bottom' => $values[2] ?? '',
 'left' => $values[1] ?? '',
 );
 }
 if ( 2 === $count ) {
 return array(
 'top' => $values[0] ?? '',
 'right' => $values[1] ?? '',
 'bottom' => $values[0] ?? '',
 'left' => $values[1] ?? '',
 );
 }
 if ( 1 === $count ) {
 return array(
 'top' => $values[0] ?? '',
 'right' => $values[0] ?? '',
 'bottom' => $values[0] ?? '',
 'left' => $values[0] ?? '',
 );
 }
 return array();
 }
 private function extract_width_from_shorthand_value( string $value ): ?string {
 $parts = preg_split( '/\s+/', trim( $value ) );
 if ( ! is_array( $parts ) ) {
 return null;
 }
 foreach ( $parts as $part ) {
 if ( preg_match( '/^\d+([a-z%]+)?$/', $part ) ) {
 return $part;
 }
 }
 return null;
 }
 private function extract_style_from_shorthand_value( string $value ): ?string {
 $parts = preg_split( '/\s+/', trim( $value ) );
 if ( ! is_array( $parts ) ) {
 return null;
 }
 foreach ( $parts as $part ) {
 if ( in_array( $part, array( 'none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset' ), true ) ) {
 return $part;
 }
 }
 return null;
 }
 private function is_nonzero_width( string $width ): bool {
 return preg_match( '/^0([a-z%]+)?$/', trim( $width ) ) ? false : true;
 }
}
