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
9 changes: 4 additions & 5 deletions .github/workflows/laravel.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
name: Checks

# lacommerce has no test suite yet, so there is nothing for PHPUnit to run. This gates what can
# be checked without one: a valid composer.json, and every PHP file parsing. When tests land,
# add a Testbench job here and it becomes a required check through the org's ruleset script.
# Fast checks that need no dependencies: a valid composer.json, and every PHP file parsing.
# The Testbench suite runs in tests.yml.
on:
pull_request:
branches: [master]
Expand Down Expand Up @@ -30,7 +29,7 @@ jobs:
tools: composer

- name: Validate composer.json
run: composer validate --no-check-publish --no-check-lock
run: composer validate --strict --no-check-publish --no-check-lock

- name: Check PHP syntax
run: find src config database -name '*.php' -print0 | xargs -0 -n1 php -l
run: find src config tests -name '*.php' -print0 | xargs -0 -n1 php -l
42 changes: 42 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Tests

on:
pull_request:
branches: [master]
# No path filter: this workflow is meant to gate merges as a required status check, and a
# required check that never reports (a docs-only pull request) blocks the merge for good.
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
phpunit:
name: PHP ${{ matrix.php }} · ${{ matrix.stability }}
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
php: ['8.4', '8.5']
stability: [prefer-lowest, prefer-stable]
steps:
- uses: actions/checkout@v7

- uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
with:
php-version: ${{ matrix.php }}
extensions: pdo_sqlite, sqlite3, mbstring
coverage: none
tools: composer

# No lock file is tracked, so this resolves fresh against composer.json every run.
- name: Install dependencies
run: composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-progress

- name: Run tests
run: vendor/bin/phpunit --colors=never
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
.DS_Store
/vendor/
composer.lock
/build/
/.phpunit.cache/
.phpunit.result.cache
41 changes: 38 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,42 @@
# Changelog

All notable changes to `lacommerce` will be documented in this file
All notable changes to `simtabi/lacommerce` are documented in this file.

## 0.1.0 - 2022-02-03
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

- Initial release
## [Unreleased]

Preparing the first tagged release. An entry dated 2022-02-03 used to sit here as `0.1.0`, but no tag was
ever cut for it and the package was never published.

### Added

- A Testbench suite covering the `HasSku`, `HasOrderNumber` and `HasTicketNumber` traits and the service
provider, run in CI on PHP 8.4 and 8.5 against lowest and stable dependencies.
- Vendor-scoped config key `simtabi.lacommerce`, published to `config/simtabi/lacommerce.php` with the tag
`simtabi::lacommerce-config`.
- `composer.json` now requires the `illuminate/*` components the source uses.

### Changed

- Requires PHP `^8.4.1 || ^8.5` and Laravel 12 or 13 (was PHP `^8.0`, no Laravel constraint).
- Package metadata, badges and documentation links point at the `simtabi` org.

### Deprecated

- The bare config key `lacommerce` and publish tag `lacommerce:config`. Both still work: a published
`config/lacommerce.php` is still read (the scoped file wins when both exist), `config('lacommerce.*')`
still returns the merged configuration, and the bare tag still publishes `config/lacommerce.php`.
Earliest removal: 0.2.0.

### Fixed

- The traits failed on every model under current Laravel: they called `static::observe()` while the model
was booting, which throws. They now register the observer's handlers directly.
- The provider loaded the package's `database/migrations` into every host application. That directory only
held a test fixture creating a `dummy_models` table; the fixture now lives under `tests/` and nothing is
loaded.
- The config was merged twice; it is merged once.
- View, translation and asset loaders and publish tags pointed at directories the package does not ship;
they are now registered only when the directory exists.
60 changes: 52 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,77 @@
# simtabi/lacommerce

