|null */ private $items = null; /** * Build from a database row. * * @param object $row Row. */ public function __construct( $row ) { foreach ( get_object_vars( $row ) as $key => $value ) { if ( property_exists( $this, $key ) && 'items' !== $key ) { $this->$key = in_array( $key, array( 'id', 'user_id', 'subtotal', 'discount', 'total', 'tax_total', 'source_id' ), true ) ? (int) $value : $value; } } } /** * URL of the post the buyer started from. * * @return string Empty when unknown or no longer public. */ public function source_url() { return paygrab_source_url( $this->source_id ); } /** * Order items. * * @return array Rows with id, product_id, name, unit_price, quantity, tax_rate. */ public function items() { if ( null === $this->items ) { global $wpdb; $t = Paygrab_Install::tables(); $this->items = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$t['items']} WHERE order_id = %d ORDER BY id ASC", $this->id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared } return $this->items; } /** * Names of the products, joined for display. * * @return string */ public function summary() { return implode( ', ', wp_list_pluck( $this->items(), 'name' ) ); } /** * Tax per rate: [ rate => [ total, tax ] ] (rounded once per rate, as the invoice rules require). * * @return array */ public function tax_breakdown() { $by_rate = array(); foreach ( $this->items() as $item ) { $rate = (int) $item->tax_rate; if ( ! isset( $by_rate[ $rate ] ) ) { $by_rate[ $rate ] = 0; } $by_rate[ $rate ] += (int) $item->unit_price * (int) $item->quantity; } // The discount is taken from the highest rate first (orders are single-rate in practice). $discount = $this->discount; krsort( $by_rate ); $out = array(); foreach ( $by_rate as $rate => $total ) { $take = min( $discount, $total ); $total -= $take; $discount -= $take; $out[ $rate ] = array( 'total' => $total, 'tax' => paygrab_tax_included( $total, $rate ), ); } return $out; } /** * Whether the order still waits for payment. * * @return bool */ public function is_pending() { return 'pending' === $this->status; } /** * Whether the order was paid (and not refunded). * * @return bool */ public function is_paid() { return 'paid' === $this->status; } /** * The payment method's label. * * @return string */ public function payment_label() { $gateway = Paygrab_Gateways::get( $this->gateway ); $label = $gateway ? $gateway->method_label( $this->payment_method ) : $this->payment_method; return (string) apply_filters( 'paygrab_payment_label', $label, $this ); } /** * Example of the transfer name the buyer should use. * * @return string */ public function transfer_name_example() { /* translators: %s: 6-digit transfer code. Example of a bank transfer name with the code in front. */ return sprintf( __( '%s YAMADA HANAKO', 'paygrab' ), $this->transfer_code ); } }