diff --git a/.env.example b/.env.example index 89d6438..7a1538a 100644 --- a/.env.example +++ b/.env.example @@ -8,7 +8,7 @@ APP_KEY= APP_DEBUG=true APP_URL=http://localhost -APP_LOCALE=en +APP_LOCALE=el APP_FALLBACK_LOCALE=en APP_FAKER_LOCALE=en_US diff --git a/CLAUDE.md b/CLAUDE.md index 3e7a5ae..bb4cced 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -14,6 +14,29 @@ ## Project Language Settings --- +## Localization + +Uses classic Laravel localization (https://laravel.com/docs/13.x/localization) — no third-party i18n routing package. + +**Locales:** Greek (`el`) is primary/default, English (`en`) is secondary. Set in `config('app.available_locales')` (`config/app.php`). + +**URL structure:** every route is prefixed with `{locale}`, including the default — `3dealer.gr/el/...` and `3dealer.gr/en/...`. Bare root (`/`) 301-redirects to `/el` (see `routes/web.php`). This avoids the ambiguity of an unprefixed default locale (see the reasoning in project memory / past conversation — prefixing every locale keeps hreflang symmetrical and scales cleanly to a third language later). + +**URL slugs are the same across both locales, permanently** — e.g. `/el/products/{x}` and `/en/products/{x}`, not `/el/proionta/{x}` vs `/en/products/{x}`. This is a deliberate, standing decision for this project, not a placeholder to revisit later. Only the visible content is translated, not the slug. Do not introduce per-locale translated slugs (e.g. a `lang/{locale}/routes.php` segment map) unless the user explicitly asks for that to change. + +**How it's wired:** +- All routes live inside `Route::prefix('{locale}')->where('locale', ...)->middleware('setlocale')` in `routes/web.php`. +- `App\Http\Middleware\SetLocale` validates the `{locale}` segment (404s if not in `available_locales`), calls `App::setLocale()`, and shares `$currentLocale`, `$altLocale`, and `$altLocaleUrl` (the same page in the other locale) to every view — this is what powers both the header's language switcher and the `` hreflang tags in `resources/views/layouts/app.blade.php`. Don't recompute this logic elsewhere; read those shared variables instead. +- When adding a new route, put it inside that `{locale}` group and give it a route `name()` — the alt-locale URL generation in the middleware depends on the current route being named (falls back to the locale root if unnamed). +- When linking to a page in Blade, prefer `route('name', [...])` (locale is a normal route param, defaults to `app()->getLocale()` implicitly via the shared route group) over hand-built path strings, except for pages that don't have a controller/route yet (e.g. `/products`, `/contact`, `/cart` placeholders in the header currently use `url('/'.app()->getLocale().'/products')` — replace with `route()` once those pages exist). +- **Every controller action for a route inside the `{locale}` group must declare `$locale` as its first parameter, even if unused** — e.g. `show(string $locale, Product $product)`. Laravel's `ControllerDispatcher` ultimately calls the controller with `...array_values($parameters)`, i.e. **positionally**. If a route-bound model parameter (like `$product`) isn't preceded by a matching `$locale` parameter in the method signature, the resolved values shift out of position and the wrong value (the locale string) gets passed where the model was expected — a `TypeError` that's easy to misread as a binding failure. Closures with zero declared parameters are unaffected (PHP just ignores the extra positional arg), so this only bites real controller methods. + +**Where translatable strings go:** +- Most UI copy is editable by the client/marketing team via **Stoic** (the headless CMS) — don't hardcode it here. +- Small strings that don't need client editing (nav labels, aria-labels, tab labels, pluralized counts) go in Laravel's own lang files at **`lang/{locale}/*.php`** (project root, per Laravel 12+ convention — not `resources/lang`). Current file: `lang/el/general.php` / `lang/en/general.php`. Use `__('general.key')` or `trans_choice('general.key', $count, [...])` for pluralized strings. + +--- + ## Tech Stack - **Laravel 12** + **Lunar PHP 1.3** (headless e-commerce) diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php new file mode 100644 index 0000000..8d8a9db --- /dev/null +++ b/app/Http/Controllers/HomeController.php @@ -0,0 +1,27 @@ +inRandomOrder() + ->limit(13) + ->get() + ->map(fn (Product $product) => [ + 'name' => $product->translateAttribute('name'), + 'price' => $product->variants->first()?->prices->first()?->price->decimal, + 'image' => $product->media->first()?->getUrl(), + 'href' => route('product.show', ['product' => $product]), + ]); + + return view('home', [ + 'heroProducts' => $products->take(5)->values(), + 'classicsProducts' => $products->slice(5)->values(), + ]); + } +} diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index 7709f8b..852bfbb 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -6,7 +6,7 @@ class ProductController extends Controller { - public function show(Product $product) + public function show(string $locale, Product $product) { $product->load([ "variants.prices.currency", diff --git a/app/Http/Middleware/SetLocale.php b/app/Http/Middleware/SetLocale.php new file mode 100644 index 0000000..b24d142 --- /dev/null +++ b/app/Http/Middleware/SetLocale.php @@ -0,0 +1,49 @@ +route('locale'); + $available = config('app.available_locales'); + + if (! in_array($locale, $available, true)) { + abort(404); + } + + App::setLocale($locale); + + // Lets route() calls omit {locale} anywhere in the request lifecycle + // (controllers, views) — without this, every route() call inside the + // {locale} group would need locale passed explicitly every time. + URL::defaults(['locale' => $locale]); + + $altLocale = collect($available)->first(fn ($l) => $l !== $locale); + $routeName = $request->route()->getName(); + + View::share('currentLocale', $locale); + View::share('altLocale', $altLocale); + View::share( + 'altLocaleUrl', + $routeName + ? route($routeName, array_merge($request->route()->parameters(), ['locale' => $altLocale])) + : url('/'.$altLocale), + ); + + return $next($request); + } +} diff --git a/bootstrap/app.php b/bootstrap/app.php index c183276..3acb151 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -11,7 +11,9 @@ health: '/up', ) ->withMiddleware(function (Middleware $middleware): void { - // + $middleware->alias([ + 'setlocale' => \App\Http\Middleware\SetLocale::class, + ]); }) ->withExceptions(function (Exceptions $exceptions): void { // diff --git a/composer.lock b/composer.lock index 9573c6c..01f1746 100644 --- a/composer.lock +++ b/composer.lock @@ -565,16 +565,18 @@ }, { "name": "boboko/core", - "version": "0.2.0", + "version": "0.3.0", "source": { "type": "git", "url": "https://code.radical-elements.com/boboko/core.git", - "reference": "0524380ab0922729d177e7bf000c61be1fba440a" + "reference": "4c003690058ee37e2789ff95a68391a1818f3f63" }, "require": { "laravel/framework": "^12.0", "laravel/tinker": "^3.0", "lunarphp/lunar": "1.3.0", + "lunarphp/meilisearch": "*", + "lunarphp/search": "*", "lunarphp/table-rate-shipping": "^1.3", "php": "^8.5", "symfony/yaml": "^7.0" @@ -605,7 +607,7 @@ } }, "description": "Core module — authentication and shared panel behaviour", - "time": "2026-07-10T12:21:42+00:00" + "time": "2026-07-12T02:38:14+00:00" }, { "name": "brick/math", @@ -811,6 +813,72 @@ }, "time": "2025-02-28T20:54:02+00:00" }, + { + "name": "clue/stream-filter", + "version": "v1.7.0", + "source": { + "type": "git", + "url": "https://github.com/clue/stream-filter.git", + "reference": "049509fef80032cb3f051595029ab75b49a3c2f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/stream-filter/zipball/049509fef80032cb3f051595029ab75b49a3c2f7", + "reference": "049509fef80032cb3f051595029ab75b49a3c2f7", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "Clue\\StreamFilter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "A simple and modern approach to stream filtering in PHP", + "homepage": "https://github.com/clue/stream-filter", + "keywords": [ + "bucket brigade", + "callback", + "filter", + "php_user_filter", + "stream", + "stream_filter_append", + "stream_filter_register" + ], + "support": { + "issues": "https://github.com/clue/stream-filter/issues", + "source": "https://github.com/clue/stream-filter/tree/v1.7.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2023-12-20T15:40:13+00:00" + }, { "name": "composer/semver", "version": "3.4.4", @@ -1120,16 +1188,16 @@ }, { "name": "doctrine/dbal", - "version": "3.10.5", + "version": "3.10.6", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "95d84866bf3c04b2ddca1df7c049714660959aef" + "reference": "c95589d775a0b2e543467d40f8c3ecccf586f2b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/95d84866bf3c04b2ddca1df7c049714660959aef", - "reference": "95d84866bf3c04b2ddca1df7c049714660959aef", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/c95589d775a0b2e543467d40f8c3ecccf586f2b4", + "reference": "c95589d775a0b2e543467d40f8c3ecccf586f2b4", "shasum": "" }, "require": { @@ -1214,7 +1282,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.10.5" + "source": "https://github.com/doctrine/dbal/tree/3.10.6" }, "funding": [ { @@ -1230,7 +1298,7 @@ "type": "tidelift" } ], - "time": "2026-02-24T08:03:57+00:00" + "time": "2026-07-21T12:57:49+00:00" }, { "name": "doctrine/deprecations", @@ -1540,16 +1608,16 @@ }, { "name": "dompdf/dompdf", - "version": "v3.1.5", + "version": "v3.1.6", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496" + "reference": "6d4b4eb8500f7a786da8868ba463a71b725a4005" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496", - "reference": "f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/6d4b4eb8500f7a786da8868ba463a71b725a4005", + "reference": "6d4b4eb8500f7a786da8868ba463a71b725a4005", "shasum": "" }, "require": { @@ -1598,9 +1666,9 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v3.1.5" + "source": "https://github.com/dompdf/dompdf/tree/v3.1.6" }, - "time": "2026-03-03T13:54:37+00:00" + "time": "2026-07-20T12:29:38+00:00" }, { "name": "dompdf/php-font-lib", @@ -2473,22 +2541,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.14.0", + "version": "7.15.2", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "aef242412e13128b5049864867bb49fc37dd39de" + "reference": "744101956d78b7c1384d0cbf379db13e859167bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/aef242412e13128b5049864867bb49fc37dd39de", - "reference": "aef242412e13128b5049864867bb49fc37dd39de", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/744101956d78b7c1384d0cbf379db13e859167bf", + "reference": "744101956d78b7c1384d0cbf379db13e859167bf", "shasum": "" }, "require": { "ext-json": "*", "guzzlehttp/promises": "^2.5.1", - "guzzlehttp/psr7": "^2.12.4", + "guzzlehttp/psr7": "^2.13", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.5 || ^3.0", @@ -2501,7 +2569,7 @@ "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", "guzzle/client-integration-tests": "3.0.3", - "guzzlehttp/test-server": "^0.6", + "guzzlehttp/test-server": "^0.7", "php-http/message-factory": "^1.1", "phpunit/phpunit": "^8.5.52 || ^9.6.34", "psr/log": "^1.1 || ^2.0 || ^3.0" @@ -2581,7 +2649,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.14.0" + "source": "https://github.com/guzzle/guzzle/tree/7.15.2" }, "funding": [ { @@ -2597,7 +2665,7 @@ "type": "tidelift" } ], - "time": "2026-07-08T22:54:09+00:00" + "time": "2026-07-26T23:23:20+00:00" }, { "name": "guzzlehttp/promises", @@ -2685,16 +2753,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "2.12.4", + "version": "2.13.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "51e27f9e2b332ab3e72f4520d5ff4f3c68c3577c" + "reference": "dad89620b7a6edb60c15858442eb2e408b45d8f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/51e27f9e2b332ab3e72f4520d5ff4f3c68c3577c", - "reference": "51e27f9e2b332ab3e72f4520d5ff4f3c68c3577c", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/dad89620b7a6edb60c15858442eb2e408b45d8f4", + "reference": "dad89620b7a6edb60c15858442eb2e408b45d8f4", "shasum": "" }, "require": { @@ -2784,7 +2852,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.12.4" + "source": "https://github.com/guzzle/psr7/tree/2.13.0" }, "funding": [ { @@ -2800,20 +2868,20 @@ "type": "tidelift" } ], - "time": "2026-07-08T15:56:20+00:00" + "time": "2026-07-16T22:23:49+00:00" }, { "name": "guzzlehttp/uri-template", - "version": "v1.0.9", + "version": "v1.0.10", "source": { "type": "git", "url": "https://github.com/guzzle/uri-template.git", - "reference": "d7580af6d3f8384325d9cd3e99b21c3ed1848176" + "reference": "f6c24c21f42b990e9a58912b332d0874df6ba839" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/uri-template/zipball/d7580af6d3f8384325d9cd3e99b21c3ed1848176", - "reference": "d7580af6d3f8384325d9cd3e99b21c3ed1848176", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/f6c24c21f42b990e9a58912b332d0874df6ba839", + "reference": "f6c24c21f42b990e9a58912b332d0874df6ba839", "shasum": "" }, "require": { @@ -2870,7 +2938,7 @@ ], "support": { "issues": "https://github.com/guzzle/uri-template/issues", - "source": "https://github.com/guzzle/uri-template/tree/v1.0.9" + "source": "https://github.com/guzzle/uri-template/tree/v1.0.10" }, "funding": [ { @@ -2886,7 +2954,65 @@ "type": "tidelift" } ], - "time": "2026-07-08T16:19:22+00:00" + "time": "2026-07-17T13:53:03+00:00" + }, + { + "name": "http-interop/http-factory-guzzle", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/http-interop/http-factory-guzzle.git", + "reference": "c2c859ceb05c3f42e710b60555f4c35b6a4a3995" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/http-interop/http-factory-guzzle/zipball/c2c859ceb05c3f42e710b60555f4c35b6a4a3995", + "reference": "c2c859ceb05c3f42e710b60555f4c35b6a4a3995", + "shasum": "" + }, + "require": { + "guzzlehttp/psr7": "^1.7||^2.0", + "php": ">=7.3", + "psr/http-factory": "^1.0" + }, + "provide": { + "psr/http-factory-implementation": "^1.0" + }, + "require-dev": { + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^9.5" + }, + "suggest": { + "guzzlehttp/psr7": "Includes an HTTP factory starting in version 2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Http\\Factory\\Guzzle\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "An HTTP Factory using Guzzle PSR7", + "keywords": [ + "factory", + "http", + "psr-17", + "psr-7" + ], + "support": { + "issues": "https://github.com/http-interop/http-factory-guzzle/issues", + "source": "https://github.com/http-interop/http-factory-guzzle/tree/1.2.1" + }, + "time": "2025-12-15T11:28:16+00:00" }, { "name": "kalnoy/nestedset", @@ -2953,16 +3079,16 @@ }, { "name": "kirschbaum-development/eloquent-power-joins", - "version": "4.3.2", + "version": "4.3.3", "source": { "type": "git", "url": "https://github.com/kirschbaum-development/eloquent-power-joins.git", - "reference": "33c189bd51a510c1ceba67222395ead08a29863a" + "reference": "c609dbbe4ad2051b667e937f1ab554067519d64b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kirschbaum-development/eloquent-power-joins/zipball/33c189bd51a510c1ceba67222395ead08a29863a", - "reference": "33c189bd51a510c1ceba67222395ead08a29863a", + "url": "https://api.github.com/repos/kirschbaum-development/eloquent-power-joins/zipball/c609dbbe4ad2051b667e937f1ab554067519d64b", + "reference": "c609dbbe4ad2051b667e937f1ab554067519d64b", "shasum": "" }, "require": { @@ -3010,22 +3136,22 @@ ], "support": { "issues": "https://github.com/kirschbaum-development/eloquent-power-joins/issues", - "source": "https://github.com/kirschbaum-development/eloquent-power-joins/tree/4.3.2" + "source": "https://github.com/kirschbaum-development/eloquent-power-joins/tree/4.3.3" }, - "time": "2026-05-28T20:35:55+00:00" + "time": "2026-07-23T11:41:37+00:00" }, { "name": "laravel/framework", - "version": "v12.63.0", + "version": "v12.64.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "7adfddbf4738f2e6cae5419b0e6bc46d4cccfbcf" + "reference": "727a8ea2949c23ca8b5316b86a00984b6017b7a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/7adfddbf4738f2e6cae5419b0e6bc46d4cccfbcf", - "reference": "7adfddbf4738f2e6cae5419b0e6bc46d4cccfbcf", + "url": "https://api.github.com/repos/laravel/framework/zipball/727a8ea2949c23ca8b5316b86a00984b6017b7a0", + "reference": "727a8ea2949c23ca8b5316b86a00984b6017b7a0", "shasum": "" }, "require": { @@ -3234,7 +3360,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2026-07-07T14:16:35+00:00" + "time": "2026-07-14T14:25:37+00:00" }, { "name": "laravel/prompts", @@ -3377,16 +3503,16 @@ }, { "name": "laravel/serializable-closure", - "version": "v2.0.13", + "version": "v2.0.15", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "b566ee0dd251f3c4078bed003a7ce015f5ea6dce" + "reference": "dccd8bcb851bb03fcc005df650b708b57cc52661" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b566ee0dd251f3c4078bed003a7ce015f5ea6dce", - "reference": "b566ee0dd251f3c4078bed003a7ce015f5ea6dce", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/dccd8bcb851bb03fcc005df650b708b57cc52661", + "reference": "dccd8bcb851bb03fcc005df650b708b57cc52661", "shasum": "" }, "require": { @@ -3434,7 +3560,7 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2026-04-16T14:03:50+00:00" + "time": "2026-07-21T16:49:22+00:00" }, { "name": "laravel/tinker", @@ -3507,16 +3633,16 @@ }, { "name": "league/commonmark", - "version": "2.8.2", + "version": "2.9.0", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "59fb075d2101740c337c7216e3f32b36c204218b" + "reference": "5703d83ba3da3b2e356a5fedc848ed6d8ffb6529" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/59fb075d2101740c337c7216e3f32b36c204218b", - "reference": "59fb075d2101740c337c7216e3f32b36c204218b", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/5703d83ba3da3b2e356a5fedc848ed6d8ffb6529", + "reference": "5703d83ba3da3b2e356a5fedc848ed6d8ffb6529", "shasum": "" }, "require": { @@ -3538,8 +3664,8 @@ "github/gfm": "0.29.0", "michelf/php-markdown": "^1.4 || ^2.0", "nyholm/psr7": "^1.5", - "phpstan/phpstan": "^1.8.2", - "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", + "phpstan/phpstan": "^2.0.0", + "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0 || ^12.0.0 || ^13.0.0", "scrutinizer/ocular": "^1.8.1", "symfony/finder": "^5.3 | ^6.0 | ^7.0 || ^8.0", "symfony/process": "^5.4 | ^6.0 | ^7.0 || ^8.0", @@ -3553,7 +3679,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.9-dev" + "dev-main": "2.10-dev" } }, "autoload": { @@ -3610,7 +3736,7 @@ "type": "tidelift" } ], - "time": "2026-03-19T13:16:38+00:00" + "time": "2026-08-03T13:42:31+00:00" }, { "name": "league/config", @@ -4232,16 +4358,16 @@ }, { "name": "livewire/livewire", - "version": "v3.8.2", + "version": "v3.8.3", "source": { "type": "git", "url": "https://github.com/livewire/livewire.git", - "reference": "e77fce60d0615d68dc6b8fafe98a6739d9752a24" + "reference": "ab9c2ac9305008aa9ab0f1beecec8ed6c3a591b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/e77fce60d0615d68dc6b8fafe98a6739d9752a24", - "reference": "e77fce60d0615d68dc6b8fafe98a6739d9752a24", + "url": "https://api.github.com/repos/livewire/livewire/zipball/ab9c2ac9305008aa9ab0f1beecec8ed6c3a591b2", + "reference": "ab9c2ac9305008aa9ab0f1beecec8ed6c3a591b2", "shasum": "" }, "require": { @@ -4296,7 +4422,7 @@ "description": "A front-end framework for Laravel.", "support": { "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v3.8.2" + "source": "https://github.com/livewire/livewire/tree/v3.8.3" }, "funding": [ { @@ -4304,7 +4430,7 @@ "type": "github" } ], - "time": "2026-06-27T03:14:20+00:00" + "time": "2026-07-31T00:08:18+00:00" }, { "name": "lukascivil/treewalker", @@ -4576,6 +4702,139 @@ ], "time": "2026-01-29T11:24:01+00:00" }, + { + "name": "lunarphp/meilisearch", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/lunarphp/meilisearch.git", + "reference": "c815564dad2dc14e570f8fdc2b375d1c5765921c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lunarphp/meilisearch/zipball/c815564dad2dc14e570f8fdc2b375d1c5765921c", + "reference": "c815564dad2dc14e570f8fdc2b375d1c5765921c", + "shasum": "" + }, + "require": { + "meilisearch/meilisearch-php": "^1.10" + }, + "type": "library", + "extra": { + "lunar": { + "name": "Meilisearch" + }, + "laravel": { + "providers": [ + "Lunar\\Meilisearch\\MeilisearchServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Lunar\\Meilisearch\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lunar", + "homepage": "https://lunarphp.io/" + } + ], + "description": "Meilisearch Addon", + "keywords": [ + "e-commerce", + "ecommerce", + "headless", + "laravel", + "lunarphp", + "meilisearch", + "store" + ], + "support": { + "issues": "https://github.com/lunarphp/meilisearch/issues", + "source": "https://github.com/lunarphp/meilisearch/tree/1.1.0" + }, + "funding": [ + { + "url": "https://github.com/lunar", + "type": "github" + } + ], + "time": "2025-02-26T12:29:01+00:00" + }, + { + "name": "lunarphp/search", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/lunarphp/search.git", + "reference": "a522411592ddca489241cd58b56ad34257ce44dc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lunarphp/search/zipball/a522411592ddca489241cd58b56ad34257ce44dc", + "reference": "a522411592ddca489241cd58b56ad34257ce44dc", + "shasum": "" + }, + "require": { + "http-interop/http-factory-guzzle": "^1.2", + "lunarphp/core": "self.version", + "meilisearch/meilisearch-php": "^1.10", + "php": "^8.2", + "spatie/laravel-data": "^4.13.1", + "typesense/typesense-php": "^4.9" + }, + "type": "project", + "extra": { + "lunar": { + "name": "Search" + }, + "laravel": { + "providers": [ + "Lunar\\Search\\SearchServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Lunar\\Search\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lunar", + "homepage": "https://lunarphp.io/" + } + ], + "description": "Ecommerce search for LunarPHP", + "keywords": [ + "e-commerce", + "ecommerce", + "headless", + "laravel", + "lunarphp", + "search", + "shop", + "store" + ], + "support": { + "issues": "https://github.com/lunarphp/search/issues", + "source": "https://github.com/lunarphp/search/tree/1.3.0" + }, + "time": "2025-11-12T16:37:26+00:00" + }, { "name": "lunarphp/table-rate-shipping", "version": "1.3.0", @@ -4789,6 +5048,86 @@ }, "time": "2026-06-23T18:43:15+00:00" }, + { + "name": "meilisearch/meilisearch-php", + "version": "v1.16.1", + "source": { + "type": "git", + "url": "https://github.com/meilisearch/meilisearch-php.git", + "reference": "f9f63e0e7d12ffaae54f7317fa8f4f4dfa8ae7b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/meilisearch/meilisearch-php/zipball/f9f63e0e7d12ffaae54f7317fa8f4f4dfa8ae7b6", + "reference": "f9f63e0e7d12ffaae54f7317fa8f4f4dfa8ae7b6", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.4 || ^8.0", + "php-http/discovery": "^1.7", + "psr/http-client": "^1.0", + "symfony/polyfill-php81": "^1.33" + }, + "require-dev": { + "http-interop/http-factory-guzzle": "^1.2.0", + "php-cs-fixer/shim": "^3.59.3", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.5 || ^10.5", + "symfony/http-client": "^5.4|^6.0|^7.0" + }, + "suggest": { + "guzzlehttp/guzzle": "Use Guzzle ^7 as HTTP client", + "http-interop/http-factory-guzzle": "Factory for guzzlehttp/guzzle", + "symfony/http-client": "Use Symfony Http client" + }, + "type": "library", + "autoload": { + "psr-4": { + "MeiliSearch\\": "src/", + "Meilisearch\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Clémentine Urquizar", + "email": "clementine@meilisearch.com" + }, + { + "name": "Bruno Casali", + "email": "bruno@meilisearch.com" + }, + { + "name": "Laurent Cazanove", + "email": "lau.cazanove@gmail.com" + }, + { + "name": "Tomas Norkūnas", + "email": "norkunas.tom@gmail.com" + } + ], + "description": "PHP wrapper for the Meilisearch API", + "keywords": [ + "api", + "client", + "instant", + "meilisearch", + "php", + "search" + ], + "support": { + "issues": "https://github.com/meilisearch/meilisearch-php/issues", + "source": "https://github.com/meilisearch/meilisearch-php/tree/v1.16.1" + }, + "time": "2025-09-18T10:15:45+00:00" + }, { "name": "monolog/monolog", "version": "3.10.0", @@ -5066,16 +5405,16 @@ }, { "name": "nette/utils", - "version": "v4.1.4", + "version": "v4.1.5", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "7da6c396d7ebe142bc857c20479d5e70a5e1aac7" + "reference": "b043439dbdf954e6c28b5ea7e34b0100f83165e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/7da6c396d7ebe142bc857c20479d5e70a5e1aac7", - "reference": "7da6c396d7ebe142bc857c20479d5e70a5e1aac7", + "url": "https://api.github.com/repos/nette/utils/zipball/b043439dbdf954e6c28b5ea7e34b0100f83165e0", + "reference": "b043439dbdf954e6c28b5ea7e34b0100f83165e0", "shasum": "" }, "require": { @@ -5095,7 +5434,7 @@ }, "suggest": { "ext-gd": "to use Image", - "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-iconv": "to use Strings::chr(), ord() and reverse()", "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", "ext-json": "to use Nette\\Utils\\Json", "ext-mbstring": "to use Strings::lower() etc...", @@ -5151,9 +5490,9 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.1.4" + "source": "https://github.com/nette/utils/tree/v4.1.5" }, - "time": "2026-05-11T20:49:54+00:00" + "time": "2026-07-17T23:02:45+00:00" }, { "name": "nikic/php-parser", @@ -5299,6 +5638,84 @@ ], "time": "2026-02-16T23:10:27+00:00" }, + { + "name": "nyholm/psr7", + "version": "1.8.2", + "source": { + "type": "git", + "url": "https://github.com/Nyholm/psr7.git", + "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nyholm/psr7/zipball/a71f2b11690f4b24d099d6b16690a90ae14fc6f3", + "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0", + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "http-interop/http-factory-tests": "^0.9", + "php-http/message-factory": "^1.0", + "php-http/psr7-integration-tests": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.4", + "symfony/error-handler": "^4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Nyholm\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" + } + ], + "description": "A fast PHP7 implementation of PSR-7", + "homepage": "https://tnyholm.se", + "keywords": [ + "psr-17", + "psr-7" + ], + "support": { + "issues": "https://github.com/Nyholm/psr7/issues", + "source": "https://github.com/Nyholm/psr7/tree/1.8.2" + }, + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } + ], + "time": "2024-09-09T07:06:30+00:00" + }, { "name": "nyholm/psr7-server", "version": "1.1.0", @@ -6006,6 +6423,73 @@ }, "time": "2025-09-24T15:06:41+00:00" }, + { + "name": "php-http/client-common", + "version": "2.7.3", + "source": { + "type": "git", + "url": "https://github.com/php-http/client-common.git", + "reference": "dcc6de29c90dd74faab55f71b79d89409c4bf0c1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/client-common/zipball/dcc6de29c90dd74faab55f71b79d89409c4bf0c1", + "reference": "dcc6de29c90dd74faab55f71b79d89409c4bf0c1", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "php-http/httplug": "^2.0", + "php-http/message": "^1.6", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0 || ^2.0", + "symfony/options-resolver": "~4.0.15 || ~4.1.9 || ^4.2.1 || ^5.0 || ^6.0 || ^7.0 || ^8.0", + "symfony/polyfill-php80": "^1.17" + }, + "require-dev": { + "doctrine/instantiator": "^1.1", + "guzzlehttp/psr7": "^1.4", + "nyholm/psr7": "^1.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.33 || ^9.6.7" + }, + "suggest": { + "ext-json": "To detect JSON responses with the ContentTypePlugin", + "ext-libxml": "To detect XML responses with the ContentTypePlugin", + "php-http/cache-plugin": "PSR-6 Cache plugin", + "php-http/logger-plugin": "PSR-3 Logger plugin", + "php-http/stopwatch-plugin": "Symfony Stopwatch plugin" + }, + "type": "library", + "autoload": { + "psr-4": { + "Http\\Client\\Common\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Common HTTP Client implementations and tools for HTTPlug", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "common", + "http", + "httplug" + ], + "support": { + "issues": "https://github.com/php-http/client-common/issues", + "source": "https://github.com/php-http/client-common/tree/2.7.3" + }, + "time": "2025-11-29T19:12:34+00:00" + }, { "name": "php-http/discovery", "version": "1.20.0", @@ -6201,6 +6685,75 @@ }, "time": "2024-09-23T11:39:58+00:00" }, + { + "name": "php-http/message", + "version": "1.16.2", + "source": { + "type": "git", + "url": "https://github.com/php-http/message.git", + "reference": "06dd5e8562f84e641bf929bfe699ee0f5ce8080a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message/zipball/06dd5e8562f84e641bf929bfe699ee0f5ce8080a", + "reference": "06dd5e8562f84e641bf929bfe699ee0f5ce8080a", + "shasum": "" + }, + "require": { + "clue/stream-filter": "^1.5", + "php": "^7.2 || ^8.0", + "psr/http-message": "^1.1 || ^2.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.6", + "ext-zlib": "*", + "guzzlehttp/psr7": "^1.0 || ^2.0", + "laminas/laminas-diactoros": "^2.0 || ^3.0", + "php-http/message-factory": "^1.0.2", + "phpspec/phpspec": "^5.1 || ^6.3 || ^7.1", + "slim/slim": "^3.0" + }, + "suggest": { + "ext-zlib": "Used with compressor/decompressor streams", + "guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories", + "laminas/laminas-diactoros": "Used with Diactoros Factories", + "slim/slim": "Used with Slim Framework PSR-7 implementation" + }, + "type": "library", + "autoload": { + "files": [ + "src/filters.php" + ], + "psr-4": { + "Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "HTTP Message related tools", + "homepage": "http://php-http.org", + "keywords": [ + "http", + "message", + "psr-7" + ], + "support": { + "issues": "https://github.com/php-http/message/issues", + "source": "https://github.com/php-http/message/tree/1.16.2" + }, + "time": "2024-10-02T11:34:13+00:00" + }, { "name": "php-http/promise", "version": "1.3.1", @@ -8056,17 +8609,101 @@ "time": "2026-02-21T21:26:52+00:00" }, { - "name": "spatie/laravel-medialibrary", - "version": "11.23.2", + "name": "spatie/laravel-data", + "version": "4.23.0", "source": { "type": "git", - "url": "https://github.com/spatie/laravel-medialibrary.git", - "reference": "cc1fdc4a9a9007101df610cd4a6733be71db4828" + "url": "https://github.com/spatie/laravel-data.git", + "reference": "230543769c996e407fec2873930626aed7dd0d3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-medialibrary/zipball/cc1fdc4a9a9007101df610cd4a6733be71db4828", - "reference": "cc1fdc4a9a9007101df610cd4a6733be71db4828", + "url": "https://api.github.com/repos/spatie/laravel-data/zipball/230543769c996e407fec2873930626aed7dd0d3b", + "reference": "230543769c996e407fec2873930626aed7dd0d3b", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^10.0|^11.0|^12.0|^13.0", + "php": "^8.1", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/reflection-docblock": "^5.3 || ^6.0", + "phpdocumentor/type-resolver": "^1.7 || ^2.0", + "spatie/laravel-package-tools": "^1.9.0", + "spatie/php-structure-discoverer": "^2.0" + }, + "require-dev": { + "fakerphp/faker": "^1.14", + "friendsofphp/php-cs-fixer": "^3.0", + "inertiajs/inertia-laravel": "^2.0|^3.0", + "livewire/livewire": "^3.0|^4.0", + "mockery/mockery": "^1.6", + "nesbot/carbon": "^2.63|^3.0", + "orchestra/testbench": "^8.37.0|^9.16|^10.9|^11.0", + "pestphp/pest": "^2.36|^3.8|^4.3", + "pestphp/pest-plugin-laravel": "^2.4|^3.0|^4.0", + "pestphp/pest-plugin-livewire": "^2.1|^3.0|^4.0", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "spatie/invade": "^1.0", + "spatie/laravel-typescript-transformer": "^2.5", + "spatie/pest-plugin-snapshots": "^2.1", + "spatie/test-time": "^1.2" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\LaravelData\\LaravelDataServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\LaravelData\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ruben Van Assche", + "email": "ruben@spatie.be", + "role": "Developer" + } + ], + "description": "Create unified resources and data transfer objects", + "homepage": "https://github.com/spatie/laravel-data", + "keywords": [ + "laravel", + "laravel-data", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-data/issues", + "source": "https://github.com/spatie/laravel-data/tree/4.23.0" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2026-05-08T14:41:13+00:00" + }, + { + "name": "spatie/laravel-medialibrary", + "version": "11.23.3", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-medialibrary.git", + "reference": "b578814b8c81a68c8ec9c9005246df5d417fe0f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-medialibrary/zipball/b578814b8c81a68c8ec9c9005246df5d417fe0f9", + "reference": "b578814b8c81a68c8ec9c9005246df5d417fe0f9", "shasum": "" }, "require": { @@ -8151,7 +8788,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-medialibrary/issues", - "source": "https://github.com/spatie/laravel-medialibrary/tree/11.23.2" + "source": "https://github.com/spatie/laravel-medialibrary/tree/11.23.3" }, "funding": [ { @@ -8163,7 +8800,7 @@ "type": "github" } ], - "time": "2026-07-09T13:26:15+00:00" + "time": "2026-07-22T07:06:25+00:00" }, { "name": "spatie/laravel-package-tools", @@ -8738,20 +9375,20 @@ }, { "name": "spomky-labs/cbor-php", - "version": "3.2.3", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/Spomky-Labs/cbor-php.git", - "reference": "dd6eb84e6d92f7b8bd0da56b4b4dd7235aed0c32" + "reference": "013d13da69cf28b1ae501887daceccc850ca1c76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/dd6eb84e6d92f7b8bd0da56b4b4dd7235aed0c32", - "reference": "dd6eb84e6d92f7b8bd0da56b4b4dd7235aed0c32", + "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/013d13da69cf28b1ae501887daceccc850ca1c76", + "reference": "013d13da69cf28b1ae501887daceccc850ca1c76", "shasum": "" }, "require": { - "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17", + "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17|^0.18", "ext-mbstring": "*", "php": ">=8.0" }, @@ -8793,7 +9430,7 @@ ], "support": { "issues": "https://github.com/Spomky-Labs/cbor-php/issues", - "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.2.3" + "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.3.0" }, "funding": [ { @@ -8805,45 +9442,44 @@ "type": "patreon" } ], - "time": "2026-04-01T12:15:20+00:00" + "time": "2026-07-15T18:56:27+00:00" }, { "name": "spomky-labs/pki-framework", - "version": "1.4.2", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/Spomky-Labs/pki-framework.git", - "reference": "aa576cbd07128075bef97ac2f8af9854e67513d8" + "reference": "e0d61661962560c1cedfef02b51b431e720aae78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/aa576cbd07128075bef97ac2f8af9854e67513d8", - "reference": "aa576cbd07128075bef97ac2f8af9854e67513d8", + "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/e0d61661962560c1cedfef02b51b431e720aae78", + "reference": "e0d61661962560c1cedfef02b51b431e720aae78", "shasum": "" }, "require": { - "brick/math": "^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17", + "brick/math": "^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17|^0.18", "ext-mbstring": "*", - "php": ">=8.1", - "psr/clock": "^1.0" + "php": ">=8.1" }, "require-dev": { "ekino/phpstan-banned-code": "^1.0|^2.0|^3.0", "ext-gmp": "*", "ext-openssl": "*", - "infection/infection": "^0.28|^0.29|^0.31|^0.32", + "infection/infection": "^0.28|^0.29|^0.31", "php-parallel-lint/php-parallel-lint": "^1.3", "phpstan/extension-installer": "^1.3|^2.0", "phpstan/phpstan": "^1.8|^2.0", "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", "phpstan/phpstan-phpunit": "^1.1|^2.0", "phpstan/phpstan-strict-rules": "^1.3|^2.0", - "phpunit/phpunit": "^10.1|^11.0|^12.0|^13.0", + "phpunit/phpunit": "^10.1|^11.0|^12.0", "rector/rector": "^1.0|^2.0", "roave/security-advisories": "dev-latest", "symfony/string": "^6.4|^7.0|^8.0", "symfony/var-dumper": "^6.4|^7.0|^8.0", - "symplify/easy-coding-standard": "^12.0|^13.0" + "symplify/easy-coding-standard": "^12.0 || ^13.0" }, "suggest": { "ext-bcmath": "For better performance (or GMP)", @@ -8903,7 +9539,7 @@ ], "support": { "issues": "https://github.com/Spomky-Labs/pki-framework/issues", - "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.4.2" + "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.5.0" }, "funding": [ { @@ -8915,7 +9551,7 @@ "type": "patreon" } ], - "time": "2026-03-23T22:56:56+00:00" + "time": "2026-07-16T10:28:45+00:00" }, { "name": "symfony/clock", @@ -8996,16 +9632,16 @@ }, { "name": "symfony/console", - "version": "v7.4.14", + "version": "v7.4.15", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "92f58bc4bf97a92ed1b9f367f0cd44f20bde0e87" + "reference": "088ec6fe0ef6819cbc301174093b6bfa4ad26930" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/92f58bc4bf97a92ed1b9f367f0cd44f20bde0e87", - "reference": "92f58bc4bf97a92ed1b9f367f0cd44f20bde0e87", + "url": "https://api.github.com/repos/symfony/console/zipball/088ec6fe0ef6819cbc301174093b6bfa4ad26930", + "reference": "088ec6fe0ef6819cbc301174093b6bfa4ad26930", "shasum": "" }, "require": { @@ -9070,7 +9706,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.14" + "source": "https://github.com/symfony/console/tree/v7.4.15" }, "funding": [ { @@ -9090,7 +9726,7 @@ "type": "tidelift" } ], - "time": "2026-06-16T11:50:14+00:00" + "time": "2026-07-27T13:51:00+00:00" }, { "name": "symfony/css-selector", @@ -9304,16 +9940,16 @@ }, { "name": "symfony/error-handler", - "version": "v7.4.14", + "version": "v7.4.15", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "4e1a093b481f323e6e326451f9760c3868430673" + "reference": "d49f6a19f326db41ae7103bdc38e3eb35a791261" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/4e1a093b481f323e6e326451f9760c3868430673", - "reference": "4e1a093b481f323e6e326451f9760c3868430673", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/d49f6a19f326db41ae7103bdc38e3eb35a791261", + "reference": "d49f6a19f326db41ae7103bdc38e3eb35a791261", "shasum": "" }, "require": { @@ -9362,7 +9998,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.4.14" + "source": "https://github.com/symfony/error-handler/tree/v7.4.15" }, "funding": [ { @@ -9382,20 +10018,20 @@ "type": "tidelift" } ], - "time": "2026-06-05T06:22:21+00:00" + "time": "2026-07-21T15:13:06+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v8.1.1", + "version": "v8.1.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "abd6c11dc468725d1627302ad10f6cd486e9e3d0" + "reference": "c14c05a9e6da7f5e375e6efc28952c7e7dbddffb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/abd6c11dc468725d1627302ad10f6cd486e9e3d0", - "reference": "abd6c11dc468725d1627302ad10f6cd486e9e3d0", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c14c05a9e6da7f5e375e6efc28952c7e7dbddffb", + "reference": "c14c05a9e6da7f5e375e6efc28952c7e7dbddffb", "shasum": "" }, "require": { @@ -9448,7 +10084,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/v8.1.1" + "source": "https://github.com/symfony/event-dispatcher/tree/v8.1.2" }, "funding": [ { @@ -9468,7 +10104,7 @@ "type": "tidelift" } ], - "time": "2026-06-09T12:28:30+00:00" + "time": "2026-07-22T15:42:13+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -9694,16 +10330,16 @@ }, { "name": "symfony/http-foundation", - "version": "v7.4.14", + "version": "v7.4.15", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "06db5ae1552177bf8572f8908839f12e3c06aed3" + "reference": "1f898ee8188adda9417fb52cf8425a8342c254e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/06db5ae1552177bf8572f8908839f12e3c06aed3", - "reference": "06db5ae1552177bf8572f8908839f12e3c06aed3", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/1f898ee8188adda9417fb52cf8425a8342c254e7", + "reference": "1f898ee8188adda9417fb52cf8425a8342c254e7", "shasum": "" }, "require": { @@ -9752,7 +10388,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.4.14" + "source": "https://github.com/symfony/http-foundation/tree/v7.4.15" }, "funding": [ { @@ -9772,20 +10408,20 @@ "type": "tidelift" } ], - "time": "2026-06-11T07:31:44+00:00" + "time": "2026-07-29T07:12:33+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.4.14", + "version": "v7.4.15", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "e99af79b1e776646eda0e1c23b7b45c184ff99be" + "reference": "403275d94f94d5626c3288c599b3b48093ba24f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/e99af79b1e776646eda0e1c23b7b45c184ff99be", - "reference": "e99af79b1e776646eda0e1c23b7b45c184ff99be", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/403275d94f94d5626c3288c599b3b48093ba24f7", + "reference": "403275d94f94d5626c3288c599b3b48093ba24f7", "shasum": "" }, "require": { @@ -9843,7 +10479,7 @@ "symfony/validator": "^6.4|^7.0|^8.0", "symfony/var-dumper": "^6.4|^7.0|^8.0", "symfony/var-exporter": "^6.4|^7.0|^8.0", - "twig/twig": "^3.12" + "twig/twig": "^3.12|^4.0" }, "type": "library", "autoload": { @@ -9871,7 +10507,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.4.14" + "source": "https://github.com/symfony/http-kernel/tree/v7.4.15" }, "funding": [ { @@ -9891,20 +10527,20 @@ "type": "tidelift" } ], - "time": "2026-06-27T09:14:35+00:00" + "time": "2026-07-29T11:40:42+00:00" }, { "name": "symfony/mailer", - "version": "v7.4.14", + "version": "v7.4.15", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "f88ce03ae73e3edb5c176ce1f337709996e88495" + "reference": "68c1f27c97edd0222eb8d440a6c8c4da5354ab46" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/f88ce03ae73e3edb5c176ce1f337709996e88495", - "reference": "f88ce03ae73e3edb5c176ce1f337709996e88495", + "url": "https://api.github.com/repos/symfony/mailer/zipball/68c1f27c97edd0222eb8d440a6c8c4da5354ab46", + "reference": "68c1f27c97edd0222eb8d440a6c8c4da5354ab46", "shasum": "" }, "require": { @@ -9955,7 +10591,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.4.14" + "source": "https://github.com/symfony/mailer/tree/v7.4.15" }, "funding": [ { @@ -9975,20 +10611,20 @@ "type": "tidelift" } ], - "time": "2026-06-13T08:51:35+00:00" + "time": "2026-07-28T07:33:02+00:00" }, { "name": "symfony/mime", - "version": "v7.4.13", + "version": "v7.4.15", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "a845722765c4f6b2ce88beaf4f4479975b186770" + "reference": "0c1daf58bc931628df0bea26840d1fc8b9a3d34b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/a845722765c4f6b2ce88beaf4f4479975b186770", - "reference": "a845722765c4f6b2ce88beaf4f4479975b186770", + "url": "https://api.github.com/repos/symfony/mime/zipball/0c1daf58bc931628df0bea26840d1fc8b9a3d34b", + "reference": "0c1daf58bc931628df0bea26840d1fc8b9a3d34b", "shasum": "" }, "require": { @@ -10044,7 +10680,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.4.13" + "source": "https://github.com/symfony/mime/tree/v7.4.15" }, "funding": [ { @@ -10064,7 +10700,78 @@ "type": "tidelift" } ], - "time": "2026-05-23T16:22:37+00:00" + "time": "2026-07-29T07:59:49+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v8.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "88f9c561f678a02d54b897014049fa839e33ff82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/88f9c561f678a02d54b897014049fa839e33ff82", + "reference": "88f9c561f678a02d54b897014049fa839e33ff82", + "shasum": "" + }, + "require": { + "php": ">=8.4.1", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v8.1.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "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": "2026-05-29T05:06:50+00:00" }, { "name": "symfony/polyfill-ctype", @@ -10151,16 +10858,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.38.1", + "version": "v1.41.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "e9247d281d694a5120554d9afaf54e070e88a603" + "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/e9247d281d694a5120554d9afaf54e070e88a603", - "reference": "e9247d281d694a5120554d9afaf54e070e88a603", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", + "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", "shasum": "" }, "require": { @@ -10209,7 +10916,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.38.1" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.41.0" }, "funding": [ { @@ -10229,7 +10936,7 @@ "type": "tidelift" } ], - "time": "2026-05-26T05:58:03+00:00" + "time": "2026-07-28T08:25:59+00:00" }, { "name": "symfony/polyfill-intl-idn", @@ -10572,6 +11279,86 @@ ], "time": "2026-04-10T16:19:22+00:00" }, + { + "name": "symfony/polyfill-php81", + "version": "v1.38.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "6bfb9c766cacffbc8e118cb87217d08ed84e5cd7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/6bfb9c766cacffbc8e118cb87217d08ed84e5cd7", + "reference": "6bfb9c766cacffbc8e118cb87217d08ed84e5cd7", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.38.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "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": "2026-05-26T12:45:58+00:00" + }, { "name": "symfony/polyfill-php82", "version": "v1.38.1", @@ -10654,16 +11441,16 @@ }, { "name": "symfony/polyfill-php83", - "version": "v1.38.2", + "version": "v1.41.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "796a26abb75ce49f3a84433cd81bf1009d73d5f8" + "reference": "5ea99087fb99c273a9b9236ed4c31e78b16103c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/796a26abb75ce49f3a84433cd81bf1009d73d5f8", - "reference": "796a26abb75ce49f3a84433cd81bf1009d73d5f8", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/5ea99087fb99c273a9b9236ed4c31e78b16103c6", + "reference": "5ea99087fb99c273a9b9236ed4c31e78b16103c6", "shasum": "" }, "require": { @@ -10710,7 +11497,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.38.2" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.41.0" }, "funding": [ { @@ -10730,7 +11517,7 @@ "type": "tidelift" } ], - "time": "2026-05-27T06:51:48+00:00" + "time": "2026-07-01T12:47:55+00:00" }, { "name": "symfony/polyfill-php84", @@ -10814,16 +11601,16 @@ }, { "name": "symfony/polyfill-php85", - "version": "v1.38.1", + "version": "v1.41.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php85.git", - "reference": "ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1" + "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1", - "reference": "ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/255fab485aaa1006ed411040c42aecd7b5302d7a", + "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a", "shasum": "" }, "require": { @@ -10870,7 +11657,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php85/tree/v1.38.1" + "source": "https://github.com/symfony/polyfill-php85/tree/v1.41.0" }, "funding": [ { @@ -10890,7 +11677,7 @@ "type": "tidelift" } ], - "time": "2026-05-26T02:25:22+00:00" + "time": "2026-07-01T12:47:55+00:00" }, { "name": "symfony/polyfill-uuid", @@ -11123,16 +11910,16 @@ }, { "name": "symfony/property-info", - "version": "v8.1.0", + "version": "v8.1.2", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "4721e8c56d0cd2378e0ef9a9899f810008b859f7" + "reference": "289ef0d4f2b9bd5245ac2604564289a8673837b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/4721e8c56d0cd2378e0ef9a9899f810008b859f7", - "reference": "4721e8c56d0cd2378e0ef9a9899f810008b859f7", + "url": "https://api.github.com/repos/symfony/property-info/zipball/289ef0d4f2b9bd5245ac2604564289a8673837b9", + "reference": "289ef0d4f2b9bd5245ac2604564289a8673837b9", "shasum": "" }, "require": { @@ -11185,7 +11972,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v8.1.0" + "source": "https://github.com/symfony/property-info/tree/v8.1.2" }, "funding": [ { @@ -11205,20 +11992,20 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-07-22T15:42:13+00:00" }, { "name": "symfony/routing", - "version": "v7.4.13", + "version": "v7.4.15", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "3a162171bb008e5e0f15dce6581373a4c0e8390d" + "reference": "80c0a93d3f8e7499f716204a1fb38ead942a7a2b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/3a162171bb008e5e0f15dce6581373a4c0e8390d", - "reference": "3a162171bb008e5e0f15dce6581373a4c0e8390d", + "url": "https://api.github.com/repos/symfony/routing/zipball/80c0a93d3f8e7499f716204a1fb38ead942a7a2b", + "reference": "80c0a93d3f8e7499f716204a1fb38ead942a7a2b", "shasum": "" }, "require": { @@ -11270,7 +12057,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.4.13" + "source": "https://github.com/symfony/routing/tree/v7.4.15" }, "funding": [ { @@ -11290,20 +12077,20 @@ "type": "tidelift" } ], - "time": "2026-05-24T11:20:33+00:00" + "time": "2026-07-21T15:13:06+00:00" }, { "name": "symfony/serializer", - "version": "v8.1.1", + "version": "v8.1.3", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "f911b744bc24658f435ea30439cfe536f0173a3a" + "reference": "6bd396438ba6c36800224e2beaf3f8f2d7439343" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/f911b744bc24658f435ea30439cfe536f0173a3a", - "reference": "f911b744bc24658f435ea30439cfe536f0173a3a", + "url": "https://api.github.com/repos/symfony/serializer/zipball/6bd396438ba6c36800224e2beaf3f8f2d7439343", + "reference": "6bd396438ba6c36800224e2beaf3f8f2d7439343", "shasum": "" }, "require": { @@ -11315,7 +12102,7 @@ "phpdocumentor/reflection-docblock": "<5.2|>=7", "phpdocumentor/type-resolver": "<1.5.1", "symfony/property-access": "<8.1", - "symfony/property-info": "<7.4", + "symfony/property-info": "<7.4.15", "symfony/type-info": "<7.4" }, "require-dev": { @@ -11334,7 +12121,7 @@ "symfony/messenger": "^7.4|^8.0", "symfony/mime": "^7.4|^8.0", "symfony/property-access": "^8.1", - "symfony/property-info": "^7.4|^8.0", + "symfony/property-info": "^7.4.15|~8.0.15|^8.1.2", "symfony/translation-contracts": "^2.5|^3", "symfony/type-info": "^7.4|^8.0", "symfony/uid": "^7.4|^8.0", @@ -11369,7 +12156,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v8.1.1" + "source": "https://github.com/symfony/serializer/tree/v8.1.3" }, "funding": [ { @@ -11389,7 +12176,7 @@ "type": "tidelift" } ], - "time": "2026-06-27T09:05:56+00:00" + "time": "2026-07-29T14:11:26+00:00" }, { "name": "symfony/service-contracts", @@ -11480,16 +12267,16 @@ }, { "name": "symfony/string", - "version": "v8.1.0", + "version": "v8.1.2", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "afd5944f4005862d961efb85c8bbd5c523c4e3c9" + "reference": "286a76b7255e5cc4bf0101a0bc5388ecf1c38ccc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/afd5944f4005862d961efb85c8bbd5c523c4e3c9", - "reference": "afd5944f4005862d961efb85c8bbd5c523c4e3c9", + "url": "https://api.github.com/repos/symfony/string/zipball/286a76b7255e5cc4bf0101a0bc5388ecf1c38ccc", + "reference": "286a76b7255e5cc4bf0101a0bc5388ecf1c38ccc", "shasum": "" }, "require": { @@ -11546,7 +12333,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v8.1.0" + "source": "https://github.com/symfony/string/tree/v8.1.2" }, "funding": [ { @@ -11566,7 +12353,7 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-07-28T07:35:25+00:00" }, { "name": "symfony/translation", @@ -11905,16 +12692,16 @@ }, { "name": "symfony/var-dumper", - "version": "v7.4.14", + "version": "v7.4.15", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "9a3a56a4a1e65a5cb4f8d13801fe8ab0a170e358" + "reference": "04ba4add636a95ff437af3a5a9499bb1d6c6d4bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9a3a56a4a1e65a5cb4f8d13801fe8ab0a170e358", - "reference": "9a3a56a4a1e65a5cb4f8d13801fe8ab0a170e358", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/04ba4add636a95ff437af3a5a9499bb1d6c6d4bd", + "reference": "04ba4add636a95ff437af3a5a9499bb1d6c6d4bd", "shasum": "" }, "require": { @@ -11930,7 +12717,7 @@ "symfony/http-kernel": "^6.4|^7.0|^8.0", "symfony/process": "^6.4|^7.0|^8.0", "symfony/uid": "^6.4|^7.0|^8.0", - "twig/twig": "^3.12" + "twig/twig": "^3.12|^4.0" }, "bin": [ "Resources/bin/var-dump-server" @@ -11968,7 +12755,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.4.14" + "source": "https://github.com/symfony/var-dumper/tree/v7.4.15" }, "funding": [ { @@ -11988,20 +12775,20 @@ "type": "tidelift" } ], - "time": "2026-06-08T20:24:16+00:00" + "time": "2026-07-21T15:13:06+00:00" }, { "name": "symfony/yaml", - "version": "v7.4.14", + "version": "v7.4.15", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "f8f328665ace2370d1e10645b807ba1646dc7dcc" + "reference": "e101850ded5d2c0d44bf32abb8996404afec2dec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/f8f328665ace2370d1e10645b807ba1646dc7dcc", - "reference": "f8f328665ace2370d1e10645b807ba1646dc7dcc", + "url": "https://api.github.com/repos/symfony/yaml/zipball/e101850ded5d2c0d44bf32abb8996404afec2dec", + "reference": "e101850ded5d2c0d44bf32abb8996404afec2dec", "shasum": "" }, "require": { @@ -12044,7 +12831,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.4.14" + "source": "https://github.com/symfony/yaml/tree/v7.4.15" }, "funding": [ { @@ -12064,7 +12851,7 @@ "type": "tidelift" } ], - "time": "2026-06-08T20:24:16+00:00" + "time": "2026-07-21T15:13:06+00:00" }, { "name": "tbachert/spi", @@ -12120,16 +12907,16 @@ }, { "name": "technikermathe/blade-lucide-icons", - "version": "v3.159.0", + "version": "v3.163.0", "source": { "type": "git", "url": "https://github.com/PascaleBeier/blade-lucide-icons.git", - "reference": "b8dec6812bc09ebad05464cc176df4f949e146c5" + "reference": "c0adc14018be273274aa027717a5e0eadd999c31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PascaleBeier/blade-lucide-icons/zipball/b8dec6812bc09ebad05464cc176df4f949e146c5", - "reference": "b8dec6812bc09ebad05464cc176df4f949e146c5", + "url": "https://api.github.com/repos/PascaleBeier/blade-lucide-icons/zipball/c0adc14018be273274aa027717a5e0eadd999c31", + "reference": "c0adc14018be273274aa027717a5e0eadd999c31", "shasum": "" }, "require": { @@ -12179,9 +12966,9 @@ ], "support": { "issues": "https://github.com/PascaleBeier/blade-lucide-icons/issues", - "source": "https://github.com/PascaleBeier/blade-lucide-icons/tree/v3.159.0" + "source": "https://github.com/PascaleBeier/blade-lucide-icons/tree/v3.163.0" }, - "time": "2026-07-10T01:55:13+00:00" + "time": "2026-07-31T01:51:31+00:00" }, { "name": "thecodingmachine/safe", @@ -12381,6 +13168,75 @@ }, "time": "2025-12-02T11:56:42+00:00" }, + { + "name": "typesense/typesense-php", + "version": "v4.9.3", + "source": { + "type": "git", + "url": "https://github.com/typesense/typesense-php.git", + "reference": "50fc2089ff4829c8e0e11d8c674e9da085b49998" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/typesense/typesense-php/zipball/50fc2089ff4829c8e0e11d8c674e9da085b49998", + "reference": "50fc2089ff4829c8e0e11d8c674e9da085b49998", + "shasum": "" + }, + "require": { + "ext-json": "*", + "monolog/monolog": "^2.1 || ^3.0 || ^3.3", + "nyholm/psr7": "^1.3", + "php": ">=7.4", + "php-http/client-common": "^1.0 || ^2.3", + "php-http/discovery": "^1.0", + "php-http/httplug": "^1.0 || ^2.2", + "psr/http-client-implementation": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "require-dev": { + "squizlabs/php_codesniffer": "3.*", + "symfony/http-client": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Typesense\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Typesense", + "email": "contact@typesense.org", + "homepage": "https://typesense.org", + "role": "Developer" + }, + { + "name": "Abdullah Al-Faqeir", + "email": "abdullah@devloops.net", + "homepage": "https://www.devloops.net", + "role": "Developer" + } + ], + "description": "PHP client for Typesense Search Server: https://github.com/typesense/typesense", + "homepage": "https://github.com/typesense/typesense-php", + "support": { + "docs": "https://typesense.org/api", + "issues": "https://github.com/typesense/typesense-php/issues", + "source": "https://github.com/typesense/typesense-php" + }, + "funding": [ + { + "url": "https://github.com/typesense", + "type": "github" + } + ], + "time": "2024-04-29T15:34:34+00:00" + }, { "name": "vlucas/phpdotenv", "version": "v5.6.4", @@ -12541,20 +13397,20 @@ }, { "name": "web-auth/cose-lib", - "version": "4.5.2", + "version": "4.6.0", "source": { "type": "git", "url": "https://github.com/web-auth/cose-lib.git", - "reference": "5b38660f90070a8e45f3dbc9528ade3b608dd77d" + "reference": "3afe04df137baf97c5c3e28c5ee6f05536405148" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/5b38660f90070a8e45f3dbc9528ade3b608dd77d", - "reference": "5b38660f90070a8e45f3dbc9528ade3b608dd77d", + "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/3afe04df137baf97c5c3e28c5ee6f05536405148", + "reference": "3afe04df137baf97c5c3e28c5ee6f05536405148", "shasum": "" }, "require": { - "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17", + "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17|^0.18", "ext-json": "*", "ext-openssl": "*", "php": ">=8.1", @@ -12596,7 +13452,7 @@ ], "support": { "issues": "https://github.com/web-auth/cose-lib/issues", - "source": "https://github.com/web-auth/cose-lib/tree/4.5.2" + "source": "https://github.com/web-auth/cose-lib/tree/4.6.0" }, "funding": [ { @@ -12608,7 +13464,7 @@ "type": "patreon" } ], - "time": "2026-05-03T09:49:50+00:00" + "time": "2026-07-16T10:19:49+00:00" }, { "name": "web-auth/webauthn-lib", diff --git a/config/app.php b/config/app.php index 423eed5..fffad52 100644 --- a/config/app.php +++ b/config/app.php @@ -78,12 +78,25 @@ | */ - 'locale' => env('APP_LOCALE', 'en'), + 'locale' => env('APP_LOCALE', 'el'), 'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'), 'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'), + /* + |-------------------------------------------------------------------------- + | Available Locales + |-------------------------------------------------------------------------- + | + | The locales the site is served in, and the ones allowed as the + | {locale} route segment (see routes/web.php and SetLocale middleware). + | Greek is the primary/default market, English is secondary. + | + */ + + 'available_locales' => ['el', 'en'], + /* |-------------------------------------------------------------------------- | Encryption Key diff --git a/lang/el/general.php b/lang/el/general.php new file mode 100644 index 0000000..cf2401c --- /dev/null +++ b/lang/el/general.php @@ -0,0 +1,18 @@ + [ + 'products' => 'Προϊόντα', + 'contact' => 'Επικοινωνία', + ], + + 'product' => [ + 'description' => 'Περιγραφή', + 'reviews' => 'Αξιολογήσεις', + ], + + // Laravel pluralization: {0} zero|{1} one|[2,*] many. :count is replaced automatically. + 'customer_reviews' => '{0} Καμία αξιολόγηση πελάτη|{1} :count αξιολόγηση πελάτη|[2,*] :count αξιολογήσεις πελατών', + +]; diff --git a/lang/en/general.php b/lang/en/general.php new file mode 100644 index 0000000..e1538e7 --- /dev/null +++ b/lang/en/general.php @@ -0,0 +1,18 @@ + [ + 'products' => 'Products', + 'contact' => 'Contact', + ], + + 'product' => [ + 'description' => 'Description', + 'reviews' => 'Reviews', + ], + + // Laravel pluralization: {0} zero|{1} one|[2,*] many. :count is replaced automatically. + 'customer_reviews' => '{0} No customer reviews|{1} :count customer review|[2,*] :count customer reviews', + +]; diff --git a/resources/css/app.css b/resources/css/app.css index 91b7f37..8e872fa 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -47,6 +47,15 @@ @keyframes back-to-top-spin { } } +@keyframes text-flicker-in { + 0%, 60% { + opacity: 0; + } + 70%, 100% { + opacity: 1; + } +} + /* ═══════════════════════════════════════════════════════════════════ COMPONENTS ═══════════════════════════════════════════════════════════════════ */ @@ -107,6 +116,12 @@ @layer components { color: theme(colors.neutral.200); } + /* ── Hero star — same burst shape/spin as back-to-top, always on ─ */ + .hero-star { + transform-origin: center; + animation: back-to-top-spin 7s infinite linear; + } + /* ── Back to top ──────────────────────────────────────────────── */ .back-to-top { opacity: 0; @@ -286,4 +301,26 @@ @layer components { .btn-primary:hover::after { transform: translate(0, 0); } + + /* ── Text flicker — word switches from regular to italic/bold once + its .is-visible ancestor appears; add data-text="" ── */ + .text-flicker { + position: relative; + display: inline-block; + } + + .text-flicker::after { + content: attr(data-text); + position: absolute; + inset: 0; + font-weight: 700; + font-style: italic; + font-weight: extra-bold; + opacity: 0; + pointer-events: none; + } + + .is-visible .text-flicker::after { + animation: text-flicker-in 0.7s ease 3 forwards; + } } diff --git a/resources/js/stimulus/appear-controller.js b/resources/js/stimulus/appear-controller.js new file mode 100644 index 0000000..f9ee0b7 --- /dev/null +++ b/resources/js/stimulus/appear-controller.js @@ -0,0 +1,20 @@ +import { Controller } from '@hotwired/stimulus' + +export default class extends Controller { + static classes = ['visible'] + + connect() { + this.observer = new IntersectionObserver(([entry]) => { + if (!entry.isIntersecting) return + + this.element.classList.add(this.visibleClass) + this.observer.disconnect() + }, { threshold: 0.3 }) + + this.observer.observe(this.element) + } + + disconnect() { + this.observer?.disconnect() + } +} diff --git a/resources/js/stimulus/carousel-controller.js b/resources/js/stimulus/carousel-controller.js new file mode 100644 index 0000000..45188f3 --- /dev/null +++ b/resources/js/stimulus/carousel-controller.js @@ -0,0 +1,28 @@ +import { Controller } from '@hotwired/stimulus' + +export default class extends Controller { + static targets = ['slide'] + static values = { index: { type: Number, default: 0 } } + + connect() { + this.showSlide() + } + + next() { + this.indexValue = (this.indexValue + 1) % this.slideTargets.length + } + + prev() { + this.indexValue = (this.indexValue - 1 + this.slideTargets.length) % this.slideTargets.length + } + + indexValueChanged() { + this.showSlide() + } + + showSlide() { + this.slideTargets.forEach((slide, i) => { + slide.classList.toggle('hidden', i !== this.indexValue) + }) + } +} diff --git a/resources/js/stimulus/index.js b/resources/js/stimulus/index.js index 3d58270..26aff03 100644 --- a/resources/js/stimulus/index.js +++ b/resources/js/stimulus/index.js @@ -3,7 +3,9 @@ // import HelloController from './controllers/hello_controller'; // application.register('hello', HelloController); +import AppearController from './appear-controller' import BackToTopController from './back-to-top-controller' +import CarouselController from './carousel-controller' import ProductFormController from './product-form-controller' import ProductGalleryController from './product-gallery-controller' import QuantityController from './quantity-controller' @@ -11,7 +13,9 @@ import StarRatingController from './star-rating-controller' import TabsController from './tabs-controller' export function registerControllers(application) { + application.register('appear', AppearController) application.register('back-to-top', BackToTopController) + application.register('carousel', CarouselController) application.register('product-form', ProductFormController) application.register('product-gallery', ProductGalleryController) application.register('quantity', QuantityController) diff --git a/resources/views/__preview_newsletter_split.blade.php b/resources/views/__preview_newsletter_split.blade.php new file mode 100644 index 0000000..a16c87e --- /dev/null +++ b/resources/views/__preview_newsletter_split.blade.php @@ -0,0 +1,7 @@ +@extends('layouts.app') + +@section('content') +
+ +
+@endsection diff --git a/resources/views/components/header.blade.php b/resources/views/components/header.blade.php index a8ef7e7..65bba13 100644 --- a/resources/views/components/header.blade.php +++ b/resources/views/components/header.blade.php @@ -1,9 +1,9 @@ -
+
{{-- Logo --}} - - {{ config('app.name') }} + + {{ config('app.name') }} {{-- Primary nav --}} @@ -11,8 +11,8 @@ {{-- Products (CSS-only hover dropdown) --}} {{-- Contact --}} - Contact + {{ __('general.nav.contact') }} {{-- Right side actions --}}
+ {{-- Language switcher --}} + @isset($altLocale) + + {{ $altLocale }} + + @endisset + {{-- Cart --}} - + diff --git a/resources/views/components/newsletter-split.blade.php b/resources/views/components/newsletter-split.blade.php new file mode 100644 index 0000000..59fac22 --- /dev/null +++ b/resources/views/components/newsletter-split.blade.php @@ -0,0 +1,62 @@ +@props([ + 'image' => null, +]) + +
+
+
+

