ProductHardDeleteManager
in package
Hard-deletes a product or a single variant: builds the plan, checks the gates and cleans up related data.
Called by ProductManager (buildPlan()) and ProductVariantManager
(buildVariantPlan(), the product stays) from the DeleteTrait::delete() hooks, inside
the delete transaction.
Contract:
- a product's variants are deleted with it;
- a product set is deleted (with its images and threads) only when it would be left empty after the deleted variants are removed (EmptiedSetResolver); a set with other content stays and only loses the item;
- IMPORTANT: history is never deleted. A set, variant or stock item referenced by an order,
complaint or gift makes the deletion refuse, because the FK of those references is
SET NULLand the history would silently lose its link. Soft delete remains available. Invoices are not affected: they keep a code and name snapshot and reference neither the product, variant nor set; - carts are cleaned up (
cart_itemshas no FK).
Everything runs as raw DBAL in the same transaction as the product delete, with no find()
(every Api read does UoW::clear()).
Table of Contents
Constants
- CART_ITEMS_TABLE : string = 'cms_mod_eshop_cart_items'
- EXTERNAL_MODULE_ESHOP : int = 4
- The eshop module in `cms_system_modules`, used by the variant to stock item mirror ({@see ProductVariantManager}).
- HANDLED_REFERENCES : array<string|int, mixed> = ['cms_mod_eshop_product_sets.cms_mod_eshop_prod...
- References to a product, variant or set with a rule other than `CASCADE` that this manager handles (`table.column`). Any other such reference makes the deletion refuse before anything is written.
- PRODUCTS_TABLE : string = 'cms_mod_eshop_products'
- SET_IMAGES_TABLE : string = 'cms_mod_eshop_product_set_image_relations'
- SET_ITEMS_TABLE : string = 'cms_mod_eshop_set_item_relations'
- SETS_TABLE : string = 'cms_mod_eshop_product_sets'
- STOCK_ITEMS_TABLE : string = 'cms_mod_store_stock_items'
- VARIANTS_TABLE : string = 'cms_mod_eshop_product_variants'
Properties
- $em : EntityManagerInterface
- $emptiedSetResolver : EmptiedSetResolver
- $productSetManager : ProductSetManager
- $unitOfWorkReset : UnitOfWorkReset
Methods
- __construct() : mixed
- apply() : Result|null
- Writes before the product row is deleted, inside the delete transaction.
- buildPlan() : ProductHardDeletePlan
- Builds the plan for deleting products; all their variants are deleted too.
- buildVariantPlan() : ProductHardDeletePlan
- Builds the plan for deleting single variants: the product stays, the variant's sale card and any bundles left empty by it are deleted. `productIds` is empty, so {@see apply()} does not detach the product from its other sets.
- findBlockers() : array<int, string>
- Returns the reasons why the product cannot be hard-deleted (empty list = it can). Writes nothing.
- findUncoveredReferences() : array<int, string>
- Returns references to a product, variant or set that do not cascade on delete and are unknown to this manager.
- reindexSearch() : void
- Best-effort after commit: removes the deleted sets from the search index and reindexes the surviving ones.
- releaseStockItemMirror() : void
- Clears the variant to stock item mirror on stock items that pointed to a deleted variant.
- collect() : void
- discardDeletedSets() : void
- Detaches the sets just deleted by SQL that are still managed (loaded earlier in the same unit of work). Their rows are gone, but the instance keeps its ManyToOne references to the comment and rating threads; once a thread manager removes and flushes one thread, the next flush would find the reference as a new entity and fail ("ProductSet#commentThread"). Today the read `UoW::clear()` in the thread manager's `find()` hides that; without it the set must go explicitly.
- findParentBundles() : array<int, array<int, int>>
- planFor() : ProductHardDeletePlan
- Builds the shared core of the plan: sets to delete, bundles that only lose an item, and what belongs to the deleted sets.
- toInt() : int
- toInts() : array<int, int>
- toStr() : string
-
variantsWithStockItems()
: array{0: list
, 1: list } - Returns the variants matching the condition (a single `IN (?)` parameter) and their stock items.
Constants
CART_ITEMS_TABLE
private
string
CART_ITEMS_TABLE
= 'cms_mod_eshop_cart_items'
EXTERNAL_MODULE_ESHOP
The eshop module in `cms_system_modules`, used by the variant to stock item mirror ({@see ProductVariantManager}).
private
int
EXTERNAL_MODULE_ESHOP
= 4
HANDLED_REFERENCES
References to a product, variant or set with a rule other than `CASCADE` that this manager handles (`table.column`). Any other such reference makes the deletion refuse before anything is written.
private
array<string|int, mixed>
HANDLED_REFERENCES
= ['cms_mod_eshop_product_sets.cms_mod_eshop_product_variants_product_variant_id', 'cms_mod_eshop_order_items.cms_mod_eshop_product_sets_product_set_id', 'cms_mod_eshop_complaint_items.cms_mod_eshop_product_sets_product_set_id', 'cms_mod_eshop_gifts.cms_mod_eshop_product_sets_product_set_id']
PRODUCTS_TABLE
private
string
PRODUCTS_TABLE
= 'cms_mod_eshop_products'
SET_IMAGES_TABLE
private
string
SET_IMAGES_TABLE
= 'cms_mod_eshop_product_set_image_relations'
SET_ITEMS_TABLE
private
string
SET_ITEMS_TABLE
= 'cms_mod_eshop_set_item_relations'
SETS_TABLE
private
string
SETS_TABLE
= 'cms_mod_eshop_product_sets'
STOCK_ITEMS_TABLE
private
string
STOCK_ITEMS_TABLE
= 'cms_mod_store_stock_items'
VARIANTS_TABLE
private
string
VARIANTS_TABLE
= 'cms_mod_eshop_product_variants'
Properties
$em read-only
private
EntityManagerInterface
$em
$emptiedSetResolver read-only
private
EmptiedSetResolver
$emptiedSetResolver
$productSetManager read-only
private
ProductSetManager
$productSetManager
$unitOfWorkReset read-only
private
UnitOfWorkReset
$unitOfWorkReset
Methods
__construct()
public
__construct(EntityManagerInterface $em, ProductSetManager $productSetManager, EmptiedSetResolver $emptiedSetResolver, UnitOfWorkReset $unitOfWorkReset) : mixed
Parameters
- $em : EntityManagerInterface
- $productSetManager : ProductSetManager
- $emptiedSetResolver : EmptiedSetResolver
- $unitOfWorkReset : UnitOfWorkReset
apply()
Writes before the product row is deleted, inside the delete transaction.
public
apply(ProductHardDeletePlan $plan) : Result|null
Deletes the doomed sets (with threads and cart items) and detaches the product from the
remaining sets, so ON DELETE CASCADE does not take them with it.
Parameters
- $plan : ProductHardDeletePlan
Return values
Result|nullbuildPlan()
Builds the plan for deleting products; all their variants are deleted too.
public
buildPlan(array<int, int> $productIds) : ProductHardDeletePlan
Parameters
- $productIds : array<int, int>
Return values
ProductHardDeletePlanbuildVariantPlan()
Builds the plan for deleting single variants: the product stays, the variant's sale card and any bundles left empty by it are deleted. `productIds` is empty, so {@see apply()} does not detach the product from its other sets.
public
buildVariantPlan(array<int, int> $variantIds) : ProductHardDeletePlan
Parameters
- $variantIds : array<int, int>
Return values
ProductHardDeletePlanfindBlockers()
Returns the reasons why the product cannot be hard-deleted (empty list = it can). Writes nothing.
public
findBlockers(ProductHardDeletePlan $plan) : array<int, string>
Parameters
- $plan : ProductHardDeletePlan
Return values
array<int, string>findUncoveredReferences()
Returns references to a product, variant or set that do not cascade on delete and are unknown to this manager.
public
findUncoveredReferences() : array<int, string>
Return values
array<int, string>reindexSearch()
Best-effort after commit: removes the deleted sets from the search index and reindexes the surviving ones.
public
reindexSearch(ProductHardDeletePlan $plan) : void
Parameters
- $plan : ProductHardDeletePlan
releaseStockItemMirror()
Clears the variant to stock item mirror on stock items that pointed to a deleted variant.
public
releaseStockItemMirror(ProductHardDeletePlan $plan) : void
Runs after the product delete, still inside the transaction.
Parameters
- $plan : ProductHardDeletePlan
collect()
private
collect(array<int, int> &$bucket, mixed $value) : void
Parameters
- $bucket : array<int, int>
- $value : mixed
discardDeletedSets()
Detaches the sets just deleted by SQL that are still managed (loaded earlier in the same unit of work). Their rows are gone, but the instance keeps its ManyToOne references to the comment and rating threads; once a thread manager removes and flushes one thread, the next flush would find the reference as a new entity and fail ("ProductSet#commentThread"). Today the read `UoW::clear()` in the thread manager's `find()` hides that; without it the set must go explicitly.
private
discardDeletedSets(array<int, int> $setIds) : void
A set not in the identity map costs only the lookup.
Parameters
- $setIds : array<int, int>
findParentBundles()
private
findParentBundles(array<int, int> $setIds) : array<int, array<int, int>>
Parameters
- $setIds : array<int, int>
Return values
array<int, array<int, int>> —bundle id mapped to all of its items
planFor()
Builds the shared core of the plan: sets to delete, bundles that only lose an item, and what belongs to the deleted sets.
private
planFor(array<int, int> $productIds, array<int, int> $variantIds, array<int, int> $stockItemIds, array<int, int> $leafSetIds) : ProductHardDeletePlan
Parameters
- $productIds : array<int, int>
- $variantIds : array<int, int>
- $stockItemIds : array<int, int>
- $leafSetIds : array<int, int>
Return values
ProductHardDeletePlantoInt()
private
toInt(mixed $value) : int
Parameters
- $value : mixed
Return values
inttoInts()
private
toInts(array<int, mixed> $values) : array<int, int>
Parameters
- $values : array<int, mixed>
Return values
array<int, int>toStr()
private
toStr(mixed $value) : string
Parameters
- $value : mixed
Return values
stringvariantsWithStockItems()
Returns the variants matching the condition (a single `IN (?)` parameter) and their stock items.
private
variantsWithStockItems(string $where, array<int, int> $ids) : array{0: list, 1: list}
Parameters
- $where : string
- $ids : array<int, int>