[![Latest version on Packagist](https://img.shields.io/packagist/v/simtabi/lacommerce.svg)](https://packagist.org/packages/simtabi/lacommerce)
[![Tests](https://github.com/laranail/lacommerce/actions/workflows/laravel.yml/badge.svg)](https://github.com/laranail/lacommerce/actions/workflows/laravel.yml)
[![Tests](https://github.com/simtabi/lacommerce/actions/workflows/tests.yml/badge.svg)](https://github.com/simtabi/lacommerce/actions/workflows/tests.yml)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

Two badges, not four: the package is not on Packagist yet, so there is no registry version to show, and
there is no static-analysis workflow.

> Handy helper generators for Laravel e-commerce projects — auto-generate unique SKUs, order numbers, and ticket numbers on your Eloquent models via the `HasSku`, `HasOrderNumber`, and `HasTicketNumber` traits, each configurable globally or per model and fully replaceable.

Compatible with PHP `^8.0`.
Compatible with PHP `^8.4.1 || ^8.5` and Laravel 12 or 13.

## Install

```bash
composer require simtabi/lacommerce
php artisan vendor:publish --tag=lacommerce:config
```

## Documentation
## Quick start guide and usage

### Getting started

The service provider is auto-discovered and the defaults work without a config file. Give each model the
destination column its trait writes to (`sku`, `order_number` or `ticket_number`) in your own migration.
To change the defaults, publish the config to `config/simtabi/lacommerce.php`:

```bash
php artisan vendor:publish --tag=simtabi::lacommerce-config
```

### Usage

```php
use Illuminate\Database\Eloquent\Model;
use Simtabi\Lacommerce\Traits\HasSku;

class Product extends Model
{
use HasSku;
}

$product = Product::create(['name' => 'Laravel is Awesome']);

echo $product->sku; // "LAR-8056449213"
```

```php
use Illuminate\Database\Eloquent\Model;
use Simtabi\Lacommerce\Traits\HasOrderNumber;

class Order extends Model
{
use HasOrderNumber;
}

echo Order::create(['name' => 'Web order'])->order_number; // "ORD-3920571846"
```

The full walkthrough is in [docs/getting-started.md](docs/getting-started.md); everything else is in the
[Documentation](#documentation) index.

## <a name="documentation"></a>Documentation

Full documentation is at **[opensource.simtabi.com/documentation/laranail/lacommerce](https://opensource.simtabi.com/documentation/laranail/lacommerce/)** — installation, getting started, each generator trait, and configuration.
Full documentation is at **[opensource.simtabi.com/documentation/simtabi/lacommerce](https://opensource.simtabi.com/documentation/simtabi/lacommerce/)** — installation, getting started, each generator trait, and configuration.

## Credits

The SKU-generation approach builds on [Cyrill Kalita / binary-cats](https://github.com/binary-cats)' work,
plus [all contributors](https://github.com/laranail/lacommerce/graphs/contributors).
plus [all contributors](https://github.com/simtabi/lacommerce/graphs/contributors).

## Contributing & security

Issues and PRs are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). Report vulnerabilities per
[SECURITY.md](SECURITY.md) (opensource@simtabi.com); participation follows the [Code of Conduct](CODE_OF_CONDUCT.md).
[SECURITY.md](SECURITY.md) (security@simtabi.com); participation follows the [Code of Conduct](CODE_OF_CONDUCT.md).

## License

Expand Down
23 changes: 17 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
"laravel",
"sku"
],
"homepage": "https://opensource.simtabi.com/products/laranail/lacommerce",
"homepage": "https://opensource.simtabi.com/products/simtabi/lacommerce",
"support": {
"docs": "https://opensource.simtabi.com/documentation/laranail/lacommerce/"
"issues": "https://github.com/simtabi/lacommerce/issues",
"source": "https://github.com/simtabi/lacommerce",
"docs": "https://opensource.simtabi.com/documentation/simtabi/lacommerce/"
},
"license": "MIT",
"authors": [
Expand All @@ -21,11 +23,15 @@
}
],
"require": {
"php": "^8.0"
"php": "^8.4.1 || ^8.5",
"illuminate/contracts": "^12.0 || ^13.0",
"illuminate/database": "^12.0 || ^13.0",
"illuminate/http": "^12.0 || ^13.0",
"illuminate/support": "^12.0 || ^13.0"
},
"require-dev": {
"orchestra/testbench": "^6.24.1",
"phpunit/phpunit": "^9.5.19"
"orchestra/testbench": "^10.6 || ^11.0",
"phpunit/phpunit": "^11.5 || ^12.0"
},
"autoload": {
"psr-4": {
Expand All @@ -46,5 +52,10 @@
"Simtabi\\Lacommerce\\Providers\\LacommerceServiceProvider"
]
}
}
},
"scripts": {
"test": "phpunit"
},
"minimum-stability": "stable",
"prefer-stable": true
}
4 changes: 2 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ How a generated value is produced on save. See the [Documentation index](../READ

## The moving parts

- **Traits** (`Traits/HasSku`, `HasOrderNumber`, `HasTicketNumber`) — added to a model; each boots a model
observer for its destination column.
- **Traits** (`Traits/HasSku`, `HasOrderNumber`, `HasTicketNumber`) — added to a model; each registers its
observer's `creating` and `updating` handlers for its destination column.
- **Observer** (`Generators/Services/Observer`) — hooks the model's create/update events and asks the
generator for a value.
- **Generator** (`Generators/Services/Generator` + per-type `Concerns/*Generator`) — builds the value from
Expand Down
43 changes: 30 additions & 13 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Configuration

Every key in `config/lacommerce.php`, published with `vendor:publish --tag=lacommerce:config`. See the
[Documentation index](../README.md#documentation).
Every key in `config/simtabi/lacommerce.php`, published with `vendor:publish --tag=simtabi::lacommerce-config`
and read from the `simtabi.lacommerce` config key. See the [Documentation index](../README.md#documentation).

## Structure

Expand All @@ -19,21 +19,21 @@ return [
],

'sku' => [
'generator' => SkuGenerator::class, // must implement GeneratorInterface
'source' => 'name', // source column(s)
'destination' => 'sku', // destination column
'generator' => SkuGenerator::class, // must implement GeneratorInterface
'source_column' => 'name', // source column(s)
'destination_column' => 'sku', // destination column
],

'ticket_number' => [
'generator' => TicketNumberGenerator::class,
'source' => 'name',
'destination' => 'ticket_number',
'generator' => TicketNumberGenerator::class,
'source_column' => 'name',
'destination_column' => 'ticket_number',
],

'order_number' => [
'generator' => OrderNumberGenerator::class,
'source' => 'name',
'destination' => 'order_number',
'generator' => OrderNumberGenerator::class,
'source_column' => 'name',
'destination_column' => 'order_number',
],
],
];
Expand All @@ -48,11 +48,28 @@ return [
| `generator.default.generate_on_create` | Generate when the model is created. |
| `generator.default.refresh_on_update` | Regenerate when the model is updated. |
| `generator.<name>.generator` | The generator class (must implement its `GeneratorInterface`). |
| `generator.<name>.source` | Source column(s) the value is derived from. |
| `generator.<name>.destination` | Column the generated value is written to. |
| `generator.<name>.source_column` | Source column(s) the value is derived from. |
| `generator.<name>.destination_column` | Column the generated value is written to. |

Override any of these per model via the trait's config method — see [Generators](tools/generators.md).

The published file replaces the defaults block by block, not key by key: a top-level key you keep
(`generator`) must carry every nested key the package reads, so publish the whole file and edit it.

## The deprecated `lacommerce` key

Before 0.1.0 the config lived under the bare key `lacommerce`, published to `config/lacommerce.php` with
`--tag=lacommerce:config`. Both still work and are deprecated; the earliest release that could remove them
is 0.2.0.

- A published `config/lacommerce.php` is still read. When `config/simtabi/lacommerce.php` also exists, it
wins.
- `config('lacommerce.*')` still returns the merged configuration.
- `--tag=lacommerce:config` still publishes `config/lacommerce.php`.

To migrate, move the file to `config/simtabi/lacommerce.php` and replace any `config('lacommerce.…')` reads
with `config('simtabi.lacommerce.…')`.

---

[← Docs index](../README.md#documentation)
6 changes: 3 additions & 3 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Generate your first SKU in three steps. See the [Documentation index](../README.

```bash
composer require simtabi/lacommerce
php artisan vendor:publish --tag=lacommerce:config
php artisan vendor:publish --tag=simtabi::lacommerce-config
```

See [Installation](installation.md).
Expand All @@ -32,15 +32,15 @@ $product = new Product();
$product->name = 'Laravel is Awesome';
$product->save();

echo $product->sku; // "LAR-80564492"
echo $product->sku; // "LAR-8056449213"
```

Order numbers and ticket numbers work the same way via `HasOrderNumber` / `HasTicketNumber`.

## Next steps

- [Generators](tools/generators.md) — all three generators, per-model config, custom generators.
- [Configuration](configuration.md) — every `config/lacommerce.php` key.
- [Configuration](configuration.md) — every `config/simtabi/lacommerce.php` key.

---

Expand Down
15 changes: 8 additions & 7 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,25 @@ Install `simtabi/lacommerce` and publish its config. See the [Documentation inde

## Requirements

- PHP `^8.0`
- Laravel (the `LacommerceServiceProvider` is auto-discovered)
- PHP `^8.4.1 || ^8.5`
- Laravel 12 or 13 (the `LacommerceServiceProvider` is auto-discovered)

## Install

```bash
composer require simtabi/lacommerce
```

The service provider registers itself. Publish the config (and optionally assets/views):
The service provider registers itself. Publish the config if you want to change the defaults:

```bash
php artisan vendor:publish --tag=lacommerce:config
php artisan vendor:publish --tag=lacommerce:assets
php artisan vendor:publish --tag=lacommerce:views
php artisan vendor:publish --tag=simtabi::lacommerce-config
```

This publishes `config/lacommerce.php` — see [Configuration](configuration.md).
This publishes `config/simtabi/lacommerce.php` — see [Configuration](configuration.md). The package ships
no views, translations or public assets, so there is nothing else to publish.

The package runs no migrations of its own: add the destination column to your own table.

> Your model needs the destination column (e.g. `sku`) on its table. If you overwrite generated values
> manually, add that column to the model's `$fillable`.
Expand Down
Loading
Loading