diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml
index c21b98049..d9b2164bd 100644
--- a/.github/workflows/build-release.yml
+++ b/.github/workflows/build-release.yml
@@ -40,6 +40,16 @@ jobs:
extensions: intl, mbstring, mysqli, gd, bcmath, zip
coverage: none
+ - name: Verify PHP patch level
+ run: |
+ MIN="8.2.35"
+ ACTUAL=$(php -r 'echo PHP_VERSION;')
+ if [ "$(printf '%s\n' "$MIN" "$ACTUAL" | sort -V | head -1)" != "$MIN" ]; then
+ echo "::error::PHP $ACTUAL is below patched minimum $MIN (CVE-2026-109618 / CVE-2026-109619)"
+ exit 1
+ fi
+ echo "PHP $ACTUAL meets minimum $MIN"
+
- name: Setup Node.js
uses: actions/setup-node@v4
with:
@@ -94,6 +104,16 @@ jobs:
env:
GITHUB_TAG: ${{ github.ref_name }}
+ - name: Normalize version for official release
+ if: startsWith(github.ref, 'refs/tags/')
+ run: |
+ VERSION="${{ steps.version.outputs.version }}"
+ # The tagged commit may still carry a -dev suffix in source files.
+ # Strip it so the archive contents report the clean release version.
+ sed -i "s/application_version = '${VERSION}-dev'/application_version = '${VERSION}'/" app/Config/App.php
+ sed -i "s/\"version\": \"${VERSION}-dev\"/,\"version\": \"${VERSION}\",/" package.json 2>/dev/null || true
+ echo "App.php now reports: $(grep application_version app/Config/App.php)"
+
- name: Validate release tag
if: startsWith(github.ref, 'refs/tags/')
run: |
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 4d823dc3f..4ecdc4753 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -43,6 +43,22 @@ jobs:
extensions: tokenizer
coverage: none
+ - name: Verify PHP patch level
+ run: |
+ ACTUAL=$(php -r 'echo PHP_VERSION;')
+ case "${ACTUAL%.*}" in
+ 8.2) MIN="8.2.35" ;;
+ 8.3) MIN="8.3.36" ;;
+ 8.4) MIN="8.4.27" ;;
+ 8.5) MIN="8.5.12" ;;
+ *) echo "::error::Unsupported PHP branch: $ACTUAL"; exit 1 ;;
+ esac
+ if [ "$(printf '%s\n' "$MIN" "$ACTUAL" | sort -V | head -1)" != "$MIN" ]; then
+ echo "::error::PHP $ACTUAL is below patched minimum $MIN (CVE-2026-109618 / CVE-2026-109619)"
+ exit 1
+ fi
+ echo "PHP $ACTUAL meets minimum $MIN"
+
- name: Get composer cache directory
run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV
diff --git a/.github/workflows/php-linter.yml b/.github/workflows/php-linter.yml
index fb94c5b86..e31d40304 100644
--- a/.github/workflows/php-linter.yml
+++ b/.github/workflows/php-linter.yml
@@ -1,6 +1,6 @@
name: PHP Linting
-on: push
+on: [push, pull_request]
jobs:
phplint:
diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml
index 125c30be6..b8fee39ea 100644
--- a/.github/workflows/phpunit.yml
+++ b/.github/workflows/phpunit.yml
@@ -56,6 +56,22 @@ jobs:
extensions: intl, mbstring, mysqli
coverage: none
+ - name: Verify PHP patch level
+ run: |
+ ACTUAL=$(php -r 'echo PHP_VERSION;')
+ case "${ACTUAL%.*}" in
+ 8.2) MIN="8.2.35" ;;
+ 8.3) MIN="8.3.36" ;;
+ 8.4) MIN="8.4.27" ;;
+ 8.5) MIN="8.5.12" ;;
+ *) echo "::error::Unsupported PHP branch: $ACTUAL"; exit 1 ;;
+ esac
+ if [ "$(printf '%s\n' "$MIN" "$ACTUAL" | sort -V | head -1)" != "$MIN" ]; then
+ echo "::error::PHP $ACTUAL is below patched minimum $MIN (CVE-2026-109618 / CVE-2026-109619)"
+ exit 1
+ fi
+ echo "PHP $ACTUAL meets minimum $MIN"
+
- name: Setup Node.js
uses: actions/setup-node@v4
with:
diff --git a/AGENTS.md b/AGENTS.md
index a35dc7595..d206b9ee9 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -28,6 +28,52 @@ This document provides guidance for AI agents working on the Open Source Point o
- Tests must pass before submitting changes
- **One test file per class under test.** A controller, model, library, or helper gets exactly one test file covering all of its behavior — `Item_kits.php` → `tests/Controllers/Item_kitsTest.php` (or `Item_kitsControllerTest.php`, matching this codebase's existing `*ControllerTest.php` suffix for controllers), `Sale_lib.php` → `tests/Libraries/Sale_libTest.php`, etc. Do not create feature- or endpoint-scoped test files alongside a class's main test file (e.g. no `Item_kitsBarcodeTest.php` next to `Item_kitsControllerTest.php`) — add the new test methods to the existing file for that class instead. If no test file exists yet for the class, create the one canonical file rather than a narrowly-scoped one.
- **Name test methods as `test{MethodUnderTest}_{Behavior}`.** `PascalCase` the method under test, then an underscore, then a short behavior phrase — `testPostSave_RejectsNegativeTaxPercent`, `testSaveLocale_AcceptsValidReferenceCodeMinMax`. Start the behavior with a verb: `Accepts`/`Requires` for valid or boundary cases, `Rejects` for invalid ones. The name should read as a self-documenting sentence and needs no docblock.
+- **Resetting the test database (full migration reset, not just `$refresh`).** When a test class needs the `ospos_tests` schema fully dropped and re-migrated from scratch (e.g. so `ospos_permissions`/`app_config` get freshly seeded), `use Tests\Support\DatabaseBootstrapTrait;` and call `$this->resetDatabaseOnce()` as the first line of `setUp()`, before `parent::setUp()`:
+ ```php
+ use Tests\Support\DatabaseBootstrapTrait;
+
+ class FooTest extends CIUnitTestCase
+ {
+ use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
+
+ protected $migrate = true;
+ protected $migrateOnce = true;
+ protected $seedOnce = true;
+ protected $refresh = false;
+ protected $namespace = null;
+
+ protected function setUp(): void
+ {
+ $this->resetDatabaseOnce();
+
+ parent::setUp();
+ // ...
+ }
+ }
+ ```
+ `DatabaseBootstrapTrait` (`tests/Support/DatabaseBootstrapTrait.php`) wraps `TestDatabaseBootstrapSeeder::reset()` with a per-class static guard so it only runs once per test class. Do **not** reinvent this with a local `private static bool $doneBootstrap` flag, `setUpBeforeClass()`, or `Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder')` followed by a manual `Config::connect($this->DBGroup)->close()`/`resetDataCache()` in the test file — those are the old patterns the trait replaces, and the manual version reintroduces the exact stale-connection bug `TestDatabaseBootstrapSeeder::reset()` already fixes internally. Only add this trait to test classes that actually touch the real test database (`DatabaseTestTrait` users) — pure unit tests that mock everything don't need it.
+ If a test class reads `config(OSPOS::class)->settings` for real (not mocking it out), also call `config(OSPOS::class)->update_settings();` right after `parent::setUp();` to force a fresh settings read post-reset. See `tests/Controllers/ReportsControllerTest.php` for that shape.
+- **Mocking OSPOS config settings.** When a test needs `config(OSPOS::class)->settings` to return fixed values instead of reading from the database, `use Tests\Support\OsposConfigFixtureTrait;` and call `$this->injectOsposSettings([...])` instead of manually constructing `new OSPOS()` + `Factories::injectMock('config', OSPOS::class, $ospos)`:
+ ```php
+ use Tests\Support\OsposConfigFixtureTrait;
+
+ class FooTest extends CIUnitTestCase
+ {
+ use OsposConfigFixtureTrait;
+
+ protected function setUp(): void
+ {
+ parent::setUp();
+
+ $this->injectOsposSettings([
+ 'number_locale' => 'en_US',
+ 'currency_decimals' => 2,
+ ]);
+ }
+ }
+ ```
+ `OSPOS::getDefaultSettings()` is `private` and only covers a handful of keys, so it is not a usable base to merge onto — each test must supply the exact settings it depends on. Use this trait regardless of whether the test also uses `DatabaseBootstrapTrait`.
## Build
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 890a137b2..fd5505d94 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,5 @@
-[unreleased]: https://github.com/opensourcepos/opensourcepos/compare/3.4.2...HEAD
+[unreleased]: https://github.com/opensourcepos/opensourcepos/compare/3.4.3...HEAD
+[3.4.3]: https://github.com/opensourcepos/opensourcepos/compare/3.4.2...3.4.3
[3.4.2]: https://github.com/opensourcepos/opensourcepos/compare/3.4.1...3.4.2
[3.4.1]: https://github.com/opensourcepos/opensourcepos/compare/3.4.0...3.4.1
[3.4.0]: https://github.com/opensourcepos/opensourcepos/compare/3.3.9...3.4.0
@@ -34,6 +35,42 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
+## [3.4.3] - 2026-10-21
+- chore: bump version to 3.4.3 by @github-actions[bot]
+- chore(deps): bump dompurify from 3.4.13 to 3.4.16 (#4723) by @dependabot[bot]
+- fix(release): delete the unstable release by name, leave drafts alone by @jekkos
+- chore(deps): bump moment from 2.30.1 to 2.31.0 (#4722) by @dependabot[bot]
+- chore(deps): bump brace-expansion (#4721) by @dependabot[bot]
+- feat(items): optimize search, attribute filtering, and sort for items view (#4652) by @objecttothis
+- fix(i18n): add missing toggle_cost_and_profit key to 32 locales (#4712) by @Rayan Abdul Cader
+- fix(expenses): refresh table when date range or filters change (#4633) by @richardmilles
+- fix(auth): return 401 JSON for AJAX requests on session timeout (#4728) by @jekkos
+- docs: add test-method naming convention to AGENTS.md (#4735) by @jekkos
+- fix(config): improve responsive layout, nested tabs behavior, and label theming (#4719) by @BudsieBuds
+- fix(taxes): reject invalid characters in tax code, category, and jurisdiction names (#4733) by @jekkos
+- fix(appconfig): refresh cached settings once and avoid stale same-request reads (#4732) by @jekkos
+- Return early from sortAndFilterCart() when no items are printable (#4713) by @Rayan Abdul Cader
+- fix: refresh cashups and items tables on filter and date range change (#4731) by @jekkos
+- chore: update Node.js version to 22 and npm-check-updates to 23.1.0 in workflows and documentation (#4741) by @BudsieBuds
+- fix(models): handle query() returning false in result-consuming methods (#4734) by @jekkos
+- feat(reports): add detailed item sales report (#4538) by @enricodelarosa
+- fix(taxes): reject negative tax rates and percentages (#4730) by @jekkos
+- fix(sales): inline invoice/quote email CSS for DOMPDF PDFs (#4747) (#4749) by @jekkos
+- docs: rewrite upgrade guide for the current CI4 install model (#4750) by @jekkos
+- refactor: move Windows build scripts into tools/build, drop CI4 migration scripts (#4729) by @jekkos
+- feat(config): scope config assets and add system info copy notifications (#4753) by @BudsieBuds
+- docs: move BUILD.md, INSTALL.md, UPGRADE.md into docs/ (#4755) by @jekkos
+- feat(tables): update loading text size and spinner to bootstrap-table (#4757) by @BudsieBuds
+- feat(db): add MySQL 8.4 support (#4048) by @Alexander Laurent
+- style(lang): add Georgian, normalize quote style across all locales, add parse tests (#4762) by @objecttothis
+- feat(install): add one-line Ubuntu installer (#4550) by @jekkos
+- fix(release): bump master version to 3.4.3-dev (#4752) by @jekkos
+- fix(config): add invoice_enable and work_order_enable to default settings fallback (#4761) by @Sai Asish Y
+- refactor(gulp): modernize build pipeline and streamline dependencies (#4759) by @BudsieBuds
+- refactor(tests): normalize test namespaces to PSR-4 and clean up composer dependencies (#4758) by @BudsieBuds
+- fix(ci): trigger PHP linting workflow on pull requests (#4764) by @BudsieBuds
+- fix(security): pin patched PHP 8.2.35+ for CVE-2026-109618/109619 (#4767) by @jekkos
+
## [3.4.2] - 2026-09-30
- Fix writable folder permission check (#4270) (#4273) by @jekkos
- Extended payment delete fix (#4274) by @jekkos
diff --git a/Dockerfile b/Dockerfile
index 4180c9259..98cad2e15 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM php:8.2-apache AS ospos
+FROM php:8.2.35-apache AS ospos
LABEL maintainer="jekkos"
RUN apt-get update && apt-get install -y --no-install-recommends \
diff --git a/README.md b/README.md
index e0a47cd30..ee27758b4 100644
--- a/README.md
+++ b/README.md
@@ -137,7 +137,7 @@ Any person or company found breaching the license agreement might find a bunch o
## 🙏 Credits
-|
DigitalOcean
| JetBrains
| GitHub
|
-| --- | --- | --- |
-| | | |
-| Many thanks to [DigitalOcean](https://www.digitalocean.com) for providing the project with hosting credits. | Many thanks to [JetBrains](https://www.jetbrains.com/) for providing a free license of [IntelliJ IDEA](https://www.jetbrains.com/idea/) to kindly support the development of OSPOS. | Many thanks to [GitHub](https://github.com) for providing free continuous integration via GitHub Actions for open-source projects. |
+| JetBrains
| GitHub
|
+| --- | --- |
+| 
| 
|
+| Many thanks to [JetBrains](https://www.jetbrains.com/) for providing a free license of [IntelliJ IDEA](https://www.jetbrains.com/idea/) to kindly support the development of OSPOS. | Many thanks to [GitHub](https://github.com) for providing free continuous integration via GitHub Actions for open-source projects. |
diff --git a/app/Config/App.php b/app/Config/App.php
index 3a5af0dd1..79c8d9f2e 100644
--- a/app/Config/App.php
+++ b/app/Config/App.php
@@ -12,7 +12,7 @@ class App extends BaseConfig
*
* @var string
*/
- public string $application_version = '3.4.3-dev';
+ public string $application_version = '3.4.4-dev';
/**
* This is the commit hash for the version you are currently using.
diff --git a/app/Database/Migrations/20170501000000_initial_schema.php b/app/Database/Migrations/20170501000000_initial_schema.php
index 057f398c4..8998071f2 100644
--- a/app/Database/Migrations/20170501000000_initial_schema.php
+++ b/app/Database/Migrations/20170501000000_initial_schema.php
@@ -25,7 +25,7 @@ class Migration_Initial_Schema extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/initial_schema.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/initial_schema.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20170501150000_upgrade_to_3_1_1.php b/app/Database/Migrations/20170501150000_upgrade_to_3_1_1.php
index ce56b0d7b..bcb7bea51 100644
--- a/app/Database/Migrations/20170501150000_upgrade_to_3_1_1.php
+++ b/app/Database/Migrations/20170501150000_upgrade_to_3_1_1.php
@@ -42,7 +42,7 @@ class Migration_Upgrade_To_3_1_1 extends Migration
}
}
- if (!executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.0.2_to_3.1.1.sql')) {
+ if (!executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.0.2_to_3.1.1.sql', false, $this->db)) {
throw new DatabaseException('Migration script 3.0.2_to_3.1.1.sql failed. Check logs for details.');
}
diff --git a/app/Database/Migrations/20180225100000_upgrade_to_3_2_0.php b/app/Database/Migrations/20180225100000_upgrade_to_3_2_0.php
index 83adfbcd0..e122a4346 100644
--- a/app/Database/Migrations/20180225100000_upgrade_to_3_2_0.php
+++ b/app/Database/Migrations/20180225100000_upgrade_to_3_2_0.php
@@ -12,7 +12,7 @@ class Migration_Upgrade_To_3_2_0 extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.1.1_to_3.2.0.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.1.1_to_3.2.0.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20180501100000_upgrade_to_3_2_1.php b/app/Database/Migrations/20180501100000_upgrade_to_3_2_1.php
index 6446e5524..5a2f3c7bb 100644
--- a/app/Database/Migrations/20180501100000_upgrade_to_3_2_1.php
+++ b/app/Database/Migrations/20180501100000_upgrade_to_3_2_1.php
@@ -12,7 +12,7 @@ class Migration_Upgrade_To_3_2_1 extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.2.0_to_3.2.1.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.2.0_to_3.2.1.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20181015100000_attributes.php b/app/Database/Migrations/20181015100000_attributes.php
index 076015b55..181e01add 100644
--- a/app/Database/Migrations/20181015100000_attributes.php
+++ b/app/Database/Migrations/20181015100000_attributes.php
@@ -12,7 +12,7 @@ class Migration_Attributes extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_attributes.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_attributes.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20190111270000_upgrade_to_3_3_0.php b/app/Database/Migrations/20190111270000_upgrade_to_3_3_0.php
index 9604aeb5e..452ac3109 100644
--- a/app/Database/Migrations/20190111270000_upgrade_to_3_3_0.php
+++ b/app/Database/Migrations/20190111270000_upgrade_to_3_3_0.php
@@ -12,7 +12,7 @@ class Migration_Upgrade_To_3_3_0 extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.2.1_to_3.3.0.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.2.1_to_3.3.0.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20190129212600_indiagst.php b/app/Database/Migrations/20190129212600_indiagst.php
index 2c5ff76e5..a19f70edd 100644
--- a/app/Database/Migrations/20190129212600_indiagst.php
+++ b/app/Database/Migrations/20190129212600_indiagst.php
@@ -17,7 +17,7 @@ class Migration_IndiaGST extends Migration
// If number of entries is greater than zero then the tax data needs to be migrated
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst.sql', false, $this->db);
$count_of_tax_codes = $this->get_count_of_tax_code_entries();
diff --git a/app/Database/Migrations/20190213210000_indiagst1.php b/app/Database/Migrations/20190213210000_indiagst1.php
index d45d7a3ca..006b8b2d4 100644
--- a/app/Database/Migrations/20190213210000_indiagst1.php
+++ b/app/Database/Migrations/20190213210000_indiagst1.php
@@ -12,7 +12,7 @@ class Migration_IndiaGST1 extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst1.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst1.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20190220210000_indiagst2.php b/app/Database/Migrations/20190220210000_indiagst2.php
index 12cf5364a..d6e499806 100644
--- a/app/Database/Migrations/20190220210000_indiagst2.php
+++ b/app/Database/Migrations/20190220210000_indiagst2.php
@@ -12,7 +12,7 @@ class Migration_IndiaGST2 extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst2.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst2.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20190301124900_decimal_attribute_type.php b/app/Database/Migrations/20190301124900_decimal_attribute_type.php
index a8235ac52..f20602994 100644
--- a/app/Database/Migrations/20190301124900_decimal_attribute_type.php
+++ b/app/Database/Migrations/20190301124900_decimal_attribute_type.php
@@ -12,7 +12,7 @@ class Migration_decimal_attribute_type extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_decimal_attribute_type.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_decimal_attribute_type.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20190317102600_add_iso_4217.php b/app/Database/Migrations/20190317102600_add_iso_4217.php
index 5778fe2b3..b683ed5f2 100644
--- a/app/Database/Migrations/20190317102600_add_iso_4217.php
+++ b/app/Database/Migrations/20190317102600_add_iso_4217.php
@@ -12,7 +12,7 @@ class Migration_add_iso_4217 extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_add_iso_4217.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_add_iso_4217.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20190427100000_paymenttracking.php b/app/Database/Migrations/20190427100000_paymenttracking.php
index 11c1cfe6b..72ce36a88 100644
--- a/app/Database/Migrations/20190427100000_paymenttracking.php
+++ b/app/Database/Migrations/20190427100000_paymenttracking.php
@@ -12,7 +12,7 @@ class Migration_PaymentTracking extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_paymenttracking.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_paymenttracking.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20190502100000_refundtracking.php b/app/Database/Migrations/20190502100000_refundtracking.php
index 18c157462..e6e376c33 100644
--- a/app/Database/Migrations/20190502100000_refundtracking.php
+++ b/app/Database/Migrations/20190502100000_refundtracking.php
@@ -12,7 +12,7 @@ class Migration_RefundTracking extends Migration
public function up(): void
{
helper(['migration', 'locale']);
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_refundtracking.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_refundtracking.sql', false, $this->db);
// Add missing cash_refund amounts to payments table
$decimals = totals_decimals();
diff --git a/app/Database/Migrations/20190612100000_dbfix.php b/app/Database/Migrations/20190612100000_dbfix.php
index 65377575f..2fdce4f33 100644
--- a/app/Database/Migrations/20190612100000_dbfix.php
+++ b/app/Database/Migrations/20190612100000_dbfix.php
@@ -12,7 +12,7 @@ class Migration_DBFix extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_dbfix.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_dbfix.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20190615100000_fix_attribute_datetime.php b/app/Database/Migrations/20190615100000_fix_attribute_datetime.php
index f07a3af89..f4762815e 100644
--- a/app/Database/Migrations/20190615100000_fix_attribute_datetime.php
+++ b/app/Database/Migrations/20190615100000_fix_attribute_datetime.php
@@ -12,7 +12,7 @@ class Migration_fix_attribute_datetime extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_fix_attribute_datetime.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_fix_attribute_datetime.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20191231100000_paymentdatefix.php b/app/Database/Migrations/20191231100000_paymentdatefix.php
index 8f2a30aeb..4efecd771 100644
--- a/app/Database/Migrations/20191231100000_paymentdatefix.php
+++ b/app/Database/Migrations/20191231100000_paymentdatefix.php
@@ -12,7 +12,7 @@ class Migration_PaymentDateFix extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.2_paymentdatefix.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.2_paymentdatefix.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20200125100000_saleschangeprice.php b/app/Database/Migrations/20200125100000_saleschangeprice.php
index 81b6051b8..a01d86d04 100644
--- a/app/Database/Migrations/20200125100000_saleschangeprice.php
+++ b/app/Database/Migrations/20200125100000_saleschangeprice.php
@@ -12,7 +12,7 @@ class Migration_SalesChangePrice extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.2_saleschangeprice.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.2_saleschangeprice.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20200819000000_modify_attr_links_constraint.php b/app/Database/Migrations/20200819000000_modify_attr_links_constraint.php
index b23172236..871011e93 100644
--- a/app/Database/Migrations/20200819000000_modify_attr_links_constraint.php
+++ b/app/Database/Migrations/20200819000000_modify_attr_links_constraint.php
@@ -12,7 +12,7 @@ class Migration_modify_attr_links_constraint extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.2_modify_attr_links_constraint.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.2_modify_attr_links_constraint.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20201110000000_add_item_kit_number.php b/app/Database/Migrations/20201110000000_add_item_kit_number.php
index 2f307a66f..f4d6a9ccc 100644
--- a/app/Database/Migrations/20201110000000_add_item_kit_number.php
+++ b/app/Database/Migrations/20201110000000_add_item_kit_number.php
@@ -12,7 +12,7 @@ class Migration_add_item_kit_number extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.3_add_kits_item_number.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.3_add_kits_item_number.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20210103000000_modify_session_datatype.php b/app/Database/Migrations/20210103000000_modify_session_datatype.php
index 5c24aab75..7334580d4 100644
--- a/app/Database/Migrations/20210103000000_modify_session_datatype.php
+++ b/app/Database/Migrations/20210103000000_modify_session_datatype.php
@@ -12,7 +12,7 @@ class Migration_modify_session_datatype extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.4_modify_session_datatype.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.4_modify_session_datatype.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20210422000000_database_optimizations.php b/app/Database/Migrations/20210422000000_database_optimizations.php
index 74aeeedef..801a628ac 100644
--- a/app/Database/Migrations/20210422000000_database_optimizations.php
+++ b/app/Database/Migrations/20210422000000_database_optimizations.php
@@ -113,7 +113,7 @@ class Migration_database_optimizations extends Migration
}
$this->db->transComplete();
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_database_optimizations.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_database_optimizations.sql', false, $this->db);
log_message('info', 'Finished migrating database optimizations.');
}
diff --git a/app/Database/Migrations/20220127000000_convertToCI4.php b/app/Database/Migrations/20220127000000_convertToCI4.php
index f860c7aaa..bc8881600 100644
--- a/app/Database/Migrations/20220127000000_convertToCI4.php
+++ b/app/Database/Migrations/20220127000000_convertToCI4.php
@@ -27,7 +27,7 @@ class ConvertToCI4 extends Migration
{
helper('migration');
- if (!executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_CI4Conversion.sql')) {
+ if (!executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_CI4Conversion.sql', false, $this->db)) {
throw new DatabaseException('Migration script 3.4.0_CI4Conversion.sql failed. Check logs for details.');
}
diff --git a/app/Database/Migrations/20240826000000_fix_duplicate_attributes.php b/app/Database/Migrations/20240826000000_fix_duplicate_attributes.php
index 6822a1589..66fd030e4 100644
--- a/app/Database/Migrations/20240826000000_fix_duplicate_attributes.php
+++ b/app/Database/Migrations/20240826000000_fix_duplicate_attributes.php
@@ -28,7 +28,7 @@ class fix_duplicate_attributes extends Migration
dropForeignKeyConstraints($foreignKeys, 'attribute_links');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_attribute_links_unique_constraint.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_attribute_links_unique_constraint.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20250425000000_sessions_migration.php b/app/Database/Migrations/20250425000000_sessions_migration.php
index 7402dda81..dfdf514b4 100644
--- a/app/Database/Migrations/20250425000000_sessions_migration.php
+++ b/app/Database/Migrations/20250425000000_sessions_migration.php
@@ -12,7 +12,7 @@ class Migration_sessions_migration extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.1_migrate_sessions_table.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.1_migrate_sessions_table.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20250522000000_AttributeLinksUniqueConstraint.php b/app/Database/Migrations/20250522000000_AttributeLinksUniqueConstraint.php
index 884d95b68..556aceb13 100644
--- a/app/Database/Migrations/20250522000000_AttributeLinksUniqueConstraint.php
+++ b/app/Database/Migrations/20250522000000_AttributeLinksUniqueConstraint.php
@@ -21,7 +21,7 @@ class AttributeLinksUniqueConstraint extends Migration
dropForeignKeyConstraints($foreignKeys, 'attribute_links');
dropColumnIfExists('ospos_attribute_links', 'generated_unique_column');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.1_attribute_links_unique_constraint.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.1_attribute_links_unique_constraint.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20250716170000_MissingConfigKeys.php b/app/Database/Migrations/20250716170000_MissingConfigKeys.php
index 85617e11e..5c2df663f 100644
--- a/app/Database/Migrations/20250716170000_MissingConfigKeys.php
+++ b/app/Database/Migrations/20250716170000_MissingConfigKeys.php
@@ -12,7 +12,7 @@ class Migration_MissingConfigKeys extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.2_missing_config_keys.sql', true);
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.2_missing_config_keys.sql', true, $this->db);
}
/**
diff --git a/app/Database/Migrations/20250729170000_NullableTaxCategoryId.php b/app/Database/Migrations/20250729170000_NullableTaxCategoryId.php
index 27367797d..d2ae8376a 100644
--- a/app/Database/Migrations/20250729170000_NullableTaxCategoryId.php
+++ b/app/Database/Migrations/20250729170000_NullableTaxCategoryId.php
@@ -12,7 +12,7 @@ class Migration_NullableTaxCategoryId extends Migration
public function up(): void
{
helper('migration');
- executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.2_nullable_tax_category_id.sql');
+ executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.2_nullable_tax_category_id.sql', false, $this->db);
}
/**
diff --git a/app/Database/Migrations/20260405000000_Mysql84Utf8mb4Conversion.php b/app/Database/Migrations/20260405000000_Mysql84Utf8mb4Conversion.php
index cd1ba2383..f6a34d6c6 100644
--- a/app/Database/Migrations/20260405000000_Mysql84Utf8mb4Conversion.php
+++ b/app/Database/Migrations/20260405000000_Mysql84Utf8mb4Conversion.php
@@ -21,7 +21,7 @@ class Migration_Mysql84Utf8mb4Conversion extends Migration
}
$script = APPPATH . 'Database/Migrations/sqlscripts/3.4.3_mysql84_utf8mb4_conversion.sql';
- if (!executeScript($script)) {
+ if (!executeScript($script, false, $this->db)) {
throw new RuntimeException('Failed to execute utf8mb4 conversion migration: ' . $script);
}
diff --git a/app/Database/Seeds/TestDatabaseBootstrapSeeder.php b/app/Database/Seeds/TestDatabaseBootstrapSeeder.php
index 134d10406..0de39a1b0 100644
--- a/app/Database/Seeds/TestDatabaseBootstrapSeeder.php
+++ b/app/Database/Seeds/TestDatabaseBootstrapSeeder.php
@@ -36,7 +36,7 @@ class TestDatabaseBootstrapSeeder extends Seeder
$serverConn->close();
// The application's shared 'tests' connection caches listTables()
- // results in dataCache['table_names'']. Because we dropped and
+ // results in dataCache['table_names']. Because we dropped and
// recreated the schema on a SEPARATE server connection above, that
// cache is now stale. Reset it so subsequent listTables()/tableExists()
// calls re-query the server instead of trusting a dropped schema's table
diff --git a/app/Helpers/migration_helper.php b/app/Helpers/migration_helper.php
index c8dd3d71b..0d030b9bb 100644
--- a/app/Helpers/migration_helper.php
+++ b/app/Helpers/migration_helper.php
@@ -8,9 +8,10 @@ use Config\Database;
* Executes a SQL migration script.
* @param string $path Path to migration script.
* @param bool $withTransaction Whether to wrap execution in a transaction.
+ * @param BaseConnection|null $db Connection to use (defaults to the default connection).
* @return bool Whether the migration executed successfully.
*/
-function executeScript(string $path, bool $withTransaction = false): bool
+function executeScript(string $path, bool $withTransaction = false, ?BaseConnection $db = null): bool
{
$version = explode('_', basename($path, '.sql'), 2)[0];
log_message('info', "Migrating to $version (file: $path)");
@@ -18,7 +19,7 @@ function executeScript(string $path, bool $withTransaction = false): bool
$sqls = explode(';', file_get_contents($path));
array_pop($sqls);
- $db = Database::connect();
+ $db ??= Database::connect();
if ($withTransaction) {
$db->transStart();
@@ -84,8 +85,8 @@ function dropForeignKeyConstraints(array $foreignKeys, string $table): void
* TODO: This function should be moved to a more global location since it may be needed outside of migrations.
* @return string The prefix before overriding.
*/
-function overridePrefix(string $prefix = ''): string {
- $db = Database::connect();
+function overridePrefix(string $prefix = '', ?BaseConnection $db = null): string {
+ $db ??= Database::connect();
$originalPrefix = $db->getPrefix();
$db->setPrefix($prefix);
@@ -136,47 +137,50 @@ function createPrimaryKey(string $table, string $index): void {
function dropAllForeignKeyConstraints(?string $table = null, ?string $column = null, ?BaseConnection $db = null): array {
$db ??= Database::connect();
$prefixedTable = $table !== null ? $db->getPrefix() . $table : null;
- $prefix = overridePrefix();
-
- $builder = $db->table('information_schema.KEY_COLUMN_USAGE kcu');
- $builder->distinct();
- $builder->select('kcu.CONSTRAINT_NAME, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME, kcu.ORDINAL_POSITION, rc.DELETE_RULE, rc.UPDATE_RULE');
- $builder->join(
- 'information_schema.REFERENTIAL_CONSTRAINTS rc',
- 'kcu.CONSTRAINT_SCHEMA = rc.CONSTRAINT_SCHEMA AND kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME AND kcu.TABLE_NAME = rc.TABLE_NAME',
- 'left'
- );
-
- if ($table !== null && $column !== null) {
- $scopedBuilder = $db->table('information_schema.KEY_COLUMN_USAGE scoped');
- $scopedBuilder->distinct();
- $scopedBuilder->select('scoped.CONSTRAINT_NAME, scoped.TABLE_NAME');
- $scopedBuilder->where('scoped.TABLE_SCHEMA', $db->database);
- $scopedBuilder->groupStart();
- $scopedBuilder->where('scoped.REFERENCED_TABLE_NAME', $prefixedTable);
- $scopedBuilder->where('scoped.REFERENCED_COLUMN_NAME', $column);
- $scopedBuilder->groupEnd();
- $scopedBuilder->orGroupStart();
- $scopedBuilder->where('scoped.TABLE_NAME', $prefixedTable);
- $scopedBuilder->where('scoped.COLUMN_NAME', $column);
- $scopedBuilder->groupEnd();
+ $prefix = overridePrefix('', $db);
+ try {
+ $builder = $db->table('information_schema.KEY_COLUMN_USAGE kcu');
+ $builder->distinct();
+ $builder->select('kcu.CONSTRAINT_NAME, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME, kcu.ORDINAL_POSITION, rc.DELETE_RULE, rc.UPDATE_RULE');
$builder->join(
- '(' . $scopedBuilder->getCompiledSelect() . ') matched',
- 'matched.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND matched.TABLE_NAME = kcu.TABLE_NAME',
- 'inner',
- false
+ 'information_schema.REFERENTIAL_CONSTRAINTS rc',
+ 'kcu.CONSTRAINT_SCHEMA = rc.CONSTRAINT_SCHEMA AND kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME AND kcu.TABLE_NAME = rc.TABLE_NAME',
+ 'left'
);
+
+ if ($table !== null && $column !== null) {
+ $scopedBuilder = $db->table('information_schema.KEY_COLUMN_USAGE scoped');
+ $scopedBuilder->distinct();
+ $scopedBuilder->select('scoped.CONSTRAINT_NAME, scoped.TABLE_NAME');
+ $scopedBuilder->where('scoped.TABLE_SCHEMA', $db->database);
+ $scopedBuilder->groupStart();
+ $scopedBuilder->where('scoped.REFERENCED_TABLE_NAME', $prefixedTable);
+ $scopedBuilder->where('scoped.REFERENCED_COLUMN_NAME', $column);
+ $scopedBuilder->groupEnd();
+ $scopedBuilder->orGroupStart();
+ $scopedBuilder->where('scoped.TABLE_NAME', $prefixedTable);
+ $scopedBuilder->where('scoped.COLUMN_NAME', $column);
+ $scopedBuilder->groupEnd();
+
+ $builder->join(
+ '(' . $scopedBuilder->getCompiledSelect() . ') matched',
+ 'matched.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND matched.TABLE_NAME = kcu.TABLE_NAME',
+ 'inner',
+ false
+ );
+ }
+
+ $builder->where('kcu.TABLE_SCHEMA', $db->database);
+ $builder->where('rc.CONSTRAINT_NAME IS NOT NULL', null, false);
+ $builder->orderBy('kcu.CONSTRAINT_NAME');
+ $builder->orderBy('kcu.ORDINAL_POSITION');
+
+ $result = $builder->get();
+ } finally {
+ overridePrefix($prefix, $db);
}
- $builder->where('kcu.TABLE_SCHEMA', $db->database);
- $builder->where('rc.CONSTRAINT_NAME IS NOT NULL', null, false);
- $builder->orderBy('kcu.CONSTRAINT_NAME');
- $builder->orderBy('kcu.ORDINAL_POSITION');
-
- $result = $builder->get();
- overridePrefix($prefix);
-
if ($result === false) {
$detail = 'unknown error';
try {
@@ -346,18 +350,20 @@ function foreignKeyExists(string $constraintName, string $tableName): bool {
$prefix = overridePrefix();
- $db = Database::connect();
- $builder = $db->table('INFORMATION_SCHEMA.TABLE_CONSTRAINTS');
- $builder->select('CONSTRAINT_NAME');
- $builder->where('TABLE_SCHEMA', $db->database);
- $builder->where('TABLE_NAME', $prefix . $tableName);
- $builder->where('CONSTRAINT_TYPE', 'FOREIGN KEY');
- $builder->where('CONSTRAINT_NAME', $constraintName);
- $query = $builder->get();
+ try {
+ $db = Database::connect();
+ $builder = $db->table('INFORMATION_SCHEMA.TABLE_CONSTRAINTS');
+ $builder->select('CONSTRAINT_NAME');
+ $builder->where('TABLE_SCHEMA', $db->database);
+ $builder->where('TABLE_NAME', $prefix . $tableName);
+ $builder->where('CONSTRAINT_TYPE', 'FOREIGN KEY');
+ $builder->where('CONSTRAINT_NAME', $constraintName);
+ $query = $builder->get();
- overridePrefix($prefix);
-
- return $query->getNumRows() > 0;
+ return $query->getNumRows() > 0;
+ } finally {
+ overridePrefix($prefix);
+ }
}
/**
@@ -371,23 +377,26 @@ function dropColumnIfExists(string $table, string $column): void
{
$prefix = overridePrefix();
- $db = Database::connect();
- $builder = $db->table('information_schema.COLUMNS');
+ try {
+ $db = Database::connect();
+ $builder = $db->table('information_schema.COLUMNS');
- // Check if the column exists in the table
- $builder->select('COLUMN_NAME')
- ->where('TABLE_SCHEMA', $db->database)
- ->where('TABLE_NAME', $prefix . $table)
- ->where('COLUMN_NAME', $column);
+ // Check if the column exists in the table
+ $builder->select('COLUMN_NAME')
+ ->where('TABLE_SCHEMA', $db->database)
+ ->where('TABLE_NAME', $prefix . $table)
+ ->where('COLUMN_NAME', $column);
- $query = $builder->get();
+ $query = $builder->get();
- if ($query->getNumRows() > 0)
- {
- // Drop the column if it exists
- $db->query("ALTER TABLE `" . $prefix . "$table` DROP COLUMN `$column`");
+ if ($query->getNumRows() > 0)
+ {
+ // Drop the column if it exists
+ $db->query("ALTER TABLE `" . $prefix . "$table` DROP COLUMN `$column`");
+ }
+ } finally {
+ overridePrefix($prefix);
}
- overridePrefix($prefix);
}
/**
diff --git a/composer.json b/composer.json
index 7db196cbd..885d0d55a 100644
--- a/composer.json
+++ b/composer.json
@@ -25,27 +25,22 @@
"matrix": "https://matrix.to/#/#opensourcepos_Lobby:gitter.im"
},
"require": {
- "php": "^8.2",
+ "php": ">=8.2.35 <8.3 || >=8.3.36 <8.4 || >=8.4.27",
"ext-intl": "*",
"codeigniter4/framework": "4.7.4",
"dompdf/dompdf": "^3.1.6",
- "ezyang/htmlpurifier": "^4.17",
- "laminas/laminas-escaper": "2.18.0",
+ "ezyang/htmlpurifier": "^4.19",
"openspout/openspout": "^4.28",
- "paragonie/random_compat": "^2.0.21",
"picqer/php-barcode-generator": "^2.4.0",
"setasign/tfpdf": "^1.34",
"tamtamchik/namecase": "^3.0.0"
},
"require-dev": {
- "codeigniter/coding-standard": "^1.8",
- "fakerphp/faker": "^1.23.0",
- "friendsofphp/php-cs-fixer": "^3.47.1",
+ "codeigniter/coding-standard": "^1.9",
+ "friendsofphp/php-cs-fixer": "^3.95",
"kint-php/kint": "^5.0.4",
- "mikey179/vfsstream": "^1.6",
- "nexusphp/cs-config": "^3.6",
- "phpunit/phpunit": "^10.5.16 || ^11.2",
- "predis/predis": "^1.1 || ^2.0"
+ "nexusphp/cs-config": "^3.29",
+ "phpunit/phpunit": "^10.5.16 || ^11.2"
},
"replace": {
"psr/log": "*"
@@ -53,6 +48,7 @@
"autoload": {
"psr-4": {
"App\\": "app/",
+ "Config\\": "app/Config/",
"CodeIgniter\\": "vendor/codeigniter4/framework/system/"
},
"exclude-from-classmap": [
diff --git a/composer.lock b/composer.lock
index 47014be3d..9d828d02d 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "4f1ca5347f1630e56c90449f4e3d1ce2",
+ "content-hash": "6c022bc8409249b371ab549c76a41f74",
"packages": [
{
"name": "codeigniter4/framework",
@@ -240,16 +240,16 @@
},
{
"name": "ezyang/htmlpurifier",
- "version": "v4.19.0",
+ "version": "v4.19.1",
"source": {
"type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git",
- "reference": "b287d2a16aceffbf6e0295559b39662612b77fcf"
+ "reference": "5e0539132d934f936fbae2c88b55d58f9438623f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/b287d2a16aceffbf6e0295559b39662612b77fcf",
- "reference": "b287d2a16aceffbf6e0295559b39662612b77fcf",
+ "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/5e0539132d934f936fbae2c88b55d58f9438623f",
+ "reference": "5e0539132d934f936fbae2c88b55d58f9438623f",
"shasum": ""
},
"require": {
@@ -295,9 +295,9 @@
],
"support": {
"issues": "https://github.com/ezyang/htmlpurifier/issues",
- "source": "https://github.com/ezyang/htmlpurifier/tree/v4.19.0"
+ "source": "https://github.com/ezyang/htmlpurifier/tree/v4.19.1"
},
- "time": "2025-10-17T16:34:55+00:00"
+ "time": "2026-09-15T15:42:51+00:00"
},
{
"name": "laminas/laminas-escaper",
@@ -362,24 +362,24 @@
},
{
"name": "masterminds/html5",
- "version": "2.10.1",
+ "version": "2.11.0",
"source": {
"type": "git",
"url": "https://github.com/Masterminds/html5-php.git",
- "reference": "fd5018f6815fff903946d0564977b44ce8010e29"
+ "reference": "a1e7a2f88ee13635d86fc61cfbdf2306a76ddfc7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fd5018f6815fff903946d0564977b44ce8010e29",
- "reference": "fd5018f6815fff903946d0564977b44ce8010e29",
+ "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/a1e7a2f88ee13635d86fc61cfbdf2306a76ddfc7",
+ "reference": "a1e7a2f88ee13635d86fc61cfbdf2306a76ddfc7",
"shasum": ""
},
"require": {
"ext-dom": "*",
- "php": ">=5.3.0"
+ "php": ">=7.4"
},
"require-dev": {
- "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9 || ^10"
+ "phpunit/phpunit": "^6 || ^7 || ^8 || ^9 || ^10"
},
"type": "library",
"extra": {
@@ -423,9 +423,9 @@
],
"support": {
"issues": "https://github.com/Masterminds/html5-php/issues",
- "source": "https://github.com/Masterminds/html5-php/tree/2.10.1"
+ "source": "https://github.com/Masterminds/html5-php/tree/2.11.0"
},
- "time": "2026-06-23T18:43:15+00:00"
+ "time": "2026-08-18T06:18:41+00:00"
},
{
"name": "openspout/openspout",
@@ -520,60 +520,6 @@
],
"time": "2025-09-03T16:03:54+00:00"
},
- {
- "name": "paragonie/random_compat",
- "version": "v2.0.21",
- "source": {
- "type": "git",
- "url": "https://github.com/paragonie/random_compat.git",
- "reference": "96c132c7f2f7bc3230723b66e89f8f150b29d5ae"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/paragonie/random_compat/zipball/96c132c7f2f7bc3230723b66e89f8f150b29d5ae",
- "reference": "96c132c7f2f7bc3230723b66e89f8f150b29d5ae",
- "shasum": ""
- },
- "require": {
- "php": ">=5.2.0"
- },
- "require-dev": {
- "phpunit/phpunit": "*"
- },
- "suggest": {
- "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
- },
- "type": "library",
- "autoload": {
- "files": [
- "lib/random.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Paragon Initiative Enterprises",
- "email": "security@paragonie.com",
- "homepage": "https://paragonie.com"
- }
- ],
- "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
- "keywords": [
- "csprng",
- "polyfill",
- "pseudorandom",
- "random"
- ],
- "support": {
- "email": "info@paragonie.com",
- "issues": "https://github.com/paragonie/random_compat/issues",
- "source": "https://github.com/paragonie/random_compat"
- },
- "time": "2022-02-16T17:07:03+00:00"
- },
{
"name": "picqer/php-barcode-generator",
"version": "v2.4.2",
@@ -663,35 +609,33 @@
},
{
"name": "sabberworm/php-css-parser",
- "version": "v9.4.0",
+ "version": "v9.5.0",
"source": {
"type": "git",
"url": "https://github.com/MyIntervals/PHP-CSS-Parser.git",
- "reference": "fd3bf9fb173e0df649bc4e3e0d088a1b2417c08f"
+ "reference": "f284e63b6e891e0c28631e54ba06c3ed102a9ef3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/fd3bf9fb173e0df649bc4e3e0d088a1b2417c08f",
- "reference": "fd3bf9fb173e0df649bc4e3e0d088a1b2417c08f",
+ "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/f284e63b6e891e0c28631e54ba06c3ed102a9ef3",
+ "reference": "f284e63b6e891e0c28631e54ba06c3ed102a9ef3",
"shasum": ""
},
"require": {
"ext-iconv": "*",
- "php": "^7.2.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
- "thecodingmachine/safe": "^1.3 || ^2.5 || ^3.4"
+ "php": "^7.2.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0 || ~8.6.0"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "1.4.0",
"phpstan/extension-installer": "1.4.3",
- "phpstan/phpstan": "1.12.33 || 2.2.2",
- "phpstan/phpstan-phpunit": "1.4.2 || 2.0.16",
- "phpstan/phpstan-strict-rules": "1.6.2 || 2.0.11",
- "phpunit/phpunit": "8.5.52",
+ "phpstan/phpstan": "1.12.33 || 2.2.9",
+ "phpstan/phpstan-phpunit": "1.4.2 || 2.0.18",
+ "phpstan/phpstan-strict-rules": "1.6.2 || 2.0.12",
+ "phpunit/phpunit": "8.5.54",
"rawr/phpunit-data-provider": "3.3.1",
- "rector/rector": "1.2.10 || 2.4.6",
- "rector/type-perfect": "1.0.0 || 2.1.3",
- "squizlabs/php_codesniffer": "4.0.1",
- "thecodingmachine/phpstan-safe-rule": "1.2.0 || 1.4.3"
+ "rector/rector": "1.2.10 || 2.6.2",
+ "rector/type-perfect": "1.0.0 || 2.1.4",
+ "squizlabs/php_codesniffer": "4.0.4"
},
"suggest": {
"ext-mbstring": "for parsing UTF-8 CSS"
@@ -699,7 +643,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "9.5.x-dev"
+ "dev-main": "9.6.x-dev"
}
},
"autoload": {
@@ -737,9 +681,9 @@
],
"support": {
"issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues",
- "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.4.0"
+ "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.5.0"
},
- "time": "2026-06-18T15:10:53+00:00"
+ "time": "2026-09-20T15:02:00+00:00"
},
{
"name": "setasign/tfpdf",
@@ -797,16 +741,16 @@
},
{
"name": "tamtamchik/namecase",
- "version": "3.0.0",
+ "version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/tamtamchik/namecase.git",
- "reference": "f963f321a3afbde83f1bb1bda1d53b848c7015dd"
+ "reference": "5963ef26311f87dac0e9b3c6a0e7f3976068176b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/tamtamchik/namecase/zipball/f963f321a3afbde83f1bb1bda1d53b848c7015dd",
- "reference": "f963f321a3afbde83f1bb1bda1d53b848c7015dd",
+ "url": "https://api.github.com/repos/tamtamchik/namecase/zipball/5963ef26311f87dac0e9b3c6a0e7f3976068176b",
+ "reference": "5963ef26311f87dac0e9b3c6a0e7f3976068176b",
"shasum": ""
},
"require": {
@@ -822,7 +766,7 @@
"branch-alias": {
"1.x": "1.x-dev",
"2.x": "2.x-dev",
- "dev-master": "3.0-dev"
+ "dev-master": "3.1-dev"
}
},
"autoload": {
@@ -855,152 +799,9 @@
],
"support": {
"issues": "https://github.com/tamtamchik/namecase/issues",
- "source": "https://github.com/tamtamchik/namecase/tree/3.0.0"
+ "source": "https://github.com/tamtamchik/namecase/tree/3.1.0"
},
- "time": "2023-01-26T15:07:18+00:00"
- },
- {
- "name": "thecodingmachine/safe",
- "version": "v3.4.0",
- "source": {
- "type": "git",
- "url": "https://github.com/thecodingmachine/safe.git",
- "reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/705683a25bacf0d4860c7dea4d7947bfd09eea19",
- "reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19",
- "shasum": ""
- },
- "require": {
- "php": "^8.1"
- },
- "require-dev": {
- "php-parallel-lint/php-parallel-lint": "^1.4",
- "phpstan/phpstan": "^2",
- "phpunit/phpunit": "^10",
- "squizlabs/php_codesniffer": "^3.2"
- },
- "type": "library",
- "autoload": {
- "files": [
- "lib/special_cases.php",
- "generated/apache.php",
- "generated/apcu.php",
- "generated/array.php",
- "generated/bzip2.php",
- "generated/calendar.php",
- "generated/classobj.php",
- "generated/com.php",
- "generated/cubrid.php",
- "generated/curl.php",
- "generated/datetime.php",
- "generated/dir.php",
- "generated/eio.php",
- "generated/errorfunc.php",
- "generated/exec.php",
- "generated/fileinfo.php",
- "generated/filesystem.php",
- "generated/filter.php",
- "generated/fpm.php",
- "generated/ftp.php",
- "generated/funchand.php",
- "generated/gettext.php",
- "generated/gmp.php",
- "generated/gnupg.php",
- "generated/hash.php",
- "generated/ibase.php",
- "generated/ibmDb2.php",
- "generated/iconv.php",
- "generated/image.php",
- "generated/imap.php",
- "generated/info.php",
- "generated/inotify.php",
- "generated/json.php",
- "generated/ldap.php",
- "generated/libxml.php",
- "generated/lzf.php",
- "generated/mailparse.php",
- "generated/mbstring.php",
- "generated/misc.php",
- "generated/mysql.php",
- "generated/mysqli.php",
- "generated/network.php",
- "generated/oci8.php",
- "generated/opcache.php",
- "generated/openssl.php",
- "generated/outcontrol.php",
- "generated/pcntl.php",
- "generated/pcre.php",
- "generated/pgsql.php",
- "generated/posix.php",
- "generated/ps.php",
- "generated/pspell.php",
- "generated/readline.php",
- "generated/rnp.php",
- "generated/rpminfo.php",
- "generated/rrd.php",
- "generated/sem.php",
- "generated/session.php",
- "generated/shmop.php",
- "generated/sockets.php",
- "generated/sodium.php",
- "generated/solr.php",
- "generated/spl.php",
- "generated/sqlsrv.php",
- "generated/ssdeep.php",
- "generated/ssh2.php",
- "generated/stream.php",
- "generated/strings.php",
- "generated/swoole.php",
- "generated/uodbc.php",
- "generated/uopz.php",
- "generated/url.php",
- "generated/var.php",
- "generated/xdiff.php",
- "generated/xml.php",
- "generated/xmlrpc.php",
- "generated/yaml.php",
- "generated/yaz.php",
- "generated/zip.php",
- "generated/zlib.php"
- ],
- "classmap": [
- "lib/DateTime.php",
- "lib/DateTimeImmutable.php",
- "lib/Exceptions/",
- "generated/Exceptions/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "description": "PHP core functions that throw exceptions instead of returning FALSE on error",
- "support": {
- "issues": "https://github.com/thecodingmachine/safe/issues",
- "source": "https://github.com/thecodingmachine/safe/tree/v3.4.0"
- },
- "funding": [
- {
- "url": "https://github.com/OskarStark",
- "type": "github"
- },
- {
- "url": "https://github.com/shish",
- "type": "github"
- },
- {
- "url": "https://github.com/silasjoisten",
- "type": "github"
- },
- {
- "url": "https://github.com/staabm",
- "type": "github"
- }
- ],
- "time": "2026-02-04T18:08:13+00:00"
+ "time": "2026-07-05T23:53:27+00:00"
}
],
"packages-dev": [
@@ -1070,21 +871,21 @@
},
{
"name": "codeigniter/coding-standard",
- "version": "v1.9.1",
+ "version": "v1.9.2",
"source": {
"type": "git",
"url": "https://github.com/CodeIgniter/coding-standard.git",
- "reference": "c7d227d3d3d0f2270405c8317c5e8c55f2262956"
+ "reference": "e9c690ebb86140a2ddf874940b0758c4b88110ce"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/CodeIgniter/coding-standard/zipball/c7d227d3d3d0f2270405c8317c5e8c55f2262956",
- "reference": "c7d227d3d3d0f2270405c8317c5e8c55f2262956",
+ "url": "https://api.github.com/repos/CodeIgniter/coding-standard/zipball/e9c690ebb86140a2ddf874940b0758c4b88110ce",
+ "reference": "e9c690ebb86140a2ddf874940b0758c4b88110ce",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
- "friendsofphp/php-cs-fixer": "^3.94",
+ "friendsofphp/php-cs-fixer": "^3.95",
"nexusphp/cs-config": "^3.28",
"php": "^8.2"
},
@@ -1120,32 +921,33 @@
"slack": "https://codeigniterchat.slack.com",
"source": "https://github.com/CodeIgniter/coding-standard"
},
- "time": "2026-02-17T18:41:24+00:00"
+ "time": "2026-04-11T20:06:02+00:00"
},
{
"name": "composer/pcre",
- "version": "3.3.2",
+ "version": "3.4.0",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
- "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e"
+ "reference": "d5a341b3fb61f3001970940afb1d332968a183ed"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
- "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
+ "url": "https://api.github.com/repos/composer/pcre/zipball/d5a341b3fb61f3001970940afb1d332968a183ed",
+ "reference": "d5a341b3fb61f3001970940afb1d332968a183ed",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0"
},
"conflict": {
- "phpstan/phpstan": "<1.11.10"
+ "phpstan/phpstan": "<2.2.2"
},
"require-dev": {
- "phpstan/phpstan": "^1.12 || ^2",
- "phpstan/phpstan-strict-rules": "^1 || ^2",
- "phpunit/phpunit": "^8 || ^9"
+ "phpstan/phpstan": "^2",
+ "phpstan/phpstan-deprecation-rules": "^2",
+ "phpstan/phpstan-strict-rules": "^2",
+ "phpunit/phpunit": "^9"
},
"type": "library",
"extra": {
@@ -1183,7 +985,7 @@
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
- "source": "https://github.com/composer/pcre/tree/3.3.2"
+ "source": "https://github.com/composer/pcre/tree/3.4.0"
},
"funding": [
{
@@ -1193,26 +995,22 @@
{
"url": "https://github.com/composer",
"type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/composer/composer",
- "type": "tidelift"
}
],
- "time": "2024-11-12T16:29:46+00:00"
+ "time": "2026-06-07T11:47:49+00:00"
},
{
"name": "composer/semver",
- "version": "3.4.4",
+ "version": "3.5.1",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
- "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95"
+ "reference": "528948210cc46f967a4b98e83b19e76f2b504993"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95",
- "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95",
+ "url": "https://api.github.com/repos/composer/semver/zipball/528948210cc46f967a4b98e83b19e76f2b504993",
+ "reference": "528948210cc46f967a4b98e83b19e76f2b504993",
"shasum": ""
},
"require": {
@@ -1254,7 +1052,7 @@
"homepage": "http://robbast.nl"
}
],
- "description": "Semver library that offers utilities, version constraint parsing and validation.",
+ "description": "Version comparison library that offers utilities, version constraint parsing and validation.",
"keywords": [
"semantic",
"semver",
@@ -1264,7 +1062,7 @@
"support": {
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/semver/issues",
- "source": "https://github.com/composer/semver/tree/3.4.4"
+ "source": "https://github.com/composer/semver/tree/3.5.1"
},
"funding": [
{
@@ -1276,7 +1074,7 @@
"type": "github"
}
],
- "time": "2025-08-20T19:15:30+00:00"
+ "time": "2026-10-05T13:12:12+00:00"
},
{
"name": "composer/xdebug-handler",
@@ -1344,6 +1142,75 @@
],
"time": "2024-05-06T16:37:16+00:00"
},
+ {
+ "name": "ergebnis/agent-detector",
+ "version": "1.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ergebnis/agent-detector.git",
+ "reference": "0cd815cec1207873c37624d33f0f2853523152f3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ergebnis/agent-detector/zipball/0cd815cec1207873c37624d33f0f2853523152f3",
+ "reference": "0cd815cec1207873c37624d33f0f2853523152f3",
+ "shasum": ""
+ },
+ "require": {
+ "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0 || ~8.6.0"
+ },
+ "require-dev": {
+ "ergebnis/composer-normalize": "^2.54.0",
+ "ergebnis/license": "^2.8.0",
+ "ergebnis/php-cs-fixer-config": "^6.60.2",
+ "ergebnis/phpstan-rules": "^2.14.0",
+ "ergebnis/phpunit-slow-test-detector": "^2.26.0",
+ "ergebnis/rector-rules": "^1.18.5",
+ "fakerphp/faker": "^1.24.1",
+ "infection/infection": "^0.26.6",
+ "phpstan/extension-installer": "^1.4.3",
+ "phpstan/phpstan": "^2.2.14",
+ "phpstan/phpstan-deprecation-rules": "^2.0.5",
+ "phpstan/phpstan-phpunit": "^2.1.1",
+ "phpstan/phpstan-strict-rules": "^2.1.0",
+ "phpunit/phpunit": "^9.6.34",
+ "rector/rector": "^2.7.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.3-dev"
+ },
+ "composer-normalize": {
+ "indent-size": 2,
+ "indent-style": "space"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Ergebnis\\AgentDetector\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Andreas Möller",
+ "email": "am@localheinz.com",
+ "homepage": "https://localheinz.com"
+ }
+ ],
+ "description": "Provides a detector for detecting the presence of an agent.",
+ "homepage": "https://github.com/ergebnis/agent-detector",
+ "support": {
+ "issues": "https://github.com/ergebnis/agent-detector/issues",
+ "security": "https://github.com/ergebnis/agent-detector/blob/main/.github/SECURITY.md",
+ "source": "https://github.com/ergebnis/agent-detector"
+ },
+ "time": "2026-10-15T11:13:32+00:00"
+ },
{
"name": "evenement/evenement",
"version": "v3.0.2",
@@ -1391,88 +1258,25 @@
},
"time": "2023-08-08T05:53:35+00:00"
},
- {
- "name": "fakerphp/faker",
- "version": "v1.24.1",
- "source": {
- "type": "git",
- "url": "https://github.com/FakerPHP/Faker.git",
- "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5",
- "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5",
- "shasum": ""
- },
- "require": {
- "php": "^7.4 || ^8.0",
- "psr/container": "^1.0 || ^2.0",
- "symfony/deprecation-contracts": "^2.2 || ^3.0"
- },
- "conflict": {
- "fzaninotto/faker": "*"
- },
- "require-dev": {
- "bamarni/composer-bin-plugin": "^1.4.1",
- "doctrine/persistence": "^1.3 || ^2.0",
- "ext-intl": "*",
- "phpunit/phpunit": "^9.5.26",
- "symfony/phpunit-bridge": "^5.4.16"
- },
- "suggest": {
- "doctrine/orm": "Required to use Faker\\ORM\\Doctrine",
- "ext-curl": "Required by Faker\\Provider\\Image to download images.",
- "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.",
- "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.",
- "ext-mbstring": "Required for multibyte Unicode string functionality."
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Faker\\": "src/Faker/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "François Zaninotto"
- }
- ],
- "description": "Faker is a PHP library that generates fake data for you.",
- "keywords": [
- "data",
- "faker",
- "fixtures"
- ],
- "support": {
- "issues": "https://github.com/FakerPHP/Faker/issues",
- "source": "https://github.com/FakerPHP/Faker/tree/v1.24.1"
- },
- "time": "2024-11-21T13:46:39+00:00"
- },
{
"name": "fidry/cpu-core-counter",
- "version": "1.3.0",
+ "version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/theofidry/cpu-core-counter.git",
- "reference": "db9508f7b1474469d9d3c53b86f817e344732678"
+ "reference": "d384a7d0d6e67aa497327260ca95023e92dc2032"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678",
- "reference": "db9508f7b1474469d9d3c53b86f817e344732678",
+ "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/d384a7d0d6e67aa497327260ca95023e92dc2032",
+ "reference": "d384a7d0d6e67aa497327260ca95023e92dc2032",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
- "fidry/makefile": "^0.2.0",
+ "fidry/makefile": "^0.2.0 || ^1.1.2",
"fidry/php-cs-fixer-config": "^1.1.2",
"phpstan/extension-installer": "^1.2.0",
"phpstan/phpstan": "^2.0",
@@ -1480,6 +1284,7 @@
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^8.5.31 || ^9.5.26",
+ "symfony/polyfill-mbstring": "^1.33",
"webmozarts/strict-phpunit": "^7.5"
},
"type": "library",
@@ -1505,7 +1310,7 @@
],
"support": {
"issues": "https://github.com/theofidry/cpu-core-counter/issues",
- "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0"
+ "source": "https://github.com/theofidry/cpu-core-counter/tree/1.4.1"
},
"funding": [
{
@@ -1513,26 +1318,27 @@
"type": "github"
}
],
- "time": "2025-08-14T07:29:31+00:00"
+ "time": "2026-09-29T22:11:39+00:00"
},
{
"name": "friendsofphp/php-cs-fixer",
- "version": "v3.94.2",
+ "version": "v3.95.27",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
- "reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63"
+ "reference": "1d0c68ee5f37446d8ad5970b82384cd1bb0a3317"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7787ceff91365ba7d623ec410b8f429cdebb4f63",
- "reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63",
+ "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/1d0c68ee5f37446d8ad5970b82384cd1bb0a3317",
+ "reference": "1d0c68ee5f37446d8ad5970b82384cd1bb0a3317",
"shasum": ""
},
"require": {
"clue/ndjson-react": "^1.3",
"composer/semver": "^3.4",
"composer/xdebug-handler": "^3.0.5",
+ "ergebnis/agent-detector": "^1.2",
"ext-filter": "*",
"ext-hash": "*",
"ext-json": "*",
@@ -1543,32 +1349,31 @@
"react/event-loop": "^1.5",
"react/socket": "^1.16",
"react/stream": "^1.4",
- "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0 || ^8.0",
+ "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0 || ^8.0 || ^9.0",
"symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
- "symfony/polyfill-mbstring": "^1.33",
- "symfony/polyfill-php80": "^1.33",
- "symfony/polyfill-php81": "^1.33",
- "symfony/polyfill-php84": "^1.33",
+ "symfony/polyfill-mbstring": "^1.37",
+ "symfony/polyfill-php80": "^1.37",
+ "symfony/polyfill-php81": "^1.37",
+ "symfony/polyfill-php84": "^1.37",
"symfony/process": "^5.4.47 || ^6.4.24 || ^7.2 || ^8.0",
"symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0"
},
"require-dev": {
- "facile-it/paraunit": "^1.3.1 || ^2.7.1",
- "infection/infection": "^0.32.3",
- "justinrainbow/json-schema": "^6.6.4",
+ "facile-it/paraunit": "^1.3.1 || ^2.11.0",
+ "infection/infection": "^0.32.7",
+ "justinrainbow/json-schema": "^6.12.0",
"keradus/cli-executor": "^2.3",
- "mikey179/vfsstream": "^1.6.12",
"php-coveralls/php-coveralls": "^2.9.1",
- "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.7",
- "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.7",
- "phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.51",
- "symfony/polyfill-php85": "^1.33",
- "symfony/var-dumper": "^5.4.48 || ^6.4.32 || ^7.4.4 || ^8.0.4",
- "symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0.1"
+ "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.8",
+ "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.8",
+ "phpunit/phpunit": "^9.6.36 || ^10.5.64 || ^11.5.56 || ^12.5.35 || ^13.3.3",
+ "symfony/polyfill-php85": "^1.41",
+ "symfony/var-dumper": "^5.4.48 || ^6.4.45 || ^7.4.18 || ^8.1.7",
+ "symfony/yaml": "^5.4.53 || ^6.4.45 || ^7.4.18 || ^8.1.6"
},
"suggest": {
"ext-dom": "For handling output formats in XML",
@@ -1609,7 +1414,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
- "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.94.2"
+ "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.95.27"
},
"funding": [
{
@@ -1617,7 +1422,7 @@
"type": "github"
}
],
- "time": "2026-02-20T16:13:53+00:00"
+ "time": "2026-09-22T09:54:55+00:00"
},
{
"name": "kint-php/kint",
@@ -1684,74 +1489,22 @@
},
"time": "2024-04-26T14:20:09+00:00"
},
- {
- "name": "mikey179/vfsstream",
- "version": "v1.6.12",
- "source": {
- "type": "git",
- "url": "https://github.com/bovigo/vfsStream.git",
- "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/fe695ec993e0a55c3abdda10a9364eb31c6f1bf0",
- "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^7.5||^8.5||^9.6",
- "yoast/phpunit-polyfills": "^2.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.6.x-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "org\\bovigo\\vfs\\": "src/main/php"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Frank Kleine",
- "homepage": "http://frankkleine.de/",
- "role": "Developer"
- }
- ],
- "description": "Virtual file system to mock the real file system in unit tests.",
- "homepage": "http://vfs.bovigo.org/",
- "support": {
- "issues": "https://github.com/bovigo/vfsStream/issues",
- "source": "https://github.com/bovigo/vfsStream/tree/master",
- "wiki": "https://github.com/bovigo/vfsStream/wiki"
- },
- "time": "2024-08-29T18:43:31+00:00"
- },
{
"name": "myclabs/deep-copy",
- "version": "1.13.4",
+ "version": "1.14.0",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a"
+ "reference": "8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a",
- "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae",
+ "reference": "8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae",
"shasum": ""
},
"require": {
- "php": "^7.1 || ^8.0"
+ "php": "^8.0"
},
"conflict": {
"doctrine/collections": "<1.6.8",
@@ -1786,42 +1539,42 @@
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
- "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4"
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.14.0"
},
"funding": [
{
- "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
- "type": "tidelift"
+ "url": "https://github.com/mnapoli",
+ "type": "github"
}
],
- "time": "2025-08-01T08:46:24+00:00"
+ "time": "2026-08-11T10:17:44+00:00"
},
{
"name": "nexusphp/cs-config",
- "version": "v3.28.1",
+ "version": "v3.29.0",
"source": {
"type": "git",
"url": "https://github.com/NexusPHP/cs-config.git",
- "reference": "4175b75a053b35dc64f37727df526520efb456f8"
+ "reference": "0fa9d490cf8b2867a83704a6b29ed2ea01eb7084"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/NexusPHP/cs-config/zipball/4175b75a053b35dc64f37727df526520efb456f8",
- "reference": "4175b75a053b35dc64f37727df526520efb456f8",
+ "url": "https://api.github.com/repos/NexusPHP/cs-config/zipball/0fa9d490cf8b2867a83704a6b29ed2ea01eb7084",
+ "reference": "0fa9d490cf8b2867a83704a6b29ed2ea01eb7084",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
- "friendsofphp/php-cs-fixer": "^3.94",
+ "friendsofphp/php-cs-fixer": "^3.95",
"php": "^8.2"
},
"require-dev": {
"nexusphp/tachycardia": "^2.4",
"phpstan/extension-installer": "^1.4",
- "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan": "^2.2",
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
- "phpunit/phpunit": "^11.5 || ^12.5"
+ "phpunit/phpunit": "^11.5 || ^12.5 || ^13.0"
},
"type": "library",
"autoload": {
@@ -1845,24 +1598,23 @@
"slack": "https://nexusphp.slack.com",
"source": "https://github.com/NexusPHP/cs-config.git"
},
- "time": "2026-02-22T12:03:01+00:00"
+ "time": "2026-08-22T13:21:04+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v5.7.0",
+ "version": "v5.9.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82"
+ "reference": "9e33da9553fe7786f0962b35f4e4ecf01be89def"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82",
- "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/9e33da9553fe7786f0962b35f4e4ecf01be89def",
+ "reference": "9e33da9553fe7786f0962b35f4e4ecf01be89def",
"shasum": ""
},
"require": {
- "ext-ctype": "*",
"ext-json": "*",
"ext-tokenizer": "*",
"php": ">=7.4"
@@ -1901,9 +1653,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.9.0"
},
- "time": "2025-12-06T11:56:16+00:00"
+ "time": "2026-09-13T18:51:52+00:00"
},
{
"name": "phar-io/manifest",
@@ -2372,26 +2124,26 @@
},
{
"name": "phpunit/phpunit",
- "version": "11.5.55",
+ "version": "11.5.57",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "adc7262fccc12de2b30f12a8aa0b33775d814f00"
+ "reference": "36b75bf56a8535623f5b3e24b27ea1823759da1a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/adc7262fccc12de2b30f12a8aa0b33775d814f00",
- "reference": "adc7262fccc12de2b30f12a8aa0b33775d814f00",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/36b75bf56a8535623f5b3e24b27ea1823759da1a",
+ "reference": "36b75bf56a8535623f5b3e24b27ea1823759da1a",
"shasum": ""
},
"require": {
"ext-dom": "*",
+ "ext-filter": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
- "ext-xml": "*",
"ext-xmlwriter": "*",
- "myclabs/deep-copy": "^1.13.4",
+ "myclabs/deep-copy": "^1.14.0",
"phar-io/manifest": "^2.0.4",
"phar-io/version": "^3.2.1",
"php": ">=8.2",
@@ -2454,93 +2206,15 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.55"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.57"
},
"funding": [
{
- "url": "https://phpunit.de/sponsors.html",
- "type": "custom"
- },
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- },
- {
- "url": "https://liberapay.com/sebastianbergmann",
- "type": "liberapay"
- },
- {
- "url": "https://thanks.dev/u/gh/sebastianbergmann",
- "type": "thanks_dev"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
- "type": "tidelift"
+ "url": "https://phpunit.de/sponsoring.html",
+ "type": "other"
}
],
- "time": "2026-02-18T12:37:06+00:00"
- },
- {
- "name": "predis/predis",
- "version": "v2.4.1",
- "source": {
- "type": "git",
- "url": "https://github.com/predis/predis.git",
- "reference": "07105e050622ed80bd60808367ced9e379f31530"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/predis/predis/zipball/07105e050622ed80bd60808367ced9e379f31530",
- "reference": "07105e050622ed80bd60808367ced9e379f31530",
- "shasum": ""
- },
- "require": {
- "php": "^7.2 || ^8.0"
- },
- "require-dev": {
- "friendsofphp/php-cs-fixer": "^3.3",
- "phpstan/phpstan": "^1.9",
- "phpunit/phpcov": "^6.0 || ^8.0",
- "phpunit/phpunit": "^8.0 || ^9.4"
- },
- "suggest": {
- "ext-relay": "Faster connection with in-memory caching (>=0.6.2)"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Predis\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Till Krüss",
- "homepage": "https://till.im",
- "role": "Maintainer"
- }
- ],
- "description": "A flexible and feature-complete Redis/Valkey client for PHP.",
- "homepage": "http://github.com/predis/predis",
- "keywords": [
- "nosql",
- "predis",
- "redis"
- ],
- "support": {
- "issues": "https://github.com/predis/predis/issues",
- "source": "https://github.com/predis/predis/tree/v2.4.1"
- },
- "funding": [
- {
- "url": "https://github.com/sponsors/tillkruss",
- "type": "github"
- }
- ],
- "time": "2025-11-12T18:00:11+00:00"
+ "time": "2026-10-05T05:47:54+00:00"
},
{
"name": "psr/container",
@@ -4211,16 +3885,16 @@
},
{
"name": "symfony/console",
- "version": "v7.4.7",
+ "version": "v7.4.21",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d"
+ "reference": "21f1bc2296f7ff6043241a8dcbc09559b3732820"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/e1e6770440fb9c9b0cf725f81d1361ad1835329d",
- "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d",
+ "url": "https://api.github.com/repos/symfony/console/zipball/21f1bc2296f7ff6043241a8dcbc09559b3732820",
+ "reference": "21f1bc2296f7ff6043241a8dcbc09559b3732820",
"shasum": ""
},
"require": {
@@ -4285,7 +3959,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v7.4.7"
+ "source": "https://github.com/symfony/console/tree/v7.4.21"
},
"funding": [
{
@@ -4305,20 +3979,20 @@
"type": "tidelift"
}
],
- "time": "2026-03-06T14:06:20+00:00"
+ "time": "2026-10-12T18:45:38+00:00"
},
{
"name": "symfony/deprecation-contracts",
- "version": "v3.6.0",
+ "version": "v3.7.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
- "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
+ "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
- "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d",
+ "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d",
"shasum": ""
},
"require": {
@@ -4331,7 +4005,7 @@
"name": "symfony/contracts"
},
"branch-alias": {
- "dev-main": "3.6-dev"
+ "dev-main": "3.7-dev"
}
},
"autoload": {
@@ -4356,7 +4030,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0"
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.1"
},
"funding": [
{
@@ -4367,25 +4041,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-09-25T14:21:43+00:00"
+ "time": "2026-06-05T06:23:12+00:00"
},
{
"name": "symfony/event-dispatcher",
- "version": "v7.4.4",
+ "version": "v7.4.17",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "dc2c0eba1af673e736bb851d747d266108aea746"
+ "reference": "d269974ee93c61d03620ffee358355bfdb471d66"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/dc2c0eba1af673e736bb851d747d266108aea746",
- "reference": "dc2c0eba1af673e736bb851d747d266108aea746",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d269974ee93c61d03620ffee358355bfdb471d66",
+ "reference": "d269974ee93c61d03620ffee358355bfdb471d66",
"shasum": ""
},
"require": {
@@ -4437,7 +4115,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.4"
+ "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.17"
},
"funding": [
{
@@ -4457,20 +4135,20 @@
"type": "tidelift"
}
],
- "time": "2026-01-05T11:45:34+00:00"
+ "time": "2026-08-21T17:40:08+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
- "version": "v3.6.0",
+ "version": "v3.7.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
- "reference": "59eb412e93815df44f05f342958efa9f46b1e586"
+ "reference": "c7de7a00ffb67842132da02ea92988a39ccd9f4e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586",
- "reference": "59eb412e93815df44f05f342958efa9f46b1e586",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c7de7a00ffb67842132da02ea92988a39ccd9f4e",
+ "reference": "c7de7a00ffb67842132da02ea92988a39ccd9f4e",
"shasum": ""
},
"require": {
@@ -4484,7 +4162,7 @@
"name": "symfony/contracts"
},
"branch-alias": {
- "dev-main": "3.6-dev"
+ "dev-main": "3.7-dev"
}
},
"autoload": {
@@ -4517,7 +4195,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0"
+ "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.7.1"
},
"funding": [
{
@@ -4528,25 +4206,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-09-25T14:21:43+00:00"
+ "time": "2026-06-05T06:23:12+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v7.4.6",
+ "version": "v7.4.21",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e"
+ "reference": "fd0e3462be6d32a0d130e8423e4940a7688162d8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/3ebc794fa5315e59fd122561623c2e2e4280538e",
- "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/fd0e3462be6d32a0d130e8423e4940a7688162d8",
+ "reference": "fd0e3462be6d32a0d130e8423e4940a7688162d8",
"shasum": ""
},
"require": {
@@ -4583,7 +4265,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v7.4.6"
+ "source": "https://github.com/symfony/filesystem/tree/v7.4.21"
},
"funding": [
{
@@ -4603,20 +4285,20 @@
"type": "tidelift"
}
],
- "time": "2026-02-25T16:50:00+00:00"
+ "time": "2026-10-06T20:05:19+00:00"
},
{
"name": "symfony/finder",
- "version": "v7.4.6",
+ "version": "v7.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf"
+ "reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/8655bf1076b7a3a346cb11413ffdabff50c7ffcf",
- "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e",
+ "reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e",
"shasum": ""
},
"require": {
@@ -4651,7 +4333,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/finder/tree/v7.4.6"
+ "source": "https://github.com/symfony/finder/tree/v7.4.20"
},
"funding": [
{
@@ -4671,20 +4353,20 @@
"type": "tidelift"
}
],
- "time": "2026-01-29T09:40:50+00:00"
+ "time": "2026-09-26T06:31:10+00:00"
},
{
"name": "symfony/options-resolver",
- "version": "v7.4.0",
+ "version": "v7.4.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
- "reference": "b38026df55197f9e39a44f3215788edf83187b80"
+ "reference": "2888fcdc4dc2fd5f7c7397be78631e8af12e02b4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/options-resolver/zipball/b38026df55197f9e39a44f3215788edf83187b80",
- "reference": "b38026df55197f9e39a44f3215788edf83187b80",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/2888fcdc4dc2fd5f7c7397be78631e8af12e02b4",
+ "reference": "2888fcdc4dc2fd5f7c7397be78631e8af12e02b4",
"shasum": ""
},
"require": {
@@ -4722,7 +4404,7 @@
"options"
],
"support": {
- "source": "https://github.com/symfony/options-resolver/tree/v7.4.0"
+ "source": "https://github.com/symfony/options-resolver/tree/v7.4.8"
},
"funding": [
{
@@ -4742,20 +4424,20 @@
"type": "tidelift"
}
],
- "time": "2025-11-12T15:39:26+00:00"
+ "time": "2026-03-24T13:12:05+00:00"
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.33.0",
+ "version": "v1.37.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
+ "reference": "141046a8f9477948ff284fa65be2095baafb94f2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
- "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2",
+ "reference": "141046a8f9477948ff284fa65be2095baafb94f2",
"shasum": ""
},
"require": {
@@ -4805,7 +4487,7 @@
"portable"
],
"support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.37.0"
},
"funding": [
{
@@ -4825,20 +4507,20 @@
"type": "tidelift"
}
],
- "time": "2024-09-09T11:45:10+00:00"
+ "time": "2026-04-10T16:19:22+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
- "version": "v1.33.0",
+ "version": "v1.43.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
- "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70"
+ "reference": "5cac8f4db97208823aa353f59a01faad2da52c75"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70",
- "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5cac8f4db97208823aa353f59a01faad2da52c75",
+ "reference": "5cac8f4db97208823aa353f59a01faad2da52c75",
"shasum": ""
},
"require": {
@@ -4887,7 +4569,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.43.0"
},
"funding": [
{
@@ -4907,20 +4589,20 @@
"type": "tidelift"
}
],
- "time": "2025-06-27T09:58:17+00:00"
+ "time": "2026-09-25T15:46:47+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
- "version": "v1.33.0",
+ "version": "v1.43.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
- "reference": "3833d7255cc303546435cb650316bff708a1c75c"
+ "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
- "reference": "3833d7255cc303546435cb650316bff708a1c75c",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/ebd57ccc7edb93d632e184efbe7693d2517bab3b",
+ "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b",
"shasum": ""
},
"require": {
@@ -4972,7 +4654,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.43.0"
},
"funding": [
{
@@ -4992,20 +4674,20 @@
"type": "tidelift"
}
],
- "time": "2024-09-09T11:45:10+00:00"
+ "time": "2026-09-23T22:02:09+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.33.0",
+ "version": "v1.43.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
+ "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
- "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/4d5d331bf731e0aedbc6b2f5e61135b7b7996a72",
+ "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72",
"shasum": ""
},
"require": {
@@ -5057,7 +4739,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.43.0"
},
"funding": [
{
@@ -5077,20 +4759,20 @@
"type": "tidelift"
}
],
- "time": "2024-12-23T08:48:59+00:00"
+ "time": "2026-09-24T15:19:04+00:00"
},
{
"name": "symfony/polyfill-php80",
- "version": "v1.33.0",
+ "version": "v1.43.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
- "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
+ "reference": "9c6a5d6b01ca51d486c813e9a9c0ed55f208bb74"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
- "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/9c6a5d6b01ca51d486c813e9a9c0ed55f208bb74",
+ "reference": "9c6a5d6b01ca51d486c813e9a9c0ed55f208bb74",
"shasum": ""
},
"require": {
@@ -5141,7 +4823,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.43.0"
},
"funding": [
{
@@ -5161,20 +4843,20 @@
"type": "tidelift"
}
],
- "time": "2025-01-02T08:10:11+00:00"
+ "time": "2026-09-25T15:50:05+00:00"
},
{
"name": "symfony/polyfill-php81",
- "version": "v1.33.0",
+ "version": "v1.38.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php81.git",
- "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c"
+ "reference": "6bfb9c766cacffbc8e118cb87217d08ed84e5cd7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
- "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
+ "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/6bfb9c766cacffbc8e118cb87217d08ed84e5cd7",
+ "reference": "6bfb9c766cacffbc8e118cb87217d08ed84e5cd7",
"shasum": ""
},
"require": {
@@ -5221,7 +4903,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-php81/tree/v1.38.1"
},
"funding": [
{
@@ -5241,20 +4923,20 @@
"type": "tidelift"
}
],
- "time": "2024-09-09T11:45:10+00:00"
+ "time": "2026-05-26T12:45:58+00:00"
},
{
"name": "symfony/polyfill-php84",
- "version": "v1.33.0",
+ "version": "v1.43.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php84.git",
- "reference": "d8ced4d875142b6a7426000426b8abc631d6b191"
+ "reference": "22c6548499cbe5c5bb072fc0c42312dff062a015"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191",
- "reference": "d8ced4d875142b6a7426000426b8abc631d6b191",
+ "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/22c6548499cbe5c5bb072fc0c42312dff062a015",
+ "reference": "22c6548499cbe5c5bb072fc0c42312dff062a015",
"shasum": ""
},
"require": {
@@ -5301,7 +4983,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-php84/tree/v1.43.0"
},
"funding": [
{
@@ -5321,20 +5003,20 @@
"type": "tidelift"
}
],
- "time": "2025-06-24T13:30:11+00:00"
+ "time": "2026-09-23T22:01:09+00:00"
},
{
"name": "symfony/process",
- "version": "v7.4.5",
+ "version": "v7.4.21",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "608476f4604102976d687c483ac63a79ba18cc97"
+ "reference": "e5247f4a5e0797d232ad8e8e6803aeb341843c83"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/608476f4604102976d687c483ac63a79ba18cc97",
- "reference": "608476f4604102976d687c483ac63a79ba18cc97",
+ "url": "https://api.github.com/repos/symfony/process/zipball/e5247f4a5e0797d232ad8e8e6803aeb341843c83",
+ "reference": "e5247f4a5e0797d232ad8e8e6803aeb341843c83",
"shasum": ""
},
"require": {
@@ -5366,7 +5048,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v7.4.5"
+ "source": "https://github.com/symfony/process/tree/v7.4.21"
},
"funding": [
{
@@ -5386,20 +5068,20 @@
"type": "tidelift"
}
],
- "time": "2026-01-26T15:07:59+00:00"
+ "time": "2026-10-08T16:56:12+00:00"
},
{
"name": "symfony/service-contracts",
- "version": "v3.6.1",
+ "version": "v3.7.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43"
+ "reference": "15e6a07ec2a2c75ceb1b21dd98105ee8456d2257"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43",
- "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/15e6a07ec2a2c75ceb1b21dd98105ee8456d2257",
+ "reference": "15e6a07ec2a2c75ceb1b21dd98105ee8456d2257",
"shasum": ""
},
"require": {
@@ -5417,7 +5099,7 @@
"name": "symfony/contracts"
},
"branch-alias": {
- "dev-main": "3.6-dev"
+ "dev-main": "3.7-dev"
}
},
"autoload": {
@@ -5453,7 +5135,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/v3.6.1"
+ "source": "https://github.com/symfony/service-contracts/tree/v3.7.3"
},
"funding": [
{
@@ -5473,20 +5155,20 @@
"type": "tidelift"
}
],
- "time": "2025-07-15T11:30:57+00:00"
+ "time": "2026-07-27T15:39:01+00:00"
},
{
"name": "symfony/stopwatch",
- "version": "v7.4.0",
+ "version": "v7.4.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
- "reference": "8a24af0a2e8a872fb745047180649b8418303084"
+ "reference": "70a852d72fec4d51efb1f48dcd968efcaf5ccb89"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/stopwatch/zipball/8a24af0a2e8a872fb745047180649b8418303084",
- "reference": "8a24af0a2e8a872fb745047180649b8418303084",
+ "url": "https://api.github.com/repos/symfony/stopwatch/zipball/70a852d72fec4d51efb1f48dcd968efcaf5ccb89",
+ "reference": "70a852d72fec4d51efb1f48dcd968efcaf5ccb89",
"shasum": ""
},
"require": {
@@ -5519,7 +5201,7 @@
"description": "Provides a way to profile code",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/stopwatch/tree/v7.4.0"
+ "source": "https://github.com/symfony/stopwatch/tree/v7.4.8"
},
"funding": [
{
@@ -5539,20 +5221,20 @@
"type": "tidelift"
}
],
- "time": "2025-08-04T07:05:15+00:00"
+ "time": "2026-03-24T13:12:05+00:00"
},
{
"name": "symfony/string",
- "version": "v7.4.6",
+ "version": "v7.4.21",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "9f209231affa85aa930a5e46e6eb03381424b30b"
+ "reference": "9bc35d074ad16a58c21cd52b18c5cacc4f4c3981"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/9f209231affa85aa930a5e46e6eb03381424b30b",
- "reference": "9f209231affa85aa930a5e46e6eb03381424b30b",
+ "url": "https://api.github.com/repos/symfony/string/zipball/9bc35d074ad16a58c21cd52b18c5cacc4f4c3981",
+ "reference": "9bc35d074ad16a58c21cd52b18c5cacc4f4c3981",
"shasum": ""
},
"require": {
@@ -5610,7 +5292,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v7.4.6"
+ "source": "https://github.com/symfony/string/tree/v7.4.21"
},
"funding": [
{
@@ -5630,7 +5312,7 @@
"type": "tidelift"
}
],
- "time": "2026-02-09T09:33:46+00:00"
+ "time": "2026-10-03T15:15:30+00:00"
},
{
"name": "theseer/tokenizer",
@@ -5689,7 +5371,7 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
- "php": "^8.2",
+ "php": ">=8.2.35 <8.3 || >=8.3.36 <8.4 || >=8.4.27",
"ext-intl": "*"
},
"platform-dev": {},
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index 856ede37f..8b41f5ed1 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -1,6 +1,6 @@
## Server Requirements
-- PHP version `8.2` to `8.4` are supported, PHP version `≤ 8.1` is NOT supported. Please note that PHP needs to have the extensions `php-json`, `php-gd`, `php-bcmath`, `php-intl`, `php-openssl`, `php-mbstring`, `php-curl` and `php-xml` installed and enabled. An unstable master build can be downloaded in the releases section.
+- PHP version `8.2.35` to `8.4.27` are supported (minimum patch levels required for CVE-2026-109618 / CVE-2026-109619 security fixes). PHP version `≤ 8.1` is NOT supported. Please note that PHP needs to have the extensions `php-json`, `php-gd`, `php-bcmath`, `php-intl`, `php-openssl`, `php-mbstring`, `php-curl` and `php-xml` installed and enabled. An unstable master build can be downloaded in the releases section.
- MySQL `5.7` is supported, also MariaDB replacement `10.x` is supported and might offer better performance.
- Apache `2.4` is supported. Nginx should work fine too, see [wiki page here](https://github.com/opensourcepos/opensourcepos/wiki/Local-Deployment-using-LEMP).
- Raspberry PI based installations proved to work, see [wiki page here]().
diff --git a/package-lock.json b/package-lock.json
index cda06b03a..96f2e8361 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@opensourcepos/opensourcepos",
- "version": "3.4.3",
+ "version": "3.4.4-dev",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@opensourcepos/opensourcepos",
- "version": "3.4.3",
+ "version": "3.4.4-dev",
"license": "MIT",
"dependencies": {
"bootstrap": "^3.4.1",
diff --git a/package.json b/package.json
index 834c46159..1a53bf713 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@opensourcepos/opensourcepos",
- "version": "3.4.3",
+ "version": "3.4.4-dev",
"description": "Open Source Point of Sale is a web based point of sale system written in the PHP language. It uses MySQL as the data storage back-end and has a simple user interface.",
"keywords": [
"point-of-sale",
diff --git a/tests/Config/Validation/OSPOSRulesTest.php b/tests/Config/Validation/OSPOSRulesTest.php
index 6371db6bd..d3c9fa748 100644
--- a/tests/Config/Validation/OSPOSRulesTest.php
+++ b/tests/Config/Validation/OSPOSRulesTest.php
@@ -7,9 +7,9 @@ use App\Models\Employee;
use CodeIgniter\Config\Factories;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\Test\CIUnitTestCase;
-use Config\OSPOS;
use Config\Services;
use PHPUnit\Framework\MockObject\MockObject;
+use Tests\Support\OsposConfigFixtureTrait;
/**
* Regression tests for the login validation flow in OSPOSRules::login_check().
@@ -19,6 +19,8 @@ use PHPUnit\Framework\MockObject\MockObject;
*/
class OSPOSRulesTest extends CIUnitTestCase
{
+ use OsposConfigFixtureTrait;
+
protected function tearDown(): void
{
Factories::reset();
@@ -138,9 +140,7 @@ class OSPOSRulesTest extends CIUnitTestCase
private function injectSettings(array $settings): void
{
- $ospos = new OSPOS();
- $ospos->settings = $settings;
- Factories::injectMock('config', OSPOS::class, $ospos);
+ $this->injectOsposSettings($settings);
}
private function injectRequest(): void
diff --git a/tests/Controllers/CashupControllerTest.php b/tests/Controllers/CashupControllerTest.php
index 5db565f6b..023eed9eb 100644
--- a/tests/Controllers/CashupControllerTest.php
+++ b/tests/Controllers/CashupControllerTest.php
@@ -3,22 +3,23 @@
namespace Tests\Controllers;
use App\Models\Cashup;
-use CodeIgniter\Config\Factories;
-use CodeIgniter\Database\Config;
use CodeIgniter\HTTP\DownloadResponse;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use CodeIgniter\Test\FeatureTestTrait;
-use Config\OSPOS;
use ReflectionProperty;
+use Tests\Support\DatabaseBootstrapTrait;
use Tests\Support\EmployeeFixtureTrait;
+use Tests\Support\OsposConfigFixtureTrait;
class CashupControllerTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
use FeatureTestTrait;
use EmployeeFixtureTrait;
+ use OsposConfigFixtureTrait;
protected $migrate = true;
protected $migrateOnce = true;
@@ -26,34 +27,24 @@ class CashupControllerTest extends CIUnitTestCase
protected $refresh = false;
protected $namespace = null;
- private static bool $doneBootstrap = false;
-
protected function setUp(): void
{
- if (self::$doneBootstrap === false) {
- Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
- Config::connect($this->DBGroup)->close();
-
- self::$doneBootstrap = true;
- }
+ $this->resetDatabaseOnce();
parent::setUp();
- $ospos = new OSPOS();
- $ospos->settings = [
+ $this->injectOsposSettings([
'company' => 'Test Co',
'dateformat' => 'Y-m-d',
'timeformat' => 'H:i:s',
'number_locale' => 'en_US',
'currency_decimals' => 2,
'thousands_separator' => ',',
- ];
- Factories::injectMock('config', OSPOS::class, $ospos);
+ ]);
}
protected function tearDown(): void
{
- Factories::reset();
parent::tearDown();
}
diff --git a/tests/Controllers/CustomersCsvImportTest.php b/tests/Controllers/CustomersCsvImportTest.php
index fc30a1288..18f0f6429 100644
--- a/tests/Controllers/CustomersCsvImportTest.php
+++ b/tests/Controllers/CustomersCsvImportTest.php
@@ -2,16 +2,17 @@
namespace Tests\Controllers;
-use CodeIgniter\Database\Config;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use CodeIgniter\Test\FeatureTestTrait;
use App\Models\Customer;
use App\Models\Employee;
+use Tests\Support\DatabaseBootstrapTrait;
class CustomersCsvImportTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
use FeatureTestTrait;
protected $migrate = true;
@@ -22,19 +23,12 @@ class CustomersCsvImportTest extends CIUnitTestCase
protected Customer $customer;
protected Employee $employee;
- private static bool $doneBootstrap = false;
-
protected function setUp(): void
{
// Reset the test database to a clean schema on the first test in this
// class so leftover customers with the same emails from prior runs
// cannot be rejected as duplicates by the import (check_email_exists).
- if (self::$doneBootstrap === false) {
- Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
- Config::connect($this->DBGroup)->close();
-
- self::$doneBootstrap = true;
- }
+ $this->resetDatabaseOnce();
parent::setUp();
// Reset any stale transaction state left on the shared in-process DB
diff --git a/tests/Controllers/EmployeesControllerTest.php b/tests/Controllers/EmployeesControllerTest.php
index 380d37ec2..b0727c72e 100644
--- a/tests/Controllers/EmployeesControllerTest.php
+++ b/tests/Controllers/EmployeesControllerTest.php
@@ -2,7 +2,6 @@
namespace Tests\Controllers;
-use CodeIgniter\Database\Config;
use CodeIgniter\HTTP\DownloadResponse;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Test\CIUnitTestCase;
@@ -12,11 +11,13 @@ use CodeIgniter\Config\Services;
use App\Models\Employee;
use App\Models\Module;
use ReflectionProperty;
+use Tests\Support\DatabaseBootstrapTrait;
use Tests\Support\EmployeeFixtureTrait;
class EmployeesControllerTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
use FeatureTestTrait;
use EmployeeFixtureTrait;
@@ -27,20 +28,13 @@ class EmployeesControllerTest extends CIUnitTestCase
protected $priorDisallowGrantChange;
- private static bool $doneBootstrap = false;
-
protected function setUp(): void
{
// Reset the test database to a known clean schema on the first test in
// this class so stale employees from prior runs (whose usernames are
// unique-key bound and whose grant sets leak into these assertions)
// cannot contaminate the assertions below.
- if (self::$doneBootstrap === false) {
- Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
- Config::connect($this->DBGroup)->close();
-
- self::$doneBootstrap = true;
- }
+ $this->resetDatabaseOnce();
parent::setUp();
// Reset any stale transaction state left on the shared in-process DB
diff --git a/tests/Controllers/HomeTest.php b/tests/Controllers/HomeTest.php
index d10c8c650..3667b80f5 100644
--- a/tests/Controllers/HomeTest.php
+++ b/tests/Controllers/HomeTest.php
@@ -2,12 +2,12 @@
namespace Tests\Controllers;
-use CodeIgniter\Database\Config;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use CodeIgniter\Test\FeatureTestTrait;
use App\Models\Employee;
use RuntimeException;
+use Tests\Support\DatabaseBootstrapTrait;
/**
* Test suite for Home controller password validation
@@ -19,6 +19,7 @@ use RuntimeException;
class HomeTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
use FeatureTestTrait;
protected $migrate = true;
@@ -26,16 +27,9 @@ class HomeTest extends CIUnitTestCase
protected $refresh = false;
protected $namespace = null;
- private static bool $doneBootstrap = false;
-
protected function setUp(): void
{
- if (self::$doneBootstrap === false) {
- Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
- Config::connect($this->DBGroup)->close();
-
- self::$doneBootstrap = true;
- }
+ $this->resetDatabaseOnce();
parent::setUp();
}
diff --git a/tests/Controllers/ItemKitsControllerTest.php b/tests/Controllers/ItemKitsControllerTest.php
index 5ea6382ce..18f84aa67 100644
--- a/tests/Controllers/ItemKitsControllerTest.php
+++ b/tests/Controllers/ItemKitsControllerTest.php
@@ -2,8 +2,6 @@
namespace Tests\Controllers;
-use CodeIgniter\Config\Factories;
-use CodeIgniter\Database\Config;
use CodeIgniter\HTTP\DownloadResponse;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Test\CIUnitTestCase;
@@ -11,14 +9,17 @@ use CodeIgniter\Test\DatabaseTestTrait;
use CodeIgniter\Test\FeatureTestTrait;
use App\Models\Item;
use App\Models\Item_kit;
-use Config\OSPOS;
use Exception;
use ReflectionProperty;
+use Tests\Support\DatabaseBootstrapTrait;
+use Tests\Support\OsposConfigFixtureTrait;
class ItemKitsControllerTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
use FeatureTestTrait;
+ use OsposConfigFixtureTrait;
protected $migrate = true;
protected $migrateOnce = true;
@@ -26,24 +27,16 @@ class ItemKitsControllerTest extends CIUnitTestCase
protected $refresh = false;
protected $namespace = null;
- private static bool $doneBootstrap = false;
-
protected Item $item;
protected Item_kit $itemKit;
protected function setUp(): void
{
- if (self::$doneBootstrap === false) {
- Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
- Config::connect($this->DBGroup)->close();
-
- self::$doneBootstrap = true;
- }
+ $this->resetDatabaseOnce();
parent::setUp();
- $ospos = new OSPOS();
- $ospos->settings = [
+ $this->injectOsposSettings([
'company' => 'Test Co',
'barcode_content' => 'id',
'barcode_type' => 'C128',
@@ -59,8 +52,7 @@ class ItemKitsControllerTest extends CIUnitTestCase
'barcode_page_cellspacing' => 1,
'barcode_generate_if_empty' => 0,
'barcode_formats' => 'null',
- ];
- Factories::injectMock('config', OSPOS::class, $ospos);
+ ]);
$this->item = model(Item::class);
$this->itemKit = model(Item_kit::class);
@@ -68,7 +60,6 @@ class ItemKitsControllerTest extends CIUnitTestCase
protected function tearDown(): void
{
- Factories::reset();
parent::tearDown();
}
diff --git a/tests/Controllers/ReportsControllerTest.php b/tests/Controllers/ReportsControllerTest.php
index 372fc6ba0..714142cc2 100644
--- a/tests/Controllers/ReportsControllerTest.php
+++ b/tests/Controllers/ReportsControllerTest.php
@@ -6,9 +6,9 @@ use CodeIgniter\HTTP\DownloadResponse;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use CodeIgniter\Test\FeatureTestTrait;
-use App\Database\Seeds\TestDatabaseBootstrapSeeder;
use App\Models\Employee;
use Config\OSPOS;
+use Tests\Support\DatabaseBootstrapTrait;
/**
* Regression tests for the reports permission bypass
@@ -24,6 +24,7 @@ use Config\OSPOS;
class ReportsControllerTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
use FeatureTestTrait;
protected $migrate = true;
@@ -31,18 +32,12 @@ class ReportsControllerTest extends CIUnitTestCase
protected $refresh = false;
protected $namespace = null;
- private static bool $doneBootstrap = false;
-
/**
* Set up test environment
*/
protected function setUp(): void
{
- if (self::$doneBootstrap === false) {
- TestDatabaseBootstrapSeeder::reset();
-
- self::$doneBootstrap = true;
- }
+ $this->resetDatabaseOnce();
parent::setUp();
diff --git a/tests/Controllers/SalesControllerTest.php b/tests/Controllers/SalesControllerTest.php
index 9bfdd9bb0..cdd82e151 100644
--- a/tests/Controllers/SalesControllerTest.php
+++ b/tests/Controllers/SalesControllerTest.php
@@ -2,7 +2,6 @@
namespace Tests\Controllers;
-use CodeIgniter\Database\Config;
use CodeIgniter\HTTP\DownloadResponse;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Test\CIUnitTestCase;
@@ -12,6 +11,7 @@ use CodeIgniter\Config\Services;
use App\Models\Employee;
use Config\Database;
use ReflectionProperty;
+use Tests\Support\DatabaseBootstrapTrait;
use Tests\Support\ItemFixtureTrait;
use Tests\Support\EmployeeFixtureTrait;
use Tests\Support\SaleFixtureTrait;
@@ -31,6 +31,7 @@ use Tests\Support\SaleFixtureTrait;
class SalesControllerTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
use FeatureTestTrait;
use ItemFixtureTrait;
use EmployeeFixtureTrait;
@@ -42,16 +43,9 @@ class SalesControllerTest extends CIUnitTestCase
protected $refresh = false;
protected $namespace = null;
- private static bool $doneBootstrap = false;
-
protected function setUp(): void
{
- if (self::$doneBootstrap === false) {
- Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
- Config::connect($this->DBGroup)->close();
-
- self::$doneBootstrap = true;
- }
+ $this->resetDatabaseOnce();
parent::setUp();
}
diff --git a/tests/Controllers/TaxesControllerTest.php b/tests/Controllers/TaxesControllerTest.php
index 8c673ea50..23ec9c8c7 100644
--- a/tests/Controllers/TaxesControllerTest.php
+++ b/tests/Controllers/TaxesControllerTest.php
@@ -2,7 +2,6 @@
namespace Tests\Controllers;
-use CodeIgniter\Database\Config;
use CodeIgniter\HTTP\DownloadResponse;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Test\CIUnitTestCase;
@@ -10,11 +9,13 @@ use CodeIgniter\Test\DatabaseTestTrait;
use CodeIgniter\Test\FeatureTestTrait;
use App\Models\Tax;
use ReflectionProperty;
+use Tests\Support\DatabaseBootstrapTrait;
use Tests\Support\EmployeeFixtureTrait;
class TaxesControllerTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
use FeatureTestTrait;
use EmployeeFixtureTrait;
@@ -24,16 +25,9 @@ class TaxesControllerTest extends CIUnitTestCase
protected $refresh = false;
protected $namespace = null;
- private static $doneBootstrap = false;
-
protected function setUp(): void
{
- if (self::$doneBootstrap === false) {
- Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
- Config::connect($this->DBGroup)->close();
-
- self::$doneBootstrap = true;
- }
+ $this->resetDatabaseOnce();
parent::setUp();
}
diff --git a/tests/helpers/GetItemDataRowTest.php b/tests/Helpers/GetItemDataRowTest.php
similarity index 92%
rename from tests/helpers/GetItemDataRowTest.php
rename to tests/Helpers/GetItemDataRowTest.php
index 89ae14729..6cdf7b152 100644
--- a/tests/helpers/GetItemDataRowTest.php
+++ b/tests/Helpers/GetItemDataRowTest.php
@@ -2,13 +2,14 @@
namespace Tests\Helpers;
-use CodeIgniter\Config\Factories;
use CodeIgniter\Test\CIUnitTestCase;
-use Config\OSPOS;
use stdClass;
+use Tests\Support\OsposConfigFixtureTrait;
class GetItemDataRowTest extends CIUnitTestCase
{
+ use OsposConfigFixtureTrait;
+
protected function setUp(): void
{
parent::setUp();
@@ -20,8 +21,7 @@ class GetItemDataRowTest extends CIUnitTestCase
protected function injectSettings(array $overrides = []): void
{
- $config = new OSPOS();
- $config->settings = array_merge([
+ $this->injectOsposSettings(array_merge([
'multi_pack_enabled' => 0,
'use_destination_based_tax' => 0,
'number_locale' => 'en_US',
@@ -29,9 +29,7 @@ class GetItemDataRowTest extends CIUnitTestCase
'quantity_decimals' => 0,
'thousands_separator' => 1,
'currency_symbol' => '$',
- ], $overrides);
-
- Factories::injectMock('config', OSPOS::class, $config);
+ ], $overrides));
}
protected function makeItem(array $overrides = []): stdClass
diff --git a/tests/helpers/LocaleHelperTest.php b/tests/Helpers/LocaleHelperTest.php
similarity index 86%
rename from tests/helpers/LocaleHelperTest.php
rename to tests/Helpers/LocaleHelperTest.php
index a76dcf00c..b82aa55a8 100644
--- a/tests/helpers/LocaleHelperTest.php
+++ b/tests/Helpers/LocaleHelperTest.php
@@ -1,19 +1,20 @@
settings = ['dateformat' => 'Y-m-d'];
- Factories::injectMock('config', OSPOS::class, $config);
+ $this->injectOsposSettings(['dateformat' => 'Y-m-d']);
}
public function testValidDateReturnsTrue(): void
diff --git a/tests/Helpers/UrlHelperTest.php b/tests/Helpers/UrlHelperTest.php
new file mode 100644
index 000000000..096eb6a5b
--- /dev/null
+++ b/tests/Helpers/UrlHelperTest.php
@@ -0,0 +1,27 @@
+assertMatchesRegularExpression('/^[A-Za-z0-9\-_]+$/', $encoded);
+
+ // Assert that decoding the encoded string returns the original data
+ $decoded = base64url_decode($encoded);
+ $this->assertEquals($data, $decoded);
+ }
+}
diff --git a/tests/helpers/export_helperTest.php b/tests/Helpers/export_helperTest.php
similarity index 100%
rename from tests/helpers/export_helperTest.php
rename to tests/Helpers/export_helperTest.php
diff --git a/tests/helpers/migration_helperTest.php b/tests/Helpers/migration_helperTest.php
similarity index 98%
rename from tests/helpers/migration_helperTest.php
rename to tests/Helpers/migration_helperTest.php
index 5fe2e5555..4e1e3b5e4 100644
--- a/tests/helpers/migration_helperTest.php
+++ b/tests/Helpers/migration_helperTest.php
@@ -1,6 +1,6 @@
settings = [
+ $this->injectOsposSettings([
'cash_rounding_code' => '',
'cash_decimals' => 2,
'currency_decimals' => 2,
'tax_decimals' => 2,
'quantity_decimals' => 2,
- ];
- Factories::injectMock('config', OSPOS::class, $ospos);
+ ]);
// Inject stub models so model() calls in Sale_lib::__construct() skip DB
$stubMethods = ['__construct'];
diff --git a/tests/Models/AppconfigTest.php b/tests/Models/AppconfigTest.php
index 566ee4163..12ca2e89b 100644
--- a/tests/Models/AppconfigTest.php
+++ b/tests/Models/AppconfigTest.php
@@ -5,12 +5,13 @@ namespace Tests\Models;
use App\Models\Appconfig;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
-use Config\Database;
use Config\OSPOS;
+use Tests\Support\DatabaseBootstrapTrait;
class AppconfigTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
protected $migrate = true;
protected $migrateOnce = true;
@@ -19,10 +20,11 @@ class AppconfigTest extends CIUnitTestCase
protected $refresh = true;
protected $namespace = null;
- public static function setUpBeforeClass(): void
+ protected function setUp(): void
{
- $seeder = Database::seeder('tests');
- $seeder->call('TestDatabaseBootstrapSeeder');
+ $this->resetDatabaseOnce();
+
+ parent::setUp();
}
private function appconfig(): Appconfig
diff --git a/tests/Models/CustomerRewardPointsTest.php b/tests/Models/CustomerRewardPointsTest.php
index 7e89a29d4..3e0be4669 100644
--- a/tests/Models/CustomerRewardPointsTest.php
+++ b/tests/Models/CustomerRewardPointsTest.php
@@ -5,8 +5,8 @@ namespace Tests\Models;
use App\Models\Customer;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
-use Config\Database;
use Tests\Support\ConcurrentDbRaceTrait;
+use Tests\Support\DatabaseBootstrapTrait;
/**
* Regression tests: adjustRewardPoints() must apply
@@ -17,6 +17,7 @@ use Tests\Support\ConcurrentDbRaceTrait;
class CustomerRewardPointsTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
use ConcurrentDbRaceTrait;
protected $migrate = true;
@@ -24,14 +25,10 @@ class CustomerRewardPointsTest extends CIUnitTestCase
protected $refresh = false;
protected $namespace = null;
- public static function setUpBeforeClass(): void
- {
- $seeder = Database::seeder('tests');
- $seeder->call('TestDatabaseBootstrapSeeder');
- }
-
protected function setUp(): void
{
+ $this->resetDatabaseOnce();
+
parent::setUp();
}
diff --git a/tests/Models/EmployeeTest.php b/tests/Models/EmployeeTest.php
index 4ff2f05a8..9fb305a93 100644
--- a/tests/Models/EmployeeTest.php
+++ b/tests/Models/EmployeeTest.php
@@ -5,20 +5,25 @@ namespace Tests\Models;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use App\Models\Employee;
+use Tests\Support\DatabaseBootstrapTrait;
use Tests\Support\EmployeeFixtureTrait;
class EmployeeTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
use EmployeeFixtureTrait;
protected $migrate = true;
protected $migrateOnce = true;
+ protected $seedOnce = true;
protected $refresh = false;
protected $namespace = null;
protected function setUp(): void
{
+ $this->resetDatabaseOnce();
+
parent::setUp();
}
diff --git a/tests/Models/GiftcardTest.php b/tests/Models/GiftcardTest.php
index d097cd673..064996058 100644
--- a/tests/Models/GiftcardTest.php
+++ b/tests/Models/GiftcardTest.php
@@ -5,8 +5,8 @@ namespace Tests\Models;
use App\Models\Giftcard;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
-use Config\Database;
use Tests\Support\ConcurrentDbRaceTrait;
+use Tests\Support\DatabaseBootstrapTrait;
/**
* Regression tests: decrementGiftcardValue() must
@@ -17,6 +17,7 @@ use Tests\Support\ConcurrentDbRaceTrait;
class GiftcardTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
use ConcurrentDbRaceTrait;
protected $migrate = true;
@@ -24,14 +25,10 @@ class GiftcardTest extends CIUnitTestCase
protected $refresh = false;
protected $namespace = null;
- public static function setUpBeforeClass(): void
- {
- $seeder = Database::seeder('tests');
- $seeder->call('TestDatabaseBootstrapSeeder');
- }
-
protected function setUp(): void
{
+ $this->resetDatabaseOnce();
+
parent::setUp();
}
diff --git a/tests/Models/ItemBulkUpdateTest.php b/tests/Models/ItemBulkUpdateTest.php
index 4e1cdcb5a..7ce3733f7 100644
--- a/tests/Models/ItemBulkUpdateTest.php
+++ b/tests/Models/ItemBulkUpdateTest.php
@@ -5,6 +5,7 @@ namespace Tests\Models;
use App\Models\Item;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
+use Tests\Support\DatabaseBootstrapTrait;
/**
* Regression coverage for mass assignment in bulk edit.
@@ -15,15 +16,13 @@ use CodeIgniter\Test\DatabaseTestTrait;
class ItemBulkUpdateTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
- /**
- * The schema is taken as it stands rather than migrated, so these tests run
- * against an existing test database without dropping it. Every row created
- * here is rolled back in tearDown().
- */
- protected $migrate = false;
- protected $refresh = false;
- protected $namespace = null;
+ protected $migrate = true;
+ protected $migrateOnce = true;
+ protected $seedOnce = true;
+ protected $refresh = false;
+ protected $namespace = null;
protected Item $item;
@@ -35,6 +34,8 @@ class ItemBulkUpdateTest extends CIUnitTestCase
protected function setUp(): void
{
+ $this->resetDatabaseOnce();
+
parent::setUp();
$this->item = model(Item::class);
diff --git a/tests/Models/ItemQuantityTest.php b/tests/Models/ItemQuantityTest.php
index 8ca38a267..8fa3e037b 100644
--- a/tests/Models/ItemQuantityTest.php
+++ b/tests/Models/ItemQuantityTest.php
@@ -5,8 +5,8 @@ namespace Tests\Models;
use App\Models\Item_quantity;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
-use Config\Database;
use Tests\Support\ConcurrentDbRaceTrait;
+use Tests\Support\DatabaseBootstrapTrait;
use Tests\Support\ItemFixtureTrait;
/**
@@ -20,6 +20,7 @@ use Tests\Support\ItemFixtureTrait;
class ItemQuantityTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
use ConcurrentDbRaceTrait;
use ItemFixtureTrait;
@@ -30,14 +31,10 @@ class ItemQuantityTest extends CIUnitTestCase
private const LOCATION_ID = 1;
- public static function setUpBeforeClass(): void
- {
- $seeder = Database::seeder('tests');
- $seeder->call('TestDatabaseBootstrapSeeder');
- }
-
protected function setUp(): void
{
+ $this->resetDatabaseOnce();
+
parent::setUp();
}
diff --git a/tests/Models/ItemSearchTest.php b/tests/Models/ItemSearchTest.php
index 24f60826b..0aaea591e 100644
--- a/tests/Models/ItemSearchTest.php
+++ b/tests/Models/ItemSearchTest.php
@@ -5,13 +5,14 @@ namespace Tests\Models;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use App\Models\Item;
-use Config\Database;
use Config\OSPOS;
+use Tests\Support\DatabaseBootstrapTrait;
use Tests\Support\ItemSearchFixtureTrait;
class ItemSearchTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
use ItemSearchFixtureTrait;
protected $migrate = true;
@@ -23,14 +24,10 @@ class ItemSearchTest extends CIUnitTestCase
protected $item;
- public static function setUpBeforeClass(): void
- {
- $seeder = Database::seeder('tests');
- $seeder->call('TestDatabaseBootstrapSeeder');
- }
-
protected function setUp(): void
{
+ $this->resetDatabaseOnce();
+
parent::setUp();
$this->item = model(Item::class);
diff --git a/tests/Models/ItemTaxesMultipleTest.php b/tests/Models/ItemTaxesMultipleTest.php
index 1c0372b67..301453123 100644
--- a/tests/Models/ItemTaxesMultipleTest.php
+++ b/tests/Models/ItemTaxesMultipleTest.php
@@ -5,12 +5,13 @@ namespace Tests\Models;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use App\Models\Item_taxes;
-use Config\Database;
+use Tests\Support\DatabaseBootstrapTrait;
use Tests\Support\ItemSearchFixtureTrait;
class ItemTaxesMultipleTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
use ItemSearchFixtureTrait;
protected $migrate = true;
@@ -22,14 +23,10 @@ class ItemTaxesMultipleTest extends CIUnitTestCase
protected $item_taxes;
- public static function setUpBeforeClass(): void
- {
- $seeder = Database::seeder('tests');
- $seeder->call('TestDatabaseBootstrapSeeder');
- }
-
protected function setUp(): void
{
+ $this->resetDatabaseOnce();
+
parent::setUp();
$this->item_taxes = model(Item_taxes::class);
diff --git a/tests/Models/Reports/Summary_taxes_test.php b/tests/Models/Reports/Summary_taxes_test.php
index ddbb43cb5..7c798054e 100644
--- a/tests/Models/Reports/Summary_taxes_test.php
+++ b/tests/Models/Reports/Summary_taxes_test.php
@@ -7,13 +7,16 @@ namespace Tests\Models\Reports;
use App\Models\Reports\Summary_taxes;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
+use Tests\Support\DatabaseBootstrapTrait;
class Summary_taxes_test extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
protected $migrate = true;
protected $migrateOnce = true;
+ protected $seedOnce = true;
protected $refresh = false;
protected $namespace = null;
@@ -22,6 +25,8 @@ class Summary_taxes_test extends CIUnitTestCase
protected function setUp(): void
{
+ $this->resetDatabaseOnce();
+
parent::setUp();
$this->seedTestData();
}
diff --git a/tests/Models/SaleTest.php b/tests/Models/SaleTest.php
index e6372d754..f2efedc80 100644
--- a/tests/Models/SaleTest.php
+++ b/tests/Models/SaleTest.php
@@ -3,9 +3,9 @@
namespace Tests\Models;
use App\Models\Sale;
-use CodeIgniter\Database\Config;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
+use Tests\Support\DatabaseBootstrapTrait;
use Tests\Support\EmployeeFixtureTrait;
use Tests\Support\FailedQueryConnectionTrait;
use Tests\Support\ItemFixtureTrait;
@@ -18,6 +18,7 @@ use Tests\Support\ItemFixtureTrait;
class SaleTest extends CIUnitTestCase
{
use DatabaseTestTrait;
+ use DatabaseBootstrapTrait;
use EmployeeFixtureTrait;
use FailedQueryConnectionTrait;
use ItemFixtureTrait;
@@ -28,18 +29,11 @@ class SaleTest extends CIUnitTestCase
protected $refresh = false;
protected $namespace = null;
- private static bool $doneBootstrap = false;
-
private const LOCATION_ID = 1;
protected function setUp(): void
{
- if (self::$doneBootstrap === false) {
- Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
- Config::connect($this->DBGroup)->close();
-
- self::$doneBootstrap = true;
- }
+ $this->resetDatabaseOnce();
parent::setUp();
}
diff --git a/tests/Support/DatabaseBootstrapTrait.php b/tests/Support/DatabaseBootstrapTrait.php
new file mode 100644
index 000000000..12ad6d15a
--- /dev/null
+++ b/tests/Support/DatabaseBootstrapTrait.php
@@ -0,0 +1,50 @@
+resetDatabaseOnce();
+ *
+ * parent::setUp();
+ * }
+ * }
+ */
+trait DatabaseBootstrapTrait
+{
+ private static bool $doneBootstrap = false;
+
+ protected function resetDatabaseOnce(): void
+ {
+ if (self::$doneBootstrap === true) {
+ return;
+ }
+
+ TestDatabaseBootstrapSeeder::reset();
+ Config::connect($this->DBGroup)->close();
+
+ self::$doneBootstrap = true;
+ }
+}
diff --git a/tests/Support/OsposConfigFixtureTrait.php b/tests/Support/OsposConfigFixtureTrait.php
new file mode 100644
index 000000000..a6e1679ec
--- /dev/null
+++ b/tests/Support/OsposConfigFixtureTrait.php
@@ -0,0 +1,50 @@
+settings = [...];
+ * Factories::injectMock(...)` block that was duplicated with slightly
+ * different settings arrays across many test files. Each test supplies the
+ * exact settings it depends on - OSPOS::getDefaultSettings() is private and
+ * only has a handful of keys, so it is not a usable base to merge onto.
+ *
+ * Usage:
+ *
+ * use Tests\Support\OsposConfigFixtureTrait;
+ *
+ * class FooTest extends CIUnitTestCase
+ * {
+ * use OsposConfigFixtureTrait;
+ *
+ * protected function setUp(): void
+ * {
+ * parent::setUp();
+ *
+ * $this->injectOsposSettings([
+ * 'invoice_enable' => false,
+ * 'number_locale' => 'en_US',
+ * ]);
+ * }
+ * }
+ */
+trait OsposConfigFixtureTrait
+{
+ /**
+ * @param array $settings
+ */
+ protected function injectOsposSettings(array $settings): OSPOS
+ {
+ $ospos = new OSPOS();
+ $ospos->settings = $settings;
+
+ Factories::injectMock('config', OSPOS::class, $ospos);
+
+ return $ospos;
+ }
+}
diff --git a/tests/helpers/UrlHelperTest.php b/tests/helpers/UrlHelperTest.php
deleted file mode 100644
index d49bc279c..000000000
--- a/tests/helpers/UrlHelperTest.php
+++ /dev/null
@@ -1,25 +0,0 @@
-assertMatchesRegularExpression('/^[A-Za-z0-9\-_]+$/', $encoded);
-
- // Assert that decoding the encoded string returns the original data
- $decoded = base64url_decode($encoded);
- $this->assertEquals($data, $decoded);
- }
- }