+ Γράψου + στο + newsletter + μας +

+ +

+ Γίνε μέλος της λίστας μας και κέρδισε 5% έκπτωση στην πρώτη σου παραγγελία, μαζί με αποκλειστικές προσφορές και νέα. +

+ +
+ @csrf +
+ + +
+ + + Επιθυμώ διακαώς 🔥 να εγγραφώ στη λίστα αποστολής ενημερωτικού υλικού + +
+
+ +
+ @if($image) + + @else +
+ Χωρίς εικόνα +
+ @endif +
+
+
diff --git a/resources/views/components/reviews-stars.blade.php b/resources/views/components/reviews-stars.blade.php index b257219..3216f07 100644 --- a/resources/views/components/reviews-stars.blade.php +++ b/resources/views/components/reviews-stars.blade.php @@ -29,7 +29,7 @@ class="flex items-center gap-1.5 text-brand" @if ($showCount && $count > 0) - ({{ $count }} customer {{ $count === 1 ? 'review' : 'reviews' }}) + ({{ trans_choice('general.customer_reviews', $count, ['count' => $count]) }}) @endif diff --git a/resources/views/components/ui/color-swatch.blade.php b/resources/views/components/ui/color-swatch.blade.php index 1ddfd67..c64a5bd 100644 --- a/resources/views/components/ui/color-swatch.blade.php +++ b/resources/views/components/ui/color-swatch.blade.php @@ -1,33 +1,5 @@ @props(['variants', 'option' => null]) -@php -$colorMap = [ - 'light blue' => 'rgb(0, 189, 255)', - 'terracotta' => 'rgb(217, 104, 73)', - 'red-black gradient' => 'rgb(198, 68, 68)', - 'green-purple gradient'=> 'rgb(5, 170, 61)', - 'metallic blue' => 'rgb(53, 121, 151)', - 'copper' => 'rgb(242, 155, 55)', - 'purple' => 'rgb(165, 77, 207)', - 'red' => 'rgb(255, 0, 0)', - 'black' => 'rgb(0, 0, 0)', - 'gray' => 'rgb(128, 128, 128)', - 'rainbow' => 'rgb(97, 195, 231)', - 'white' => 'rgb(255, 255, 255)', - 'gold' => 'rgb(212, 154, 6)', - 'brown' => 'rgb(154, 86, 48)', - 'blue' => 'rgb(0, 91, 211)', - 'orange' => 'rgb(255, 138, 0)', - 'pink' => 'rgb(255, 192, 203)', - 'yellow' => 'rgb(255, 229, 0)', - 'green' => 'rgb(5, 170, 61)', - 'blue-purple gradient' => 'rgb(159, 113, 247)', - 'silver' => 'rgb(211, 211, 211)', - 'sparkly black' => 'rgb(5, 5, 5)', - 'plum' => 'rgb(198, 34, 159)', -]; -@endphp -
@if($option)

