OrderEmailGenerator
in package
Renders the transactional order e-mails and hands them to the e-mail queue owner.
E-mails are never sent directly. Each prepare*() method renders one and returns a
PreparedOrderEmail; the caller (OrderTransitionManager) enqueues it through
EmailQueueManager::enqueue() on its own DBAL
connection, so the insert joins the caller's transaction. This class only renders.
Rendering (Latte and I/O) runs before the final transaction on purpose: inside it, it would
needlessly widen the lock window on orders.
The render is a local minimal copy of SendEmailTrait::setTemplate() (e-mail template path,
email.latte, {#BODY#}, Latte string loader, DateHelper, PriceLatteExtension). The trait
is not used directly because this service is not a Manager and has no settingContext/findBy().
Template sources:
prepareStatusEmail():OrderStatusText.emailSubject/emailBodyfor the order language;prepareDefaultEmail(): system templateES_ORDER_CHANGEDthrough EmailManager;prepareExpeditionEmail():ShipperText.emailSubject/emailBodyoforder.expeditionShipper, guarded byShipper::getSendEmail();prepareNewOrderAdminEmail(): system templateES_NEW_ORDERto the shop administrator (not the customer), queued by OrderAdminNoticeManager.
Every prepare*() returns null on an empty template or a failed guard (including a system
template or its language turned off in the admin), and also when the
render fails (see renderTemplate(); the error is logged to the eshop.general channel). Nothing is
queued then, instead of the customer receiving an empty e-mail with no trace.
The language is order.language, falling back to LanguageManager::getDefaultLanguageId().
A missing or empty template is not looked up in another language: it yields null.
IMPORTANT: amounts and dates are formatted by the localization and language of the order, not of the request. A transition is triggered by the admin (Czech localization) or by cron (none), so without the override an English customer would get Czech price and date formats. The render runs inside PriceFormatContext::runWith() and dates go through DocumentLocale.
Tags
Table of Contents
Constants
- DEFAULT_EMAIL_KEY : string = 'ES_ORDER_CHANGED'
- NEW_ORDER_EMAIL_KEY : string = 'ES_NEW_ORDER'
- SETTING_MODULE_CORE : int = 0
- SETTING_MODULE_SYSTEM : int = 1
- VOUCHER_EMAIL_KEY : string = 'ES_NEW_VOUCHER'
Properties
- $calculator : OrderCalculator
- $emailManager : EmailManager
- $languageManager : LanguageManager
- $priceFormatContext : PriceFormatContext
- $priceLatteExtension : PriceLatteExtension
- $settingContext : SettingContext
- $translator : Translator
Methods
- __construct() : mixed
- prepareDefaultEmail() : PreparedOrderEmail|null
- Renders the system template `ES_ORDER_CHANGED` (value `status` = status name).
- prepareExpeditionEmail() : PreparedOrderEmail|null
- Renders the dispatch notice from `ShipperText` of `order.expeditionShipper` and the order expedition columns.
- prepareNewOrderAdminEmail() : PreparedOrderEmail|null
- Renders the system template `ES_NEW_ORDER`: the notice to the shop administrator about a new order from the checkout (the customer gets the status e-mail, not this one).
- prepareStatusEmail() : PreparedOrderEmail|null
- Renders the e-mail from the status template in the order language.
- prepareVoucherEmail() : PreparedOrderEmail|null
- Renders the system template `ES_NEW_VOUCHER` (compensation voucher from {@see VoucherGenerator}).
- recapValues() : array<string, mixed>
- Builds the variables of the order e-mail templates.
- adminEmail() : string|null
- Seller e-mail of the order, falling back to the site mailbox `1/email.address`; `null` when neither is valid.
- customerEmail() : string|null
- formatMoney() : string
- inOrderFormat() : PreparedOrderEmail|null
- Runs the render in the localization and language of the order. An order without localization (historical) falls back to the request localization.
- isTransferPayment() : bool
- Tells whether the payment is a bank transfer: the method sends a proforma invoice and has no payment gateway (same rule as `OrderCheckoutManager::targetStatusKey()`).
- orderLocalization() : object|null
- Returns the order localization (snapshot from checkout/admin).
- render() : PreparedOrderEmail|null
- Renders subject and body; a failed render (see {@see renderTemplate()}) returns `null`, so no empty e-mail is queued.
- renderSubject() : string
- Renders the subject as a Latte string (no wrapper template).
- renderTemplate() : string|null
- Renders the e-mail, returning `null` on failure.
- resolveLanguageId() : int
- Returns `order.language`, falling back to the site-wide default language.
Constants
DEFAULT_EMAIL_KEY
private
string
DEFAULT_EMAIL_KEY
= 'ES_ORDER_CHANGED'
NEW_ORDER_EMAIL_KEY
private
string
NEW_ORDER_EMAIL_KEY
= 'ES_NEW_ORDER'
SETTING_MODULE_CORE
private
int
SETTING_MODULE_CORE
= 0
SETTING_MODULE_SYSTEM
private
int
SETTING_MODULE_SYSTEM
= 1
VOUCHER_EMAIL_KEY
private
string
VOUCHER_EMAIL_KEY
= 'ES_NEW_VOUCHER'
Properties
$calculator read-only
private
OrderCalculator
$calculator
$emailManager read-only
private
EmailManager
$emailManager
$languageManager read-only
private
LanguageManager
$languageManager
$priceFormatContext read-only
private
PriceFormatContext
$priceFormatContext
$priceLatteExtension read-only
private
PriceLatteExtension
$priceLatteExtension
$settingContext read-only
private
SettingContext
$settingContext
$translator read-only
private
Translator
$translator
Methods
__construct()
public
__construct(SettingContext $settingContext, EmailManager $emailManager, LanguageManager $languageManager, PriceLatteExtension $priceLatteExtension, OrderCalculator $calculator, PriceFormatContext $priceFormatContext, Translator $translator) : mixed
Parameters
- $settingContext : SettingContext
- $emailManager : EmailManager
- $languageManager : LanguageManager
- $priceLatteExtension : PriceLatteExtension
- $calculator : OrderCalculator
- $priceFormatContext : PriceFormatContext
- $translator : Translator
prepareDefaultEmail()
Renders the system template `ES_ORDER_CHANGED` (value `status` = status name).
public
prepareDefaultEmail(Order $order, OrderStatus $status[, string|null $invoicePdfPath = null ][, string|null $invoiceVariableSymbol = null ]) : PreparedOrderEmail|null
Returns null when the template is missing in the database or empty for the order language.
The invoice PDF is attached like in prepareStatusEmail().
IMPORTANT: the created and approved statuses have send_email=0, so this default e-mail is the only one
the customer receives. Without the attachment here the order confirmation would never reach
the customer by e-mail.
Parameters
- $order : Order
- $status : OrderStatus
- $invoicePdfPath : string|null = null
- $invoiceVariableSymbol : string|null = null
Return values
PreparedOrderEmail|nullprepareExpeditionEmail()
Renders the dispatch notice from `ShipperText` of `order.expeditionShipper` and the order expedition columns.
public
prepareExpeditionEmail(Order $order) : PreparedOrderEmail|null
Returns null when the shipper is missing, Shipper::getSendEmail() is false, or the
template is empty. The status name is read from order.status, which the transition must
set to the target status before calling this method (there is no $status parameter).
Parameters
- $order : Order
Return values
PreparedOrderEmail|nullprepareNewOrderAdminEmail()
Renders the system template `ES_NEW_ORDER`: the notice to the shop administrator about a new order from the checkout (the customer gets the status e-mail, not this one).
public
prepareNewOrderAdminEmail(TOrderGraph $order, string $adminLink) : PreparedOrderEmail|null
Recipient: the seller e-mail of the order (the Invoicer seller of the shop, snapshot on the
order), falling back to the site mailbox 1/email.address (the same rule as the reservation
notice to a company). The text is in the default site language (the operator), amounts and
dates in the order format. The subject is rendered as Latte ({$orderNumber}).
Values (flat, no array access in the template): orderNumber, orderDate, customerName,
customerCompany, customerEmail, customerPhone, shippingName, paymentName,
totalPrice (payable amount with the currency) and adminLink (absolute link to the order in
the administration, '' when no absolute address is known).
Returns null when the template is missing, turned off (the default) or empty in
that language, when no recipient address is known, or when the render fails.
Parameters
- $order : TOrderGraph
- $adminLink : string
Return values
PreparedOrderEmail|nullprepareStatusEmail()
Renders the e-mail from the status template in the order language.
public
prepareStatusEmail(Order $order, OrderStatus $status, string|null $invoicePdfPath[, string|null $invoiceVariableSymbol = null ]) : PreparedOrderEmail|null
Returns null for an empty template (missing text, or empty subject or body; a status
without e-mail, e.g. a new order). The invoice PDF is attached when $invoicePdfPath is given.
Parameters
- $order : Order
- $status : OrderStatus
- $invoicePdfPath : string|null
- $invoiceVariableSymbol : string|null = null
Return values
PreparedOrderEmail|nullprepareVoucherEmail()
Renders the system template `ES_NEW_VOUCHER` (compensation voucher from {@see VoucherGenerator}).
public
prepareVoucherEmail(Order $order, Voucher $voucher, array{voucherLevelId: int, durationDays: int, minPrice: string, maxPrice: string, percents: int, fixedAmount: ?string} $level, string $orderTotal) : PreparedOrderEmail|null
Values: voucher.code/percents/price/endDate/minPrice/maxPrice and currency.shortcut.
For a percentage band price is only an informative percents % of $orderTotal; the
redemption itself is always percentage-based. For a fixed-amount band (getHasPercents()
is false) price is level['fixedAmount'], the real voucher value.
Parameters
- $order : Order
- $voucher : Voucher
- $level : array{voucherLevelId: int, durationDays: int, minPrice: string, maxPrice: string, percents: int, fixedAmount: ?string}
- $orderTotal : string
Return values
PreparedOrderEmail|nullrecapValues()
Builds the variables of the order e-mail templates.
public
recapValues(TOrderGraph $order[, string|null $invoiceVariableSymbol = null ]) : array<string, mixed>
The templates live in the database (order_status_texts.email_body, email_texts.body)
and read these values through Latte expressions. Amounts arrive already formatted in the
order currency (filter priceFormat); the template only prints them.
$order:orderNumber,variableSymbol,totalPriceWithVat(the payable rounded amount),itemsTotal,rounding(only whenroundingLine),roundingLine,withVat,totalBase,note$items:name,code,quantity,unit,unitPrice,totalPrice,fees(text informative only: already included in the price, not added)$shipping/$payment:name,price(ornull);$payment.isTransfer$vouchers:code,discount(positive discount amount)$gifts:name,amount(gifts of the order, free of charge)$vatRecap:rate,base,vat,total(empty for an order without VAT)$order.taxNote: VAT clause in the order language and Czech; an empty string means the treatment has no clause (domestic supply by a VAT payer)$bank:account,iban,swift,bankName,variableSymbol,amount,missing(missingis a transfer without a seller account; the template must say so instead of leaving a blank)
Values include VAT (the paid amounts) for an order with VAT; for a non-payer *WithVat
equals the base.
Parameters
- $order : TOrderGraph
- $invoiceVariableSymbol : string|null = null
-
variable symbol of the issued invoice (a transfer is matched by it)
Return values
array<string, mixed>adminEmail()
Seller e-mail of the order, falling back to the site mailbox `1/email.address`; `null` when neither is valid.
private
adminEmail(Order $order) : string|null
Parameters
- $order : Order
Return values
string|nullcustomerEmail()
private
customerEmail(Order $order) : string|null
Parameters
- $order : Order
Return values
string|nullformatMoney()
private
formatMoney(string|float|null $amount, object|null $currency) : string
Parameters
- $amount : string|float|null
- $currency : object|null
Return values
stringinOrderFormat()
Runs the render in the localization and language of the order. An order without localization (historical) falls back to the request localization.
private
inOrderFormat(TOrderGraph $order, callable(): Array $render) : PreparedOrderEmail|null
Parameters
- $order : TOrderGraph
- $render : callable(): Array
Return values
PreparedOrderEmail|nullisTransferPayment()
Tells whether the payment is a bank transfer: the method sends a proforma invoice and has no payment gateway (same rule as `OrderCheckoutManager::targetStatusKey()`).
private
isTransferPayment(object|null $orderPaymentMethod) : bool
The OrderPaymentMethod snapshot carries only name and price, so the method properties are
read from the catalog entity (lazy). A failed read means "not a transfer": the e-mail then
simply omits the payment details.
Parameters
- $orderPaymentMethod : object|null
Return values
boolorderLocalization()
Returns the order localization (snapshot from checkout/admin).
private
orderLocalization(TOrderGraph $order) : object|null
A lazy proxy detached after UoW::clear() may not initialize; the result is then null
and the request format is used, so the e-mail does not fail.
Parameters
- $order : TOrderGraph
Return values
object|nullrender()
Renders subject and body; a failed render (see {@see renderTemplate()}) returns `null`, so no empty e-mail is queued.
private
render(string $subject, string $body, string $to, array<string, mixed> $values, array<int, array{fileName: string, filePath: string, contentType: ?string}> $files, bool $preferred) : PreparedOrderEmail|null
Parameters
- $subject : string
- $body : string
- $to : string
- $values : array<string, mixed>
- $files : array<int, array{fileName: string, filePath: string, contentType: ?string}>
- $preferred : bool
Return values
PreparedOrderEmail|nullrenderSubject()
Renders the subject as a Latte string (no wrapper template).
private
renderSubject(string $subject, array<string, mixed> $values) : string
The output is plain text: HTML entities from escaping are decoded and tags stripped. A
render error returns the subject as written in the template (the e-mail is not dropped
because of its subject) and is logged to eshop.general.
Parameters
- $subject : string
- $values : array<string, mixed>
Return values
stringrenderTemplate()
Renders the e-mail, returning `null` on failure.
private
renderTemplate(string $body, array<string, mixed> $values) : string|null
IMPORTANT: a failed render (broken Latte template, unwritable tempDir, missing email.latte)
must neither break the transition nor produce an empty e-mail. It catches \Throwable, not
just \Exception: an \Error from a broken template or helper would otherwise abort the
final transaction. The failure is logged to eshop.general and prepare*() returns null, so
nothing is queued.
Parameters
- $body : string
- $values : array<string, mixed>
Return values
string|nullresolveLanguageId()
Returns `order.language`, falling back to the site-wide default language.
private
resolveLanguageId(Order $order) : int
Parameters
- $order : Order