Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions inc/Abilities/DiceFmTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ static function ( string $level, string $message, array $context = array() ) use
'date_end' => $dice_event['date_end'] ?? '',
'venue' => $dice_event['venue'] ?? '',
'url' => $dice_event['url'] ?? '',
'price' => $dice_event['price'] ?? null,
'currency' => $dice_event['currency'] ?? '',
'ticket_types' => $dice_event['ticket_types'] ?? array(),
'timezone' => $dice_event['timezone'] ?? '',
'location' => $dice_event['location'] ?? null,
);
Expand Down Expand Up @@ -293,10 +296,64 @@ private function mapEvent( array $dice_event ): array {
'venueCity' => $venue_city,
'venueState' => $venue_state,
'venueCoordinates' => $venue_coordinates,
'price' => $this->mapPrice( $dice_event ),
'ticketUrl' => $dice_event['url'] ?? '',
);
}

/**
* Map Dice price fields to display format.
*
* @param array $dice_event Raw Dice event.
* @return string
*/
private function mapPrice( array $dice_event ): string {
$currency = strtoupper( trim( (string) ( $dice_event['currency'] ?? 'USD' ) ) );

if ( isset( $dice_event['price'] ) && is_numeric( $dice_event['price'] ) && (float) $dice_event['price'] > 0 ) {
$amount = (float) $dice_event['price'] / 100;
return \DataMachineEvents\Core\PriceFormatter::formatStructured( $amount, $amount, $currency );
}

$ticket_types = $dice_event['ticket_types'] ?? array();
if ( ! is_array( $ticket_types ) || empty( $ticket_types ) ) {
return '';
}

$face_values = array();
$total_values = array();

foreach ( $ticket_types as $ticket_type ) {
if ( ! is_array( $ticket_type ) || empty( $ticket_type['price'] ) || ! is_array( $ticket_type['price'] ) ) {
continue;
}

$price_data = $ticket_type['price'];

if ( isset( $price_data['face_value'] ) && is_numeric( $price_data['face_value'] ) ) {
$face_values[] = (float) $price_data['face_value'] / 100;
}

if ( isset( $price_data['total'] ) && is_numeric( $price_data['total'] ) ) {
$total_values[] = (float) $price_data['total'] / 100;
}
}

if ( ! empty( $face_values ) ) {
return \DataMachineEvents\Core\PriceFormatter::formatStructured( min( $face_values ), max( $face_values ), $currency );
}

if ( ! empty( $total_values ) ) {
return \DataMachineEvents\Core\PriceFormatter::formatStructured( min( $total_values ), max( $total_values ), $currency );
}

if ( isset( $dice_event['price'] ) && is_numeric( $dice_event['price'] ) ) {
return \DataMachineEvents\Core\PriceFormatter::formatStructured( (float) $dice_event['price'] / 100, null, $currency );
}

return '';
}