@@ -42,11 +14,9 @@ class="flex flex-wrap gap-2" > @foreach($variants as $variant) @php - $value = $variant->values->first(); - $label = $value?->translate('name') ?? ''; - $labelEn = mb_strtolower($value?->translate('name', 'en') ?? ''); - $labelEl = mb_strtolower($value?->translate('name', 'el') ?? ''); - $bg = $colorMap[$labelEl] ?? $colorMap[$labelEn] ?? '#cccccc'; + $value = $variant->values->first(); + $label = $value?->translate('name') ?? ''; + $bg = $value?->meta['hex'] ?? '#cccccc'; @endphp + +

+ + + @else +

Δεν βρέθηκαν προϊόντα.

+ @endif +
+
+ + {{-- Info / trivia --}} +
+
+ Χωρίς εικόνα +
+ +
+

+ Gaming φιγούρες, κρανία, κλειδοθήκες, dark humor και ό,τι πιο τρελό σου περνάει απ' το μυαλό — όλα σχεδιασμένα και τυπωμένα σε 3D, ένα προς ένα, εδώ στην Ελλάδα. +

+

+ Στρώση-στρώση,
+ 0.1mm τη φορά +

+

+ Τόσο λεπτή είναι κάθε στρώση υλικού σε ένα 3D εκτυπωμένο κομμάτι — πιο λεπτή κι από τρίχα. Δεν κρατάμε αποθέματα: κάθε παραγγελία τυπώνεται ειδικά για σένα, στο χρώμα και στο μέγεθος που θες. +

