Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
# Release Notes for Variant Manager

## 4.0.0 - 2026-09-14

> {tip} This release removes the `VariantAttributeOption` element type. See [upgrading to 4.x](./docs/upgrade.md) before updating.

### Added

- Added drag ordering to the “Variant Attributes” listing, for arranging an attribute's options in the order a storefront should render them.
- Added a `resave/variant-attributes` command, for re-saving attributes and options and rewriting their search keywords.

### Changed

- Nested attribute options under their attribute in a single “Variant Attributes” listing, replacing the separate “Attribute Options” section.
- Renamed the read-only “CSV Name” and “CSV Value” labels to “System Name”, and the Title field on an attribute or option to “Display Name”.
- Labeled an attribute or option by its system name, followed by its display name in brackets where the two differ, and made both searchable.
- Moved attribute registration from the end of a CSV import to each variant save, so a failed import can now leave registry rows that the orphan prune clears.

### Fixed

- Fixed a bug where attribute values written outside the control panel stayed unregistered until the backfill ran.

### Removed

- Removed the `VariantAttributeOption` element type; an option is now a `VariantAttribute` with an `attributeId`, and its value is `name` rather than `value`.

## 3.0.0 - 2026-09-11

> {tip} Run `./craft variant-manager/attributes/backfill` to take advantage of new features.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ composer require fostercommerce/variant-manager
./craft plugin/install variant-manager
```

See [`docs/installation.md`](./docs/installation.md) for the full installation and configuration guide, and [`docs/upgrade.md`](./docs/upgrade.md) if you are coming from 2.x.
See [`docs/installation.md`](./docs/installation.md) for the full installation and configuration guide, and [`docs/upgrade.md`](./docs/upgrade.md) if you are coming from 2.x or 3.x.

## Importing

Expand Down
8 changes: 4 additions & 4 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ composer require fostercommerce/variant-manager
./craft plugin/install variant-manager
```

In the CP you should see a **Variant Manager** nav item with four subnav entries: **Dashboard**, **Variants**, **Variant Attributes** and **Attribute Options**.
In the CP you should see a **Variant Manager** nav item with three subnav entries: **Dashboard**, **Variants** and **Variant Attributes**.

## 2. Configure

Expand Down Expand Up @@ -58,9 +58,9 @@ Check the variants tab:

## 7. See the attributes the import registered

**Variant Manager -> Variant Attributes**. The import created `Color` and `Size`. **Variant Manager -> Attribute Options** lists `Red`, `Blue`, `Small` and `Medium`, each with the attribute it belongs to.
**Variant Manager -> Variant Attributes**. The import created `Color` and `Size`, each with its options nested under it: `Red` and `Blue` under `Color`, `Small` and `Medium` under `Size`.

Open `Red`. Its **CSV Value** is read-only; its title is not. The **Used by** count shows how many variants store `Red`. Rename the title to `Crimson` and save. No variant changed, and a template reading `option.title` now shows `Crimson`.
Open `Red`. Its **System Name** is read-only; its **Display Name** is not. The **Used by** count shows how many variants store `Red`. Rename the display name to `Crimson` and save. No variant changed, and a template reading `option.title` now shows `Crimson`.

See [variant attributes](./user-guide/variant-attributes.md).

Expand Down Expand Up @@ -88,4 +88,4 @@ For deeper reading:
- [Variant Attributes field](./reference/field-type.md), how the attribute data is stored and read.
- [Variant attributes](./user-guide/variant-attributes.md), attaching swatches and notes to attribute values.
- [Template tags](./dev-guide/template-tags.md) and [recipes](./recipes/add-to-cart.md), using the attributes on the storefront.
- [Upgrading to 3.x](./upgrade.md), if you are coming from 2.x.
- [Upgrading](./upgrade.md), if you are coming from 2.x or 3.x.
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Import and export Craft Commerce product variants from CSV files.

## Upgrading

Coming from 2.x? See [upgrading to 3.x](./upgrade.md).
Coming from 2.x or 3.x? See [upgrading](./upgrade.md).

