mailer = $mailer; $this->vars = $vars; $this->customers = $customers; $this->orders = $orders; $this->invoices = $invoices; $this->payments = $payments; } /** * {@inheritdoc} */ public function register(): void { add_action( 'hostkhata_order_placed', array( $this, 'on_order_placed' ), 10, 1 ); add_action( 'hostkhata_order_fulfilled', array( $this, 'on_order_fulfilled' ), 10, 1 ); add_action( 'hostkhata_invoice_issued', array( $this, 'on_invoice_issued' ), 10, 1 ); add_action( 'hostkhata_payment_recorded', array( $this, 'on_payment_recorded' ), 10, 2 ); add_action( 'hostkhata_payment_refunded', array( $this, 'on_payment_refunded' ), 10, 2 ); add_action( 'hostkhata_customer_created', array( $this, 'on_customer_created' ), 10, 1 ); add_action( 'hostkhata_customer_status_changed', array( $this, 'on_customer_status_changed' ), 10, 3 ); add_action( 'hostkhata_payment_claimed', array( $this, 'on_payment_claimed' ), 10, 2 ); add_action( 'hostkhata_payment_rejected', array( $this, 'on_payment_rejected' ), 10, 3 ); add_action( 'hostkhata_customer_request', array( $this, 'on_customer_request' ), 10, 3 ); } /** * Order received: tell the customer and the admin. * * @since 0.1.0 * * @param int $order_id Order id. * @return void */ public function on_order_placed( $order_id ): void { $this->guard( function () use ( $order_id ) { $order = $this->orders->find( (int) $order_id ); if ( null === $order ) { return; } $customer = $this->customers->find( $order['customer_id'] ); $vars = array_merge( $this->vars->base( $customer ), $this->vars->order( $order ) ); $this->to_customer( 'order_received', $customer, $vars, 'order', $order['id'] ); $this->mailer->queue_to_admin( 'admin_new_order', $vars, 'order', $order['id'] ); } ); } /** * Order fulfilled: tell the customer their account is ready. * * @since 0.1.0 * * @param int $order_id Order id. * @return void */ public function on_order_fulfilled( $order_id ): void { $this->guard( function () use ( $order_id ) { $order = $this->orders->find( (int) $order_id ); if ( null === $order ) { return; } $customer = $this->customers->find( $order['customer_id'] ); $vars = array_merge( $this->vars->base( $customer ), $this->vars->order( $order ), $this->vars->order_details( $order['id'] ) ); $this->to_customer( 'account_ready', $customer, $vars, 'order', $order['id'] ); } ); } /** * Invoice issued: send it to the customer. * * @since 0.1.0 * * @param int $invoice_id Invoice id. * @return void */ public function on_invoice_issued( $invoice_id ): void { $this->guard( function () use ( $invoice_id ) { $invoice = $this->invoices->find( (int) $invoice_id ); // An invoice with nothing to pay needs no email. if ( null === $invoice || $invoice['total'] <= 0 ) { return; } $customer = $this->customers->find( $invoice['customer_id'] ); $this->to_customer( 'invoice_issued', $customer, array_merge( $this->vars->base( $customer ), $this->vars->invoice( $invoice ) ), 'invoice', $invoice['id'] ); } ); } /** * Payment recorded: send a receipt. * * @since 0.1.0 * * @param int $payment_id Payment id. * @param int $invoice_id Invoice id. * @return void */ public function on_payment_recorded( $payment_id, $invoice_id = 0 ): void { $this->payment_email( 'payment_received', (int) $payment_id, (int) $invoice_id ); } /** * Refund recorded: tell the customer. * * @since 0.1.0 * * @param int $refund_id Refund row id. * @param int $invoice_id Invoice id. * @return void */ public function on_payment_refunded( $refund_id, $invoice_id = 0 ): void { $this->payment_email( 'payment_refunded', (int) $refund_id, (int) $invoice_id ); } /** * A new customer who can log in right away gets a welcome email. * * @since 0.1.0 * * @param int $customer_id Customer id. * @return void */ public function on_customer_created( $customer_id ): void { $this->guard( function () use ( $customer_id ) { $customer = $this->customers->find( (int) $customer_id ); /** * Filters whether a new customer gets the welcome email. * * @since 0.1.0 * * @param bool $send Whether to send it. */ if ( $customer && CustomerStatus::ACTIVE === $customer['status'] && apply_filters( 'hostkhata_send_welcome_email', true ) ) { $this->to_customer( 'welcome', $customer, $this->vars->base( $customer ), 'customer', $customer['id'] ); } } ); } /** * A customer who was waiting for approval and is now active is told so. * * @since 0.1.0 * * @param int $customer_id Customer id. * @param string $from Old status. * @param string $to New status. * @return void */ public function on_customer_status_changed( $customer_id, $from = '', $to = '' ): void { if ( CustomerStatus::PENDING !== $from || CustomerStatus::ACTIVE !== $to ) { return; } $this->guard( function () use ( $customer_id ) { $customer = $this->customers->find( (int) $customer_id ); if ( $customer ) { $this->to_customer( 'account_approved', $customer, $this->vars->base( $customer ), 'customer', $customer['id'] ); } } ); } /** * A customer reported a payment: tell the admin to check it. * * @since 0.1.0 * * @param int $payment_id Payment id. * @param int $invoice_id Invoice id. * @return void */ public function on_payment_claimed( $payment_id, $invoice_id = 0 ): void { $this->guard( function () use ( $payment_id, $invoice_id ) { $payment = $this->payments->find( (int) $payment_id ); $invoice = $this->invoices->find( (int) $invoice_id ); if ( null === $payment || null === $invoice ) { return; } $customer = $this->customers->find( $invoice['customer_id'] ); $vars = array_merge( $this->vars->base( $customer ), $this->vars->invoice( $invoice ), array( 'payment_amount' => $this->vars->money( $payment['amount'] ), 'payment_method' => $payment['gateway'], 'payment_reference' => '' !== $payment['transaction_id'] ? $payment['transaction_id'] : $payment['sender_number'], 'admin_url' => admin_url( 'admin.php?page=hostkhata#/payments' ), ) ); $this->mailer->queue_to_admin( 'admin_payment_claim', $vars, 'invoice', $invoice['id'] ); } ); } /** * A reported payment was rejected: tell the customer. * * @since 0.1.0 * * @param int $payment_id Payment id. * @param int $invoice_id Invoice id. * @param string $reason Reason given by the admin. * @return void */ public function on_payment_rejected( $payment_id, $invoice_id = 0, $reason = '' ): void { $this->guard( function () use ( $payment_id, $invoice_id, $reason ) { $payment = $this->payments->find( (int) $payment_id ); $invoice = $this->invoices->find( (int) $invoice_id ); if ( null === $payment || null === $invoice ) { return; } $customer = $this->customers->find( $invoice['customer_id'] ); $vars = array_merge( $this->vars->base( $customer ), $this->vars->invoice( $invoice ), array( 'payment_amount' => $this->vars->money( $payment['amount'] ), 'reason' => (string) $reason, ) ); $this->to_customer( 'payment_rejected', $customer, $vars, 'invoice', $invoice['id'] ); } ); } /** * A customer sent a request: tell the admin. * * @since 0.1.0 * * @param int $customer_id Customer id. * @param string $type Kind of request, as text. * @param string $message What the customer wrote. * @return void */ public function on_customer_request( $customer_id, $type = '', $message = '' ): void { $this->guard( function () use ( $customer_id, $type, $message ) { $customer = $this->customers->find( (int) $customer_id ); if ( null === $customer ) { return; } $vars = array_merge( $this->vars->base( $customer ), array( 'request_type' => (string) $type, 'request_message' => (string) $message, 'admin_url' => admin_url( 'admin.php?page=hostkhata#/customers/' . $customer['id'] ), ) ); $this->mailer->queue_to_admin( 'admin_customer_request', $vars, 'customer', $customer['id'] ); } ); } /** * Queues a payment or refund email. * * @param string $key Template key. * @param int $payment_id Payment row id. * @param int $invoice_id Invoice id. * @return void */ private function payment_email( string $key, int $payment_id, int $invoice_id ): void { $this->guard( function () use ( $key, $payment_id, $invoice_id ) { $payment = $this->payments->find( $payment_id ); $invoice = $this->invoices->find( $invoice_id ); if ( null === $payment || null === $invoice ) { return; } $customer = $this->customers->find( $invoice['customer_id'] ); $vars = array_merge( $this->vars->base( $customer ), $this->vars->invoice( $invoice ), array( 'payment_amount' => $this->vars->money( $payment['amount'] ) ) ); $this->to_customer( $key, $customer, $vars, 'invoice', $invoice['id'] ); } ); } /** * Queues an email to a customer, unless they cannot be written to. * * @param string $key Template key. * @param array|null $customer Customer row. * @param array $vars Merge tag values. * @param string $related_type Related object type. * @param int $related_id Related object id. * @return void */ private function to_customer( string $key, ?array $customer, array $vars, string $related_type, int $related_id ): void { if ( null === $customer || CustomerStatus::ANONYMISED === $customer['status'] || empty( $customer['user_email'] ) ) { return; } $this->mailer->queue( $key, (string) $customer['user_email'], trim( $customer['first_name'] . ' ' . $customer['last_name'] ), $vars, $related_type, $related_id ); } /** * Runs a handler and swallows any error. * * @param callable $handler Handler. * @return void */ private function guard( callable $handler ): void { try { $handler(); } catch ( Throwable $e ) { do_action( 'hostkhata_log', 'error', 'Email event failed: ' . $e->getMessage(), array() ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Prefixed. } } }