+
+ Δες τα προϊόντα +
+
+
+ +
+ + {{-- Classics --}} +
+
+

Τα αγαπημένα μας

+ Δες όλα +
+ +
+ + +
+ @forelse($classicsProducts->chunk(4) as $page) +
+ @foreach($page as $product) + + @endforeach +
+ @empty +

Δεν βρέθηκαν προϊόντα.

+ @endforelse +
+ + +
+
+ +
+ +
+@endsection diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index d3c2607..d0aae3d 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -1,5 +1,5 @@ - + @@ -15,6 +15,13 @@ @yield('title', config('app.name')) + {{-- Reciprocal hreflang: self-reference + the alternate locale + x-default --}} + @isset($currentLocale) + + + + @endisset + @stack('seo') @vite(['resources/css/app.css', 'resources/js/app.js']) @@ -24,7 +31,7 @@ -
+
@yield('content')
diff --git a/resources/views/product/show.blade.php b/resources/views/product/show.blade.php index 5179eee..1eec3e5 100644 --- a/resources/views/product/show.blade.php +++ b/resources/views/product/show.blade.php @@ -4,7 +4,7 @@ @section('description', $product->translateAttribute('description')) @section('content') -
+
@php $collection = $product->collections->first(); @endphp @@ -182,9 +182,9 @@ class="absolute bottom-6 right-8 text-white text-sm"
diff --git a/resources/views/product/show2.blade.php b/resources/views/product/show2.blade.php index 5179eee..323280e 100644 --- a/resources/views/product/show2.blade.php +++ b/resources/views/product/show2.blade.php @@ -4,7 +4,7 @@ @section('description', $product->translateAttribute('description')) @section('content') -
+
@php $collection = $product->collections->first(); @endphp diff --git a/resources/views/welcome.blade.php b/resources/views/welcome.blade.php deleted file mode 100644 index b7355d7..0000000 --- a/resources/views/welcome.blade.php +++ /dev/null @@ -1,277 +0,0 @@ - - - - - - - {{ config('app.name', 'Laravel') }} - - - - - - - @if (file_exists(public_path('build/manifest.json')) || file_exists(public_path('hot'))) - @vite(['resources/css/app.css', 'resources/js/app.js']) - @else - - @endif - - -
- @if (Route::has('login')) - - @endif -
-
-
-
-

Let's get started

-

Laravel has an incredibly rich ecosystem.
We suggest starting with the following.

- - -
-
- {{-- Laravel Logo --}} - - - - - - - - - - - {{-- Light Mode 12 SVG --}} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {{-- Dark Mode 12 SVG --}} - -
-
-
-
- - @if (Route::has('login')) - - @endif - - diff --git a/routes/web.php b/routes/web.php index 1a076ed..bb1ff74 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,12 +1,23 @@ name( - "product.show", -); +Route::prefix('{locale}') + ->where(['locale' => implode('|', config('app.available_locales'))]) + ->middleware('setlocale') + ->group(function () { + Route::get('/', [HomeController::class, 'index'])->name('home'); + + Route::get('/products/{product}', [ProductController::class, 'show'])->name( + 'product.show', + ); + + Route::get('/__preview/newsletter-split', function () { + return view('__preview_newsletter_split'); + }); + });