renderCollections($content, $template, $booking, $recipient); $content = $this->replaceScalars($content, $booking, $recipient, $extra); return (string) apply_filters( 'DayTidy/F__DayTidy/Notifications/Renderer__render/output', $content, $template, $booking, $recipient, $field ); } /** * @param mixed[] $template * @param mixed[] $recipient */ private function renderCollections(string $content, array $template, Booking $booking, array $recipient): string { $collections = [ 'participant_list' => 'participantList', 'option_list' => 'optionList', 'session_list' => 'sessionList', ]; foreach ($collections as $key => $method) { if (strpos($content, '{' . $key . '}') === false) continue; $content = str_replace('{' . $key . '}', $this->{$method}($template, $booking, $recipient), $content); } return $content; } /** * @param mixed[] $recipient * @param mixed[] $extra */ private function replaceScalars(string $content, Booking $booking, array $recipient = [], array $extra = []): string { $values = array_merge($this->basePlaceholders($booking, $recipient), $extra); $replacements = []; foreach ($values as $key => $value) { $replacements['{' . $key . '}'] = (string) $value; } return strtr($content, $replacements); } /** * @param mixed[] $recipient * @return string[] */ private function basePlaceholders(Booking $booking, array $recipient): array { $offering = $booking->offering(); $offering_post = $offering ? $offering->get() : null; $draft = null; $form = []; try { $draft = $booking->getData(); $form = $draft->getMappedForm(); } catch (\Throwable $e) { $draft = null; $form = []; } $transaction = null; try { $transaction = $booking->getTransaction(); } catch (\Throwable $e) { $transaction = null; } $gateway = ''; $gateway_ref_id = ''; $total = $booking->total()->render(); $payable = $total; $coupon = $draft ? $draft->getCoupon() : ''; if ($transaction) { try { $gateway = $transaction->getGateway()->title(); } catch (\Throwable $e) { $gateway = ''; } $gateway_ref_id = $transaction->getGatewayRefId(); $total = $booking->price($transaction->getTotal())->render(); $payable = $booking->price($transaction->getPayable())->render(); $coupon = $transaction->getCouponCodes() ?: $coupon; } $first_name = $this->field($form['first_name'] ?? []); $last_name = $this->field($form['last_name'] ?? []); $email = $this->field($form['email'] ?? []); if ($email === '') $email = sanitize_email((string) get_post_meta($booking->id(), 'daytidy_email', true)); $offering_id = $offering ? $offering->id() : 0; $booking_status = esc_html($booking->bookingStatus()); return apply_filters('DayTidy/F__DayTidy/Notifications/Renderer__placeholders/values', [ 'site_name' => esc_html(get_bloginfo('name')), 'site_url' => esc_url(home_url('/')), 'admin_email' => esc_html((string) get_option('admin_email')), 'date' => esc_html(wp_date(Date::wp())), 'time' => esc_html(wp_date(Time::wp())), 'datetime' => esc_html(wp_date(DateTime::wp())), 'booking_id' => (string) $booking->id(), 'booking_ref' => esc_html($booking->refId()), 'booking_email' => esc_html($email), 'booking_first_name' => esc_html($first_name), 'booking_last_name' => esc_html($last_name), 'booking_total' => esc_html($total), 'booking_payable' => esc_html($payable), 'booking_gateway' => esc_html($gateway), 'booking_gateway_ref_id' => esc_html($gateway_ref_id), 'booking_status' => $booking_status, 'booking_confirmation_status' => $booking_status, 'booking_verification_status' => $booking_status, 'booking_payment_status' => esc_html($booking->paymentStatus()), 'booking_coupon' => esc_html($coupon), 'booking_portal_url' => esc_url((new CustomerPortalUrlService())->bookingUrl($booking->id())), 'booking_verification_code' => '', 'booking_verification_code_expiry_minutes' => '', 'offering_id' => (string) $offering_id, 'offering_title' => esc_html($offering_post ? $offering_post->post_title : ''), 'offering_link' => $offering_id ? esc_url(get_permalink($offering_id)) : '', 'offering_admin_link' => $offering_id ? esc_url((string) get_edit_post_link($offering_id, '')) : '', 'recipient_email' => esc_html((string) ($recipient['email'] ?? '')), 'recipient_name' => esc_html((string) ($recipient['name'] ?? '')), 'recipient_context' => esc_html((string) ($recipient['context'] ?? '')), ], $booking, $recipient); } /** * @param mixed[] $template * @param mixed[] $recipient */ private function participantList(array $template, Booking $booking, array $recipient): string { $item_template = $this->collectionTemplate($template, 'participant_list'); $output = ''; foreach ($booking->getData()->getMappedParticipants() as $participant) { if (!is_array($participant)) continue; $first = $this->field($participant['first_name'] ?? []); $last = $this->field($participant['last_name'] ?? []); $email = $this->participantEmail($participant); $name = trim($first . ' ' . $last); $output .= $this->replaceScalars($item_template, $booking, $recipient, [ 'participant_name' => esc_html($name ?: $email), 'participant_email' => esc_html($email), 'participant_fields' => $this->participantFields($participant), ]); } return $output; } /** * @param mixed[] $template * @param mixed[] $recipient */ private function optionList(array $template, Booking $booking, array $recipient): string { $offering = $booking->offering(); if (!$offering) return ''; $item_template = $this->collectionTemplate($template, 'option_list'); $output = ''; foreach ($booking->getData()->getOptions() as $option_id => $quantity) { $quantity = (int) $quantity; if ($quantity <= 0) continue; $option = $offering->getOptions()->get((int) $option_id); if (!$option) continue; $output .= $this->replaceScalars($item_template, $booking, $recipient, [ 'option_title' => esc_html($option->title()), 'option_quantity' => (string) $quantity, 'option_price' => esc_html($booking->price($option->price())->render()), ]); } return $output; } /** * @param mixed[] $template * @param mixed[] $recipient */ private function sessionList(array $template, Booking $booking, array $recipient): string { $offering = $booking->offering(); $tz = $offering ? $offering->getTimeZone() : null; $item_template = $this->collectionTemplate($template, 'session_list'); $output = ''; foreach ($booking->getData()->getAllSessions() as $session) { $output .= $this->replaceScalars($item_template, $booking, $recipient, [ 'session_item' => esc_html(DayTidyDateTime::render($session, DateTime::wp(), $tz)), 'date_item' => esc_html(DayTidyDateTime::render($session, Date::wp(), $tz)), 'time_item' => esc_html(DayTidyDateTime::render($session, Time::wp(), $tz)), ]); } return $output; } /** * @param mixed[] $template */ private function collectionTemplate(array $template, string $key): string { $collections = isset($template['collections']) && is_array($template['collections']) ? $template['collections'] : []; $defaults = Defaults::collectionTemplates(); $item_template = (string) ($collections[$key] ?? $defaults[$key] ?? ''); return $this->removeCollectionPlaceholders($item_template); } private function removeCollectionPlaceholders(string $template): string { foreach (Registry::collectionKeys() as $key) { $template = str_replace('{' . $key . '}', '', $template); } return $template; } /** * @param mixed[] $participant */ private function participantEmail(array $participant): string { if (isset($participant['email']) && is_array($participant['email'])) { return $this->field($participant['email']); } foreach ($participant as $field) { if (!is_array($field)) continue; $value = $this->field($field); $type = (string) ($field['type'] ?? ''); if ($type === 'email' && is_email($value)) return $value; if (is_email($value)) return $value; } return ''; } /** * @param mixed[] $participant */ private function participantFields(array $participant): string { $items = ''; foreach ($participant as $field) { if (!is_array($field)) continue; $label = (string) ($field['label'] ?? ''); $value = $this->field($field); if ($label === '' || $value === '') continue; $items .= '
' . esc_html($label) . '
' . esc_html($value) . '
'; } return $items ? '
' . $items . '
' : ''; } /** * @param mixed[] $field */ private function field(array $field): string { return $this->stringify($field['value'] ?? ''); } /** * @param mixed $value */ private function stringify($value): string { if (is_array($value)) { $parts = []; foreach ($value as $item) $parts[] = $this->stringify($item); return implode(', ', array_filter($parts)); } return trim(wp_strip_all_tags((string) $value)); } }