|list $data Data. * @param int $status HTTP status. * * @since 0.1.0 */ public static function ok( array $data, int $status = 200 ): WP_REST_Response { return new WP_REST_Response( $data, $status ); } /** * Map a domain exception to WP_Error. * * @param DomainException $e Exception. * * @since 0.1.0 */ public static function from_domain( DomainException $e ): WP_Error { if ( $e instanceof \Bookline\Application\Session\StepValidationException ) { $result = $e->result(); return new WP_Error( 'bookline_session_validation', $e->getMessage(), [ 'status' => 422, 'fields' => $result->field_errors(), 'notices' => $result->notices(), ] ); } $code = $e->code(); $status = 400; $message = $e->getMessage(); $data = [ 'status' => $status ]; if ( $e instanceof EditionLimitReached ) { $status = 422; $message = self::edition_limit_message( $e ); $data = [ 'status' => $status, 'dimension' => $e->dimension()->value, 'max' => $e->max(), ]; } elseif ( $e instanceof NamedFeatureDenied ) { $status = 422; $message = self::named_feature_message( $e ); $data = [ 'status' => $status, 'feature' => $e->feature()->value, ]; } elseif ( str_contains( $code, 'not_found' ) ) { $status = 404; $data['status'] = $status; } elseif ( str_contains( $code, 'expired' ) ) { $status = 410; $data['status'] = $status; } elseif ( str_contains( $code, 'slot' ) || str_contains( $code, 'conflict' ) ) { $status = 409; $data['status'] = $status; } elseif ( str_contains( $code, 'step' ) || str_contains( $code, 'validation' ) || str_contains( $code, 'incomplete' ) ) { $status = 422; $data['status'] = $status; } return new WP_Error( 'bookline_' . str_replace( '.', '_', $code ), $message, $data ); } /** * Generic error. * * @param string $code Error code. * @param string $message Message. * @param int $status HTTP status. * @param array $data Extra data. * * @since 0.1.0 */ public static function error( string $code, string $message, int $status, array $data = [] ): WP_Error { return new WP_Error( $code, $message, array_merge( [ 'status' => $status ], $data ) ); } /** * Translated capacity copy. No upgrade URL — this plugin's size. * * @param EditionLimitReached $e Exception. */ private static function edition_limit_message( EditionLimitReached $e ): string { $max = $e->max(); return match ( $e->dimension() ) { EditionDimension::Service => sprintf( /* translators: %d: maximum number of services in this plugin */ _n( 'This plugin supports at most %d service.', 'This plugin supports at most %d services.', $max, 'buildler' ), $max ), EditionDimension::Agent => sprintf( /* translators: %d: maximum number of staff in this plugin */ _n( 'This plugin supports at most %d staff member.', 'This plugin supports at most %d staff members.', $max, 'buildler' ), $max ), EditionDimension::Location => sprintf( /* translators: %d: maximum number of locations in this plugin */ _n( 'This plugin supports at most %d location.', 'This plugin supports at most %d locations.', $max, 'buildler' ), $max ), EditionDimension::BookingForm => sprintf( /* translators: %d: maximum number of booking forms in this plugin */ _n( 'This plugin supports at most %d booking form.', 'This plugin supports at most %d booking forms.', $max, 'buildler' ), $max ), }; } /** * Translated plan-map copy. * * @param NamedFeatureDenied $e Exception. */ private static function named_feature_message( NamedFeatureDenied $e ): string { return match ( $e->feature() ) { NamedFeature::GroupBookings => __( 'Group bookings are not included in this plan.', 'buildler' ), NamedFeature::Coupons => __( 'Coupons are not included in this plan.', 'buildler' ), NamedFeature::Deposits => __( 'Deposits are not included in this plan.', 'buildler' ), NamedFeature::StripePaypal => __( 'PayPal is not included in this plan.', 'buildler' ), NamedFeature::GoogleCalendar => __( 'Google Calendar is not included in this plan.', 'buildler' ), NamedFeature::OutlookAppleCalendar => __( 'Outlook and Apple Calendar are not included in this plan.', 'buildler' ), NamedFeature::SmsWhatsapp => __( 'SMS and WhatsApp are not included in this plan.', 'buildler' ), NamedFeature::ExtrasPackages => __( 'Packages and service extras are not included in this plan.', 'buildler' ), NamedFeature::Meetings => __( 'Video meetings are not included in this plan.', 'buildler' ), NamedFeature::CustomFields => __( 'Custom fields are not included in this plan.', 'buildler' ), NamedFeature::AutomationsFull => __( 'The full automation action set is not included in this plan.', 'buildler' ), NamedFeature::Reports => __( 'Financial reports are not included in this plan.', 'buildler' ), }; } }