CoolCMS API

OrderPayloadHelper
in package

FinalYes

Pure helper without any I/O (no entity manager, DBAL or files): parses and validates the payload of the admin order form (`api/eshop/order/build`), applies the seller snapshot to the entity and serializes the recalculated order for the AJAX response.

Orchestration stays in OrderBuildTrait (and so in OrderManager, which saves the order); only side-effect-free code belongs here, because Models/Helpers/ means pure computation without I/O.

Table of Contents

Constants

CHARGE_VALUE_OUT_OF_RANGE  : string = 'chargeValueOutOfRange'
Error code of shipping/payment with a negative price or a rate outside 0..100.
LINE_PRICE_REQUIRED  : string = 'linePriceRequired'
Error code of a line without a price (missing or not a number).
LINE_VALUE_OUT_OF_RANGE  : string = 'lineValueOutOfRange'
Error code of a line with a value outside its business range (see {@see lineRangeError()}).
MAX_QUANTITY  : int = 4294967295
Largest quantity of an order line: `cms_mod_eshop_order_items.quantity` is `unsigned int`.
MONEY_MAX_EXCLUSIVE  : string = '10000000'
Exclusive upper bound of a money amount: the price columns are `decimal(10,3)`.
NESTED_ID_KEYS  : array<string|int, mixed> = ['seller' => ['sellerId', 'sellerContactId', 's...
Nested objects (`payload[<object>][<key>]`) holding a record id.
ORDER_ID_KEYS  : array<string|int, mixed> = ['id', 'userId', 'userTypeId', 'currencyId', 'l...
Top-level payload keys holding a record id.
ROW_ID_KEYS  : array<string|int, mixed> = ['lines' => ['setId', 'orderItemId'], 'gifts' =...
Row lists (`payload[<list>][<n>][<key>]`) holding a record id.

Methods

applySellerPayload()  : void
Applies the seller snapshot from the payload. The admin form fills it from the Invoicer directory through a picker, but the values stay manually editable: for an old order this is the only way to issue an invoice with the data valid at that time. The server therefore looks up and overwrites nothing from the directory; what arrives is stored (the same trusted-rows contract as for lines).
chargeRangeError()  : string|null
Returns the error message of shipping/payment whose sent `price` is negative or `vat` outside 0..100, or null. A missing value is fine (the resolver prefills it); the bounds are the same as for a line.
findInvalidIdPath()  : string|null
Returns the first id in the build payload that is not canonical, as a path (`lines[0].orderItemId`), or null when every id is fine. Lenient casting would turn `'1.9'` / `1.9` into 1 and `'1e2'` into 100, so a malformed row would silently edit another order item. Absent, null, `''` and `0` mean "not set" (`setId = 0` with `orderItemId` is the "sales card gone" row); anything else must pass {@see RequestParamShape::positiveInt()}. Checked before any lookup or builder.
lineRangeError()  : string|null
Returns the error message of a line whose value is outside its business range, or null.
payloadGiftLines()  : array<int, array{giftId: int, amount?: int}>
payloadId()  : int|null
Canonical record id ({@see RequestParamShape::positiveInt()}) or `null` = not set.
payloadInt()  : int|null
Reads counts (`quantity`, `amount`), not ids; ids go through {@see self::payloadId()}.
payloadLines()  : array{0: list, 1: ?string, 2: ?string}
Parses trusted lines: `price` is required (the form always carries it from the prefill or snapshot), and a missing or invalid value on any line is a hard failure with no silent fallback to the catalog; the second returned item carries the error message, the third its code.
payloadPriceOrNull()  : string|null
Shipping and payment `price`/`vat` are optional, unlike `lines`: a missing value tells `buildShipperFromRow()`/`buildPaymentMethodFromRow()` to compute the price through the resolver (prefill) rather than that it is an error.
payloadStringList()  : array<int, string>
payloadStrOrNull()  : string|null
serializeOrder()  : array<string, mixed>
Serializes the recalculated order for the AJAX preview/response of the form (scalar data only; the admin form reads it and does not hydrate it back into the entity).
isDecimalWithin()  : bool
Plain decimal (dot notation, no exponent) within the bounds; `$maxExclusive` for a column bound.
isIdOrUnset()  : bool
isWholeNumberWithin()  : bool
Whole number (plain digits, optional minus) within `[$min, $max]`; compared as strings, no float overflow.

Constants

CHARGE_VALUE_OUT_OF_RANGE

Error code of shipping/payment with a negative price or a rate outside 0..100.

public string CHARGE_VALUE_OUT_OF_RANGE = 'chargeValueOutOfRange'

LINE_PRICE_REQUIRED

Error code of a line without a price (missing or not a number).

public string LINE_PRICE_REQUIRED = 'linePriceRequired'

LINE_VALUE_OUT_OF_RANGE

Error code of a line with a value outside its business range (see {@see lineRangeError()}).

public string LINE_VALUE_OUT_OF_RANGE = 'lineValueOutOfRange'

MAX_QUANTITY

Largest quantity of an order line: `cms_mod_eshop_order_items.quantity` is `unsigned int`.

private int MAX_QUANTITY = 4294967295

MONEY_MAX_EXCLUSIVE

Exclusive upper bound of a money amount: the price columns are `decimal(10,3)`.

private string MONEY_MAX_EXCLUSIVE = '10000000'

NESTED_ID_KEYS

Nested objects (`payload[<object>][<key>]`) holding a record id.

private array<string|int, mixed> NESTED_ID_KEYS = ['seller' => ['sellerId', 'sellerContactId', 'sellerBankAccountId'], 'customer' => ['customerId', 'customerContactId'], 'shipping' => ['tariffId'], 'payment' => ['paymentMethodId']]

ORDER_ID_KEYS

Top-level payload keys holding a record id.

private array<string|int, mixed> ORDER_ID_KEYS = ['id', 'userId', 'userTypeId', 'currencyId', 'languageId', 'localizationId', 'paymentRegionId', 'statusId']

ROW_ID_KEYS

Row lists (`payload[<list>][<n>][<key>]`) holding a record id.

private array<string|int, mixed> ROW_ID_KEYS = ['lines' => ['setId', 'orderItemId'], 'gifts' => ['giftId']]

Methods

applySellerPayload()

Applies the seller snapshot from the payload. The admin form fills it from the Invoicer directory through a picker, but the values stay manually editable: for an old order this is the only way to issue an invoice with the data valid at that time. The server therefore looks up and overwrites nothing from the directory; what arrives is stored (the same trusted-rows contract as for lines).

public applySellerPayload(Order $order, array<string|int, mixed> $seller) : void
Parameters
$order : Order
$seller : array<string|int, mixed>

chargeRangeError()

Returns the error message of shipping/payment whose sent `price` is negative or `vat` outside 0..100, or null. A missing value is fine (the resolver prefills it); the bounds are the same as for a line.

public chargeRangeError(array<string|int, mixed> $row, string $label) : string|null
Parameters
$row : array<string|int, mixed>
$label : string
Return values
string|null

findInvalidIdPath()

Returns the first id in the build payload that is not canonical, as a path (`lines[0].orderItemId`), or null when every id is fine. Lenient casting would turn `'1.9'` / `1.9` into 1 and `'1e2'` into 100, so a malformed row would silently edit another order item. Absent, null, `''` and `0` mean "not set" (`setId = 0` with `orderItemId` is the "sales card gone" row); anything else must pass {@see RequestParamShape::positiveInt()}. Checked before any lookup or builder.

public findInvalidIdPath(array<string|int, mixed> $payload) : string|null
Parameters
$payload : array<string|int, mixed>
Return values
string|null

lineRangeError()

Returns the error message of a line whose value is outside its business range, or null.

public lineRangeError(array<string|int, mixed> $row, int $setId) : string|null
  • quantity (when sent): a whole number from 1 to the unsigned int column; a return is a complaint or a credit note, never a negative or zero order line;
  • price: not negative and below the decimal(10,3) bound; a refund is a credit note;
  • vat (when sent): 0..100;
  • discountPercents (when sent): 0..100. The order chain (OrderCalculator, the document and the e-mail) reads a discount <= 0 as none and caps it at 100, so anything else would not be counted.
Parameters
$row : array<string|int, mixed>
$setId : int
Return values
string|null

payloadGiftLines()

public payloadGiftLines(mixed $raw) : array<int, array{giftId: int, amount?: int}>
Parameters
$raw : mixed
Return values
array<int, array{giftId: int, amount?: int}>

payloadId()

Canonical record id ({@see RequestParamShape::positiveInt()}) or `null` = not set.

public payloadId(array<string|int, mixed> $payload, string $key) : int|null

A malformed id is never re-read as another one; self::findInvalidIdPath() rejects it up front, so here it can only mean "not set".

Parameters
$payload : array<string|int, mixed>
$key : string
Return values
int|null

payloadInt()

Reads counts (`quantity`, `amount`), not ids; ids go through {@see self::payloadId()}.

public payloadInt(array<string|int, mixed> $payload, string $key) : int|null
Parameters
$payload : array<string|int, mixed>
$key : string
Return values
int|null

payloadLines()

Parses trusted lines: `price` is required (the form always carries it from the prefill or snapshot), and a missing or invalid value on any line is a hard failure with no silent fallback to the catalog; the second returned item carries the error message, the third its code.

public payloadLines(mixed $raw) : array{0: list, 1: ?string, 2: ?string}

The values must also be in their business range (lineRangeError()): the admin form checks the same bounds, this is the authority for any other caller. Without it a negative price or a discount over 100 % was stored on the line while OrderCalculator left it out of the total (it floors the total at zero and caps the discount), so the order total did not match its lines.

Optional orderItemId is the id of an existing item of this order that the line edits; it lets OrderSnapshotBuilder::buildItemsFromRows() carry the item over (id, frozen stock breakdown, price snapshot) instead of creating a new one.

Parameters
$raw : mixed
Return values
array{0: list, 1: ?string, 2: ?string}

payloadPriceOrNull()

Shipping and payment `price`/`vat` are optional, unlike `lines`: a missing value tells `buildShipperFromRow()`/`buildPaymentMethodFromRow()` to compute the price through the resolver (prefill) rather than that it is an error.

public payloadPriceOrNull(array<string|int, mixed> $payload, string $key) : string|null
Parameters
$payload : array<string|int, mixed>
$key : string
Return values
string|null

payloadStringList()

public payloadStringList(mixed $raw) : array<int, string>
Parameters
$raw : mixed
Return values
array<int, string>

payloadStrOrNull()

public payloadStrOrNull(array<string|int, mixed> $payload, string $key) : string|null
Parameters
$payload : array<string|int, mixed>
$key : string
Return values
string|null

serializeOrder()

Serializes the recalculated order for the AJAX preview/response of the form (scalar data only; the admin form reads it and does not hydrate it back into the entity).

public serializeOrder(Order $order) : array<string, mixed>
Parameters
$order : Order
Return values
array<string, mixed>

isDecimalWithin()

Plain decimal (dot notation, no exponent) within the bounds; `$maxExclusive` for a column bound.

private isDecimalWithin(mixed $value, numeric-string $min, numeric-string $max[, bool $maxExclusive = false ]) : bool
Parameters
$value : mixed
$min : numeric-string
$max : numeric-string
$maxExclusive : bool = false
Return values
bool

isIdOrUnset()

private isIdOrUnset(mixed $value) : bool
Parameters
$value : mixed
Return values
bool

isWholeNumberWithin()

Whole number (plain digits, optional minus) within `[$min, $max]`; compared as strings, no float overflow.

private isWholeNumberWithin(mixed $value, int $min, int $max) : bool
Parameters
$value : mixed
$min : int
$max : int
Return values
bool
On this page

Search results