diff --git a/app/Http/Controllers/Club/ShopController.php b/app/Http/Controllers/Club/ShopController.php
index b733c284..fa957099 100644
--- a/app/Http/Controllers/Club/ShopController.php
+++ b/app/Http/Controllers/Club/ShopController.php
@@ -2,10 +2,10 @@
namespace App\Http\Controllers\Club;
-use App\Enums\Customers\Civility;
use App\Enums\Mercanet\PaymentResponse;
use App\Enums\Mercanet\RedirectionStatusCode;
use App\Enums\Mercanet\TransactionResponse;
+use App\Enums\Shop\ContactFormCivility;
use App\Enums\Shop\OrderStatus;
use App\Enums\Shop\OrderType;
use App\Exceptions\CBPayementError;
@@ -66,10 +66,9 @@ class ShopController extends Controller
// * Pseudo mutex let database fail (unique ref) to check if order has already been processed
try {
- $order = new Order();
- $order->ref = str_replace('-', '', $request->ref);
- // @phpstan-ignore assign.propertyType
- $order->civility = Civility::make(intval($request->coords->civility));
+ $order = new Order();
+ $order->ref = str_replace('-', '', $request->ref);
+ $order->civility = ContactFormCivility::make(intval($request->coords['civility']));
$order->payementType = OrderType::make(intval($request->payementMethod));
$order->status = OrderStatus::waiting;
$order->customer_id = $customerModel->getKey();
diff --git a/app/Models/Offer.php b/app/Models/Offer.php
index 1fd3417a..42d8dd27 100644
--- a/app/Models/Offer.php
+++ b/app/Models/Offer.php
@@ -8,6 +8,9 @@ use App\Traits\Models\ActivityLog;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
+use Spatie\SchemaOrg\Schema;
+use Uwil\SchemaOrg\Laravel\Interfaces\SchemaOrgInterface;
+use Uwil\SchemaOrg\Laravel\Traits\SchemaOrgTrait;
/**
* @property string|null $title Offer title.
@@ -37,10 +40,11 @@ use Illuminate\Support\Facades\Cache;
*
* @property-read \App\Models\Product $products Product polymorphic relationship.
*/
-class Offer extends Model
+class Offer extends Model implements SchemaOrgInterface
{
use ActivityLog;
use HasFactory;
+ use SchemaOrgTrait;
/**
* The attributes that are mass assignable.
@@ -149,4 +153,73 @@ class Offer extends Model
return GeneralSetting::query()->where('type', SettingsType::offersCount)->firstOrFail()->value['count'];
});
}
+
+ /**
+ * Create a SchemaOrg.
+ *
+ * @return \Spatie\SchemaOrg\JobPosting
+ * @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
+ */
+ public function toSchemaOrg(): \Spatie\SchemaOrg\JobPosting
+ {
+ $schemaJob = Schema::jobPosting()
+ ->title($this->title)
+ ->hiringOrganization($this->getOrganizationSchema());
+
+ // Recruiter.
+ $recruiter = Schema::contactPoint();
+ if (!empty($this->recruiter_firstname) || !empty($this->recruiter_lastname)) {
+ $recruiter->name(sprintf(
+ "%s %s",
+ $this->recruiter_firstname ?? '',
+ $this->recruiter_lastname ?? '',
+ ));
+ }
+ if (!empty($this->recruiter_job)) {
+ $recruiter->contactType($this->recruiter_job);
+ }
+ if (!empty($this->recruiter_picture)) {
+ $recruiter->image(
+ Schema::imageObject()
+ ->url(asset($this->recruiter_picture))
+ ->headline(sprintf(
+ "Photo du recruteur %s %s",
+ $this->recruiter_firstname ?? '',
+ $this->recruiter_lastname ?? '',
+ ))
+ );
+ $schemaJob->applicationContact($recruiter);
+ }
+
+ // Location.
+ $location = Schema::place()
+ ->isAccessibleForFree(true)
+ ->publicAccess(true);
+ if (!empty($this->location_longitude)) {
+ $location->longitude($this->location_longitude);
+ }
+ if (!empty($this->location_latitude)) {
+ $location->latitude($this->location_latitude);
+ }
+ if (!empty($this->location)) {
+ $location->address($this->location);
+ }
+ if (!empty($this->location_details)) {
+ $location->description($this->location_details);
+ }
+ $schemaJob->jobLocation($location);
+
+ // Other.
+ if (!empty($this->description)) {
+ $schemaJob->description($this->description);
+ }
+ if (!empty($this->contract)) {
+ $schemaJob->employmentType($this->contract);
+ }
+ if (!empty($this->created_at)) {
+ $schemaJob->datePosted($this->created_at);
+ }
+
+ return $schemaJob;
+ }
}
diff --git a/app/Models/Product.php b/app/Models/Product.php
index 5a110273..ab209df8 100644
--- a/app/Models/Product.php
+++ b/app/Models/Product.php
@@ -277,7 +277,7 @@ class Product extends Model implements SeoInterface, Sitemapable, SchemaOrgInter
$schema = Schema::Product()
->name($model->seo_title)
->description($model->seo_description)
- ->url(route('fo.products.show', $model))
+ ->url(route('fo.products.show', $model->slug))
->keywords('produit')
->releaseDate($model->created_at)
->image([
diff --git a/app/Models/Recipe.php b/app/Models/Recipe.php
index 3b8a4291..49e020f8 100644
--- a/app/Models/Recipe.php
+++ b/app/Models/Recipe.php
@@ -285,7 +285,7 @@ class Recipe extends Model implements SeoInterface, Sitemapable, SchemaOrgInterf
$schema = Schema::Recipe()
->name($model->title)
->description($model->seo_description)
- ->url(route('fo.recipes.show', $model))
+ ->url(route('fo.recipes.show', $model->slug))
->inLanguage(config('schema-org.website.languages'))
->keywords('recette')
->recipeCategory([
@@ -297,9 +297,6 @@ class Recipe extends Model implements SeoInterface, Sitemapable, SchemaOrgInterf
->dateCreated($model->created_at)
->dateModified($model->updated_at)
->datePublished($model->created_at)
- ->cookTime(
- Schema::duration()->setProperty("@value", $model->formatDurationIso($model->cooking_time))
- )
->prepTime(
Schema::duration()->setProperty("@value", $model->formatDurationIso($model->preparation_time))
)
@@ -324,6 +321,13 @@ class Recipe extends Model implements SeoInterface, Sitemapable, SchemaOrgInterf
->reviewCount(1)
);
+ // Cooking time associated.
+ if ($model->cooking_time) {
+ $schema->cookTime(
+ Schema::duration()->setProperty("@value", $model->formatDurationIso($model->cooking_time))
+ );
+ }
+
// Steps associated.
preg_match_all('/
(.*?)<\/li>/', $model->preparation, $step);
$schema->steps($step[1]);
@@ -331,46 +335,58 @@ class Recipe extends Model implements SeoInterface, Sitemapable, SchemaOrgInterf
// Ingredients associated.
$ingredientsList = collect($model->ingredients_list)
->map(function ($item) {
- // @phpstan-ignore ternary.elseUnreachable
- return trim(($item['label_unit'] !== null ? $item['label_unit'] : '') . ' ' . $item['label_value']);
+ return trim(
+ // @phpstan-ignore ternary.elseUnreachable
+ ($item['value'] !== null ? $item['value'] : '') . ' ' .
+ // @phpstan-ignore ternary.elseUnreachable
+ ($item['label_unit'] !== null ? $item['label_unit'] : '') . ' ' .
+ $item['label_value']
+ );
})
->all();
$schema->ingredients($ingredientsList);
// Products associated.
- if ($model->products->count() && !$asReference) {
- $linkedProducts = $model->products->map(function (Product $product) {
+ $productsAssociated = $model->products->where('published', true)->values();
+ if ($productsAssociated->count() && !$asReference) {
+ $linkedProducts = $productsAssociated->map(function (Product $product) {
return $product->toSchemaOrg(true);
})->toArray();
$schema->subjectOf($linkedProducts);
// Nutritionnal values.
- $allNutritionnalValues = $model->products->map(function (Product $productModel) {
- return collect($productModel->getNutritionnalValue()->toArray())
- // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
- ->reject(function ($value, $key) {
- return str_contains($key, '_percent') || in_array($key, [
- 'id',
- 'product_id',
- 'created_at',
- 'updated_at'
- ]);
- })
- ->toArray();
+ $allNutritionnalValues = $productsAssociated->map(function (Product $productModel) {
+ if ($productModel->getNutritionnalValue()) {
+ return collect($productModel->getNutritionnalValue()->toArray())
+ // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
+ ->reject(function ($value, $key) {
+ return str_contains($key, '_percent') || in_array($key, [
+ 'id',
+ 'product_id',
+ 'created_at',
+ 'updated_at'
+ ]);
+ })
+ ->toArray();
+ } else {
+ return [];
+ }
})->reduce(function (?array $carry, array $item) {
foreach ($item as $key => $value) {
$carry[$key] = ($carry[$key] ?? 0) + $value;
}
return $carry;
});
- $schema->nutrition(
- Schema::nutritionInformation()
- ->carbohydrateContent($allNutritionnalValues['carbohydrates'])
- ->fatContent($allNutritionnalValues['fat'])
- ->proteinContent($allNutritionnalValues['protein'])
- ->sugarContent($allNutritionnalValues['sugar'])
- );
+ if ($allNutritionnalValues) {
+ $schema->nutrition(
+ Schema::nutritionInformation()
+ ->carbohydrateContent($allNutritionnalValues['carbohydrates'])
+ ->fatContent($allNutritionnalValues['fat'])
+ ->proteinContent($allNutritionnalValues['protein'])
+ ->sugarContent($allNutritionnalValues['sugar'])
+ );
+ }
} //end if
// Video associated.
diff --git a/app/Models/StaticPage.php b/app/Models/StaticPage.php
index bad731cb..6dc69731 100644
--- a/app/Models/StaticPage.php
+++ b/app/Models/StaticPage.php
@@ -12,6 +12,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
use Spatie\SchemaOrg\Schema;
+use Spatie\SchemaOrg\WebPage;
use Uwil\SchemaOrg\Laravel\Interfaces\SchemaOrgInterface;
use Uwil\SchemaOrg\Laravel\Traits\SchemaOrgTrait;
@@ -207,7 +208,7 @@ class StaticPage extends Model implements SchemaOrgInterface
*/
public function toSchemaOrg(): \Spatie\SchemaOrg\WebPage
{
- return Schema::webPage()
+ $schema = Schema::webPage()
->name($this->seo_title)
->description($this->seo_description)
->headline($this->title)
@@ -224,80 +225,29 @@ class StaticPage extends Model implements SchemaOrgInterface
->publisher($this->getOrganizationSchema())
->author($this->getOrganizationSchema())
->isPartOf($this->getWebsiteSchema());
+
+ if (request()->routeIs('fo.recruitment.show')) {
+ return $this->toSchemaOrgRecruitment($schema);
+ }
+
+ return $schema;
}
/**
* Create a SchemaOrg for the recruitment page.
*
+ * @param \Spatie\SchemaOrg\WebPage $schemaBase
* @return \Spatie\SchemaOrg\WebPage
- * @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
*/
- public function toSchemaOrgRecruitment(): \Spatie\SchemaOrg\WebPage
+ public function toSchemaOrgRecruitment(WebPage $schemaBase): \Spatie\SchemaOrg\WebPage
{
// @phpcs:enable
- $schema = self::toSchemaOrg()->keywords(['recrutement', 'emplois']);
+ $schema = $schemaBase->keywords(['recrutement', 'emplois']);
$offers = [];
// @phpstan-ignore argument.type
Offer::getOffersCached()->each(function (Offer $offerModel) use (&$offers) {
- $schemaJob = Schema::jobPosting()->title($offerModel->title);
-
- // Recruiter.
- $recruiter = Schema::person();
- if (!empty($offerModel->recruiter_firstname)) {
- $recruiter->givenName($offerModel->recruiter_firstname);
- }
- if (!empty($offerModel->recruiter_lastname)) {
- $recruiter->familyName($offerModel->recruiter_lastname);
- }
- if (!empty($offerModel->recruiter_job)) {
- $recruiter->jobTitle($offerModel->recruiter_job);
- }
- $recruiter->affiliation($this->getOrganizationSchema());
- $recruiter->brand($this->getBrandSchema());
- if (!empty($offerModel->recruiter_picture)) {
- $recruiter->image(
- Schema::imageObject()
- ->url(asset($offerModel->recruiter_picture))
- ->headline(sprintf(
- "Photo du recruteur %s %s",
- $offerModel->recruiter_firstname ?? '',
- $offerModel->recruiter_lastname ?? ''
- ))
- );
- }
- $schemaJob->hiringOrganization($recruiter);
-
- // Location.
- $location = Schema::place()
- ->isAccessibleForFree(true)
- ->publicAccess(true);
- if (!empty($offerModel->location_longitude)) {
- $location->longitude($offerModel->location_longitude);
- }
- if (!empty($offerModel->location_latitude)) {
- $location->latitude($offerModel->location_latitude);
- }
- if (!empty($offerModel->location)) {
- $location->address($offerModel->location);
- }
- $schemaJob->jobLocation($location);
-
- // Other.
- if (!empty($offerModel->description)) {
- $schemaJob->description($offerModel->description);
- }
- if (!empty($offerModel->contract)) {
- $schemaJob->employmentType($offerModel->contract);
- }
- if (!empty($offerModel->location_details)) {
- $schemaJob->jobLocationType($offerModel->location_details);
- }
- if (!empty($offerModel->created_at)) {
- $schemaJob->datePosted($offerModel->created_at);
- }
-
- $offers[] = $schemaJob;
+ $offers[] = $offerModel->toSchemaOrg();
});
if (!empty($offers)) {
diff --git a/composer.lock b/composer.lock
index 7ccbc6ed..ccb8f1cf 100644
--- a/composer.lock
+++ b/composer.lock
@@ -6004,16 +6004,16 @@
},
{
"name": "sentry/sentry",
- "version": "4.13.0",
+ "version": "4.14.0",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-php.git",
- "reference": "b54a0eaedfc27fc2da587e64455a66cd29cd3c4d"
+ "reference": "f8c50304bd2f1640704345274bdd5af150b6945d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/b54a0eaedfc27fc2da587e64455a66cd29cd3c4d",
- "reference": "b54a0eaedfc27fc2da587e64455a66cd29cd3c4d",
+ "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/f8c50304bd2f1640704345274bdd5af150b6945d",
+ "reference": "f8c50304bd2f1640704345274bdd5af150b6945d",
"shasum": ""
},
"require": {
@@ -6077,7 +6077,7 @@
],
"support": {
"issues": "https://github.com/getsentry/sentry-php/issues",
- "source": "https://github.com/getsentry/sentry-php/tree/4.13.0"
+ "source": "https://github.com/getsentry/sentry-php/tree/4.14.0"
},
"funding": [
{
@@ -6089,27 +6089,27 @@
"type": "custom"
}
],
- "time": "2025-06-10T15:39:27+00:00"
+ "time": "2025-06-13T17:22:57+00:00"
},
{
"name": "sentry/sentry-laravel",
- "version": "4.14.1",
+ "version": "4.15.0",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-laravel.git",
- "reference": "8b71a9209e8a01cb5728e743e99299d87d688010"
+ "reference": "481398f05e4b0f5886f6092e1b95b626a438deff"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/8b71a9209e8a01cb5728e743e99299d87d688010",
- "reference": "8b71a9209e8a01cb5728e743e99299d87d688010",
+ "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/481398f05e4b0f5886f6092e1b95b626a438deff",
+ "reference": "481398f05e4b0f5886f6092e1b95b626a438deff",
"shasum": ""
},
"require": {
"illuminate/support": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0",
"nyholm/psr7": "^1.0",
"php": "^7.2 | ^8.0",
- "sentry/sentry": "^4.10",
+ "sentry/sentry": "^4.13",
"symfony/psr-http-message-bridge": "^1.0 | ^2.0 | ^6.0 | ^7.0"
},
"require-dev": {
@@ -6166,7 +6166,7 @@
],
"support": {
"issues": "https://github.com/getsentry/sentry-laravel/issues",
- "source": "https://github.com/getsentry/sentry-laravel/tree/4.14.1"
+ "source": "https://github.com/getsentry/sentry-laravel/tree/4.15.0"
},
"funding": [
{
@@ -6178,7 +6178,7 @@
"type": "custom"
}
],
- "time": "2025-06-07T07:52:41+00:00"
+ "time": "2025-06-12T20:56:36+00:00"
},
{
"name": "setasign/fpdi",
@@ -9523,16 +9523,16 @@
},
{
"name": "uwil/schema-org-laravel",
- "version": "2.0.0",
+ "version": "2.1.0",
"source": {
"type": "git",
"url": "git@lab.s-web.fr:ldc-web/projets/schema-org-laravel.git",
- "reference": "2a0e46155fbde286d52044959c4ef7188fa5136e"
+ "reference": "b3473db7c2bb423d030fac68dcaaee8d083e58f7"
},
"dist": {
"type": "zip",
- "url": "https://lab.s-web.fr/api/v4/projects/120/packages/composer/archives/uwil/schema-org-laravel.zip?sha=2a0e46155fbde286d52044959c4ef7188fa5136e",
- "reference": "2a0e46155fbde286d52044959c4ef7188fa5136e",
+ "url": "https://lab.s-web.fr/api/v4/projects/120/packages/composer/archives/uwil/schema-org-laravel.zip?sha=b3473db7c2bb423d030fac68dcaaee8d083e58f7",
+ "reference": "b3473db7c2bb423d030fac68dcaaee8d083e58f7",
"shasum": ""
},
"require": {
@@ -10488,16 +10488,16 @@
},
{
"name": "filp/whoops",
- "version": "2.18.2",
+ "version": "2.18.3",
"source": {
"type": "git",
"url": "https://github.com/filp/whoops.git",
- "reference": "89dabca1490bc77dbcab41c2b20968c7e44bf7c3"
+ "reference": "59a123a3d459c5a23055802237cb317f609867e5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/filp/whoops/zipball/89dabca1490bc77dbcab41c2b20968c7e44bf7c3",
- "reference": "89dabca1490bc77dbcab41c2b20968c7e44bf7c3",
+ "url": "https://api.github.com/repos/filp/whoops/zipball/59a123a3d459c5a23055802237cb317f609867e5",
+ "reference": "59a123a3d459c5a23055802237cb317f609867e5",
"shasum": ""
},
"require": {
@@ -10547,7 +10547,7 @@
],
"support": {
"issues": "https://github.com/filp/whoops/issues",
- "source": "https://github.com/filp/whoops/tree/2.18.2"
+ "source": "https://github.com/filp/whoops/tree/2.18.3"
},
"funding": [
{
@@ -10555,7 +10555,7 @@
"type": "github"
}
],
- "time": "2025-06-11T20:42:19+00:00"
+ "time": "2025-06-16T00:02:10+00:00"
},
{
"name": "hamcrest/hamcrest-php",
@@ -13594,16 +13594,16 @@
},
{
"name": "squizlabs/php_codesniffer",
- "version": "3.13.0",
+ "version": "3.13.1",
"source": {
"type": "git",
"url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
- "reference": "65ff2489553b83b4597e89c3b8b721487011d186"
+ "reference": "1b71b4dd7e7ef651ac749cea67e513c0c832f4bd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/65ff2489553b83b4597e89c3b8b721487011d186",
- "reference": "65ff2489553b83b4597e89c3b8b721487011d186",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/1b71b4dd7e7ef651ac749cea67e513c0c832f4bd",
+ "reference": "1b71b4dd7e7ef651ac749cea67e513c0c832f4bd",
"shasum": ""
},
"require": {
@@ -13674,7 +13674,7 @@
"type": "thanks_dev"
}
],
- "time": "2025-05-11T03:36:00+00:00"
+ "time": "2025-06-12T15:04:34+00:00"
},
{
"name": "symfony/polyfill-php81",
diff --git a/resources/views/fo/pages/recruitment.blade.php b/resources/views/fo/pages/recruitment.blade.php
index a8cac779..98c50a10 100644
--- a/resources/views/fo/pages/recruitment.blade.php
+++ b/resources/views/fo/pages/recruitment.blade.php
@@ -249,6 +249,4 @@
@endpush
-@push('scripts')
- {!! $staticPageModel->toSchemaOrgRecruitment()->toScript() !!}
-@endpush
+