$items * @return bool False when there is no recipient or nothing to bill. */ public function send( \WP_User $student, array $items, string $reference = '' ): bool { if ( '' === (string) $student->user_email || [] === $items ) { return false; } $currency = (string) $items[0]['currency']; $total = 0.0; $lines = []; $emails = []; foreach ( $items as $item ) { $amount = (float) $item['amount']; $total += $amount; $lines[] = sprintf( /* translators: 1: item description, 2: due date, 3: currency, 4: amount */ __( '- %1$s (due %2$s): %3$s %4$s', 'unsupervised-schedular' ), (string) $item['label'], $this->formatDate( $item['due_date'] ?? null ), $currency, number_format( $amount, 2 ) ); $etransfer = (string) ( $item['etransfer_email'] ?? '' ); if ( '' !== $etransfer ) { $emails[ $etransfer ] = true; } } $body = __( 'You have upcoming payments due:', 'unsupervised-schedular' ) . "\n\n" . implode( "\n", $lines ) . "\n\n" . sprintf( /* translators: 1: currency, 2: total amount */ __( 'Total due: %1$s %2$s', 'unsupervised-schedular' ), $currency, number_format( $total, 2 ) ); if ( [] !== $emails ) { $body .= "\n\n" . sprintf( /* translators: %s: e-transfer destination email address(es) */ __( 'Please send your e-transfer to: %s', 'unsupervised-schedular' ), implode( ', ', array_keys( $emails ) ) ); } if ( '' !== $reference ) { $body .= "\n\n" . sprintf( /* translators: %s: payment reference code */ __( 'Please include this reference with your payment: %s', 'unsupervised-schedular' ), $reference ); } return (bool) wp_mail( $student->user_email, __( 'Payment due', 'unsupervised-schedular' ), $body ); } /** * Present a stored `Y-m-d` due date in a friendlier form; falls back to the * raw value (or an empty string) when it is not a parseable date. */ private function formatDate( ?string $date ): string { if ( null === $date || '' === $date ) { return ''; } $parsed = \DateTimeImmutable::createFromFormat( '!Y-m-d', $date ); return false !== $parsed ? $parsed->format( 'M j, Y' ) : $date; } }