## Where to go

Expand Down
2 changes: 1 addition & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ With DDEV:
ddev composer require fostercommerce/variant-manager -w && ddev craft plugin/install variant-manager
```

After install the CP navigation gets a **Variant Manager** item with **Dashboard** and **Variants**. **Variant Attributes** and **Attribute Options** appear for users with `variant-manager:manage-attributes`.
After install the CP navigation gets a **Variant Manager** item with **Dashboard** and **Variants**. **Variant Attributes** appears for users with `variant-manager:manage-attributes`.

## Configure

Expand Down
15 changes: 15 additions & 0 deletions docs/reference/console-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,21 @@ Reads every variant in batches. Anything already registered is skipped, so the c

The **Utilities -> Variant Attributes** utility runs the same work in the queue.

## `resave/variant-attributes`

Re-save every attribute and option.

```sh
./craft resave/variant-attributes --update-search-index
```

Craft's own resave command, with an action this plugin adds. `--update-search-index` rewrites the search keywords for each row, which is what picks up a system name stored before the row was last saved. `resave/all` includes it.

| Option | Default | Description |
|--------|---------|-------------|
| `--update-search-index` | `false` | Rewrite each row's search keywords. |
| `--queue` | `false` | Run in the queue instead of the console. |

## `variant-manager/attributes/orphans`

List attributes and options whose name or value is no longer stored on any variant.
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/permissions.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ Admins bypass every check.

See [user-guide/permissions](../user-guide/permissions.md) for who typically gets what.

Field layouts at **Settings -> Plugins -> Variant Manager** require an admin account. `variant-manager:manage-attributes` covers the attribute and option elements, including an attribute's display type, and Craft's own `utility:variant-manager-attributes` permission controls whether the utility is listed.
Field layouts at **Settings -> Plugins -> Variant Manager** require an admin account. `variant-manager:manage-attributes` covers attributes and their options, including an attribute's display type, and Craft's own `utility:variant-manager-attributes` permission controls whether the utility is listed.
62 changes: 55 additions & 7 deletions docs/upgrade.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,64 @@
# Upgrading to 3.x
# Upgrading

Upgrade one major at a time, in order. Coming from 2.x to 4.x means working through both sections below, starting with 3.x.

## Upgrading to 4.x

Twig using `getAttributeOptions` or `getAttributeRegistry` keeps working. PHP that names an option element directly needs changing.

### Attribute options are no longer their own element type

`VariantAttributeOption` is removed. An option is a `VariantAttribute` with an `attributeId`, and its value is `name` rather than `value`.

| 3.x | 4.x |
| --- | --- |
| `VariantAttributeOption::find()` | `VariantAttribute::find()->attributeId($attributeId)` |
| `$option->value` | `$option->name` |
| `variant_manager_attribute_options` table | `variant_manager_attributes`, with `attributeId` set |

`variantQueryForOption()`, `variantCountForOption()` and `isOptionInUse()` take a `VariantAttribute`.

Element IDs and UIDs are unchanged, so anything relating to an option still resolves.

A query against the dropped table or the old element type string returns nothing instead of raising an error, so check integrations that read the database directly.

### Options moved under their attribute

Options are children of their attribute at **Variant Manager -> Variant Attributes**. The separate **Attribute Options** section is gone. Switch the listing to structure view to drag an attribute's options into the order a storefront should render them.

### After updating

Run migrations:

```sh
./craft up
```

Then rewrite search keywords, so existing attributes and options are searchable by their system name:

```sh
./craft resave/variant-attributes --update-search-index
```

If anything writes attribute values to variants outside the control panel, run the backfill once. On 3.x those values stayed unregistered until it ran; from 4.0.0 on, every variant save registers them.

```sh
./craft variant-manager/attributes/backfill
```

## Upgrading to 3.x

Existing templates keep working. This page is the setup the update needs, plus one change to the Variant Attributes field.

## Editing in the Variant Attributes field moved
### Editing in the Variant Attributes field moved

The field showed an editable box per value with a **Save Attributes** button. Both are gone, along with the `variant-manager/product-variants/save-variant-attributes` action and its route.

Names and values are now chips. Click one to open the attribute or option in a slideout and edit it there, including any custom fields you have added.

Editing there is global: renaming an option changes what every product using that value shows, with no import and no change to any variant. To change the value the CSV writes, edit the CSV and reimport.

## After updating
### After updating

Run migrations and project config changes:

Expand All @@ -26,12 +74,12 @@ Then run the backfill once:

It reads every variant and registers the names and values already stored on them. Safe to re-run.

On a site that imports CSVs this is a catch-up for data that predates 3.x. On a site that does not import, it is the only thing that populates the registry, so it is the setup step.
This is a catch-up for data that predates 3.x. On 3.x, imports and control panel saves register what they store; values written by an integration stay unregistered until the backfill runs again.

## Grant the new permission
### Grant the new permission

Existing user groups do not have `variant-manager:manage-attributes`. Grant it at **Users -> {group} -> Permissions** to anyone who should see the **Variant Attributes** and **Attribute Options** sections or run the utility. See [permissions](./reference/permissions.md).
Existing user groups do not have `variant-manager:manage-attributes`. Grant it at **Users -> {group} -> Permissions** to anyone who should see the **Variant Attributes** section or run the utility. See [permissions](./reference/permissions.md).

## Set field layouts in development
### Set field layouts in development

An attribute's two field layouts are project config. Set them in your development environment and deploy them. The screen is read-only where `allowAdminChanges` is off, so they cannot be set in production directly.
15 changes: 10 additions & 5 deletions docs/user-guide/variant-attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,31 @@ Variants keep storing names and values as plain text, so imports and exports are

| Source | When |
|--------|------|
| A variant save | Any save that stores a name and value on a variant registers them, including an integration writing through Craft's API. |
| CSV import | Every import registers the names and values it contains. |
| **Utilities -> Variant Attributes** | Reads every variant in one pass. Run it once after installing. |
| `./craft variant-manager/attributes/backfill` | The same work from the command line. |

Each new attribute and option is recorded in the [activity log](./activity-log.md).
Each new attribute and option is recorded in the [activity log](./activity-log.md). A save with no signed-in user, such as a console command or a queue job, is logged against `Unknown`.

## Names

Each attribute and option has two names.

| Name | Editable | Shown to |
|------|----------|----------|
| **CSV Name** / **CSV Value** | No | The import. It is the exact text in your CSV. |
| Title | Yes | Shoppers, if your templates use it. |
| **System Name** | No | Whatever wrote the value. It is the exact text stored on the variant. |
| **Display Name** | Yes | Shoppers, if your templates use it. |

Rename an option's title to change what shoppers read. Every product using that value picks it up, with no import and no change to any variant.
Rename an option's display name to change what shoppers read. Every product using that value picks it up, with no import and no change to any variant. Templates read it as `option.title`.

The control panel labels a row by its system name, and adds the display name in brackets once the two differ: `PBS200 (Pebble Stone)`. Search matches either one.

## Where to find them

**Variant Manager -> Variant Attributes** lists every attribute. **Variant Manager -> Attribute Options** lists every value, with a sidebar entry per attribute for narrowing the list. An option shows how many variants use it.
**Variant Manager -> Variant Attributes** lists every attribute with its options nested under it, the way entries in a Structure section are. An option shows how many variants use it.

An option belongs to the attribute it sits under, so `Blue` under `Color` and `Blue` under `Paint chips` are separate rows with their own fields. Drag a row to reorder it among the rows sharing its attribute. Dragging an option onto a different attribute is refused, since that would change which value it stands for.

In the Variant Attributes field on a variant, each name and value is a chip. Click one to open its row in a slideout. A name or value with no row yet shows as plain text until an import or the backfill registers it.

Expand Down
Loading
Loading