private function parseDateTimeUtc( string $datetime_utc, string $timezone ): array {
if ( empty( $datetime_utc ) ) {
return array(
Expand Down
4 changes: 4 additions & 0 deletions inc/Cli/DiceFmTestCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ private function outputResult( array $result ): void {
\WP_CLI::log( '[RAW] Date: ' . ( $raw['date'] ?? '' ) );
\WP_CLI::log( '[RAW] Date End: ' . ( $raw['date_end'] ?? '' ) );
\WP_CLI::log( '[RAW] Venue: ' . ( $raw['venue'] ?? '' ) );
\WP_CLI::log( '[RAW] Price: ' . wp_json_encode( $raw['price'] ?? null ) );
\WP_CLI::log( '[RAW] Currency: ' . ( $raw['currency'] ?? '' ) );
\WP_CLI::log( '[RAW] Ticket Types: ' . ( isset( $raw['ticket_types'] ) ? wp_json_encode( $raw['ticket_types'] ) : '[]' ) );
\WP_CLI::log( '[RAW] Timezone: ' . ( $raw['timezone'] ?? '' ) );

if ( isset( $raw['location'] ) && is_array( $raw['location'] ) ) {
Expand All @@ -121,6 +124,7 @@ private function outputResult( array $result ): void {
\WP_CLI::log( '[MAPPED] Venue City: ' . ( $mapped['venueCity'] ?? '(none)' ) );
\WP_CLI::log( '[MAPPED] Venue State: ' . ( $mapped['venueState'] ?? '(none)' ) );
\WP_CLI::log( '[MAPPED] Venue Timezone: ' . ( $mapped['venueTimezone'] ?? '(none)' ) );
\WP_CLI::log( '[MAPPED] Price: ' . ( $mapped['price'] ?? '' ) );
\WP_CLI::log( '[MAPPED] Ticket URL: ' . ( $mapped['ticketUrl'] ?? '' ) );

$issues = $event['issues'] ?? array();
Expand Down
65 changes: 65 additions & 0 deletions inc/Core/PriceFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@

class PriceFormatter {

/**
* Canonical display string for free events.
*/
private const FREE_LABEL = 'Free';

/**
* Format a price range as a display string.
*
Expand Down Expand Up @@ -50,6 +55,56 @@ public static function formatRange( ?float $min, ?float $max = null ): string {
return '$' . number_format( $min, 2 ) . ' - $' . number_format( $max, 2 );
}

/**
* Format a structured price payload into a display string.
*
* Treats explicit free flags and all-zero values as free.
* Non-USD currencies are prefixed with the ISO currency code while preserving
* the existing dollar-based numeric formatting behavior.
*
* @param float|null $min Minimum price.
* @param float|null $max Maximum price.
* @param string $currency ISO currency code.
* @param bool|null $is_free Explicit free signal from source data.
* @return string Formatted price string.
*/
public static function formatStructured( ?float $min = null, ?float $max = null, string $currency = 'USD', ?bool $is_free = null ): string {
if ( true === $is_free ) {
return self::formatFree();
}

$normalized_min = null !== $min ? (float) $min : null;
$normalized_max = null !== $max ? (float) $max : null;

if ( self::isZeroOrLess( $normalized_min ) && self::isZeroOrLess( $normalized_max ) ) {
if ( null !== $normalized_min || null !== $normalized_max ) {
return self::formatFree();
}
return '';
}

$formatted = self::formatRange( $normalized_min, $normalized_max );
if ( '' === $formatted ) {
return '';
}

$currency = strtoupper( trim( $currency ) );
if ( '' === $currency || 'USD' === $currency ) {
return $formatted;
}

return $currency . ' ' . $formatted;
}

/**
* Format a free event label.
*
* @return string
*/
public static function formatFree(): string {
return self::FREE_LABEL;
}

/**
* Parse a price string and extract numeric values.
*
Expand Down Expand Up @@ -91,4 +146,14 @@ public static function parse( string $raw ): array {
public static function isFree( string $raw ): bool {
return preg_match( '/^free$/i', trim( $raw ) ) === 1;
}

/**
* Whether the provided numeric value is null or non-positive.
*
* @param float|null $value Numeric value.
* @return bool
*/
private static function isZeroOrLess( ?float $value ): bool {
return null === $value || $value <= 0;
}
}
55 changes: 54 additions & 1 deletion inc/Steps/EventImport/Handlers/DiceFm/DiceFm.php
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ private function fetch_dice_fm_events( $api_key, $city, $partner_id, ExecutionCo
private function convert_dice_fm_event( $event ) {
$venue_data = $this->extract_venue_data( $event );
$timezone = $event['timezone'] ?? '';
$price = $this->extractPrice( $event );

$start_parsed = $this->parseDateTimeUtc( $event['date'] ?? '', $timezone );
$end_parsed = $this->parseDateTimeUtc( $event['date_end'] ?? '', $timezone );
Expand All @@ -254,7 +255,7 @@ private function convert_dice_fm_event( $event ) {
'endTime' => $end_parsed['time'],
'venue' => sanitize_text_field( $venue_data['venue_name'] ),
'artist' => '',
'price' => '',
'price' => $price,
'ticketUrl' => esc_url_raw( $event['url'] ?? '' ),
'description' => wp_kses_post( $event['description'] ?? '' ),
'venueAddress' => sanitize_text_field( $venue_data['venue_address'] ),
Expand All @@ -267,6 +268,58 @@ private function convert_dice_fm_event( $event ) {
);
}

/**
* Extract and format Dice.fm event pricing.
*
* Supports both top-level cent amount (`price`) and per-ticket pricing
* (`ticket_types[].price`).
*
* @param array $event Raw Dice.fm event data.
* @return string Formatted price string for event-details block.
*/
private function extractPrice( array $event ): string {
$currency = strtoupper( trim( (string) ( $event['currency'] ?? 'USD' ) ) );

if ( isset( $event['price'] ) && is_numeric( $event['price'] ) ) {
$top_level_price = (float) $event['price'] / 100;
return $this->formatStructuredPrice( $top_level_price, $top_level_price, $currency );
}

$ticket_types = $event['ticket_types'] ?? array();
if ( ! is_array( $ticket_types ) || empty( $ticket_types ) ) {
return '';
}

$face_values = array();
$total_values = array();

foreach ( $ticket_types as $ticket_type ) {
if ( ! is_array( $ticket_type ) || empty( $ticket_type['price'] ) || ! is_array( $ticket_type['price'] ) ) {
continue;
}

$price_data = $ticket_type['price'];

if ( isset( $price_data['face_value'] ) && is_numeric( $price_data['face_value'] ) ) {
$face_values[] = (float) $price_data['face_value'] / 100;
}

if ( isset( $price_data['total'] ) && is_numeric( $price_data['total'] ) ) {
$total_values[] = (float) $price_data['total'] / 100;
}
}

if ( ! empty( $face_values ) ) {
return $this->formatStructuredPrice( min( $face_values ), max( $face_values ), $currency );
}

if ( ! empty( $total_values ) ) {
return $this->formatStructuredPrice( min( $total_values ), max( $total_values ), $currency );
}

return '';
}

/**
* Extract venue data from Dice.fm event
*
Expand Down
13 changes: 13 additions & 0 deletions inc/Steps/EventImport/Handlers/EventImportHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,19 @@ protected function formatPriceRange( ?float $min, ?float $max = null ): string {
return PriceFormatter::formatRange( $min, $max );
}

/**
* Format structured price data into a display string.
*
* @param float|null $min Minimum price.
* @param float|null $max Maximum price.
* @param string $currency ISO currency code.
* @param bool|null $is_free Explicit free flag.
* @return string
*/
protected function formatStructuredPrice( ?float $min = null, ?float $max = null, string $currency = 'USD', ?bool $is_free = null ): string {
return PriceFormatter::formatStructured( $min, $max, $currency, $is_free );
}

/**
* Store event context (venue + core fields) in engine data.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,17 @@ protected function extractTimeFromText( string $text ): ?string {
protected function formatPriceRange( ?float $min, ?float $max = null ): string {
return PriceFormatter::formatRange( $min, $max );
}

/**
* Format structured price data into a display string.
*
* @param float|null $min Minimum price.
* @param float|null $max Maximum price.
* @param string $currency ISO currency code.
* @param bool|null $is_free Explicit free flag.
* @return string
*/
protected function formatStructuredPrice( ?float $min = null, ?float $max = null, string $currency = 'USD', ?bool $is_free = null ): string {
return PriceFormatter::formatStructured( $min, $max, $currency, $is_free );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ private function parseImage( array &$event, array $raw_event ): void {

private function parsePrice( array &$event, array $raw_event ): void {
if ( ! empty( $raw_event['is_free'] ) ) {
$event['price'] = 'Free';
$event['price'] = $this->formatStructuredPrice( null, null, 'USD', true );
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ private function parseBooking( array $event, array $venue_data ): array {
}

if ( empty( $price ) && ! empty( $event['isAccessibleForFree'] ) ) {
$price = 'Free';
$price = $this->formatStructuredPrice( null, null, 'USD', true );
}

return array_merge(
Expand Down
Loading