feat: add metadata url transformer
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace WPContentSync\Url;
|
||||
|
||||
final class MetadataUrlTransformer {
|
||||
private UrlTransformer $url_transformer;
|
||||
|
||||
public function __construct( UrlTransformer $url_transformer ) {
|
||||
$this->url_transformer = $url_transformer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform URLs within a metadata value.
|
||||
*
|
||||
* @param mixed $value Metadata value.
|
||||
* @param UrlMappingCollection $mappings URL mappings.
|
||||
* @return mixed
|
||||
*/
|
||||
public function transformValue( $value, UrlMappingCollection $mappings ) {
|
||||
if ( is_array( $value ) ) {
|
||||
return $this->transformArray( $value, $mappings );
|
||||
}
|
||||
|
||||
if ( ! is_string( $value ) ) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ( $this->isSerialized( $value ) ) {
|
||||
// phpcs:ignore -- Required to transform serialized metadata while preserving valid string lengths.
|
||||
$unserialized = unserialize( $value, array( 'allowed_classes' => false ) );
|
||||
|
||||
// phpcs:ignore -- Required to reserialize metadata with updated string lengths.
|
||||
return serialize( $this->transformValue( $unserialized, $mappings ) );
|
||||
}
|
||||
|
||||
if ( $this->isJsonObjectOrArray( $value ) ) {
|
||||
$decoded = json_decode( $value, true );
|
||||
|
||||
if ( is_array( $decoded ) && JSON_ERROR_NONE === json_last_error() ) {
|
||||
$encoded = wp_json_encode( $this->transformArray( $decoded, $mappings ) );
|
||||
|
||||
if ( is_string( $encoded ) ) {
|
||||
return $encoded;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->url_transformer->transformString( $value, $mappings );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform URLs within a metadata array.
|
||||
*
|
||||
* @param array<mixed> $value Metadata array.
|
||||
* @param UrlMappingCollection $mappings URL mappings.
|
||||
* @return array<mixed>
|
||||
*/
|
||||
private function transformArray( array $value, UrlMappingCollection $mappings ): array {
|
||||
$transformed = array();
|
||||
|
||||
foreach ( $value as $key => $item ) {
|
||||
$transformed[ $key ] = $this->transformValue( $item, $mappings );
|
||||
}
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
|
||||
private function isSerialized( string $value ): bool {
|
||||
$trimmed = trim( $value );
|
||||
|
||||
if ( 'N;' === $trimmed ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( 'b:0;' === $trimmed ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! preg_match( '/^(?:a|O|s|i|d|b):/', $trimmed ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// phpcs:ignore -- Validation must parse PHP serialized metadata.
|
||||
return false !== @unserialize( $trimmed, array( 'allowed_classes' => false ) );
|
||||
}
|
||||
|
||||
private function isJsonObjectOrArray( string $value ): bool {
|
||||
$trimmed = trim( $value );
|
||||
|
||||
return '' !== $trimmed && in_array( $trimmed[0], array( '{', '[' ), true );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user