MultiplierLimits
in package
Server-side limits on the number of rows of `Contributte\FormMultiplier\Multiplier`.
Without $maxCopies (third constructor argument) the library materializes an arbitrarily
large received HTTP tree. With $maxCopies excess rows are silently cut (array_slice),
which is unacceptable for financial documents and trees (silent data loss). Hence two layers:
guard()reads the raw HTTP data ($form->getHttpData()) before materialization and adds a global form error when exceeded, soonSuccessand the save never run;$maxCopiesas theMultiplierthird argument, a second defense if (1) is missing or bypassed (direct call without a POST).
The limits are a product decision, not numbers derived from code, so they live in one place as named constants instead of copied numbers at each caller.
Table of Contents
Constants
- CATEGORY_PARAMETER_GROUPS : int = 100
- Outer `parameterGroups`.
- CATEGORY_PARAMETERS_PER_GROUP : int = 200
- Nested `parameters` within one group.
- FEED_TREE_CHILDREN_PER_NODE : int = 500
- Nested `children` of one node.
- FEED_TREE_ROOTS : int = 500
- Root nodes of `parameters`.
- FEED_TREE_TOTAL_NODES : int = 5000
- Total number of tree nodes (roots plus all children).
- INVOICE_GIFTS : int = 100
- `gifts` (`InvoiceGift`, `InvoiceTemplateGift`, `OrderGift`).
- INVOICE_ITEMS : int = 500
- `items` (`InvoiceItem`, `InvoiceTemplateItem`, `OrderItem`).
- INVOICE_VOUCHERS : int = 100
- `vouchers` (`InvoiceVoucher`, `InvoiceTemplateVoucher`, `OrderVoucher`).
- MESSAGE : string = '//admin.general.multiplierLimit'
- Global message (`//` bypasses the form domain prefix, as in {@see ColumnGate}).
- PRODUCT_SET_RELATION_ROWS : int = 500
- `setItems`, `accessories`, `tags`, `fees` and `links`; the same limit for each.
- SHIPPER_TARIFF_BANDS_PER_GENERATION : int = 100
- Nested `bands` within one generation.
- SHIPPER_TARIFF_GENERATIONS : int = 50
- Outer `generations`.
- STOCK_DOCUMENT_LINES : int = 1000
- `lines` (`StockMovement` rows of the document).
Methods
- count() : int
- Number of real rows in the raw HTTP data (without submit buttons).
- exceeds() : bool
- Returns true when the raw HTTP data carry more rows than the limit allows.
- guard() : bool
- Checks raw rows against the limit; when exceeded, adds a global form error (the text is already translated with the limit filled in, hence `translate: false`) and returns false.
- message() : string
- Returns the translated message with the limit filled in, for callers that need it outside `guard()` (flash).
- rows() : array<int|string, array<string|int, mixed>>
- Keeps only rows (arrays) of the raw multiplier HTTP data.
Constants
CATEGORY_PARAMETER_GROUPS
Outer `parameterGroups`.
public
int
CATEGORY_PARAMETER_GROUPS
= 100
CATEGORY_PARAMETERS_PER_GROUP
Nested `parameters` within one group.
public
int
CATEGORY_PARAMETERS_PER_GROUP
= 200
FEED_TREE_CHILDREN_PER_NODE
Nested `children` of one node.
public
int
FEED_TREE_CHILDREN_PER_NODE
= 500
FEED_TREE_ROOTS
Root nodes of `parameters`.
public
int
FEED_TREE_ROOTS
= 500
FEED_TREE_TOTAL_NODES
Total number of tree nodes (roots plus all children).
public
int
FEED_TREE_TOTAL_NODES
= 5000
INVOICE_GIFTS
`gifts` (`InvoiceGift`, `InvoiceTemplateGift`, `OrderGift`).
public
int
INVOICE_GIFTS
= 100
INVOICE_ITEMS
`items` (`InvoiceItem`, `InvoiceTemplateItem`, `OrderItem`).
public
int
INVOICE_ITEMS
= 500
INVOICE_VOUCHERS
`vouchers` (`InvoiceVoucher`, `InvoiceTemplateVoucher`, `OrderVoucher`).
public
int
INVOICE_VOUCHERS
= 100
MESSAGE
Global message (`//` bypasses the form domain prefix, as in {@see ColumnGate}).
public
string
MESSAGE
= '//admin.general.multiplierLimit'
The translator fills %d with the real limit, not a number copied into the translation.
PRODUCT_SET_RELATION_ROWS
`setItems`, `accessories`, `tags`, `fees` and `links`; the same limit for each.
public
int
PRODUCT_SET_RELATION_ROWS
= 500
SHIPPER_TARIFF_BANDS_PER_GENERATION
Nested `bands` within one generation.
public
int
SHIPPER_TARIFF_BANDS_PER_GENERATION
= 100
SHIPPER_TARIFF_GENERATIONS
Outer `generations`.
public
int
SHIPPER_TARIFF_GENERATIONS
= 50
STOCK_DOCUMENT_LINES
`lines` (`StockMovement` rows of the document).
public
int
STOCK_DOCUMENT_LINES
= 1000
Methods
count()
Number of real rows in the raw HTTP data (without submit buttons).
public
static count(mixed $rawRows) : int
Parameters
- $rawRows : mixed
Return values
intexceeds()
Returns true when the raw HTTP data carry more rows than the limit allows.
public
static exceeds(mixed $rawRows, int $max) : bool
Parameters
- $rawRows : mixed
- $max : int
Return values
boolguard()
Checks raw rows against the limit; when exceeded, adds a global form error (the text is already translated with the limit filled in, hence `translate: false`) and returns false.
public
static guard(Form $form, mixed $rawRows, int $max) : bool
Call it before the object graph is built, typically from $form->onAnchor[] inside the
add*Multiplier() method: $form->getHttpData() needs an anchored form, and the form is
not anchored yet while createComponentEditForm() runs (Nette anchors the component after
the factory returns), the same reason Multiplier defers loading HTTP data.
IMPORTANT: not every admin template renders addError() (see the BasePresenter::createForm()
docblock). A caller whose template does not render $form->getErrors() must surface the
error through its own channel (flash or component notice), otherwise nothing is saved and
the user sees no reason.
Parameters
- $form : Form
- $rawRows : mixed
- $max : int
Return values
boolmessage()
Returns the translated message with the limit filled in, for callers that need it outside `guard()` (flash).
public
static message(Form $form, int $max) : string
Parameters
- $form : Form
- $max : int
Return values
stringrows()
Keeps only rows (arrays) of the raw multiplier HTTP data.
public
static rows(mixed $rawRows) : array<int|string, array<string|int, mixed>>
Like the library ComponentResolver::getPurgedHttpData(), it drops the multiplier submit
buttons (multiplier_creator*), which lie in the HTTP data as strings on the same level
as the numbered rows, not inside them.
Parameters
- $rawRows : mixed