> Keyed by template key. */ public function all(): array { $stored = get_option( self::OPTION, array() ); $stored = is_array( $stored ) ? $stored : array(); $result = array(); foreach ( self::defaults() as $key => $template ) { $change = isset( $stored[ $key ] ) && is_array( $stored[ $key ] ) ? $stored[ $key ] : array(); $template['key'] = $key; $template['subject'] = isset( $change['subject'] ) && '' !== $change['subject'] ? (string) $change['subject'] : $template['subject']; $template['body'] = isset( $change['body'] ) && '' !== $change['body'] ? (string) $change['body'] : $template['body']; $template['enabled'] = isset( $change['enabled'] ) ? (bool) $change['enabled'] : true; $template['modified'] = isset( $change['subject'] ) || isset( $change['body'] ); $result[ $key ] = $template; } return $result; } /** * One template, or null for an unknown key. * * @since 0.1.0 * * @param string $key Template key. * @return array|null */ public function get( string $key ): ?array { $all = $this->all(); return $all[ $key ] ?? null; } /** * Saves the changes of a template. * * @since 0.1.0 * * @param string $key Template key. * @param array $raw `subject`, `body` and/or `enabled`. * @return array{template: array|null, errors: array} */ public function save( string $key, array $raw ): array { $template = $this->get( $key ); if ( null === $template ) { return array( 'template' => null, 'errors' => array( 'key' => __( 'Unknown email template.', 'hostkhata' ) ), ); } $errors = array(); $change = array(); if ( array_key_exists( 'subject', $raw ) ) { $subject = Sanitizer::text( $raw['subject'] ); if ( '' === $subject ) { $errors['subject'] = __( 'The subject cannot be empty.', 'hostkhata' ); } elseif ( mb_strlen( $subject ) > self::SUBJECT_MAX ) { $errors['subject'] = __( 'Use at most 200 characters.', 'hostkhata' ); } else { $change['subject'] = $subject; } } if ( array_key_exists( 'body', $raw ) ) { $body = Sanitizer::textarea( $raw['body'] ); if ( '' === trim( $body ) ) { $errors['body'] = __( 'The message cannot be empty.', 'hostkhata' ); } elseif ( mb_strlen( $body ) > self::BODY_MAX ) { $errors['body'] = __( 'Use at most 10000 characters.', 'hostkhata' ); } else { $change['body'] = $body; } } if ( array_key_exists( 'enabled', $raw ) ) { $change['enabled'] = Sanitizer::boolean( $raw['enabled'] ); } if ( $errors ) { return array( 'template' => null, 'errors' => $errors, ); } $stored = get_option( self::OPTION, array() ); $stored = is_array( $stored ) ? $stored : array(); $stored[ $key ] = array_merge( isset( $stored[ $key ] ) && is_array( $stored[ $key ] ) ? $stored[ $key ] : array(), $change ); update_option( self::OPTION, $stored, false ); return array( 'template' => $this->get( $key ), 'errors' => array(), ); } /** * Puts a template back to its default wording (it stays switched on or off). * * @since 0.1.0 * * @param string $key Template key. * @return array|null The template, or null for an unknown key. */ public function reset( string $key ): ?array { if ( null === $this->get( $key ) ) { return null; } $stored = get_option( self::OPTION, array() ); $stored = is_array( $stored ) ? $stored : array(); if ( isset( $stored[ $key ] ) ) { unset( $stored[ $key ]['subject'], $stored[ $key ]['body'] ); update_option( self::OPTION, $stored, false ); } return $this->get( $key ); } /** * The built-in templates. * * @since 0.1.0 * * @return array> */ public static function defaults(): array { $customer = array( 'customer_name', 'business_name', 'site_url', 'portal_url' ); return array( 'order_received' => array( 'label' => __( 'Order received', 'hostkhata' ), 'audience' => 'customer', 'tags' => array_merge( $customer, array( 'order_number', 'order_total' ) ), 'subject' => __( 'We received your order {order_number}', 'hostkhata' ), 'body' => __( "Hello {customer_name},\n\nThank you for your order {order_number} ({order_total}). We will set it up as soon as it is paid and send you the details.\n\nYou can follow your order here: {portal_url}\n\n{business_name}", 'hostkhata' ), ), 'admin_new_order' => array( 'label' => __( 'New order (to you)', 'hostkhata' ), 'audience' => 'admin', 'tags' => array_merge( $customer, array( 'order_number', 'order_total', 'admin_url' ) ), 'subject' => __( 'New order {order_number} from {customer_name}', 'hostkhata' ), 'body' => __( "A new order {order_number} for {order_total} was placed by {customer_name}.\n\nOpen it: {admin_url}", 'hostkhata' ), ), 'account_ready' => array( 'label' => __( 'Account ready', 'hostkhata' ), 'audience' => 'customer', 'tags' => array_merge( $customer, array( 'order_number', 'details' ) ), 'subject' => __( 'Your order {order_number} is ready', 'hostkhata' ), 'body' => __( "Hello {customer_name},\n\nYour order {order_number} has been set up:\n\n{details}\n\nFor your security we never send passwords by email. If you need your login details, contact us.\n\n{business_name}", 'hostkhata' ), ), 'invoice_issued' => array( 'label' => __( 'Invoice issued', 'hostkhata' ), 'audience' => 'customer', 'tags' => array_merge( $customer, array( 'invoice_number', 'invoice_total', 'invoice_balance', 'due_date', 'invoice_url', 'payment_instructions' ) ), 'subject' => __( 'Invoice {invoice_number} from {business_name}', 'hostkhata' ), 'body' => __( "Hello {customer_name},\n\nInvoice {invoice_number} for {invoice_total} is due on {due_date}.\n\nView the invoice: {invoice_url}\n\n{payment_instructions}\n\n{business_name}", 'hostkhata' ), ), 'payment_received' => array( 'label' => __( 'Payment received', 'hostkhata' ), 'audience' => 'customer', 'tags' => array_merge( $customer, array( 'invoice_number', 'payment_amount', 'invoice_balance', 'invoice_url' ) ), 'subject' => __( 'Payment received for invoice {invoice_number}', 'hostkhata' ), 'body' => __( "Hello {customer_name},\n\nWe received your payment of {payment_amount} for invoice {invoice_number}. The balance is now {invoice_balance}.\n\nThank you!\n\n{business_name}", 'hostkhata' ), ), 'payment_refunded' => array( 'label' => __( 'Refund recorded', 'hostkhata' ), 'audience' => 'customer', 'tags' => array_merge( $customer, array( 'invoice_number', 'payment_amount' ) ), 'subject' => __( 'Refund for invoice {invoice_number}', 'hostkhata' ), 'body' => __( "Hello {customer_name},\n\nWe refunded {payment_amount} for invoice {invoice_number}.\n\n{business_name}", 'hostkhata' ), ), 'invoice_reminder' => array( 'label' => __( 'Invoice due reminder', 'hostkhata' ), 'audience' => 'customer', 'tags' => array_merge( $customer, array( 'invoice_number', 'invoice_balance', 'due_date', 'days', 'invoice_url', 'payment_instructions' ) ), 'subject' => __( 'Reminder: invoice {invoice_number} is due {due_date}', 'hostkhata' ), 'body' => __( "Hello {customer_name},\n\nThis is a friendly reminder that invoice {invoice_number} ({invoice_balance} outstanding) is due on {due_date}.\n\nView the invoice: {invoice_url}\n\n{payment_instructions}\n\n{business_name}", 'hostkhata' ), ), 'invoice_overdue' => array( 'label' => __( 'Invoice overdue', 'hostkhata' ), 'audience' => 'customer', 'tags' => array_merge( $customer, array( 'invoice_number', 'invoice_balance', 'due_date', 'days', 'invoice_url', 'payment_instructions' ) ), 'subject' => __( 'Overdue: invoice {invoice_number}', 'hostkhata' ), 'body' => __( "Hello {customer_name},\n\nInvoice {invoice_number} ({invoice_balance} outstanding) was due on {due_date} and is now {days} day(s) overdue. Please pay as soon as you can to avoid any interruption.\n\nView the invoice: {invoice_url}\n\n{payment_instructions}\n\n{business_name}", 'hostkhata' ), ), 'domain_reminder' => array( 'label' => __( 'Domain renewal reminder', 'hostkhata' ), 'audience' => 'customer', 'tags' => array_merge( $customer, array( 'domain', 'expires_on', 'days' ) ), 'subject' => __( 'Your domain {domain} expires on {expires_on}', 'hostkhata' ), 'body' => __( "Hello {customer_name},\n\nYour domain {domain} expires on {expires_on}. Contact us to renew it so you do not lose it.\n\n{business_name}", 'hostkhata' ), ), 'service_reminder' => array( 'label' => __( 'Hosting renewal reminder', 'hostkhata' ), 'audience' => 'customer', 'tags' => array_merge( $customer, array( 'domain', 'due_date', 'days', 'amount' ) ), 'subject' => __( 'Your hosting for {domain} renews on {due_date}', 'hostkhata' ), 'body' => __( "Hello {customer_name},\n\nYour hosting for {domain} renews on {due_date} ({amount}). We will send you an invoice.\n\n{business_name}", 'hostkhata' ), ), 'welcome' => array( 'label' => __( 'Welcome', 'hostkhata' ), 'audience' => 'customer', 'tags' => $customer, 'subject' => __( 'Welcome to {business_name}', 'hostkhata' ), 'body' => __( "Hello {customer_name},\n\nYour account is ready. You can see your orders, invoices and hosting, and tell us about your payments here:\n\n{portal_url}\n\n{business_name}", 'hostkhata' ), ), 'account_approved' => array( 'label' => __( 'Account approved', 'hostkhata' ), 'audience' => 'customer', 'tags' => $customer, 'subject' => __( 'Your account was approved', 'hostkhata' ), 'body' => __( "Hello {customer_name},\n\nYour account was approved. You can log in here:\n\n{portal_url}\n\n{business_name}", 'hostkhata' ), ), 'admin_payment_claim' => array( 'label' => __( 'Payment reported (to you)', 'hostkhata' ), 'audience' => 'admin', 'tags' => array_merge( $customer, array( 'invoice_number', 'payment_amount', 'payment_method', 'payment_reference', 'admin_url' ) ), 'subject' => __( '{customer_name} reported a payment for {invoice_number}', 'hostkhata' ), 'body' => __( "{customer_name} says they paid {payment_amount} for invoice {invoice_number} by {payment_method} (reference: {payment_reference}).\n\nCheck it and confirm or reject it: {admin_url}", 'hostkhata' ), ), 'payment_rejected' => array( 'label' => __( 'Reported payment rejected', 'hostkhata' ), 'audience' => 'customer', 'tags' => array_merge( $customer, array( 'invoice_number', 'payment_amount', 'reason', 'invoice_url' ) ), 'subject' => __( 'We could not confirm your payment for {invoice_number}', 'hostkhata' ), 'body' => __( "Hello {customer_name},\n\nWe could not confirm your payment of {payment_amount} for invoice {invoice_number}. {reason}\n\nPlease check the details and tell us again, or contact us.\n\n{invoice_url}\n\n{business_name}", 'hostkhata' ), ), 'admin_customer_request' => array( 'label' => __( 'Customer request (to you)', 'hostkhata' ), 'audience' => 'admin', 'tags' => array_merge( $customer, array( 'request_type', 'request_message', 'admin_url' ) ), 'subject' => __( 'Request from {customer_name}: {request_type}', 'hostkhata' ), 'body' => __( "{customer_name} sent a request ({request_type}):\n\n{request_message}\n\nOpen the customer: {admin_url}", 'hostkhata' ), ), 'notice' => array( 'label' => __( 'Notice', 'hostkhata' ), 'audience' => 'customer', 'tags' => array_merge( $customer, array( 'notice_title', 'notice_body' ) ), 'subject' => '{notice_title}', 'body' => __( "Hello {customer_name},\n\n{notice_body}\n\n{business_name}", 'hostkhata' ), ), ); } }