Downloadable Product Decoupling Report¶
Modules Scanned¶
Magento_Downloadable(app/code/Magento/Downloadable)Magento_DownloadableGraphQl(app/code/Magento/DownloadableGraphQl)Magento_DownloadableImportExport(app/code/Magento/DownloadableImportExport)
Constants Inventory¶
Downloadable (Main Module)¶
| Constant | Class | Value | Visibility |
|---|---|---|---|
TYPE_DOWNLOADABLE |
Model\Product\Type |
'downloadable' |
public |
PRICE_CODE |
Pricing\Price\LinkPrice |
'link_price' |
public |
LINK_TYPE_URL |
Helper\Download |
'url' |
public |
LINK_TYPE_FILE |
Helper\Download |
'file' |
public |
XML_PATH_CONTENT_DISPOSITION |
Helper\Download |
'catalog/downloadable/content_disposition' |
public |
CODE_IS_DOWNLOADABLE |
Api\Data\ProductAttributeInterface |
'is_downloadable' |
public |
DOWNLOADABLE_LINKS |
Api\Data\DownloadableOptionInterface |
'downloadable_links' |
public |
XML_PATH_LINKS_TITLE |
Model\Link |
'catalog/downloadable/links_title' |
public |
XML_PATH_DEFAULT_DOWNLOADS_NUMBER |
Model\Link |
'catalog/downloadable/downloads_number' |
public |
XML_PATH_TARGET_NEW_WINDOW |
Model\Link |
'catalog/downloadable/links_target_new_window' |
public |
XML_PATH_CONFIG_IS_SHAREABLE |
Model\Link |
'catalog/downloadable/shareable' |
public |
LINK_SHAREABLE_YES |
Model\Link |
1 |
public |
LINK_SHAREABLE_NO |
Model\Link |
0 |
public |
LINK_SHAREABLE_CONFIG |
Model\Link |
2 |
public |
KEY_TITLE |
Model\Link |
'title' |
public |
KEY_SORT_ORDER |
Model\Link |
'sort_order' |
public |
KEY_IS_SHAREABLE |
Model\Link |
'is_shareable' |
public |
KEY_PRICE |
Model\Link |
'price' |
public |
KEY_NUMBER_OF_DOWNLOADS |
Model\Link |
'number_of_downloads' |
public |
KEY_LINK_TYPE |
Model\Link |
'link_type' |
public |
KEY_LINK_FILE |
Model\Link |
'link_file' |
public |
KEY_LINK_FILE_CONTENT |
Model\Link |
'link_file_content' |
public |
KEY_LINK_URL |
Model\Link |
'link_url' |
public |
KEY_SAMPLE_TYPE |
Model\Link |
'sample_type' |
public |
KEY_SAMPLE_FILE |
Model\Link |
'sample_file' |
public |
KEY_SAMPLE_FILE_CONTENT |
Model\Link |
'sample_file_content' |
public |
KEY_SAMPLE_URL |
Model\Link |
'sample_url' |
public |
XML_PATH_SAMPLES_TITLE |
Model\Sample |
'catalog/downloadable/samples_title' |
public |
KEY_TITLE |
Model\Sample |
'title' |
public |
KEY_SORT_ORDER |
Model\Sample |
'sort_order' |
public |
KEY_SAMPLE_TYPE |
Model\Sample |
'sample_type' |
public |
KEY_SAMPLE_FILE |
Model\Sample |
'sample_file' |
public |
KEY_SAMPLE_FILE_CONTENT |
Model\Sample |
'sample_file_content' |
public |
KEY_SAMPLE_URL |
Model\Sample |
'sample_url' |
public |
XML_PATH_ORDER_ITEM_STATUS |
Model\Link\Purchased\Item |
'catalog/downloadable/order_item_status' |
public |
LINK_STATUS_PENDING |
Model\Link\Purchased\Item |
'pending' |
public |
LINK_STATUS_AVAILABLE |
Model\Link\Purchased\Item |
'available' |
public |
LINK_STATUS_EXPIRED |
Model\Link\Purchased\Item |
'expired' |
public |
LINK_STATUS_PENDING_PAYMENT |
Model\Link\Purchased\Item |
'pending_payment' |
public |
LINK_STATUS_PAYMENT_REVIEW |
Model\Link\Purchased\Item |
'payment_review' |
public |
DEFAULT_MIME_TYPE |
Model\File\ContentUploader |
'application/octet-stream' |
public |
PARAM_DOWNLOADABLE_DOMAINS |
Model\Url\DomainValidator |
'downloadable_domains' |
public |
DATA |
Model\File\Content |
'file_data' |
public |
NAME |
Model\File\Content |
'name' |
public |
DATA_KEY |
Model\Product\TypeHandler\Sample |
'sample' |
public |
IDENTIFIER_KEY |
Model\Product\TypeHandler\Sample |
'sample_id' |
public |
FIELD_IS_DELETE |
Model\Product\TypeHandler\AbstractTypeHandler |
'is_delete' |
public |
FIELD_FILE |
Model\Product\TypeHandler\AbstractTypeHandler |
'file' |
public |
CHILDREN_PATH |
Ui\..\Composite |
'downloadable/children' |
public |
CONTAINER_LINKS |
Ui\..\Composite |
'container_links' |
public |
CONTAINER_SAMPLES |
Ui\..\Composite |
'container_samples' |
public |
INPUT_KEY_DOMAINS |
Console\Command\DomainsAddCommand |
'domains' |
public |
INPUT_KEY_DOMAINS |
Console\Command\DomainsRemoveCommand |
'domains' |
public |
ADMIN_RESOURCE |
Controller\Adminhtml\Downloadable\File |
'Magento_Catalog::products' |
public |
DownloadableGraphQl¶
| Constant | Class | Value | Visibility |
|---|---|---|---|
DOWNLOADABLE_PRODUCT |
Model\DownloadableProductTypeResolver |
'DownloadableProduct' |
public |
OPTION_TYPE |
Resolver\Product\DownloadableLinksValueUid |
'downloadable' |
private |
DownloadableImportExport¶
| Constant | Class | Value | Visibility |
|---|---|---|---|
PAIR_VALUE_SEPARATOR |
Import\Product\Type\Downloadable |
'=' |
public |
DEFAULT_SORT_ORDER |
Import\Product\Type\Downloadable |
0 |
public |
DEFAULT_NUMBER_OF_DOWNLOADS |
Import\Product\Type\Downloadable |
0 |
public |
DEFAULT_IS_SHAREABLE |
Import\Product\Type\Downloadable |
2 |
public |
DEFAULT_WEBSITE_ID |
Import\Product\Type\Downloadable |
0 |
public |
DOWNLOADABLE_PATCH_SAMPLES |
Import\Product\Type\Downloadable |
'downloadable/files/samples' |
public |
DOWNLOADABLE_PATCH_LINKS |
Import\Product\Type\Downloadable |
'downloadable/files/links' |
public |
DOWNLOADABLE_PATCH_LINK_SAMPLES |
Import\Product\Type\Downloadable |
'downloadable/files/link_samples' |
public |
URL_OPTION_VALUE |
Import\Product\Type\Downloadable |
'url' |
public |
FILE_OPTION_VALUE |
Import\Product\Type\Downloadable |
'file' |
public |
COL_DOWNLOADABLE_SAMPLES |
Import\Product\Type\Downloadable |
'downloadable_samples' |
public |
COL_DOWNLOADABLE_LINKS |
Import\Product\Type\Downloadable |
'downloadable_links' |
public |
DEFAULT_GROUP_TITLE |
Import\Product\Type\Downloadable |
'' |
public |
DEFAULT_PURCHASED_SEPARATELY |
Import\Product\Type\Downloadable |
1 |
public |
ERROR_OPTIONS_NOT_FOUND |
Import\Product\Type\Downloadable |
'optionsNotFound' |
public |
ERROR_GROUP_TITLE_NOT_FOUND |
Import\Product\Type\Downloadable |
'groupTitleNotFound' |
public |
ERROR_OPTION_NO_TITLE |
Import\Product\Type\Downloadable |
'optionNoTitle' |
public |
ERROR_MOVE_FILE |
Import\Product\Type\Downloadable |
'moveFile' |
public |
ERROR_COLS_IS_EMPTY |
Import\Product\Type\Downloadable |
'emptyOptions' |
public |
Cross-Module Constant Usage (Production Code)¶
No Downloadable constants are referenced by external modules. All constant usage is internal within the Downloadable module family.
External Module Coupling to Downloadable¶
PHP use Imports (Production Code)¶
| External Module | File | Import |
|---|---|---|
| CustomerDownloadableGraphQl | Model/Resolver/CustomerDownloadableProducts.php |
Magento\DownloadableGraphQl\Model\ResourceModel\GetPurchasedDownloadableProducts |
Hardcoded String 'downloadable' Outside Downloadable Modules¶
| Module | File | Usage |
|---|---|---|
| Sales | Block/Adminhtml/Order/Create/Search/Grid/Renderer/Price.php:21 |
if ($row->getTypeId() == 'downloadable') |
| Reports | Block/Adminhtml/Product/Downloads/Grid.php:73 |
->addAttributeToFilter('type_id', ['downloadable']) |
| Wishlist | Model/Wishlist/BuyRequest/DownloadableLinkDataProvider.php:17 |
private const PROVIDER_OPTION_TYPE = 'downloadable' |
| QuoteDownloadableLinks | Model/Cart/BuyRequest/DownloadableLinkDataProvider.php:19 |
private const OPTION_TYPE = 'downloadable' |
XML References to Downloadable Classes¶
| External Module | File | Reference |
|---|---|---|
| RemoteStorage | etc/di.xml:152 |
<type name="Magento\DownloadableImportExport\Helper\Uploader"> |
| Wishlist | etc/di.xml:57 |
<virtualType name="Magento\Downloadable\Pricing\Price\Pool"> — injects wishlist price |
| Wishlist | view/frontend/layout/wishlist_index_configure_type_downloadable.xml |
Renders Magento\Downloadable\Block\Catalog\Product\Samples, View\Type, Product\Links blocks |
| Msrp | view/frontend/layout/catalog_product_view_type_downloadable.xml:10 |
<referenceBlock name="product.info.downloadable.options"> |
| QuoteGraphQl | etc/di.xml:18 |
<item name="downloadable" xsi:type="string">DownloadableCartItem</item> |
| WishlistGraphQl | etc/graphql/di.xml:22 |
<item name="downloadable" xsi:type="object">...DownloadableLinkDataProvider</item> |
| QuoteDownloadableLinks | etc/graphql/di.xml:12 |
<item name="downloadable" xsi:type="object">...DownloadableLinkDataProvider</item> |
Composer require Dependencies on magento/module-downloadable¶
| Module | Type |
|---|---|
| Msrp | hard require |
| RemoteStorage | hard require |
| Reports | hard require |
| QuoteGraphQl | hard require |
| GiftMessageGraphQl | hard require (no actual code reference found — phantom dependency) |
| Wishlist | suggest (already optional) |
Modules Selected for Decoupling¶
1. Magento_Sales — EASY¶
Current state:
- composer.json: no dependency on magento/module-downloadable
- module.xml: no sequence dependency
Coupling points (1 file):
| File | Type | Details |
|---|---|---|
Block/Adminhtml/Order/Create/Search/Grid/Renderer/Price.php:21 |
Hardcoded string | if ($row->getTypeId() == 'downloadable') — adds link price to product price in admin order create grid |
Decoupling approach: Replace type-specific check with a generic approach — either make downloadable price handling pluggable, or use product type's price model directly.
2. Magento_Reports — EASY¶
Current state:
- composer.json: hard require on magento/module-downloadable
- module.xml: no sequence dependency
Coupling points (1 file):
| File | Type | Details |
|---|---|---|
Block/Adminhtml/Product/Downloads/Grid.php:73 |
Hardcoded string | ->addAttributeToFilter('type_id', ['downloadable']) — filters grid to only show downloadable products |
Decoupling approach: The downloads grid is specifically for downloadable products. The filter uses a string, not a class constant. Move magento/module-downloadable from require to suggest. The grid will simply return no results if downloadable products don't exist.
3. Magento_Wishlist — MODERATE (already partially decoupled)¶
Current state:
- composer.json: magento/module-downloadable already in suggest
- module.xml: no sequence dependency
Coupling points:
| File / Location | Type | Details |
|---|---|---|
Model/Wishlist/BuyRequest/DownloadableLinkDataProvider.php:17 |
Hardcoded string | private const PROVIDER_OPTION_TYPE = 'downloadable' — string comparison only, no class import |
Pricing/ConfiguredPrice/Downloadable.php |
Class name | Named after downloadable, likely self-contained (similar pattern to ConfigurableProduct) |
etc/di.xml:57 |
XML virtualType | <virtualType name="Magento\Downloadable\Pricing\Price\Pool"> — injects wishlist pricing into downloadable's price pool |
view/frontend/layout/wishlist_index_configure_type_downloadable.xml |
Layout XML | Renders Downloadable blocks (Samples, Type, Links) |
Decoupling approach: Same pattern as Configurable — PHP is already clean, coupling is XML-only. Layout is type-handle-based (loaded only for downloadable products). The di.xml virtualType could be moved to the Downloadable module's own DI.
4. Magento_Msrp — EASY¶
Current state:
- composer.json: hard require on magento/module-downloadable
- module.xml: no sequence dependency
Coupling points (1 file):
| File | Type | Details |
|---|---|---|
view/frontend/layout/catalog_product_view_type_downloadable.xml:10 |
Layout XML | <referenceBlock name="product.info.downloadable.options"> — adds MSRP notice to downloadable options |
Decoupling approach: This is a type-specific layout handle (catalog_product_view_type_downloadable). It only loads when viewing a downloadable product page. Move magento/module-downloadable to suggest. The layout handle simply won't be triggered when Downloadable is absent.
5. Magento_RemoteStorage — MODERATE¶
Current state:
- composer.json: hard require on both magento/module-downloadable and magento/module-downloadable-import-export
Coupling points (1 file):
| File | Type | Details |
|---|---|---|
etc/di.xml:152 |
XML type override | <type name="Magento\DownloadableImportExport\Helper\Uploader"> — configures filesystem driver for downloadable import uploads |
Decoupling approach: The DI <type> configuration is only applied when the target class exists. Move dependencies to suggest. Magento's DI will safely ignore the type configuration when DownloadableImportExport is not installed.
6. Magento_GiftMessageGraphQl — EASY (phantom dependency)¶
Current state:
- composer.json: hard require on magento/module-downloadable
- No actual code, XML, or string references to Downloadable found
Coupling points: None found. This appears to be a phantom/unnecessary dependency.
Decoupling approach: Simply remove magento/module-downloadable from require.
Summary¶
| Module | Difficulty | Key Change |
|---|---|---|
| GiftMessageGraphQl | Trivial | Remove phantom require dependency |
| Sales | Easy | Hardcoded 'downloadable' string in 1 admin block |
| Reports | Easy | Hardcoded 'downloadable' string filter, move to suggest |
| Msrp | Easy | Layout handle only, move to suggest |
| RemoteStorage | Easy | DI type config only, move to suggest |
| Wishlist | Already done | Already suggest, XML coupling is type-handle-based |