| @@ -302,14 +302,48 @@ | ||
| 302 | 302 | return $guest->getTotalGuestCount(); |
| 303 | 303 | } |
| 304 | 304 | |
| 305 | 305 | if ($key == 'form_data_html') { |
| 306 | - return __('will be available soon', 'fluent-booking'); | |
| 306 | + // isPublic: hidden fields stay out, the recipient may be the guest. | |
| 307 | + return self::renderFormData( | |
| 308 | + BookingFieldService::getFormattedCustomBookingData($guest, static::$requireHtml, true), | |
| 309 | + static::$requireHtml | |
| 310 | + ); | |
| 307 | 311 | } |
| 308 | 312 | |
| 309 | - return Arr::get($guest, $key, ''); | |
| 313 | + return self::resolveScalarAttribute($guest, $key); | |
| 310 | 314 | } |
| 311 | 315 | |
| 316 | + protected static function renderFormData($fields, $isHtml) | |
| 317 | + { | |
| 318 | + $rows = ''; | |
| 319 | + | |
| 320 | + foreach ($fields as $field) { | |
| 321 | + $value = Arr::get($field, 'value'); | |
| 322 | + | |
| 323 | + if ($value === '' || $value === null || $value === []) { | |
| 324 | + continue; | |
| 325 | + } | |
| 326 | + | |
| 327 | + if (!$isHtml) { | |
| 328 | + $rows .= $field['label'] . ': ' . $value . PHP_EOL; | |
| 329 | + continue; | |
| 330 | + } | |
| 331 | + | |
| 332 | + // File values are download anchors; everything else is raw guest input. | |
| 333 | + $value = Arr::get($field, 'type') == 'file' ? wp_kses_post($value) : nl2br(esc_html($value)); | |
| 334 | + | |
| 335 | + $rows .= '<tr><th style="padding:6px 12px;background-color:#f8f8f8;text-align:' . (is_rtl() ? 'right' : 'left') . ';">' . esc_html($field['label']) . '</th></tr>' | |
| 336 | + . '<tr><td style="padding:6px 12px 12px 12px;">' . $value . '</td></tr>'; | |
| 337 | + } | |
| 338 | + | |
| 339 | + if (!$isHtml || !$rows) { | |
| 340 | + return trim($rows); | |
| 341 | + } | |
| 342 | + | |
| 343 | + return '<table width="100%" cellpadding="0" cellspacing="0" style="border-collapse:collapse;"><tbody>' . $rows . '</tbody></table>'; | |
| 344 | + } | |
| 345 | + | |
| 312 | 346 | protected static function getBookingEventData($key) |
| 313 | 347 | { |
| 314 | 348 | $bookingEvent = static::$store['booking_event']; |
| 315 | 349 | |
| @@ -318,13 +352,13 @@ | ||
| 318 | 352 | } |
| 319 | 353 | |
| 320 | 354 | $fillables = (new CalendarSlot())->getFillable(); |
| 321 | 355 | |
| 322 | - if (in_array($key, $fillables) || isset($bookingEvent->{$key})) { | |
| 356 | + if (in_array($key, $fillables)) { | |
| 323 | 357 | return $bookingEvent->{$key}; |
| 324 | 358 | } |
| 325 | 359 | |
| 326 | - return ''; | |
| 360 | + return self::resolveScalarAttribute($bookingEvent, $key); | |
| 327 | 361 | } |
| 328 | 362 | |
| 329 | 363 | protected static function getCalendarData($key) |
| 330 | 364 | { |
| @@ -335,13 +369,28 @@ | ||
| 335 | 369 | } |
| 336 | 370 | |
| 337 | 371 | $fillables = (new Calendar())->getFillable(); |
| 338 | 372 | |
| 339 | - if (in_array($key, $fillables) || isset($calendar->{$key})) { | |
| 373 | + if (in_array($key, $fillables)) { | |
| 340 | 374 | return $calendar->{$key}; |
| 341 | 375 | } |
| 342 | 376 | |
| 343 | - return ''; | |
| 377 | + return self::resolveScalarAttribute($calendar, $key); | |
| 378 | + } | |
| 379 | + | |
| 380 | + /** | |
| 381 | + * Resolve a scalar attribute only; never a relation (dumps as JSON) or a | |
| 382 | + * dotted hop into a relation's columns. | |
| 383 | + */ | |
| 384 | + protected static function resolveScalarAttribute($model, $key) | |
| 385 | + { | |
| 386 | + if (strpos($key, '.') !== false) { | |
| 387 | + return ''; | |
| 388 | + } | |
| 389 | + | |
| 390 | + $value = isset($model[$key]) ? $model[$key] : ''; | |
| 391 | + | |
| 392 | + return is_scalar($value) ? $value : ''; | |
| 344 | 393 | } |
| 345 | 394 | |
| 346 | 395 | protected static function getPaymentData($key) |
| 347 | 396 | { |