# storetown-media/module-product-attachments

> Adds file attachments (PDF, Office, images, videos, YouTube) to products with frontend download and inline preview (PDF, images, txt/csv, Word, Excel, PowerPoint), mass assign, CSV import, auto-assign rules and category grouping for Adobe Commerce / Magento Open Source.

`composer require storetown-media/module-product-attachments`

Canonical URL: https://packagento.com/storetown-media/module-product-attachments

## At a glance

- **Vendor**: Storetown Media (https://packagento.com/storetown-media.md)
- **Latest version**: v2.1.0 — released 2026-08-23
- **Pricing**: $99.00/year, subscription
- **Package type**: Magento 2 module
- **Status**: active, accepting new buyers

## Installation

This is a paid package. The Packagento install flow is licence-gated, so a Composer install needs a licence + project + project credentials in place first.

1. **Sign in or create an account** at https://packagento.com/customer/account/.

2. **Purchase the package.** Open https://packagento.com/storetown-media/module-product-attachments, add it to your cart, and complete checkout. A licence is minted automatically once payment clears.

3. **Create or pick a project, then activate the licence on it.**
   - Projects represent the Magento installs you deploy to. Manage them at https://packagento.com/projects/.
   - Activate the new licence on the project you'll deploy this package to. Activation is what generates the Composer credentials scoped to that project.

4. **Add the project credentials to your Magento codebase.**

   Grab the project's public + private key from https://packagento.com/projects/ (open the project, then its Credentials tab), and add them to `auth.json`:

   ```json
   {
     "http-basic": {
       "packagento.com": {
         "username": "ppk_live_...",
         "password": "psk_live_..."
       }
     }
   }
   ```

   Add the Packagento Composer repository to `composer.json`:

   ```json
   {
     "repositories": [
       { "type": "composer", "url": "https://packagento.com" }
     ]
   }
   ```

5. **Install and apply.**

   ```bash
   composer require storetown-media/module-product-attachments:*
   bin/magento setup:upgrade
   bin/magento setup:di:compile
   bin/magento cache:flush
   ```

## What it does

Adds file attachments (PDF, Office, images, videos, YouTube) to products with frontend download and inline preview (PDF, images, txt/csv, Word, Excel, PowerPoint), mass assign, CSV import, auto-assign rules and category grouping for Adobe Commerce / Magento Open Source.

## README

Attach files (PDF, DOC, images, archives, video, YouTube) to products and display them as a download list with inline preview on the product detail page. Mass-assign from the catalog grid, bulk-import via CSV, or let a rule engine attach files automatically based on product conditions.

### Features

- **Product Attachments tab** on the product edit page with file upload, YouTube URL, title, category and sort order
- **Central admin grid** under `Catalog > Product Attachments > Manage Attachments` with column filters, full-text search, mass delete and mass category assign
- **Mass Assign** from the catalog product grid mass-action: upload one file once and attach it to many products at once
- **CSV Import** with line-by-line validation
- **Auto-Assign Rules** with condition engine (category, attribute set, any product attribute), AND / OR combinations, optional `Apply on Save`, optional nightly cron, automatic FPC flush
- **Frontend `Attachments` tab** with thumbnails, colour-coded file-type badges, file size, download counter
- **Inline preview modal** for PDFs (iframe), images, YouTube videos and direct video files — no page reload, no external viewer
- **Attachment categories** with sort order and optional grouping on the product page
- **Custom file-type badges** — upload icon, set label and badge colour per file extension
- **Customer-group access restrictions** with separate guest-download toggle
- **Store-view-aware configuration** for every setting
- **English + German translations** included; ready for additional languages via standard Magento i18n CSV files
- **Clean code**: PSR-4, strict types, declarative schema, service contracts, no core rewrites, Adobe EQP-compliant

### Requirements

- Magento Open Source 2.4.x or Adobe Commerce 2.4.x
- PHP 8.1, 8.2, 8.3 or 8.4

### Installation

#### Via Composer (recommended)

```bash
composer require storetown-media/module-product-attachments
bin/magento module:enable STM_ProductAttachments
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
```

#### Manual installation

1. Extract the archive so the module sources land under `app/code/STM/ProductAttachments/`.
2. Run:

```bash
bin/magento module:enable STM_ProductAttachments
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
```

If Magento is in `production` mode, also run `bin/magento setup:static-content:deploy` for every active locale.

### Usage

#### Adding attachments to a product

1. Open a product in **Catalog > Products**.
2. Scroll down to the **Product Attachments** tab.
3. Click **Add Attachment**, upload a file (or paste a YouTube URL), enter a title, optionally assign a category and set a sort order.
4. Save the product.

#### Mass assign from the product grid

1. Go to **Catalog > Products** and select multiple products.
2. From the **Actions** dropdown choose **Assign Attachment**.
3. Upload the file, enter a title and click **Assign**.

#### CSV import

1. Open **Catalog > Product Attachments > Import Attachments**.
2. Upload your attachment files to `pub/media/import/attachments/`.
3. Prepare a CSV with the columns `sku, title, file_path` (required) and `category, sort_order` (optional).
4. Pick the CSV and click **Import**.

#### Auto-assign rules

1. Open **Catalog > Product Attachments > Auto-Assign Rules**.
2. Click **Add Rule**, name the rule, upload the file and define one or more conditions on category, attribute set or any product attribute.
3. Set `Apply on Save` to attach immediately when the rule is saved, or trigger via the **Apply** action in the rule grid, or wait for the optional nightly cron.

#### Frontend display

Attachments appear as a tab on the product detail page. Image files show a thumbnail; other file types display a colour-coded badge (red for PDF, blue for Word, green for Excel, …). Each row offers **Preview** (inline modal) and **Download** actions.

### Configuration

All settings live under **Stores > Configuration > STM > Product Attachments** and are scope-aware down to the store view. Configuration groups: Manage & Import, General, File, Display, Attachment Categories, File Extension Icons, Auto-Assign Rules, Access Restrictions.

### File storage

Uploaded files are stored under `pub/media/stm/attachments/`. Custom file-extension icons under `pub/media/stm/extension_icons/`. CSV import expects the source files under `pub/media/import/attachments/`.

### Uninstall

```bash
bin/magento module:disable STM_ProductAttachments
bin/magento setup:upgrade
bin/magento cache:flush
```

To fully uninstall via Composer, run `bin/magento module:uninstall STM_ProductAttachments` followed by the standard upgrade / compile / flush sequence.

The module creates four own tables (`stm_product_attachments`, `stm_attachment_categories`, `stm_attachment_file_extensions`, `stm_attachment_rules`) and does not modify any Magento core tables. Uploaded files remain under `pub/media/stm/attachments/` after uninstall and can be removed manually.

### License

Commercial — Storetown Media Commercial License. See [LICENSE.txt](LICENSE.txt) for full terms.

### Support

Issues, questions and feature requests are handled by Storetown Media. Use the support link on the Adobe Commerce Marketplace listing or write to support@storetown-media.de. Expected response time is within two business days.

## Changelog


All notable changes to STM Product Attachments will be documented in this file.

### [2.1.0] - 2026-04-25

#### Added

- Inline preview now supports plain-text files (`.txt`), CSV (`.csv`), Word (`.doc`/`.docx`), Excel (`.xls`/`.xlsx`) and PowerPoint (`.pptx`) in addition to PDF, images and video. Office documents are rendered server-side to clean HTML by [PhpSpreadsheet](https://phpspreadsheet.readthedocs.io/), [PhpWord](https://phpoffice.github.io/PHPWord/) and [PhpPresentation](https://phpoffice.github.io/PHPPresentation/) — no third-party viewer (e.g. Microsoft Office Online Viewer) and no extra Content-Security-Policy host whitelist required. CSV files are parsed with auto-detected delimiter and rendered as a styled table; PPTX slides are rendered as 16:9 slide-cards with heading detection and bullet indent levels.
- Legacy binary `.ppt` files surface a friendly "save as .pptx and re-upload" message inside the preview iframe rather than failing silently.

#### Changed

- Preview controller now derives the response `Content-Type` from the actual file extension (whitelisted map) rather than the stored `file_type` column. This makes the preview robust against MIME drift if a file is replaced on disk and the stored MIME no longer matches.

#### Internal

- Preview overlay re-uses a single `iframe` slot for all HTML/PDF-served types (`pdf`, `text`, `csv`, `office`) via a small `typeToSlot` mapping, instead of one slot per type.
- Three new Composer dependencies: `phpoffice/phpspreadsheet`, `phpoffice/phpword`, `phpoffice/phppresentation` (each MIT-licensed, all maintained by the [PhpOffice](https://github.com/PHPOffice) organisation).
- Database schema: column `file_type` extended from `VARCHAR(50)` to `VARCHAR(100)` on `stm_product_attachments` and `stm_attachment_rules`. The 50-char limit silently truncated Office-XML MIME types (`application/vnd.openxmlformats-officedocument.*` is 74-78 chars), causing INSERT failures in MySQL strict mode and stored-MIME drift in non-strict mode. Affected columns are now wide enough to hold the full MIME for `.docx`, `.xlsx` and `.pptx`.

### [2.0.1] - 2026-04-25

#### Fixed

- Inline preview now works reliably after a file is replaced on the product edit page. The attachment's `file_type` is now derived server-side from the actual file on disk via `finfo` with an extension-based fallback, instead of trusting the client-sent MIME header. The previous behaviour could leave a stale MIME on the database row when the dynamic-rows file uploader carried over the previous file's `type`, causing the preview controller to return 404 for any attachment whose stored MIME did not match the file extension. Affected `Controller/Adminhtml/Manage/Save.php`, `Controller/Adminhtml/Attachment/MassAssignPost.php` and the CSV importer.

#### Internal

- New `FileProcessor::detectMimeType(string $relativePath): ?string` consolidates MIME detection in one place. The duplicate extension map in `Model/Import/AttachmentImporter::guessMimeType()` was removed in favour of the shared helper.

### [2.0.0] - 2026-04-24

First public release on the Adobe Commerce Marketplace. Consolidation of the previously internally distributed `Storetown_ProductAttachments` 1.x line, renamed to `STM_ProductAttachments`, audited for Adobe EQP compliance and re-licensed for Marketplace distribution.

#### Breaking Changes

- Module renamed from `Storetown_ProductAttachments` to `STM_ProductAttachments`. The PHP namespace changed from `Storetown\ProductAttachments` to `STM\ProductAttachments` and the install path from `app/code/Storetown/ProductAttachments/` to `app/code/STM/ProductAttachments/`. Composer package name changed to `storetown-media/module-product-attachments`. The previous internal 1.x line therefore cannot be upgraded in-place; **fresh install only**.
- Database tables renamed: `storetown_product_attachments` → `stm_product_attachments`, `storetown_attachment_categories` → `stm_at

_(Changelog truncated for .md surface. Full history on https://packagento.com/storetown-media/module-product-attachments.)_

## Recent Versions

| Version | Released |
|---|---|
| v2.1.0 | 2026-08-23 |

## Dependencies

### Require

| Package | Constraint |
|---|---|
| magento/framework | ^103.0 |
| magento/module-backend | ^102.0 |
| magento/module-catalog | ^104.0 |
| magento/module-config | ^101.2 |
| magento/module-customer | ^103.0 |
| magento/module-media-storage | ^100.4 |
| magento/module-store | ^101.1 |
| magento/module-ui | ^101.2 |
| php | ~8.1.0\|\|~8.2.0\|\|~8.3.0\|\|~8.4.0 |
| phpoffice/phppresentation | ^0.9 \|\| ^1.0 |
| phpoffice/phpspreadsheet | ^2.0 \|\| ^3.0 \|\| ^4.0 \|\| ^5.0 |
| phpoffice/phpword | ^1.2 |

### Require (dev)

| Package | Constraint |
|---|---|
| phpunit/phpunit | ^9.5 \|\| ^10.0 |

## Quality

Latest release (v2.1.0) fails the Packagento QA pipeline. Verdicts below are per-cell (Magento line × PHP version) for the matrixed tools, and run-once for the static / security tiers.


### Compatibility

Each Magento line is installed on its supported PHP versions, then the module is built (DI compile + static-content deploy). Cells show passed / failed / untested; staircase gaps render as `–`.

| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | Pass | Pass | – | – |
| 2.4.8 | – | Pass | Pass | – |
| 2.4.9 | – | – | Pass | not tested |


### Code Quality

Advisory checks against the module's source. Never affect the Compatibility verdict — a phpcs finding can't make a module incompatible.

#### Static Analysis

Coding standards (phpcs), mess detection (phpmd), copy-pasted code (cpd), PHP cross-version compatibility, composer.json validity. Each runs once for the whole module.

| Tool | Status | Findings | Summary |
|---|---|---|---|
| PHPCS | Pass | 0 |  |
| PHPMD | Warning | 208 | 208 rule violations (UnusedPrivateField:208) |
| Cpd | Warning | 3 | 3 duplicated chunks spanning 215 total lines (min-lines=5, min-tokens=70) |
| Composer validate | Pass | 0 |  |

#### PHPStan

Type-checks the module against a real Magento install. Re-runs per Magento + PHP version because resolvable symbols differ between releases.

| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | 24 | 24 | – | – |
| 2.4.8 | – | 24 | 24 | – |
| 2.4.9 | – | – | 24 | N/A |


### Tests

Unit and integration suites run per Magento + PHP cell. Test failures speak to the module's behaviour, not its compatibility with a line, so they're reported here separately.

#### Unit Tests

| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | N/A | N/A | – | – |
| 2.4.8 | – | N/A | N/A | – |
| 2.4.9 | – | – | N/A | N/A |

#### Integration Tests

| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | N/A | N/A | – | – |
| 2.4.8 | – | N/A | N/A | – |
| 2.4.9 | – | – | N/A | N/A |


### Security

Dependency-advisory audit (composer audit) plus a source malware scan. A malware detection fails the version outright.

| Tool | Status | Findings | Summary |
|---|---|---|---|
| Composer audit | Pass | 0 |  |
| Malware scan | Pass | 0 |  |

## Licence and pricing

Subscription — $99.00/year, auto-renews until cancelled. Includes all minor + patch upgrades within the licensed major. One licence per project; cancelling stops auto-renewal but the existing licence keeps working until its end date.

Refundable within 14 days of first purchase via https://packagento.com/account/refunds/.

## Install via Claude Code or any MCP client

The Packagento MCP server can run the licence + project + Composer steps above in one tool call:

```
purchase_and_install_packages(
  composer_names=["storetown-media/module-product-attachments"],
  project_id="proj_xxx"
)
```

This handles cart, checkout, licence minting, project activation, and writes auth.json credentials. Connect a client with `claude mcp add packagento https://mcp.packagento.com`. Full setup at https://packagento.com/docs/mcp-setup.

## Vendor

Storetown Media is a Magento 2 vendor on Packagento. See https://packagento.com/storetown-media.md for their full catalogue.

