' . nl2br( esc_html( $note ) ) . '

'; } catch ( \Throwable $e ) { OrderingPolicy::report_display( $e ); } } /** * The note for an email, plain text, or '' for none: only a customer * email in `NOTE_EMAILS`, only with the setting on, only for an order with * a valid scheduled time (never a time it wasn't scheduled for). * * @param mixed $order Order. * @param mixed $sent_to_admin Whether the email goes to the store. * @param mixed $email The `WC_Email`. * @return string */ private static function note( $order, $sent_to_admin, $email ) { if ( $sent_to_admin || ! $email instanceof \WC_Email || ! in_array( $email->id, self::NOTE_EMAILS, true ) || ! Behaviour::scheduled_order_note() ) { return ''; } $ts = OrderMeta::get_scheduled_for( $order ); if ( null === $ts ) { return ''; } // Only `{scheduled_for}`: the closed message's tokens map to themselves, so they stay as typed. $note = OrderingPolicy::fill( Behaviour::scheduled_order_note_text(), array( 'next_open' => '{next_open}', 'closures_label' => '{closures_label}', 'scheduled_for' => OrderingPolicy::format_time( $ts ), ) ); /** * The scheduled-order note in a customer email (OW-062), plain text, * `{scheduled_for}` already replaced. Return '' to show none. It is * escaped when printed, so markup shows as text. * * @param string $note The note. * @param WC_Order $order Order. * @param WC_Email $email Email. */ $note = apply_filters( 'hourgate_scheduled_order_note', $note, $order, $email ); return is_string( $note ) ? trim( $note ) : ''; } /** * Add the "Scheduled for" row after the payment method (or last when there is none). * * @param mixed $total_rows Rows WooCommerce built, keyed (`cart_subtotal`, `payment_method`, ...). * @param mixed $order Order. * @return mixed */ public static function add_totals_row( $total_rows, $order ) { if ( ! is_array( $total_rows ) ) { return $total_rows; } try { $rows = self::rows( $order ); if ( ! $rows ) { return $total_rows; } if ( ! array_key_exists( 'payment_method', $total_rows ) ) { return array_merge( $total_rows, $rows ); } $result = array(); foreach ( $total_rows as $key => $row ) { $result[ $key ] = $row; if ( 'payment_method' === $key ) { $result = array_merge( $result, $rows ); } } return $result; } catch ( \Throwable $e ) { OrderingPolicy::report_display( $e ); return $total_rows; } } /** * The admin order screen: the scheduled time and the "placed while closed" flag. * * @param mixed $order Order. * @return void */ public static function admin_box( $order ) { try { $rows = self::rows( $order ); if ( OrderMeta::is_placed_while_closed( $order ) ) { $rows['placed_while_closed'] = array( 'label' => __( 'Placed while the store was closed', 'hourgate' ), 'value' => __( 'Yes', 'hourgate' ), ); } if ( ! $rows ) { return; } echo '
'; foreach ( $rows as $row ) { if ( ! is_array( $row ) || ! isset( $row['label'], $row['value'] ) || ! is_scalar( $row['label'] ) || ! is_scalar( $row['value'] ) ) { continue; } echo '

' . esc_html( (string) $row['label'] ) . ' ' . esc_html( (string) $row['value'] ) . '

'; } echo '
'; } catch ( \Throwable $e ) { OrderingPolicy::report_display( $e ); } } /** * The rows to show for an order, keyed (`scheduled_for`), or none. * * @param mixed $order Order. * @return array */ private static function rows( $order ) { $rows = array(); $ts = OrderMeta::get_scheduled_for( $order ); if ( null !== $ts ) { $rows['scheduled_for'] = array( 'label' => __( 'Scheduled for:', 'hourgate' ), 'value' => OrderingPolicy::format_time( $ts ), ); } /** * Rows HourGate adds to an order's totals and to the admin order screen. * * Keyed like WooCommerce's totals rows, each `array( 'label' => string, 'value' => string )` * as plain text (WooCommerce's templates and the admin box escape it). Rows that aren't * well formed are skipped by the admin box. * * @param array $rows Rows, keyed. * @param WC_Order $order Order. */ $filtered = apply_filters( 'hourgate_order_display_rows', $rows, $order ); return is_array( $filtered ) ? self::clean( $filtered ) : array(); } /** * Keep only rows with a string label and value, so a bad filter result can't break a template. * * @param array $rows Rows. * @return array */ private static function clean( array $rows ) { $clean = array(); foreach ( $rows as $key => $row ) { if ( is_array( $row ) && isset( $row['label'], $row['value'] ) && is_string( $row['label'] ) && is_string( $row['value'] ) ) { $clean[ $key ] = array( 'label' => $row['label'], 'value' => $row['value'], ); } } return $clean; } }