Compare commits
No commits in common. "addBanner" and "fixEslint/k" have entirely different histories.
addBanner
...
fixEslint/
188 changed files with 1799 additions and 28067 deletions
15
.env.example
15
.env.example
|
|
@ -56,14 +56,6 @@ MAIL_PASSWORD=null
|
|||
MAIL_FROM_ADDRESS="hello@example.com"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
MAIL_LIST_BREEDER=
|
||||
MAIL_LIST_COMMITMENTS=
|
||||
MAIL_LIST_EXPORT=
|
||||
MAIL_LIST_FINANCE=
|
||||
MAIL_LIST_INFO=
|
||||
MAIL_LIST_PRESS=
|
||||
MAIL_LIST_RESTAURATION=
|
||||
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
|
||||
# TELESCOPE
|
||||
|
|
@ -88,10 +80,3 @@ MEILISEARCH_KEY=
|
|||
UWIL_ADMIN_SECURE_CIDR_LIST=""
|
||||
UWIL_ADMIN_SECURE_CIDR_PROJECT_ALLOWED_LIST=""
|
||||
|
||||
# MATOMO
|
||||
MATOMO_SITE_ID=
|
||||
|
||||
# RECAPTCHA
|
||||
GOOGLE_RECAPTCHA_PUBLIC=
|
||||
GOOGLE_RECAPTCHA_PRIVATE=
|
||||
GOOGLE_RECAPTCHA_VERSION=
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
npx --no -- commitlint --config node_modules/@uwil/husky-config/commitlint.config.cjs --edit $1
|
||||
|
|
@ -29,17 +29,14 @@ COPY --from=vendor /app/vendor/ /app/vendor/
|
|||
WORKDIR /app
|
||||
RUN npm config set @ldc-web:registry https://lab.s-web.fr/api/v4/packages/npm/
|
||||
RUN npm config set -- '//lab.s-web.fr/api/v4/packages/npm/:_authToken' "${GITLAB_PASSWORD}"
|
||||
RUN npm config set @uwil:registry=https://lab.s-web.fr/api/v4/groups/ldc-web/-/packages/npm/
|
||||
RUN npm config set -- '//lab.s-web.fr/api/v4/groups/ldc-web/-/packages/npm/:_authToken' "${GITLAB_PASSWORD}"
|
||||
RUN npm ci && npm run prod
|
||||
|
||||
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/uwil-production-8.5:${PHP_8_5_TAG}
|
||||
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/uwil-production-8.4:170625-130159
|
||||
|
||||
ARG USER=www-data
|
||||
|
||||
COPY --chown=${USER}:${USER} . /app/srcs
|
||||
COPY --chown=${USER}:${USER} ./resources/favicon/front/ /app/srcs/public/
|
||||
COPY --chown=${USER}:${USER} ./resources/favicon/back/ /app/srcs/public/back/
|
||||
COPY --chown=${USER}:${USER} ./resources/favicon /app/srcs/public
|
||||
COPY --from=vendor --chown=${USER}:${USER} /app/vendor/ /app/srcs/vendor/
|
||||
COPY --from=frontend --chown=${USER}:${USER} /app/public/build/ /app/srcs/public/build/
|
||||
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@ class LocalDateTime implements CastsAttributes
|
|||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param string|integer|null $value
|
||||
* @param array $attributes
|
||||
* @return \Carbon\Carbon|null
|
||||
* @phpcs:disable
|
||||
*/
|
||||
public function get(Model $model, string $key, mixed $value, array $attributes): ?\Carbon\Carbon
|
||||
public function get(Model $model, string $key, string|int|null $value, array $attributes): ?\Carbon\Carbon
|
||||
{
|
||||
// phpcs:enable
|
||||
return $value
|
||||
|
|
@ -31,12 +31,12 @@ class LocalDateTime implements CastsAttributes
|
|||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param string|integer|null $value
|
||||
* @param array $attributes
|
||||
* @return \Carbon\Carbon|null
|
||||
* @phpcs:disable
|
||||
*/
|
||||
public function set(Model $model, string $key, mixed $value, array $attributes): ?\Carbon\Carbon
|
||||
public function set(Model $model, string $key, string|int|null $value, array $attributes): ?\Carbon\Carbon
|
||||
{
|
||||
// phpcs:enable
|
||||
return $value
|
||||
|
|
|
|||
|
|
@ -27,20 +27,225 @@ enum ContactFormType: int
|
|||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::collaborator->name => 'enums.contactFormType.collaborator',
|
||||
self::breeder->name => 'enums.contactFormType.breeder',
|
||||
self::professional->name => 'enums.contactFormType.professional',
|
||||
self::restauration->name => 'enums.contactFormType.restauration',
|
||||
self::export->name => 'enums.contactFormType.export',
|
||||
self::finance->name => 'enums.contactFormType.finance',
|
||||
self::commitments->name => 'enums.contactFormType.commitments',
|
||||
self::product->name => 'enums.contactFormType.product',
|
||||
self::info->name => 'enums.contactFormType.info',
|
||||
self::press->name => 'enums.contactFormType.press',
|
||||
self::collaborator->name => 'enums.contactFormType.collaborator.label',
|
||||
self::breeder->name => 'enums.contactFormType.breeder.label',
|
||||
self::professional->name => 'enums.contactFormType.professional.label',
|
||||
self::restauration->name => 'enums.contactFormType.restauration.label',
|
||||
self::export->name => 'enums.contactFormType.export.label',
|
||||
self::finance->name => 'enums.contactFormType.finance.label',
|
||||
self::commitments->name => 'enums.contactFormType.commitments.label',
|
||||
self::product->name => 'enums.contactFormType.product.label',
|
||||
self::info->name => 'enums.contactFormType.info.label',
|
||||
self::press->name => 'enums.contactFormType.press.label',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the slug for each type.
|
||||
* Optionnal SUBTYPES definition.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const SUBTYPES = [
|
||||
self::professional->name => [
|
||||
self::restauration,
|
||||
self::export,
|
||||
],
|
||||
self::collaborator->name => [],
|
||||
self::breeder->name => [],
|
||||
self::restauration->name => [],
|
||||
self::export->name => [],
|
||||
self::finance->name => [],
|
||||
self::commitments->name => [],
|
||||
self::product->name => [],
|
||||
self::info->name => [],
|
||||
self::press->name => [],
|
||||
];
|
||||
|
||||
/**
|
||||
* Get Class
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function isSubtype(): bool
|
||||
{
|
||||
foreach (self::SUBTYPES as $subtypes) {
|
||||
if (in_array($this, $subtypes, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionnal TOPLEVELS definition.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const TOPLEVELS = [
|
||||
self::professional->name => true,
|
||||
self::collaborator->name => true,
|
||||
self::breeder->name => true,
|
||||
self::restauration->name => false,
|
||||
self::export->name => false,
|
||||
self::finance->name => true,
|
||||
self::commitments->name => true,
|
||||
self::product->name => true,
|
||||
self::info->name => true,
|
||||
self::press->name => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* Get Class
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function topLevel(): ?string
|
||||
{
|
||||
return !empty(self::TOPLEVELS[$this->name]) ?
|
||||
self::TOPLEVELS[$this->name] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data-target
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dataTarget(): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::professional => 'askPro',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the subtitle
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function subtitle(): string
|
||||
{
|
||||
return match (true) {
|
||||
$this === self::restauration => __('enums.contactFormType.' . $this->name . '.subtitle'),
|
||||
default => __('enums.contactFormType.' . $this->name . '.label'),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the slug for each type
|
||||
*
|
||||
* @param string|null $locale
|
||||
* @return string|null
|
||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity
|
||||
*/
|
||||
public function slug(?string $locale = null): ?string
|
||||
{
|
||||
// phpcs:enable
|
||||
return match ($this) {
|
||||
self::collaborator => Lang::get('enums.contactFormType.collaborator.slug', [], $locale),
|
||||
self::breeder => Lang::get('enums.contactFormType.breeder.slug', [], $locale),
|
||||
self::professional => null,
|
||||
self::restauration => Lang::get('enums.contactFormType.restauration.slug', [], $locale),
|
||||
self::export => Lang::get('enums.contactFormType.export.slug', [], $locale),
|
||||
self::finance => Lang::get('enums.contactFormType.finance.slug', [], $locale),
|
||||
self::commitments => Lang::get('enums.contactFormType.commitments.slug', [], $locale),
|
||||
self::product => Lang::get('enums.contactFormType.product.slug', [], $locale),
|
||||
self::info => Lang::get('enums.contactFormType.info.slug', [], $locale),
|
||||
self::press => null,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current lang slug match in specific lang slug
|
||||
*
|
||||
* @param string $slug
|
||||
* @param string $locale
|
||||
* @return self
|
||||
*/
|
||||
public static function fromSlug(string $slug, string $locale): ?self
|
||||
{
|
||||
foreach (self::cases() as $case) {
|
||||
$caseSlug = $case->slug($locale);
|
||||
|
||||
if (
|
||||
$caseSlug !== null &&
|
||||
mb_strtolower($caseSlug) === mb_strtolower($slug)
|
||||
) {
|
||||
return $case;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the route
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function route(): ?string
|
||||
{
|
||||
$commonRoutes = [
|
||||
self::collaborator,
|
||||
self::breeder,
|
||||
self::export,
|
||||
self::finance,
|
||||
self::commitments,
|
||||
self::product,
|
||||
self::info,
|
||||
self::restauration
|
||||
];
|
||||
return match (true) {
|
||||
in_array($this, $commonRoutes, true) => route('front.contact.show', ['slug' => $this->slug()]),
|
||||
$this === self::professional => null,
|
||||
$this === self::press =>
|
||||
RouteHelper::routeNameChecker('front.dynamic-pages.espace-presse') . '#page-press-form',
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the route for the contact form type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getLabelisedRoutes(): array
|
||||
{
|
||||
return collect(self::cases())->mapWithKeys(fn($enum) => [
|
||||
$enum->name => (object) [
|
||||
"label" => $enum->label(),
|
||||
"route" => $enum->route(),
|
||||
],
|
||||
])->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the slug for each type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function seo(): array
|
||||
{
|
||||
$commonRoutes = [
|
||||
self::collaborator,
|
||||
self::breeder,
|
||||
self::export,
|
||||
self::finance,
|
||||
self::commitments,
|
||||
self::professional,
|
||||
self::product,
|
||||
self::info,
|
||||
self::press,
|
||||
self::restauration
|
||||
];
|
||||
return match (true) {
|
||||
in_array($this, $commonRoutes, true) => [
|
||||
'title' => __('enums.contactFormType.' . $this->name . '.seo.title'),
|
||||
'description' => __('enums.contactFormType.' . $this->name . '.seo.description'),
|
||||
],
|
||||
default => [],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the slug for each type
|
||||
*
|
||||
* @return array
|
||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity
|
||||
|
|
@ -49,17 +254,34 @@ enum ContactFormType: int
|
|||
{
|
||||
// phpcs:enable
|
||||
return match ($this) {
|
||||
self::breeder => config('mail.to.breeder'),
|
||||
self::restauration => config('mail.to.restauration'),
|
||||
self::export => config('mail.to.export'),
|
||||
self::finance => config('mail.to.finance'),
|
||||
self::commitments => config('mail.to.commitments'),
|
||||
self::info => config('mail.to.info'),
|
||||
self::press => config('mail.to.press'),
|
||||
self::collaborator,
|
||||
self::product,
|
||||
self::professional => null
|
||||
// phpcs:ignore Squiz.Commenting.InlineComment
|
||||
self::collaborator => [],
|
||||
self::breeder => [
|
||||
'marie-charlotte.garnier@ldc.fr',
|
||||
'dylan.chevalier@ldc.fr',
|
||||
],
|
||||
self::professional => null,
|
||||
self::restauration => [
|
||||
'rhd@ldc.fr',
|
||||
],
|
||||
self::export => [
|
||||
'alexis.lambert@ldc.fr',
|
||||
'bruno.lafon@ldc.fr',
|
||||
],
|
||||
self::finance => [
|
||||
'david.eluaud@ldc.fr',
|
||||
'malaury.offe@ldc.fr',
|
||||
],
|
||||
self::commitments => [
|
||||
'claire-marie.gesland@ldc.fr',
|
||||
],
|
||||
self::product => [],
|
||||
self::info => [
|
||||
'blandine.durand-gratian@ldc.fr',
|
||||
'malaury.offe@ldc.fr',
|
||||
],
|
||||
self::press => [
|
||||
'communicationgroupe@ldc.fr',
|
||||
],
|
||||
}; //end match
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Contact;
|
||||
|
||||
use Uwil\LaravelCommon\Traits\Enums\BaseEnum;
|
||||
|
||||
enum ExportAskingType: int
|
||||
{
|
||||
use BaseEnum;
|
||||
|
||||
case customer = 1;
|
||||
case provider = 2;
|
||||
case other = 3;
|
||||
|
||||
/**
|
||||
* Optionnal labels definition.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::customer->name => 'enums.exportAskingType.customer',
|
||||
self::provider->name => 'enums.exportAskingType.provider',
|
||||
self::other->name => 'enums.exportAskingType.other',
|
||||
];
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ enum DynamicFieldTypes: int
|
|||
{
|
||||
use BaseEnum;
|
||||
|
||||
// Name must be one word in lowercase.
|
||||
// Name must be one word in lowercase.
|
||||
case string = 1;
|
||||
case textarea = 2;
|
||||
case wysiwyg = 3;
|
||||
|
|
@ -25,11 +25,9 @@ enum DynamicFieldTypes: int
|
|||
case color = 14;
|
||||
case model = 15;
|
||||
case staticroute = 16;
|
||||
case video = 17;
|
||||
|
||||
// Specific inputs.
|
||||
case position = 101;
|
||||
case contactform = 102;
|
||||
// Specific inputs.
|
||||
case position = 101;
|
||||
|
||||
/**
|
||||
* Labels definition.
|
||||
|
|
@ -53,11 +51,9 @@ enum DynamicFieldTypes: int
|
|||
self::color->name => 'enums.dynamic-field-types.color',
|
||||
self::model->name => 'enums.dynamic-field-types.model',
|
||||
self::staticroute->name => 'enums.dynamic-field-types.staticroute',
|
||||
self::video->name => 'enums.dynamic-field-types.video',
|
||||
|
||||
// Specific inputs.
|
||||
self::position->name => 'enums.dynamic-field-types.position',
|
||||
self::contactform->name => 'enums.dynamic-field-types.contactform',
|
||||
self::position->name => 'enums.dynamic-field-types.position',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -74,17 +70,15 @@ enum DynamicFieldTypes: int
|
|||
self::image->name => 'required|file|mimes:jpg,jpeg,png,webp|max:5120|dimensions:width=100,height=100',
|
||||
self::list->name => 'required|array|min:1|max:10',
|
||||
self::file->name => 'required|file|mimes:pdf|max:5120',
|
||||
self::vimeoid->name => 'required',
|
||||
self::youtubeid->name => 'required',
|
||||
self::vimeoid->name => 'required|string|min:8|max:10',
|
||||
self::youtubeid->name => 'required|string|size:11',
|
||||
self::date->name => 'required|date',
|
||||
self::color->name => 'required|string|hex_color',
|
||||
self::model->name => 'required|numeric|exists:dynamic_pages,id',
|
||||
self::staticroute->name => 'required|numeric|between:1,99',
|
||||
self::video->name => 'required',
|
||||
self::staticroute->name => 'required|numeric|between:1,10',
|
||||
|
||||
// Specific inputs.
|
||||
self::position->name => 'required|numeric|between:1,5',
|
||||
self::contactform->name => 'required|numeric|between:1,10'
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -101,7 +95,6 @@ enum DynamicFieldTypes: int
|
|||
* Is array definition.
|
||||
*
|
||||
* @return array
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const ISARRAY = [
|
||||
self::string->name => false,
|
||||
|
|
@ -120,10 +113,8 @@ enum DynamicFieldTypes: int
|
|||
self::color->name => false,
|
||||
self::model->name => false,
|
||||
self::staticroute->name => false,
|
||||
self::video->name => false,
|
||||
|
||||
// Specific inputs.
|
||||
self::position->name => false,
|
||||
self::contactform->name => false,
|
||||
self::position->name => false,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,18 +21,18 @@ enum OrdersEnum: int
|
|||
self::desc->name => 'enums.orders.desc',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Get the orders to display using the app locale.
|
||||
* Get the orders to display using the app locale
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function ordersWithLocal(): bool
|
||||
{
|
||||
$locale = config('app.locale');
|
||||
return match ($this) {
|
||||
self::asc,
|
||||
/** @phpstan-ignore-next-line */
|
||||
self::desc => true,
|
||||
return match (true) {
|
||||
$this === self::asc => true,
|
||||
$this === self::desc => true,
|
||||
default => $locale === "fr" ? true : false,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,17 @@ enum StaticRoutesEnum: int
|
|||
use BaseEnum;
|
||||
|
||||
// Set all cases for each static routes.
|
||||
case collaborator = 1;
|
||||
case breeder = 2;
|
||||
case professional = 3;
|
||||
case restauration = 4;
|
||||
case export = 5;
|
||||
case finance = 6;
|
||||
case commitments = 7;
|
||||
case product = 8;
|
||||
case info = 9;
|
||||
case press = 10;
|
||||
case search = 11;
|
||||
|
||||
/**
|
||||
* Get array of each route with his matching value.
|
||||
|
|
@ -17,29 +28,29 @@ enum StaticRoutesEnum: int
|
|||
* @param callable|null $callback
|
||||
* @return array
|
||||
*/
|
||||
public static function getRoutes(?callable $callback = null)
|
||||
public static function getRoutes(?callable $callback = null): array
|
||||
{
|
||||
// $dataKeyValue = array_merge([], [
|
||||
// self::search->name => (object) [
|
||||
// 'label' => trans('front.search.title'),
|
||||
// 'route' => '/recherche?texte=LDC',
|
||||
// ]
|
||||
// ]);
|
||||
// return collect($dataKeyValue)
|
||||
// ->reject(fn($item) => is_null($item->label) || is_null($item->route))
|
||||
// ->map(function ($item, $key) {
|
||||
// $targetEnum = collect(self::cases())
|
||||
// ->first(fn($enum) => $enum->name === $key);
|
||||
$dataKeyValue = array_merge(ContactFormType::getLabelisedRoutes(), [
|
||||
self::search->name => (object) [
|
||||
'label' => trans('front.search.title'),
|
||||
'route' => '/recherche?texte=LDC',
|
||||
]
|
||||
]);
|
||||
return collect($dataKeyValue)
|
||||
->reject(fn($item) => is_null($item->label) || is_null($item->route))
|
||||
->map(function ($item, $key) {
|
||||
$targetEnum = collect(self::cases())
|
||||
->first(fn($enum) => $enum->name === $key);
|
||||
|
||||
// return (object) [
|
||||
// 'label' => ucfirst($item->label),
|
||||
// 'value' => $targetEnum->value,
|
||||
// 'route' => $item->route,
|
||||
// ];
|
||||
// })
|
||||
// ->when(!is_null($callback), fn ($collection) => $collection->filter($callback))
|
||||
// ->values()
|
||||
// ->toArray();
|
||||
return (object) [
|
||||
'label' => ucfirst($item->label),
|
||||
'value' => $targetEnum->value,
|
||||
'route' => $item->route,
|
||||
];
|
||||
})
|
||||
->when(!is_null($callback), fn ($collection) => $collection->filter($callback))
|
||||
->values()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use Uwil\LaravelCommon\Traits\Enums\BaseEnum;
|
||||
|
||||
enum VideoProviderEnum: int
|
||||
{
|
||||
use BaseEnum;
|
||||
|
||||
case youtube = 1;
|
||||
case vimeo = 2;
|
||||
|
||||
/**
|
||||
* Optionnal labels definition.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::youtube->name => 'youtube',
|
||||
self::vimeo->name => 'viméo',
|
||||
];
|
||||
|
||||
/**
|
||||
* Is array definition.
|
||||
*
|
||||
* @return array
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const COLOR = [
|
||||
self::youtube->name => "#FF0000",
|
||||
self::vimeo->name => "#00B2EA",
|
||||
];
|
||||
}
|
||||
|
|
@ -6,9 +6,9 @@ use App\Enums\DynamicFieldTypes;
|
|||
use App\Enums\DynamicPages\PageStatusEnum;
|
||||
use App\Models\DynamicPage;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Uwil\LaravelCommon\Helpers\FileHelper;
|
||||
use Uwil\LaravelCommon\Helpers\ToolboxHelper;
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ class DynamicPageHelper
|
|||
? ''
|
||||
: data_get($newContent, $key, '');
|
||||
if ($old) {
|
||||
FileHelper::removeOldModelFilesFromHtml($new ?? '', $old);
|
||||
FileHelper::removeOldModelFilesFromHtml($new, $old);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -181,9 +181,9 @@ class DynamicPageHelper
|
|||
/**
|
||||
* Get all segments url for dynamic pages.
|
||||
*
|
||||
* @param \App\Models\DynamicPage $page
|
||||
* @param \Illuminate\Database\Eloquent\Collection $pages
|
||||
* @param string $locale
|
||||
* @param \App\Models\DynamicPage $page
|
||||
* @param \Illuminate\Support\Collection $pages
|
||||
* @param string $locale
|
||||
* @return array|null
|
||||
*/
|
||||
public static function getAllDynamicPageSegments(DynamicPage $page, Collection $pages, string $locale): ?array
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Enums\Contact\ContactFormType;
|
||||
use App\Models\DynamicPage;
|
||||
use Illuminate\Routing\Route;
|
||||
use Uwil\LaravelCommon\Controllers\Controller;
|
||||
|
|
@ -62,6 +63,7 @@ class RouteHelper extends Controller
|
|||
}
|
||||
return self::resolve(
|
||||
self::getDynamicPageLocalizedUrl($route, $localeCode),
|
||||
self::getContactShowLocalizedUrl($route, $localeCode),
|
||||
) ?? LaravelLocalization::getLocalizedURL($localeCode, null, [], false);
|
||||
}
|
||||
|
||||
|
|
@ -81,6 +83,48 @@ class RouteHelper extends Controller
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the localized url for contact page show.
|
||||
*
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @param string $localeCode
|
||||
* @return string|false|null
|
||||
*/
|
||||
private static function getContactShowLocalizedUrl(Route $route, string $localeCode)
|
||||
{
|
||||
$contactPage = $route->parameter('contactPage');
|
||||
|
||||
if ($contactPage) {
|
||||
$localizedUrl = LaravelLocalization::getLocalizedURL(
|
||||
$localeCode,
|
||||
null,
|
||||
[],
|
||||
false
|
||||
);
|
||||
$parsed = parse_url($localizedUrl);
|
||||
if (!isset($parsed['path'])) {
|
||||
return $localizedUrl;
|
||||
}
|
||||
|
||||
$segments = explode('/', trim($parsed['path'], '/'));
|
||||
$currentSlug = end($segments);
|
||||
|
||||
$enum = ContactFormType::fromSlug(
|
||||
$currentSlug,
|
||||
app()->getLocale()
|
||||
);
|
||||
|
||||
if ($enum) {
|
||||
$translatedSlug = $enum->slug($localeCode);
|
||||
if ($translatedSlug) {
|
||||
$segments[count($segments) - 1] = $translatedSlug;
|
||||
return '/' . implode('/', $segments);
|
||||
}
|
||||
}
|
||||
return $localizedUrl;
|
||||
} //end if
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the localized url for all dynamic pages.
|
||||
*
|
||||
|
|
@ -93,10 +137,10 @@ class RouteHelper extends Controller
|
|||
/** @var \App\Models\DynamicPage|null $dynamicPage */
|
||||
$dynamicPage = $route->parameter('dynamicPage');
|
||||
if ($dynamicPage instanceof DynamicPage) {
|
||||
$path = $dynamicPage->getLocalizedPath($localeCode);
|
||||
$defPath = $path ?? "";
|
||||
return LaravelLocalization::getLocalizedURL($localeCode, "/{$defPath}", [], false);
|
||||
$path = $dynamicPage->getLocalizedPath($localeCode);
|
||||
if ($path) {
|
||||
return LaravelLocalization::getLocalizedURL($localeCode, "/{$path}", [], false);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,43 +64,29 @@ class TranslationHelper
|
|||
}
|
||||
|
||||
/**
|
||||
* Assert that a value is unique inside a JSON translation field.
|
||||
*
|
||||
* The uniqueness can optionally be scoped to another attribute/value pair.
|
||||
* If $anotherDbAttribute and $anotherValue are provided, the uniqueness
|
||||
* will be checked only within that scope. Otherwise, the value must be
|
||||
* globally unique.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model The model instance being validated.
|
||||
* @param string $value The translated value to check.
|
||||
* @param string $dbAttribute The JSON column containing translations.
|
||||
* @param string|null $anotherValue Optional value used to scope uniqueness.
|
||||
* @param string|null $anotherDbAttribute Optional database column used to scope uniqueness.
|
||||
* @param string|null $errorAttribute Optional attribute name used in the validation error.
|
||||
* @param string|null $errorTranslation Optional translated attribute label for the error message.
|
||||
* Assert value is unique in a translation field.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $value
|
||||
* @param string $dbAttribute
|
||||
* @param string|null $errorAttribute
|
||||
* @param string|null $errorTranslation
|
||||
* @return void
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException If the value is already used.
|
||||
* @throws \Illuminate\Validation\ValidationException Value is already used.
|
||||
*/
|
||||
public static function assertTranslationFieldIsUnique(
|
||||
Model $model,
|
||||
string $value,
|
||||
string $dbAttribute,
|
||||
?string $anotherValue = null,
|
||||
?string $anotherDbAttribute = null,
|
||||
?string $errorAttribute = null,
|
||||
?string $errorTranslation = null,
|
||||
): void {
|
||||
$modelClass = get_class($model);
|
||||
$query = $modelClass::query()
|
||||
$exists = $modelClass::query()
|
||||
->whereKeyNot($model->getKey())
|
||||
->whereRaw("JSON_SEARCH(`{$dbAttribute}`, 'one', ?) IS NOT NULL", [$value]);
|
||||
|
||||
if ($anotherDbAttribute !== null) {
|
||||
$query->where($anotherDbAttribute, $anotherValue);
|
||||
}
|
||||
if ($query->exists()) {
|
||||
->whereRaw("JSON_SEARCH($dbAttribute, 'one', ?) IS NOT NULL", [$value])
|
||||
->exists();
|
||||
if ($exists) {
|
||||
throw ValidationException::withMessages([
|
||||
$errorAttribute ?? $dbAttribute => trans("validation.unique", [
|
||||
'attribute' => $errorTranslation ?? trans("validation.attributes.$dbAttribute"),
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Models\Company;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class CompanyController
|
||||
{
|
||||
/**
|
||||
* Retrieve all published companies with their associated activity and sector.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getCompanies(): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
$companies = Company::query()->where('published', true)->with('companyActivity', 'companySector')->get();
|
||||
|
||||
$data = $companies->map(function ($company) {
|
||||
return array_filter([
|
||||
'name' => $company->name,
|
||||
'logo' => $company->logo,
|
||||
'informations' => $company->informations,
|
||||
'responsable' => $company->responsable,
|
||||
'employees' => $company->employees,
|
||||
'url' => $company->url,
|
||||
'latitude' => $company->latitude,
|
||||
'longitude' => $company->longitude,
|
||||
'type_activite' => Str::lower($company->companyActivity->name),
|
||||
'filiere' => $company->companySector?->name,
|
||||
], fn($value) => !is_null($value));
|
||||
});
|
||||
|
||||
return response()->json($data);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Back;
|
||||
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Uwil\LaravelBackend\Controllers\AuthenticatedSessionController as PackageAuthenticatedSessionController;
|
||||
|
||||
class AuthenticatedSessionController extends PackageAuthenticatedSessionController
|
||||
{
|
||||
/**
|
||||
* Destroy an authenticated session.
|
||||
*/
|
||||
public function destroy(Request $request): RedirectResponse
|
||||
{
|
||||
Auth::guard('backend')->logout();
|
||||
|
||||
$request->session()->invalidate();
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
return to_route('front.dynamic-pages.accueil.fr');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -92,10 +92,8 @@ class CompanySectorController extends Controller
|
|||
*/
|
||||
public function show(CompanySector $company_sector): \Inertia\Response
|
||||
{
|
||||
$companies = $company_sector->companies()->paginate(ItemsPerPaginationEnum::five->value());
|
||||
return Inertia::render('CompanySectors/Show', [
|
||||
'data' => CommonResource::make($company_sector),
|
||||
'companies' => CommonResource::collection($companies),
|
||||
'modelName' => $this->modelName,
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace App\Http\Controllers\Back;
|
||||
|
||||
use App\Http\Requests\Back\DocumentCategories\StoreDocumentCategoryRequest;
|
||||
use App\Http\Requests\Back\DocumentCategories\UpdateDocumentCategoryRequest;
|
||||
use App\Http\Requests\Back\DocumentCategory\StoreDocumentCategoryRequest;
|
||||
use App\Http\Requests\Back\DocumentCategory\UpdateDocumentCategoryRequest;
|
||||
use App\Models\DocumentCategory;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
|
@ -99,7 +99,7 @@ class DocumentCategoryController extends Controller
|
|||
/**
|
||||
* Store a newly created resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Back\DocumentCategories\StoreDocumentCategoryRequest $request
|
||||
* @param \App\Http\Requests\Back\News\StoreDocumentCategoryRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(StoreDocumentCategoryRequest $request): \Illuminate\Http\RedirectResponse
|
||||
|
|
@ -131,8 +131,8 @@ class DocumentCategoryController extends Controller
|
|||
/**
|
||||
* Update the specified resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Back\DocumentCategories\UpdateDocumentCategoryRequest $request
|
||||
* @param \App\Models\DocumentCategory $document_category
|
||||
* @param \App\Http\Requests\Back\News\UpdateDocumentCategoryRequest $request
|
||||
* @param \App\Models\DocumentCategory $document_category
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ namespace App\Http\Controllers\Back;
|
|||
use App\Enums\Document\DocumentStatusEnum;
|
||||
use App\Enums\YearsEnum;
|
||||
use App\Helpers\DocumentHelper;
|
||||
use App\Http\Requests\Back\Documents\StoreDocumentRequest;
|
||||
use App\Http\Requests\Back\Documents\UpdateDocumentRequest;
|
||||
use App\Http\Requests\Back\Document\StoreDocumentRequest;
|
||||
use App\Http\Requests\Back\Document\UpdateDocumentRequest;
|
||||
use App\Models\Document;
|
||||
use App\Models\DocumentCategory;
|
||||
use App\Models\DocumentTag;
|
||||
|
|
@ -62,7 +62,6 @@ class DocumentController extends Controller
|
|||
|
||||
/** Custom pagination */
|
||||
$docModels = $this->paginate($query);
|
||||
|
||||
return Inertia::render('Document/Index', [
|
||||
'documentsModel' => CommonResource::collection($docModels),
|
||||
'searchFields' => $searchFields,
|
||||
|
|
@ -108,7 +107,7 @@ class DocumentController extends Controller
|
|||
/**
|
||||
* Store a newly created resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Back\Documents\StoreDocumentRequest $request
|
||||
* @param \App\Http\Requests\Back\Document\StoreDocumentRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(StoreDocumentRequest $request): \Illuminate\Http\RedirectResponse
|
||||
|
|
@ -144,8 +143,8 @@ class DocumentController extends Controller
|
|||
/**
|
||||
* Update the specified resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Back\Documents\UpdateDocumentRequest $request
|
||||
* @param \App\Models\Document $document
|
||||
* @param \App\Http\Requests\Back\Document\UpdateDocumentRequest $request
|
||||
* @param \App\Models\Document $document
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateDocumentRequest $request, Document $document): \Illuminate\Http\RedirectResponse
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace App\Http\Controllers\Back;
|
||||
|
||||
use App\Http\Requests\Back\DocumentTags\StoreDocumentTagRequest;
|
||||
use App\Http\Requests\Back\DocumentTags\UpdateDocumentTagRequest;
|
||||
use App\Http\Requests\Back\DocumentTag\StoreDocumentTagRequest;
|
||||
use App\Http\Requests\Back\DocumentTag\UpdateDocumentTagRequest;
|
||||
use App\Models\DocumentTag;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
|
@ -99,7 +99,7 @@ class DocumentTagController extends Controller
|
|||
/**
|
||||
* Store a newly created resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Back\DocumentTags\StoreDocumentTagRequest $request
|
||||
* @param \App\Http\Requests\Back\News\StoreDocumentTagRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(StoreDocumentTagRequest $request): \Illuminate\Http\RedirectResponse
|
||||
|
|
@ -131,8 +131,8 @@ class DocumentTagController extends Controller
|
|||
/**
|
||||
* Update the specified resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Back\DocumentTags\UpdateDocumentTagRequest $request
|
||||
* @param \App\Models\DocumentTag $document_tag
|
||||
* @param \App\Http\Requests\Back\News\UpdateDocumentTagRequest $request
|
||||
* @param \App\Models\DocumentTag $document_tag
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace App\Http\Controllers\Back;
|
||||
|
||||
use App\Enums\Contact\ContactFormType;
|
||||
use App\Enums\DynamicPages\PageStatusEnum;
|
||||
use App\Enums\ElementPositionEnum;
|
||||
use App\Http\Requests\Back\DynamicPages\StoreDynamicPageRequest;
|
||||
|
|
@ -93,7 +92,6 @@ class DynamicPageController extends Controller
|
|||
'pageConfigModels' => $pageConfigModels,
|
||||
'enumDynamicPageStatus' => PageStatusEnum::toArray(),
|
||||
'enumElementPosition' => ElementPositionEnum::toArray(),
|
||||
'enumContactFormType' => ContactFormType::toArray(),
|
||||
'modelName' => $this->modelName,
|
||||
]);
|
||||
}
|
||||
|
|
@ -152,9 +150,7 @@ class DynamicPageController extends Controller
|
|||
'pageConfigModels' => $pageConfigModels,
|
||||
'enumDynamicPageStatus' => PageStatusEnum::toArray(),
|
||||
'enumElementPosition' => ElementPositionEnum::toArray(),
|
||||
'enumContactFormType' => ContactFormType::toArray(),
|
||||
'modelName' => $this->modelName,
|
||||
'dynamicPageUrl' => DynamicPage::getAccessModel($dynamic_page->id),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,8 +43,9 @@ class InputsController extends Controller
|
|||
return response()->json(['error' => 'Invalid model class'], 404);
|
||||
}
|
||||
|
||||
|
||||
// Determine the field to display.
|
||||
$model = new $modelClass();
|
||||
$model = new $modelClass();
|
||||
$isTranslatable = method_exists($model, 'getTranslations');
|
||||
|
||||
$locale = app()->getLocale();
|
||||
|
|
@ -119,7 +120,7 @@ class InputsController extends Controller
|
|||
|
||||
$url = (method_exists($modelClass, 'getAccessModel'))
|
||||
? $modelClass::getAccessModel($validated['selectedEntry'])
|
||||
: self::getAccessModel($validated['selectedEntry'], $validated['modelName']);
|
||||
: static::getAccessModel($validated['selectedEntry'], $validated['modelName']);
|
||||
|
||||
$token = Crypt::encryptString(json_encode([
|
||||
'modelName' => $validated['modelName'],
|
||||
|
|
@ -183,7 +184,7 @@ class InputsController extends Controller
|
|||
public function uploadFile(UploadFileRequest $request): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
// Get the class of the target model and verify its existence.
|
||||
$modelName = Str::singular($request->validated()['folder']);
|
||||
$modelName = Str::singular($request->validated()['folder']);
|
||||
$modelClass = "App\\Models\\$modelName";
|
||||
if (!class_exists($modelClass)) {
|
||||
return response()->json(['error' => 'Invalid model class'], 404);
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
namespace App\Http\Controllers\Back;
|
||||
|
||||
use App\Enums\News\NewsStatusEnum;
|
||||
use App\Http\Requests\Back\NewsCategories\StoreNewsCategoryRequest;
|
||||
use App\Http\Requests\Back\NewsCategories\UpdateNewsCategoryRequest;
|
||||
use App\Http\Requests\Back\NewsCategory\StoreNewsCategoryRequest;
|
||||
use App\Http\Requests\Back\NewsCategory\UpdateNewsCategoryRequest;
|
||||
use App\Models\NewsCategory;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
|
@ -102,7 +102,7 @@ class NewsCategoryController extends Controller
|
|||
/**
|
||||
* Store a newly created resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Back\NewsCategories\StoreNewsCategoryRequest $request
|
||||
* @param \App\Http\Requests\Back\NewsCategory\StoreNewsCategoryRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(StoreNewsCategoryRequest $request): \Illuminate\Http\RedirectResponse
|
||||
|
|
@ -134,8 +134,8 @@ class NewsCategoryController extends Controller
|
|||
/**
|
||||
* Update the specified resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Back\NewsCategories\UpdateNewsCategoryRequest $request
|
||||
* @param \App\Models\NewsCategory $news_category
|
||||
* @param \App\Http\Requests\Back\News\UpdateNewsCategoryRequest $request
|
||||
* @param \App\Models\NewsCategory $news_category
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
namespace App\Http\Controllers\Back;
|
||||
|
||||
use App\Enums\News\NewsStatusEnum;
|
||||
use App\Http\Requests\Back\NewsTags\StoreNewsTagRequest;
|
||||
use App\Http\Requests\Back\NewsTags\UpdateNewsTagRequest;
|
||||
use App\Http\Requests\Back\NewsTag\StoreNewsTagRequest;
|
||||
use App\Http\Requests\Back\NewsTag\UpdateNewsTagRequest;
|
||||
use App\Models\NewsTag;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
|
@ -102,7 +102,7 @@ class NewsTagController extends Controller
|
|||
/**
|
||||
* Store a newly created resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Back\NewsTags\StoreNewsTagRequest $request
|
||||
* @param \App\Http\Requests\Back\NewsTag\StoreNewsTagRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(StoreNewsTagRequest $request): \Illuminate\Http\RedirectResponse
|
||||
|
|
@ -134,8 +134,8 @@ class NewsTagController extends Controller
|
|||
/**
|
||||
* Update the specified resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Back\NewsTags\UpdateNewsTagRequest $request
|
||||
* @param \App\Models\NewsTag $news_tag
|
||||
* @param \App\Http\Requests\Back\News\UpdateNewsTagRequest $request
|
||||
* @param \App\Models\NewsTag $news_tag
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateNewsTagRequest $request, NewsTag $news_tag): \Illuminate\Http\RedirectResponse
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use App\Http\Requests\Front\Contact\ContactRequest;
|
|||
use App\Jobs\Mails\SendContactMail;
|
||||
use App\Models\ContactCount;
|
||||
use App\Models\MailContactData;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\HtmlString;
|
||||
use LDC\LDCCRM\Enums\ApiError;
|
||||
|
|
@ -18,6 +17,33 @@ use LDC\LDCCRM\Models\SingleOptin;
|
|||
|
||||
class ContactController
|
||||
{
|
||||
/**
|
||||
* Show contact index page.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$types = ContactFormType::toArray();
|
||||
return view('front.pages.contact.index', compact('types'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show contact show page.
|
||||
*
|
||||
* @param string $slug
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(string $slug): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$enumType = collect(ContactFormType::all())->first(function ($enum) use ($slug) {
|
||||
return $enum->slug() === $slug;
|
||||
});
|
||||
if (!$enumType) {
|
||||
return redirect()->route('front.contact.index');
|
||||
}
|
||||
return view('front.pages.contact.show', compact('enumType'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Contact send.
|
||||
|
|
@ -27,16 +53,12 @@ class ContactController
|
|||
*/
|
||||
public function send(ContactRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$validatedData = $request->validated();
|
||||
$messageContact = new MailContactData($validatedData);
|
||||
$data = $request->validated();
|
||||
$messageContact = new MailContactData($data);
|
||||
$contactMessage = "";
|
||||
$hasContactError = false;
|
||||
$newsletterMessage = null;
|
||||
$hasNewsletterError = false;
|
||||
|
||||
/** @var boolean $isNewsletter */
|
||||
$isNewsletter = isset($validatedData['newsletter']) ? $validatedData['newsletter'] : false;
|
||||
|
||||
try {
|
||||
dispatch(new SendContactMail($messageContact))
|
||||
->onConnection('database')
|
||||
|
|
@ -48,7 +70,7 @@ class ContactController
|
|||
$hasContactError = true;
|
||||
$contactMessage = trans('Une erreur est survenue lors de l\'envoi du message de contact.');
|
||||
}
|
||||
if ($isNewsletter) {
|
||||
if (!empty($data['newsletter']) && $data['newsletter']) {
|
||||
try {
|
||||
SingleOptin::setStatus($request->email, true);
|
||||
$newsletterMessage = trans("Votre inscription à la newsletter a été prise en compte");
|
||||
|
|
@ -68,8 +90,8 @@ class ContactController
|
|||
}
|
||||
}
|
||||
ContactCount::updateOrInsert(
|
||||
['type' => $validatedData['enumType']],
|
||||
['submissions' => DB::raw('submissions + 1')]
|
||||
['type' => $data['enumType']],
|
||||
['submissions' => \DB::raw('submissions + 1')]
|
||||
);
|
||||
|
||||
$contactMessage = trans('Votre message a bien été envoyé.');
|
||||
|
|
|
|||
|
|
@ -68,14 +68,13 @@ class HomeController extends Controller
|
|||
/**
|
||||
* Call the CRM to add a single optin
|
||||
*
|
||||
* @param \App\Http\Requests\Front\SingleOptinRequest $request
|
||||
* @param \App\Http\Requests\Fo\SingleOptinRequest $request
|
||||
* @return string|array|null|\Illuminate\Contracts\Translation\Translator
|
||||
* @throws \LDC\LDCCRM\Exceptions\ValidationException ValidationException.
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException BindingResolutionException.
|
||||
*/
|
||||
public function addOptIn(
|
||||
SingleOptinRequest $request,
|
||||
): string|array|null|\Illuminate\Contracts\Translation\Translator {
|
||||
public function addOptIn(SingleOptinRequest $request)
|
||||
{
|
||||
try {
|
||||
SingleOptin::setStatus($request->email, true);
|
||||
return \response(trans("Votre inscription à la newsletter a été prise en compte"), 200);
|
||||
|
|
|
|||
|
|
@ -2,17 +2,16 @@
|
|||
|
||||
namespace App\Http\Controllers\Front;
|
||||
|
||||
use App\Enums\OrdersEnum;
|
||||
use App\Enums\YearsEnum;
|
||||
use App\Http\Requests\Front\PostsRequest;
|
||||
use App\Models\Document;
|
||||
use App\Models\DocumentTag;
|
||||
use Carbon\Carbon;
|
||||
use App\Models\News;
|
||||
use App\Models\NewsTag;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
|
||||
use Illuminate\Support\Collection;
|
||||
use App\Enums\YearsEnum;
|
||||
use App\Models\Document;
|
||||
use App\Enums\OrdersEnum;
|
||||
use App\Models\DocumentTag;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Collection;
|
||||
use App\Http\Requests\Front\PostsRequest;
|
||||
use Uwil\LaravelCommon\Controllers\Controller;
|
||||
use Uwil\LaravelCommon\Helpers\CollectionHelper;
|
||||
|
||||
|
|
@ -27,14 +26,12 @@ class PostsController extends Controller
|
|||
/**
|
||||
* Extract unique years from date field in a collection.
|
||||
*
|
||||
* @param EloquentCollection $model
|
||||
* @param string $field
|
||||
* @param \Illuminate\Support\Collection $model
|
||||
* @param string $field
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
private function getUniqueYearsFromCollection(
|
||||
EloquentCollection $model,
|
||||
string $field,
|
||||
): \Illuminate\Support\Collection {
|
||||
private function getUniqueYearsFromCollection(Collection $model, string $field): \Illuminate\Support\Collection
|
||||
{
|
||||
return $model->pluck($field)
|
||||
->map(fn($date) => Carbon::parse($date)->year)
|
||||
->unique()
|
||||
|
|
@ -58,30 +55,27 @@ class PostsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Build the common filters configuration for front-end listing pages.
|
||||
* If the type is "documents" the "order" filter is included.
|
||||
* Build the common filters configuration for front-end listing pages
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $category
|
||||
* @param EloquentCollection $publishedTags
|
||||
* @param EloquentCollection $model
|
||||
* If the type is "documents" the "order" filter is included
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $category
|
||||
* @param \Illuminate\Database\Eloquent\Collection $publishedTags
|
||||
* @param \Illuminate\Database\Eloquent\Collection $model
|
||||
* @return array
|
||||
*/
|
||||
private function getFilters(
|
||||
string $type,
|
||||
string $category,
|
||||
EloquentCollection $publishedTags,
|
||||
EloquentCollection $model,
|
||||
): array {
|
||||
private function getFilters(string $type, string $category, Collection $publishedTags, Collection $model): array
|
||||
{
|
||||
$filters = [];
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$tags = $publishedTags->map(fn(DocumentTag|NewsTag $tag) => [
|
||||
'title' => $tag->name,
|
||||
'tag' => $tag->slug,
|
||||
'category' => $category,
|
||||
])
|
||||
->values();
|
||||
$tags = collect($publishedTags)
|
||||
->map(fn($tag) => [
|
||||
'title' => $tag->name,
|
||||
'tag' => $tag->slug,
|
||||
'category' => $category,
|
||||
])
|
||||
->values();
|
||||
|
||||
$enumYears = collect(YearsEnum::toArray())
|
||||
->map(fn($year) => YearsEnum::make((int) $year->value))
|
||||
|
|
@ -146,19 +140,18 @@ class PostsController extends Controller
|
|||
*/
|
||||
public function ajaxLoadNews(PostsRequest $request): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
$validatedData = $request->validated();
|
||||
$data = $request->validated();
|
||||
$perPage = 9;
|
||||
$selectedFilters = [];
|
||||
|
||||
/** @var string $slugCategory */
|
||||
$slugCategory = $validatedData['category'];
|
||||
$category = $data['category'];
|
||||
app()->setLocale($data['locale']);
|
||||
|
||||
app()->setLocale($validatedData['locale']);
|
||||
$publishedNewsTags = NewsTag::getTagsByCategoryInCurrentLocale($category);
|
||||
|
||||
$publishedNewsTags = NewsTag::getTagsByCategoryInCurrentLocale($slugCategory);
|
||||
$newsModel = News::getPublishedNewsByCategoryInCurrentLocale($slugCategory);
|
||||
$newsModel = News::getPublishedNewsByCategoryInCurrentLocale($category);
|
||||
|
||||
$requestedTags = collect($validatedData['filters']['tags'] ?? '')
|
||||
$requestedTags = collect($data['filters']['tags'] ?? '')
|
||||
->filter()
|
||||
->unique()
|
||||
->values();
|
||||
|
|
@ -169,13 +162,13 @@ class PostsController extends Controller
|
|||
'title' => $tag->name,
|
||||
'tag' => $tag->slug,
|
||||
'color' => $tag->color,
|
||||
'category' => $slugCategory,
|
||||
'category' => $category,
|
||||
])
|
||||
->values();
|
||||
|
||||
if ($selectedTags->isNotEmpty()) {
|
||||
$newsModel = $newsModel->filter(function ($newsModel) use ($selectedTags) {
|
||||
return $newsModel->tags->contains(
|
||||
$newsModel = $newsModel->filter(function ($news) use ($selectedTags) {
|
||||
return $news->tags->contains(
|
||||
fn ($tag) => $selectedTags->contains('id', $tag->id)
|
||||
);
|
||||
});
|
||||
|
|
@ -183,14 +176,14 @@ class PostsController extends Controller
|
|||
$selectedFilters['tags'] = $selectedTags;
|
||||
}
|
||||
|
||||
$selectedYears = collect($validatedData['filters']['years'] ?? '')
|
||||
$selectedYears = collect($data['filters']['years'] ?? '')
|
||||
->map(fn (string $label) => YearsEnum::makeFromLabel(Str::replace('-', '/', $label)))
|
||||
->filter()
|
||||
->map(fn($year) => [
|
||||
'title' => $year->label(),
|
||||
'tag' => Str::replace('/', '-', $year->label()),
|
||||
'value' => explode('/', $year->label())[1],
|
||||
'category' => $slugCategory,
|
||||
'category' => $category,
|
||||
])
|
||||
->values();
|
||||
|
||||
|
|
@ -204,7 +197,7 @@ class PostsController extends Controller
|
|||
|
||||
$newsModel = $newsModel->sortByDesc('published_at');
|
||||
|
||||
$filters = $this->getFilters('news', $slugCategory, $publishedNewsTags, $newsModel);
|
||||
$filters = $this->getFilters('news', $category, $publishedNewsTags, $newsModel);
|
||||
|
||||
// Custom pagination.
|
||||
$newsModel = CollectionHelper::paginate($newsModel, $perPage);
|
||||
|
|
@ -234,36 +227,36 @@ class PostsController extends Controller
|
|||
*/
|
||||
public function ajaxLoadDocuments(PostsRequest $request): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
$validatedData = $request->validated();
|
||||
$data = $request->validated();
|
||||
$perPage = 3;
|
||||
$selectedFilters = [];
|
||||
|
||||
/** @var string $slugCategory */
|
||||
$slugCategory = $validatedData['category'];
|
||||
$category = $data['category'];
|
||||
app()->setLocale($data['locale']);
|
||||
|
||||
app()->setLocale($validatedData['locale']);
|
||||
$publishedDocumentsTags = DocumentTag::getTagsByCategoryInCurrentLocale($category);
|
||||
|
||||
$documentTagModels = DocumentTag::getTagsByCategoryInCurrentLocale($slugCategory);
|
||||
$documentModels = Document::getPublishedDocumentsByCategoryInCurrentLocale($slugCategory);
|
||||
$documentsModel = Document::getPublishedDocumentsByCategoryInCurrentLocale($category);
|
||||
|
||||
$requestedTags = collect($validatedData['filters']['tags'] ?? '')
|
||||
$requestedTags = collect($data['filters']['tags'] ?? '')
|
||||
->filter()
|
||||
->unique()
|
||||
->values();
|
||||
$selectedTags = $documentTagModels
|
||||
|
||||
$selectedTags = $publishedDocumentsTags
|
||||
->filter(fn ($tag) => $requestedTags->contains($tag->slug ?? null))
|
||||
->map(fn ($tag) => [
|
||||
'id' => $tag->id,
|
||||
'title' => $tag->name,
|
||||
'tag' => $tag->slug,
|
||||
'color' => $tag->color,
|
||||
'category' => $slugCategory,
|
||||
'category' => $category,
|
||||
])
|
||||
->values();
|
||||
|
||||
if ($selectedTags->isNotEmpty()) {
|
||||
$documentModels = $documentModels->filter(function ($documentModel) use ($selectedTags) {
|
||||
return $documentModel->tags->contains(
|
||||
$documentsModel = $documentsModel->filter(function ($documents) use ($selectedTags) {
|
||||
return $documents->tags->contains(
|
||||
fn ($tag) => $selectedTags->contains('id', $tag->id)
|
||||
);
|
||||
});
|
||||
|
|
@ -271,65 +264,64 @@ class PostsController extends Controller
|
|||
$selectedFilters['tags'] = $selectedTags;
|
||||
}
|
||||
|
||||
$selectedYears = collect($validatedData['filters']['years'] ?? '')
|
||||
$selectedYears = collect($data['filters']['years'] ?? '')
|
||||
->map(fn (string $label) => YearsEnum::makeFromLabel(Str::replace('-', '/', $label)))
|
||||
->filter()
|
||||
->map(fn($year) => [
|
||||
'title' => $year->label(),
|
||||
'tag' => Str::replace('/', '-', $year->label()),
|
||||
'value' => $year->value,
|
||||
'category' => $slugCategory,
|
||||
'category' => $category,
|
||||
])
|
||||
->values();
|
||||
|
||||
if ($selectedYears->isNotEmpty()) {
|
||||
$documentModels = $documentModels->filter(function ($documentModel) use ($selectedYears) {
|
||||
return $selectedYears->contains('value', $documentModel->exercice);
|
||||
$documentsModel = $documentsModel->filter(function ($documents) use ($selectedYears) {
|
||||
return $selectedYears->contains('value', $documents->exercice);
|
||||
});
|
||||
|
||||
$selectedFilters['years'] = $selectedYears;
|
||||
}
|
||||
|
||||
$selectedOrder = collect($validatedData['filters']['order'] ?? '')
|
||||
$selectedOrder = collect($data['filters']['order'] ?? '')
|
||||
->map(fn (string $label) => OrdersEnum::makeFromLabel($label))
|
||||
->filter()
|
||||
->map(fn($order) => [
|
||||
'title' => trans($order->label()),
|
||||
'tag' => $order->name(),
|
||||
'category' => $slugCategory,
|
||||
'category' => $category,
|
||||
])
|
||||
->values();
|
||||
|
||||
if ($selectedOrder->isNotEmpty()) {
|
||||
$firstTag = $selectedOrder->map(fn($order) => $order['tag'])->first();
|
||||
$documentModels = $firstTag === 'desc'
|
||||
? $documentModels->sortByDesc('published_at')
|
||||
: $documentModels->sortBy('published_at');
|
||||
$documentsModel = $selectedOrder->map->tag->first() === 'desc'
|
||||
? $documentsModel->sortByDesc('published_at')
|
||||
: $documentsModel->sortBy('published_at');
|
||||
|
||||
$selectedFilters['order'] = $selectedOrder->all();
|
||||
} else {
|
||||
$documentModels = $documentModels->sortByDesc('published_at');
|
||||
$documentsModel = $documentsModel->sortByDesc('published_at');
|
||||
}
|
||||
|
||||
$filters = $this->getFilters('documents', $slugCategory, $documentTagModels, $documentModels);
|
||||
$filters = $this->getFilters('documents', $category, $publishedDocumentsTags, $documentsModel);
|
||||
|
||||
// Custom pagination.
|
||||
$documentModels = CollectionHelper::paginate($documentModels, $perPage);
|
||||
$documentsModel = CollectionHelper::paginate($documentsModel, $perPage);
|
||||
|
||||
return response()->json([
|
||||
'pagination' => [
|
||||
'total' => $documentModels->total(),
|
||||
'nbItems' => count($documentModels->items()),
|
||||
'currentPage' => $documentModels->currentPage(),
|
||||
'lastPage' => $documentModels->lastPage(),
|
||||
'hasMore' => $documentModels->currentPage() < $documentModels->lastPage(),
|
||||
'total' => $documentsModel->total(),
|
||||
'nbItems' => count($documentsModel->items()),
|
||||
'currentPage' => $documentsModel->currentPage(),
|
||||
'lastPage' => $documentsModel->lastPage(),
|
||||
'hasMore' => $documentsModel->currentPage() < $documentsModel->lastPage(),
|
||||
],
|
||||
'filters' => view('components.front.posts.filters-dropdowns', ['filters' => $filters])->render(),
|
||||
'selectedFilters' => view('components.front.posts.selected-filters', [
|
||||
'selectedFilters' => $selectedFilters,
|
||||
])->render(),
|
||||
'news' => view('components.front.posts.documents', [
|
||||
'documentsList' => $documentModels->items(),
|
||||
'documentsList' => $documentsModel->items(),
|
||||
])->render()
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,10 +20,9 @@ class ForceLocale
|
|||
* The issue occurred when two browser tabs were open in different locales:
|
||||
* the data being saved could end up using the other tab’s locale.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param Closure $next
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @return mixed
|
||||
* @throws ValidationException Not supported locale.
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): mixed
|
||||
{
|
||||
|
|
@ -44,7 +43,7 @@ class ForceLocale
|
|||
$requestLocale = $request->locale ?? config('app.fallback_locale');
|
||||
// 2. If prefix is not in supportedLocales
|
||||
if (!in_array($requestLocale, LaravelLocalization::getSupportedLanguagesKeys(), true)) {
|
||||
throw ValidationException::withMessages(["Langue" => "Not supported locale."]);
|
||||
throw ValidationException::withMessages(["Langue" => "locale pas accepté"]);
|
||||
}
|
||||
// 3. Set new locale if locale and prefix are not the same
|
||||
if ($requestLocale !== app()->getLocale()) {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ namespace App\Http\Middleware;
|
|||
use App\Enums\DynamicFieldTypes;
|
||||
use App\Enums\ModelsList;
|
||||
use App\Enums\StaticRoutesEnum;
|
||||
use App\Enums\VideoProviderEnum;
|
||||
use App\Helpers\TranslationHelper;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyActivity;
|
||||
|
|
@ -140,7 +139,6 @@ class HandleInertiaRequests extends Middleware
|
|||
'enumDynamicFieldTypes' => DynamicFieldTypes::toArray(),
|
||||
'enumModelsList' => ModelsList::toArray(),
|
||||
'enumStaticRoutes' => StaticRoutesEnum::getRoutes(),
|
||||
'videoProviderEnum' => VideoProviderEnum::toArray(),
|
||||
'errors' => $errors,
|
||||
'translations' => $translations,
|
||||
];
|
||||
|
|
|
|||
|
|
@ -5,18 +5,13 @@ namespace App\Http\Middleware;
|
|||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
|
||||
class Lang
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
* Not used but need it for uwil package.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
|
||||
public function handle(Request $request, Closure $next): mixed
|
||||
{
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,9 @@
|
|||
namespace App\Http\Requests\Back\Companies;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Traits\Requests\HasInertiaPicture;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use App\Traits\Requests\HasInertiaPicture;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Uwil\LaravelCommon\Rules\WysiwygLength;
|
||||
|
||||
class StoreCompanyRequest extends FormRequest
|
||||
{
|
||||
|
|
@ -49,7 +48,7 @@ class StoreCompanyRequest extends FormRequest
|
|||
),
|
||||
'responsable' => 'required|nullable|string|between:3,255',
|
||||
'url' => 'nullable|string|between:3,255',
|
||||
'informations' => ['required', 'string', new WysiwygLength(10, 5000)],
|
||||
'informations' => 'required|string|between:3,255',
|
||||
'employees' => 'required|nullable|numeric|between:0,100000',
|
||||
'latitude' => 'required|numeric|between:-90,90',
|
||||
'longitude' => 'required|numeric|between:-180,180',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Back\Documents;
|
||||
namespace App\Http\Requests\Back\Document;
|
||||
|
||||
use App\Enums\Document\DocumentStatusEnum;
|
||||
use App\Enums\YearsEnum;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Back\Documents;
|
||||
namespace App\Http\Requests\Back\Document;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Back\DocumentCategories;
|
||||
namespace App\Http\Requests\Back\DocumentCategory;
|
||||
|
||||
use App\Models\DocumentCategory;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Back\DocumentCategories;
|
||||
namespace App\Http\Requests\Back\DocumentCategory;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Back\DocumentTags;
|
||||
namespace App\Http\Requests\Back\DocumentTag;
|
||||
|
||||
use App\Models\DocumentTag;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Back\DocumentTags;
|
||||
namespace App\Http\Requests\Back\DocumentTag;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
|
|
@ -4,7 +4,6 @@ namespace App\Http\Requests\Back\News;
|
|||
|
||||
use App\Enums\News\NewsStatusEnum;
|
||||
use App\Models\News;
|
||||
use App\Rules\Video;
|
||||
use App\Traits\Requests\HasInertiaPicture;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Back\NewsCategories;
|
||||
namespace App\Http\Requests\Back\NewsCategory;
|
||||
|
||||
use App\Models\NewsCategory;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Back\NewsCategories;
|
||||
namespace App\Http\Requests\Back\NewsCategory;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Back\NewsTags;
|
||||
namespace App\Http\Requests\Back\NewsTag;
|
||||
|
||||
use App\Models\NewsTag;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Back\NewsTags;
|
||||
namespace App\Http\Requests\Back\NewsTag;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ class StorePageConfigRequest extends FormRequest
|
|||
'string',
|
||||
'between:3,255',
|
||||
'regex:/^[a-z0-9]+(?:[-_][a-z0-9]+)*$/',
|
||||
function ($attribute, $value, $fail) {
|
||||
function ($attribute, $value, $fail) use ($prefix) {
|
||||
$parentPath = implode('.', array_slice(explode('.', $attribute), 0, -2));
|
||||
$levelItems = data_get($this->input(), $parentPath, []);
|
||||
$keysAtLevel = collect($levelItems)->pluck('key')->filter()->toArray();
|
||||
|
|
|
|||
|
|
@ -2,12 +2,9 @@
|
|||
|
||||
namespace App\Http\Requests\Back;
|
||||
|
||||
use App\Enums\Contact\ContactFormType;
|
||||
use App\Enums\ElementPositionEnum;
|
||||
use App\Enums\DynamicFieldTypes;
|
||||
use App\Enums\StaticRoutesEnum;
|
||||
use App\Models\PageConfig;
|
||||
use App\Rules\Video;
|
||||
use App\Traits\Requests\HasInertiaPicture;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Str;
|
||||
|
|
@ -203,19 +200,6 @@ abstract class UpdateDynamicFieldRequest extends FormRequest
|
|||
),
|
||||
]);
|
||||
break;
|
||||
case DynamicFieldTypes::contactform->value:
|
||||
$rules = array_merge($rules, [
|
||||
$ruleKey => array_merge(
|
||||
$this->compileValidate(DynamicFieldTypes::position->getValidation(), $input),
|
||||
[new Enum(ContactFormType::class)],
|
||||
),
|
||||
]);
|
||||
break;
|
||||
case DynamicFieldTypes::video->value:
|
||||
$rules = array_merge($rules, [
|
||||
$ruleKey => new Video(),
|
||||
]);
|
||||
break;
|
||||
default:
|
||||
throw new \UnexpectedValueException("Unrecognized dynamic type: " . ($input['type'] ?? 'null'));
|
||||
} //end switch
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ namespace App\Http\Requests\Front\Contact;
|
|||
use App\Enums\Contact\BreedType;
|
||||
use App\Enums\Contact\ContactFormType;
|
||||
use App\Enums\Contact\CustomerAskingType;
|
||||
use App\Enums\Contact\ExportAskingType;
|
||||
use App\Enums\Contact\PressType;
|
||||
use App\Enums\Department;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
|
@ -94,19 +93,12 @@ class ContactRequest extends FormRequest
|
|||
|
||||
// Validation for restauration and export commun fields.
|
||||
if (
|
||||
ContactFormType::restauration->equals(ContactFormType::make($typeContactForm))
|
||||
) {
|
||||
$rules = array_merge($rules, [
|
||||
'type' => ['array', 'min:1'],
|
||||
'type.*' => [Rule::enum(CustomerAskingType::class)],
|
||||
]);
|
||||
}
|
||||
if (
|
||||
ContactFormType::restauration->equals(ContactFormType::make($typeContactForm)) ||
|
||||
ContactFormType::export->equals(ContactFormType::make($typeContactForm))
|
||||
) {
|
||||
$rules = array_merge($rules, [
|
||||
'type' => ['array', 'min:1'],
|
||||
'type.*' => [Rule::enum(ExportAskingType::class)],
|
||||
'type.*' => [Rule::enum(CustomerAskingType::class)],
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,10 @@
|
|||
|
||||
namespace App\Http\Requests\Front;
|
||||
|
||||
use App\Traits\Requests\Api\HasLaravelFailedValidation;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class PostsRequest extends FormRequest
|
||||
{
|
||||
use HasLaravelFailedValidation;
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
|
|
@ -19,7 +16,7 @@ class PostsRequest extends FormRequest
|
|||
return [
|
||||
'page' => 'required|integer',
|
||||
'category' => 'required|string',
|
||||
'locale' => ['required', 'string', Rule::in(config('app.locales'))],
|
||||
'locale' => 'required|string',
|
||||
'filters' => 'nullable|array',
|
||||
'filters.order' => 'nullable|string|in:asc,desc',
|
||||
'filters.tags' => 'nullable|array',
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class Company extends Model
|
|||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
* @var array<int, string, array[]>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
|
|
@ -67,7 +67,7 @@ class Company extends Model
|
|||
/**
|
||||
* Relations should be included in the cache.
|
||||
*
|
||||
* @var list<string>
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected static $cacheRelations = [
|
||||
'companyActivity',
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class CompanyActivity extends Model implements TranslatableModel
|
|||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
* @var array<int, string, array[]>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class CompanySector extends Model implements TranslatableModel
|
|||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
* @var array<int, string, array[]>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ class ContactCount extends Model
|
|||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'type',
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use App\Enums\Document\DocumentStatusEnum;
|
|||
use App\Enums\YearsEnum;
|
||||
use App\Helpers\DocumentHelper;
|
||||
use App\Helpers\TranslationHelper;
|
||||
use App\Models\Documentable;
|
||||
use App\Traits\Models\HasCache;
|
||||
use App\Traits\Models\HasTranslations;
|
||||
use App\Traits\Models\HasUwilImages;
|
||||
|
|
@ -19,32 +18,6 @@ use Illuminate\Support\Facades\App;
|
|||
use Laravel\Scout\Searchable;
|
||||
use Uwil\LaravelActivityLogs\Traits\ActivityLog;
|
||||
|
||||
/**
|
||||
* @property integer $id
|
||||
* Id of the document.
|
||||
* @property string $name
|
||||
* Name of the document.
|
||||
* @property string $path
|
||||
* Path of the document.
|
||||
* @property boolean $is_issuu
|
||||
* Issu status of the document.
|
||||
* @property string $issuu_path
|
||||
* Issu path of the document.
|
||||
* @property string $exercice
|
||||
* Exercice of the document.
|
||||
* @property \App\Enums\Document\DocumentStatusEnum $status
|
||||
* Status of the document.
|
||||
* @property-read \Carbon\Carbon $created_at
|
||||
* Created date of the document.
|
||||
* @property-read \Carbon\Carbon $updated_at
|
||||
* Updated date of the document.
|
||||
* @property-read \Illuminate\Support\Carbon $deleted_at
|
||||
* Deleted date of the document.
|
||||
* @property \Illuminate\Database\Eloquent\Collection<int, \App\Models\DocumentCategory> $categories
|
||||
* Associated document categories of the document.
|
||||
* @property \Illuminate\Database\Eloquent\Collection<int, \App\Models\DocumentTag> $tags
|
||||
* Associated document tags of the document.
|
||||
*/
|
||||
class Document extends Model implements TranslatableModel
|
||||
{
|
||||
use ActivityLog;
|
||||
|
|
@ -108,7 +81,7 @@ class Document extends Model implements TranslatableModel
|
|||
/**
|
||||
* Relations should be included in the cache.
|
||||
*
|
||||
* @var list<string>
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected static $cacheRelations = [
|
||||
'categories',
|
||||
|
|
@ -351,24 +324,24 @@ class Document extends Model implements TranslatableModel
|
|||
/**
|
||||
* Get all published news by category.
|
||||
*
|
||||
* @param string $slugCategory
|
||||
* @return \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document>
|
||||
* @param string $category
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public static function getPublishedDocumentsByCategoryInCurrentLocale(
|
||||
string $slugCategory,
|
||||
): \Illuminate\Database\Eloquent\Collection {
|
||||
public static function getPublishedDocumentsByCategoryInCurrentLocale(string $category)
|
||||
{
|
||||
$locale = App::getLocale();
|
||||
|
||||
return Document::getModelsCached()
|
||||
->where('status', DocumentStatusEnum::published)
|
||||
->filter(function ($document) use ($slugCategory, $locale) {
|
||||
->filter(function ($document) use ($category, $locale) {
|
||||
$hasPath = !empty($document->getTranslation('path', $locale, false));
|
||||
|
||||
$hasIssuuPath = $document->is_issuu === true
|
||||
&& !empty($document->getTranslation('issuu_path', $locale, false));
|
||||
|
||||
return ($hasPath || $hasIssuuPath) && $document->categories->contains(
|
||||
fn($documentCategoryModel) => $documentCategoryModel->slug === $slugCategory
|
||||
fn($cat) => $cat->slug === $category
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
@ -376,11 +349,11 @@ class Document extends Model implements TranslatableModel
|
|||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
* Relation to Tag.
|
||||
* Relation to Tag
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function tags(): \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
public function tags(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
{
|
||||
return $this->morphedByMany(
|
||||
DocumentTag::class,
|
||||
|
|
@ -388,15 +361,15 @@ class Document extends Model implements TranslatableModel
|
|||
'documentables',
|
||||
'document_id',
|
||||
'documentable_id'
|
||||
)->using(Documentable::class)->withTimestamps();
|
||||
)->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* Relation to Category.
|
||||
* Relation to Category
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function categories(): \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
public function categories(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
{
|
||||
return $this->morphedByMany(
|
||||
DocumentCategory::class,
|
||||
|
|
@ -404,6 +377,6 @@ class Document extends Model implements TranslatableModel
|
|||
'documentables',
|
||||
'document_id',
|
||||
'documentable_id'
|
||||
)->using(Documentable::class)->withTimestamps();
|
||||
)->withTimestamps();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,22 +10,6 @@ use Illuminate\Database\Eloquent\Model;
|
|||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Uwil\LaravelActivityLogs\Traits\ActivityLog;
|
||||
|
||||
/**
|
||||
* @property integer $id
|
||||
* Id of the category.
|
||||
* @property string $name
|
||||
* Name of the category.
|
||||
* @property string $slug
|
||||
* Slug of the category.
|
||||
* @property-read \Carbon\Carbon $created_at
|
||||
* Created date of the category.
|
||||
* @property-read \Carbon\Carbon $updated_at
|
||||
* Updated date of the category.
|
||||
* @property-read \Illuminate\Support\Carbon $deleted_at
|
||||
* Deleted date of the category.
|
||||
* @property \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||
* Associated documents of the category.
|
||||
*/
|
||||
class DocumentCategory extends Model implements TranslatableModel
|
||||
{
|
||||
use ActivityLog;
|
||||
|
|
@ -54,14 +38,12 @@ class DocumentCategory extends Model implements TranslatableModel
|
|||
'slug'
|
||||
];
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
* Associated documents of the category.
|
||||
* Relation to Document
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function documents(): \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
public function documents(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
{
|
||||
return $this->morphToMany(
|
||||
Document::class,
|
||||
|
|
|
|||
|
|
@ -11,24 +11,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||
use Illuminate\Support\Facades\App;
|
||||
use Uwil\LaravelActivityLogs\Traits\ActivityLog;
|
||||
|
||||
/**
|
||||
* @property integer $id
|
||||
* Id of the tag.
|
||||
* @property string $name
|
||||
* Name of the tag.
|
||||
* @property string $slug
|
||||
* Slug of the tag.
|
||||
* @property string $color
|
||||
* Color of the tag.
|
||||
* @property-read \Carbon\Carbon $created_at
|
||||
* Created date of the tag.
|
||||
* @property-read \Carbon\Carbon $updated_at
|
||||
* Updated date of the tag.
|
||||
* @property-read \Illuminate\Support\Carbon $deleted_at
|
||||
* Deleted date of the tag.
|
||||
* @property \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||
* Associated documents of the tag.
|
||||
*/
|
||||
class DocumentTag extends Model implements TranslatableModel
|
||||
{
|
||||
use ActivityLog;
|
||||
|
|
@ -61,20 +43,34 @@ class DocumentTag extends Model implements TranslatableModel
|
|||
/**
|
||||
* Relations should be included in the cache.
|
||||
*
|
||||
* @var list<string>
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected static $cacheRelations = [
|
||||
'documents',
|
||||
];
|
||||
|
||||
// * METHODS
|
||||
/**
|
||||
* Relation to Document
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function documents(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
{
|
||||
return $this->morphToMany(
|
||||
Document::class,
|
||||
'documentable',
|
||||
'documentables',
|
||||
'documentable_id',
|
||||
'document_id'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Tags by category.
|
||||
*
|
||||
* @param string $slugCategory
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection<int, \App\Models\DocumentTag>
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public static function getTagsByCategoryInCurrentLocale(
|
||||
string $slugCategory,
|
||||
|
|
@ -96,22 +92,4 @@ class DocumentTag extends Model implements TranslatableModel
|
|||
})->isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
* Associated documents of the tag.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
*/
|
||||
public function documents(): \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
{
|
||||
return $this->morphToMany(
|
||||
Document::class,
|
||||
'documentable',
|
||||
'documentables',
|
||||
'documentable_id',
|
||||
'document_id'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\MorphPivot;
|
||||
|
||||
/**
|
||||
* @property integer $id Id of the document.
|
||||
* @property \App\Models\Document $document_id Name of the document.
|
||||
* @property \App\Models\DocumentCategory|\App\Models\DocumentTag $documentable_id Name of the category or tag.
|
||||
* @property class-string<static> $documentable_type Class of the category or tag.
|
||||
* @property-read \Carbon\Carbon $created_at Created date of the document.
|
||||
* @property-read \Carbon\Carbon $updated_at Updated date of the document.
|
||||
*/
|
||||
class Documentable extends MorphPivot
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $table = 'documentables';
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::created(fn() => Document::resetCache());
|
||||
static::updated(fn() => Document::resetCache());
|
||||
static::deleted(fn() => Document::resetCache());
|
||||
}
|
||||
}
|
||||
|
|
@ -13,15 +13,11 @@ use App\Traits\Models\HasUwilImages;
|
|||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Laravel\Scout\Searchable;
|
||||
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
|
||||
use Uwil\LaravelActivityLogs\Traits\ActivityLog;
|
||||
use Spatie\Sitemap\Contracts\Sitemapable;
|
||||
use Spatie\Sitemap\Tags\Url;
|
||||
use Uwil\SitemapGenerator\Lib\SitemapHelper;
|
||||
|
||||
/**
|
||||
* @property string $id_key Unique key identification of the dynamic page.
|
||||
|
|
@ -37,7 +33,7 @@ use Uwil\SitemapGenerator\Lib\SitemapHelper;
|
|||
* @property-read \Illuminate\Support\Carbon $updated_at Date on which the dynamic page was updated.
|
||||
* @property-read \Illuminate\Support\Carbon $deleted_at Date on which the dynamic page was updated.
|
||||
*/
|
||||
class DynamicPage extends Model implements TranslatableModel, Sitemapable
|
||||
class DynamicPage extends Model implements TranslatableModel
|
||||
{
|
||||
use ActivityLog;
|
||||
use HasCache;
|
||||
|
|
@ -90,7 +86,7 @@ class DynamicPage extends Model implements TranslatableModel, Sitemapable
|
|||
/**
|
||||
* Relations should be included in the cache.
|
||||
*
|
||||
* @var list<string>
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected static $cacheRelations = [
|
||||
'config',
|
||||
|
|
@ -108,14 +104,7 @@ class DynamicPage extends Model implements TranslatableModel, Sitemapable
|
|||
static::creating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
// Set id_key from title.
|
||||
$idKey = self::generateUniqueField(
|
||||
'dynamic_pages',
|
||||
'id_key',
|
||||
Str::slug($model->title),
|
||||
$model->id
|
||||
);
|
||||
|
||||
$model->id_key = $idKey;
|
||||
$model->id_key = Str::slug($model->title);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
|
|
@ -142,42 +131,6 @@ class DynamicPage extends Model implements TranslatableModel, Sitemapable
|
|||
}
|
||||
|
||||
// * METHODS
|
||||
/**
|
||||
* Generate unique value from model field
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $field
|
||||
* @param string $baseValue
|
||||
* @param mixed $ignoreId
|
||||
* @return string
|
||||
*/
|
||||
public static function generateUniqueField(
|
||||
string $table,
|
||||
string $field,
|
||||
string $baseValue,
|
||||
int|string|null $ignoreId = null
|
||||
): string {
|
||||
$value = $baseValue;
|
||||
$counter = 1;
|
||||
|
||||
// Boucle tant que le slug existe en base
|
||||
while (true) {
|
||||
$query = DB::table($table)->where($field, $value);
|
||||
|
||||
if ($ignoreId) {
|
||||
$query->where('id', '!=', $ignoreId);
|
||||
}
|
||||
|
||||
if (!$query->exists()) {
|
||||
// On a trouvé un slug unique
|
||||
return $value;
|
||||
}
|
||||
|
||||
// Sinon on incrémente le suffixe
|
||||
$value = $baseValue . '_' . $counter;
|
||||
$counter++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpublished all children pages if change status published from draft/unpublished.
|
||||
|
|
@ -245,8 +198,8 @@ class DynamicPage extends Model implements TranslatableModel, Sitemapable
|
|||
self::assertRootIsUnique($model);
|
||||
} else {
|
||||
$slug = $model->slug ?? Str::slug($model->title);
|
||||
TranslationHelper::assertTranslationFieldIsUnique($model, $model->title, 'title', $model->page_id, 'page_id');
|
||||
TranslationHelper::assertTranslationFieldIsUnique($model, $slug, 'slug', $model->page_id, 'page_id');
|
||||
TranslationHelper::assertTranslationFieldIsUnique($model, $model->title, 'title');
|
||||
TranslationHelper::assertTranslationFieldIsUnique($model, $slug, 'slug');
|
||||
$model->setAttribute('slug', $slug);
|
||||
}
|
||||
// Check translations.
|
||||
|
|
@ -374,7 +327,7 @@ class DynamicPage extends Model implements TranslatableModel, Sitemapable
|
|||
/**
|
||||
* Get fields that we want to keep in the current locale.
|
||||
*
|
||||
* @return array
|
||||
* @return array.
|
||||
*/
|
||||
public static function searchTransFields(): array
|
||||
{
|
||||
|
|
@ -460,7 +413,7 @@ class DynamicPage extends Model implements TranslatableModel, Sitemapable
|
|||
? strip_tags(collect($this->getTranslation('content', $locale))
|
||||
->flatten()
|
||||
->filter(fn($value, $key) =>
|
||||
is_string($value) &&
|
||||
is_string($value) &&
|
||||
!empty($value) &&
|
||||
!is_numeric($value) &&
|
||||
!in_array($key, ['order', 'id']) &&
|
||||
|
|
@ -475,47 +428,6 @@ class DynamicPage extends Model implements TranslatableModel, Sitemapable
|
|||
return $data;
|
||||
}
|
||||
|
||||
// * SITEMAP
|
||||
|
||||
/**
|
||||
* toSitemapTag method
|
||||
*
|
||||
* @return Url|string|array
|
||||
*/
|
||||
public function toSitemapTag(): Url | string | array
|
||||
{
|
||||
$sitemapLines = [];
|
||||
$locales = array_keys(config('laravellocalization.supportedLocales', ['fr' => "Français"]));
|
||||
|
||||
foreach ($locales as $locale) {
|
||||
$slug = $this->getTranslation('slug', $locale, false);
|
||||
|
||||
// Homepage has no slug.
|
||||
if ($slug || $this->isRoot) {
|
||||
$sitemapLines[] = SitemapHelper::generateUrl(
|
||||
$this->getLocalizedUrl($locale),
|
||||
locales: $this->locales(),
|
||||
getAlternate: fn (string $locale) => $this->getLocalizedUrl($locale)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $sitemapLines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get localized URL.
|
||||
*
|
||||
* @param string $locale
|
||||
* @return string|false
|
||||
*/
|
||||
public function getLocalizedUrl(string $locale): string|false
|
||||
{
|
||||
return in_array($locale, $this->locales()) ?
|
||||
route("front.dynamic-pages.$this->id_key.$locale") :
|
||||
false;
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class MailContactData extends Model
|
|||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
* @var array<int, string, array[]>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'enumType',
|
||||
|
|
|
|||
|
|
@ -17,56 +17,34 @@ use Illuminate\Support\Arr;
|
|||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Scout\Searchable;
|
||||
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
|
||||
use Mcamara\LaravelLocalization\Interfaces\LocalizedUrlRoutable;
|
||||
use Uwil\LaravelActivityLogs\Traits\ActivityLog;
|
||||
use Spatie\Sitemap\Tags\Url;
|
||||
use Uwil\SitemapGenerator\Interfaces\Sitemapable;
|
||||
use Uwil\SitemapGenerator\Lib\SitemapHelper;
|
||||
|
||||
/**
|
||||
* @property string $seo_title
|
||||
* SEO title of the news.
|
||||
* @property string $seo_description
|
||||
* SEO description of the news.
|
||||
* @property string $title
|
||||
* Title of the news.
|
||||
* @property string $slug
|
||||
* Slug of the news.
|
||||
* @property string $picture
|
||||
* Main img of the news.
|
||||
* @property string $picture_alt
|
||||
* Alt text for the picture.
|
||||
* @property string $picture_title
|
||||
* Title for the picture.
|
||||
* @property string $content
|
||||
* Content of the news.
|
||||
* @property boolean $inverted
|
||||
* Are image and content inverted in front
|
||||
* @property string $vimeo_id
|
||||
* Optionnal vimeo_id
|
||||
* @property boolean $has_show_picture
|
||||
* Show the picture in the show page
|
||||
* @property \App\Enums\News\NewsStatusEnum $status
|
||||
* Status of the news.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at
|
||||
* Date on which the news was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at
|
||||
* Date on which the news was updated.
|
||||
* @property-read \Illuminate\Support\Carbon $deleted_at
|
||||
* Date on which the news was updated.
|
||||
* @property \Illuminate\Database\Eloquent\Collection<int, \App\Models\NewsCategory> $categories
|
||||
* Associated news categories of the news.
|
||||
* @property \Illuminate\Database\Eloquent\Collection<int, \App\Models\NewsTag> $tags
|
||||
* Associated news tags of the news.
|
||||
* @property string $seo_title SEO title of the news.
|
||||
* @property string $seo_description SEO description of the news.
|
||||
* @property string $title Title of the news.
|
||||
* @property string $slug Slug of the news.
|
||||
* @property string $picture Main img of the news.
|
||||
* @property string $picture_alt Alt text for the picture.
|
||||
* @property string $picture_title Title for the picture.
|
||||
* @property string $content Content of the news.
|
||||
* @property boolean $inverted Are image and content inverted in front
|
||||
* @property string $vimeo_id Optionnal vimeo_id
|
||||
* @property boolean $has_show_picture Show the picture in the show page
|
||||
* @property \App\Enums\News\NewsStatusEnum $status Status of the news.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Date on which the news was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Date on which the news was updated.
|
||||
* @property-read \Illuminate\Support\Carbon $deleted_at Date on which the news was updated.
|
||||
*/
|
||||
class News extends Model implements TranslatableModel, LocalizedUrlRoutable, Sitemapable
|
||||
class News extends Model implements TranslatableModel, LocalizedUrlRoutable
|
||||
{
|
||||
use ActivityLog;
|
||||
use HasCache;
|
||||
use HasFactory;
|
||||
use HasTranslations;
|
||||
use SoftDeletes;
|
||||
use HasCache;
|
||||
use HasUwilImages {
|
||||
HasUwilImages::inertiaFill as traitInertiaFill;
|
||||
}
|
||||
|
|
@ -135,7 +113,7 @@ class News extends Model implements TranslatableModel, LocalizedUrlRoutable, Sit
|
|||
'unpublished_at',
|
||||
'inverted',
|
||||
'vimeo_id',
|
||||
'has_show_picture',
|
||||
'has_show_picture'
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -167,7 +145,7 @@ class News extends Model implements TranslatableModel, LocalizedUrlRoutable, Sit
|
|||
/**
|
||||
* Relations should be included in the cache.
|
||||
*
|
||||
* @var list<string>
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected static $cacheRelations = [
|
||||
'categories',
|
||||
|
|
@ -354,9 +332,9 @@ class News extends Model implements TranslatableModel, LocalizedUrlRoutable, Sit
|
|||
* Get the url to access a specific resource.
|
||||
*
|
||||
* @param integer $id Id field of the target model.
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public static function getAccessModel(int $id): ?string
|
||||
public static function getAccessModel(int $id): string
|
||||
{
|
||||
$targetModel = self::getModelsCached()->firstWhere('id', $id);
|
||||
if (!$targetModel) {
|
||||
|
|
@ -454,7 +432,8 @@ class News extends Model implements TranslatableModel, LocalizedUrlRoutable, Sit
|
|||
* Get all published news by category.
|
||||
*
|
||||
* @param string $category
|
||||
* @return \Illuminate\Database\Eloquent\Collection<int, \App\Models\News>
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public static function getPublishedNewsByCategoryInCurrentLocale(string $category)
|
||||
{
|
||||
|
|
@ -469,49 +448,6 @@ class News extends Model implements TranslatableModel, LocalizedUrlRoutable, Sit
|
|||
});
|
||||
}
|
||||
|
||||
// * SITEMAP
|
||||
|
||||
/**
|
||||
* toSitemapTag method
|
||||
*
|
||||
* @return Url|string|array
|
||||
*/
|
||||
public function toSitemapTag(): Url | string | array
|
||||
{
|
||||
$model = $this;
|
||||
$locales = $model->locales();
|
||||
$sitemapUrls = [];
|
||||
|
||||
foreach ($locales as $locale) {
|
||||
if (in_array($locale, config('sitemap-generator.supported_locales'))) {
|
||||
$sitemapUrls[] = SitemapHelper::generateUrl(
|
||||
$model->getLocalizedUrl($locale),
|
||||
$model,
|
||||
$locales,
|
||||
currentLocale: $locale,
|
||||
isNews: true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $sitemapUrls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get localized URL from Mcamara\LaravelLocalization.
|
||||
*
|
||||
* @param string $locale
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalizedUrl(string $locale): string
|
||||
{
|
||||
return LaravelLocalization::getURLFromRouteNameTranslated(
|
||||
$locale,
|
||||
'routes.front.news',
|
||||
['news' => $this]
|
||||
) ?? route('front.news.show', $this);
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
|
|
@ -527,7 +463,7 @@ class News extends Model implements TranslatableModel, LocalizedUrlRoutable, Sit
|
|||
'newsables',
|
||||
'news_id',
|
||||
'newsable_id'
|
||||
)->using(Newsable::class);
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -543,6 +479,6 @@ class News extends Model implements TranslatableModel, LocalizedUrlRoutable, Sit
|
|||
'newsables',
|
||||
'news_id',
|
||||
'newsable_id'
|
||||
)->using(Newsable::class)->withTimestamps();
|
||||
)->withTimestamps();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,21 +8,16 @@ use App\Traits\Models\HasCache;
|
|||
use App\Traits\Models\HasTranslations;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Str;
|
||||
use Uwil\LaravelActivityLogs\Traits\ActivityLog;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* Id of the news.
|
||||
* @property string $name
|
||||
* Name of the category.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at
|
||||
* Date on which the category was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at
|
||||
* Date on which the category was updated.
|
||||
* @property \Illuminate\Database\Eloquent\Collection<int, \App\Models\News> $news
|
||||
* Associated news of the category.
|
||||
* @property int $news_id News focused.
|
||||
* @property string $name Name of the category.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Date on which the news was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Date on which the news was updated.
|
||||
*/
|
||||
class NewsCategory extends Model implements TranslatableModel
|
||||
{
|
||||
|
|
@ -35,7 +30,7 @@ class NewsCategory extends Model implements TranslatableModel
|
|||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
* @var array<int, string, array[]>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
|
|
@ -68,8 +63,6 @@ class NewsCategory extends Model implements TranslatableModel
|
|||
});
|
||||
}
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Manage model fields.
|
||||
*
|
||||
|
|
@ -87,14 +80,12 @@ class NewsCategory extends Model implements TranslatableModel
|
|||
TranslationHelper::validateFallbackTranslations($model);
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
* Associated news of the category.
|
||||
* The relation with News
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function news(): \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
public function news(): BelongsToMany
|
||||
{
|
||||
return $this->morphToMany(
|
||||
News::class,
|
||||
|
|
|
|||
|
|
@ -12,18 +12,11 @@ use Uwil\LaravelActivityLogs\Traits\ActivityLog;
|
|||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
/**
|
||||
* @property int $news_id
|
||||
* News focused.
|
||||
* @property string $name
|
||||
* Name of the tag.
|
||||
* @property string $color
|
||||
* Color of the tag
|
||||
* @property-read \Illuminate\Support\Carbon $created_at
|
||||
* Date on which the tag was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at
|
||||
* Date on which the tag was updated.
|
||||
* @property \Illuminate\Database\Eloquent\Collection<int, \App\Models\News> $news
|
||||
* Associated news of the tag.
|
||||
* @property int $news_id News focused.
|
||||
* @property string $name Name of the tag.
|
||||
* @property string $color Color of the tag
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Date on which the news was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Date on which the news was updated.
|
||||
*/
|
||||
class NewsTag extends Model implements TranslatableModel
|
||||
{
|
||||
|
|
@ -57,19 +50,33 @@ class NewsTag extends Model implements TranslatableModel
|
|||
/**
|
||||
* Relations should be included in the cache.
|
||||
*
|
||||
* @var list<string>
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected static $cacheRelations = [
|
||||
'news',
|
||||
];
|
||||
|
||||
// * METHODS
|
||||
/**
|
||||
* Relation to Document
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function news(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
{
|
||||
return $this->morphToMany(
|
||||
News::class,
|
||||
'newsable',
|
||||
'newsables',
|
||||
'newsable_id',
|
||||
'news_id'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Tags by category.
|
||||
*
|
||||
* @param string $slugCategory
|
||||
* @return \Illuminate\Database\Eloquent\Collection<int, \App\Models\NewsTag>
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public static function getTagsByCategoryInCurrentLocale(
|
||||
string $slugCategory,
|
||||
|
|
@ -86,22 +93,4 @@ class NewsTag extends Model implements TranslatableModel
|
|||
})->isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
* Associated news of the tag.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
*/
|
||||
public function news(): \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
{
|
||||
return $this->morphToMany(
|
||||
News::class,
|
||||
'newsable',
|
||||
'newsables',
|
||||
'newsable_id',
|
||||
'news_id'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\MorphPivot;
|
||||
|
||||
/**
|
||||
* @property integer $id Id of the news.
|
||||
* @property \App\Models\News $news_id Name of the news.
|
||||
* @property \App\Models\NewsCategory|\App\Models\NewsTag $newsable_id Name of the category or tag.
|
||||
* @property class-string<static> $newsable_type Class of the category or tag.
|
||||
* @property-read \Carbon\Carbon $created_at Created date of the news.
|
||||
* @property-read \Carbon\Carbon $updated_at Updated date of the news.
|
||||
*/
|
||||
class Newsable extends MorphPivot
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $table = 'newsables';
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::created(fn() => News::resetCache());
|
||||
static::updated(fn() => News::resetCache());
|
||||
static::deleted(fn() => News::resetCache());
|
||||
}
|
||||
}
|
||||
|
|
@ -113,21 +113,51 @@ class PageConfig extends Model implements TranslatableModel
|
|||
TranslationHelper::validateFallbackTranslations($model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the config is updated.
|
||||
*
|
||||
* @param array $newArray
|
||||
* @param array $originalArray
|
||||
* @return boolean
|
||||
*/
|
||||
private static function isConfigUpdated(array $newArray, array $originalArray): bool
|
||||
{
|
||||
if (count($newArray) !== count($originalArray)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($newArray as $i => $subA) {
|
||||
$subB = $originalArray[$i] ?? null;
|
||||
if ($subB === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ksort($subA);
|
||||
ksort($subB);
|
||||
|
||||
if ($subA != $subB) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the target model from a specific id and model name.
|
||||
*
|
||||
* @param string $modelId
|
||||
* @param string $modelName
|
||||
* @return \Illuminate\Database\Eloquent\Model|null
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public static function getModelFromInputModelConfig(
|
||||
string $modelId,
|
||||
string $modelName,
|
||||
): ?\Illuminate\Database\Eloquent\Model {
|
||||
): \Illuminate\Database\Eloquent\Model {
|
||||
$studly = Str::studly(Str::singular($modelName));
|
||||
$class = "App\\Models\\{$studly}";
|
||||
|
||||
if (!class_exists($class)) {
|
||||
if (!$class || !class_exists($class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ class DynamicPageRouteServiceProvider extends ServiceProvider
|
|||
$slug = $dynamicPageModel->getTranslation('slug', $locale);
|
||||
|
||||
// If no slug for the locale → skip.
|
||||
/** @phpstan-ignore-next-line */
|
||||
if (!empty($slug) && !$slug) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,187 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use App\Enums\VideoProviderEnum;
|
||||
use Illuminate\Contracts\Validation\DataAwareRule;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Arr;
|
||||
use Uwil\LaravelCommon\Rules\IsValidVimeoId;
|
||||
use Uwil\LaravelCommon\Rules\IsValidYoutubeId;
|
||||
|
||||
/**
|
||||
* Check the length of a Wysiwyg field, excluding tags and end spaces.
|
||||
*
|
||||
* @package Uwil\LaravelCommon\Rules
|
||||
*/
|
||||
class Video implements ValidationRule, DataAwareRule
|
||||
{
|
||||
protected array $data = [];
|
||||
|
||||
public function setData(array $data): static
|
||||
{
|
||||
$this->data = $data;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct method.
|
||||
*
|
||||
* @param integer $min The minimum length of the content (excluding tags). Default is 15.
|
||||
* @param integer|null $max The maximum length of the content (excluding tags).
|
||||
* Default is null (max will be defined by the type of the column in DB).
|
||||
* @return void
|
||||
* @throws \InvalidArgumentException If $max < $min.
|
||||
*/
|
||||
public function __construct() {}
|
||||
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param mixed $value
|
||||
* @param \Closure $fail
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function validate(string $attribute, mixed $value, \Closure $fail): void
|
||||
{
|
||||
|
||||
$lengthRules = [
|
||||
$attribute . '.alt' => ['min' => 3, 'max' => 255],
|
||||
$attribute . '.caption' => ['min' => 3, 'max' => 255],
|
||||
];
|
||||
|
||||
if (!$value) {
|
||||
return;
|
||||
}
|
||||
|
||||
$fields = [
|
||||
$attribute . '.alt',
|
||||
$attribute . '.caption',
|
||||
$attribute . '.isMuted',
|
||||
$attribute . '.hasControls',
|
||||
$attribute . '.canFullScreen',
|
||||
$attribute . '.provider',
|
||||
$attribute . '.videoId',
|
||||
$attribute . '.format',
|
||||
];
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$fieldValue = Arr::get($this->data, $field);
|
||||
if (in_array($field, [
|
||||
$attribute . '.alt',
|
||||
$attribute . '.caption'
|
||||
])) {
|
||||
$lengthRule = $lengthRules[$field] ?? null;
|
||||
|
||||
if ($lengthRule) {
|
||||
$min = $lengthRule['min'] ?? 0;
|
||||
$max = $lengthRule['max'] ?? PHP_INT_MAX;
|
||||
if ($fieldValue === null && $field === $attribute . '.caption') {
|
||||
continue;
|
||||
}
|
||||
if ($fieldValue === null && $field === $attribute . '.title') {
|
||||
continue;
|
||||
}
|
||||
if (strlen($fieldValue) < $min) {
|
||||
$fail(__('validation.min.string', [
|
||||
'attribute' => self::getTranslatedAttribute($field),
|
||||
'min' => $min
|
||||
]));
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen($fieldValue) > $max) {
|
||||
$fail(__('validation.max.string', [
|
||||
'attribute' => self::getTranslatedAttribute($field),
|
||||
'max' => $max
|
||||
]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Boolean fields
|
||||
if (in_array($field, [$attribute . '.isMuted', $attribute . '.hasControls', $attribute . '.canFullScreen'])) {
|
||||
$fieldValue = (bool)$fieldValue;
|
||||
if (!is_bool($fieldValue)) {
|
||||
$fail(__('validation.boolean', [
|
||||
'attribute' => self::getTranslatedAttribute($field),
|
||||
]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if($field === $attribute . '.format') {
|
||||
if($fieldValue != "landscape" && $fieldValue != "portrait") {
|
||||
$fail(__('validation.custom.format', [
|
||||
'attribute' => self::getTranslatedAttribute($field),
|
||||
]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ($field === $attribute . '.provider') {
|
||||
|
||||
$fieldValue = (int) $fieldValue;
|
||||
|
||||
if (!is_int($fieldValue)) {
|
||||
$fail(__('validation.integer', [
|
||||
'attribute' => self::getTranslatedAttribute($field),
|
||||
]));
|
||||
return;
|
||||
}
|
||||
|
||||
$enumValues = array_map(fn($case) => $case->value, VideoProviderEnum::cases());
|
||||
if (!in_array($fieldValue, $enumValues)) {
|
||||
$fail(__('validation.in', [
|
||||
'attribute' => self::getTranslatedAttribute($field),
|
||||
]));
|
||||
return;
|
||||
}
|
||||
|
||||
if ($field === $attribute . '.videoId') {
|
||||
$provider = Arr::get($this->data, $attribute . '.provider');
|
||||
|
||||
if ($provider === \App\Enums\VideoProviderEnum::vimeo->value) {
|
||||
$rule = new IsValidVimeoId();
|
||||
} elseif ($provider === \App\Enums\VideoProviderEnum::youtube->value) {
|
||||
$rule = new IsValidYoutubeId();
|
||||
} else {
|
||||
$fail(__('validation.invalid', [
|
||||
'attribute' => self::getTranslatedAttribute($attribute . '.provider'),
|
||||
]));
|
||||
return;
|
||||
}
|
||||
$rule->validate($field, $fieldValue, $fail);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the correct translation for the given attrribute.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return string
|
||||
*/
|
||||
private static function getTranslatedAttribute(string $attribute): string
|
||||
{
|
||||
$parts = explode('.', $attribute);
|
||||
if (count($parts) > 1) {
|
||||
$parts[0] = 'video_';
|
||||
$attribute = implode('.', $parts);
|
||||
}
|
||||
|
||||
/** @var \Illuminate\Translation\Translator $trans */
|
||||
$trans = trans();
|
||||
if ($trans->has('validation.attributes.' . $attribute)) {
|
||||
return trans('validation.attributes.' . $attribute);
|
||||
}
|
||||
if ($trans->has('validation.custom.' . $attribute)) {
|
||||
return trans('validation.custom.' . $attribute);
|
||||
}
|
||||
return $attribute;
|
||||
}
|
||||
}
|
||||
|
|
@ -28,13 +28,10 @@ trait HasCache
|
|||
static::deleted(function () {
|
||||
self::resetCache();
|
||||
});
|
||||
/** @phpstan-ignore-next-line */
|
||||
if (method_exists(static::class, 'initializeSoftDeletes')) {
|
||||
/** @phpstan-ignore-next-line */
|
||||
static::restored(function () {
|
||||
self::resetCache();
|
||||
});
|
||||
/** @phpstan-ignore-next-line */
|
||||
static::forceDeleted(function () {
|
||||
self::resetCache();
|
||||
});
|
||||
|
|
@ -60,12 +57,11 @@ trait HasCache
|
|||
public static function getModelsCached(): \Illuminate\Database\Eloquent\Collection
|
||||
{
|
||||
return Cache::remember(static::getCacheKey(), 86400, function () {
|
||||
/** @var class-string<static> $class */
|
||||
$class = static::class;
|
||||
/** @phpstan-ignore-next-line */
|
||||
|
||||
/** @var \Illuminate\Database\Eloquent\Model $class */
|
||||
return $class::query()
|
||||
->when(
|
||||
/** @phpstan-ignore-next-line */
|
||||
property_exists($class, 'cacheRelations') && is_array($class::$cacheRelations),
|
||||
function ($query) use ($class) {
|
||||
$query->with($class::$cacheRelations);
|
||||
|
|
@ -80,8 +76,8 @@ trait HasCache
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getCacheKey(): string
|
||||
private static function getCacheKey(): string
|
||||
{
|
||||
return sprintf("cache_%s", str_replace('\\', '_', static::class));
|
||||
return 'cache_' . str_replace('\\', '_', static::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,11 +42,9 @@ trait HasUwilImages
|
|||
*/
|
||||
protected static function bootHasUwilImages(): void
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
$hadSoftDelete = method_exists(static::class, 'initializeSoftDeletes');
|
||||
|
||||
if ($hadSoftDelete) {
|
||||
/** @phpstan-ignore-next-line */
|
||||
static::forceDeleted(function (self $model) {
|
||||
self::initLoop($model, self::FORCE_DELETE_ACTION);
|
||||
});
|
||||
|
|
@ -136,8 +134,9 @@ trait HasUwilImages
|
|||
continue;
|
||||
} //end if
|
||||
|
||||
// TODO pas testé
|
||||
// PAS TESTE.
|
||||
if (is_array($originalValue) && is_array($currentValue)) {
|
||||
dd('juste array');
|
||||
static::traverseAndManage(
|
||||
$model,
|
||||
$originalValue,
|
||||
|
|
@ -169,7 +168,7 @@ trait HasUwilImages
|
|||
$forceDeleteImage = $eventType === self::FORCE_DELETE_ACTION;
|
||||
$imagesFields = self::getImageFields($model);
|
||||
$wysiwygFields = self::getWysiwygFields($model);
|
||||
$isTranslatable = method_exists($model, 'getTranslations');
|
||||
$isTranslatable = method_exists($model, 'getTranslations') ?? false;
|
||||
$locale = config('app.locale');
|
||||
$availableLocales = array_keys(config('laravellocalization.supportedLocales', ['fr' => "Frenchouz"]));
|
||||
|
||||
|
|
@ -231,6 +230,7 @@ trait HasUwilImages
|
|||
$path = $isList ? "$fieldPath.$key" : (is_int($key) ? $fieldPath : "$fieldPath.$key");
|
||||
// TODO cette récursivité n'a pas encore été testé.
|
||||
if (is_array($oldValue) || is_array($newValue)) {
|
||||
dd('pas testé');
|
||||
static::traverseAndManage(
|
||||
$model,
|
||||
(array) $oldValue,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ trait HasLaravelFailedValidation
|
|||
* @return void
|
||||
* @throws \Illuminate\Http\Exceptions\HttpResponseException Override ajax code error.
|
||||
*/
|
||||
protected function failedValidation(Validator $validator): void
|
||||
protected function failedValidation(Validator $validator): \Illuminate\Http\Exceptions\HttpResponseException
|
||||
{
|
||||
$response = response()->json([
|
||||
'errors' => $validator->errors(),
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ trait HasInertiaPicture
|
|||
*/
|
||||
protected function mergeInertiaPicture(): void
|
||||
{
|
||||
if (empty($this->convertedFiles)) {
|
||||
if (empty($this->convertedFiles) || !is_array($this->convertedFiles)) {
|
||||
return;
|
||||
}
|
||||
$original = $this->all();
|
||||
|
|
@ -47,7 +47,7 @@ trait HasInertiaPicture
|
|||
* Set picture rules (UploadedFile or string path).
|
||||
*
|
||||
* @param string $rules
|
||||
* @return array<mixed>
|
||||
* @return string
|
||||
*/
|
||||
protected function pictureRules(string $rules): array
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use Illuminate\View\Component;
|
|||
|
||||
class NewsNextEventComponent extends Component
|
||||
{
|
||||
/** @var \Illuminate\Support\Collection<int, \App\Models\News> $nextEvents List of published news. */
|
||||
/** @var array<\App\Models\News> $nextEvents List of published news. */
|
||||
public $nextEvents;
|
||||
|
||||
/**
|
||||
|
|
@ -17,15 +17,12 @@ class NewsNextEventComponent extends Component
|
|||
*/
|
||||
public function __construct()
|
||||
{
|
||||
/** @var \App\Models\NewsCategory|null $newsCategory */
|
||||
$newsCategory = NewsCategory::getModelsCached()
|
||||
->filter(fn($category) => $category->getTranslation('slug', 'fr') === "actualites")
|
||||
->first();
|
||||
/** @var \App\Models\NewsTag|null $eventTag */
|
||||
|
||||
$eventTag = NewsTag::getTagsByCategoryInCurrentLocale($newsCategory->slug)
|
||||
->filter(
|
||||
fn(\Illuminate\Database\Eloquent\Model $tag) => $tag->getTranslation('slug', 'fr') === "actualites-rh"
|
||||
)
|
||||
->filter(fn($tag) => $tag->getTranslation('slug', 'fr') === "evenement")
|
||||
->first();
|
||||
|
||||
$eventTagId = $eventTag ? $eventTag->id : null;
|
||||
|
|
@ -33,7 +30,7 @@ class NewsNextEventComponent extends Component
|
|||
$this->nextEvents = News::getPublishedNewsByCategoryInCurrentLocale($newsCategory->slug)
|
||||
->filter(function ($news) use ($eventTagId) {
|
||||
return $news->tags->contains(
|
||||
fn($tag) => $eventTagId === $tag->id
|
||||
fn ($tag) => $eventTagId === $tag->id
|
||||
);
|
||||
})
|
||||
->sortByDesc('published_at')
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@ class OurImplantations extends Component
|
|||
/** @var string $id Identification of the section. */
|
||||
public string $id;
|
||||
|
||||
/** @var array Content section. */
|
||||
/** @var $implantations Content section. */
|
||||
public $implantations;
|
||||
|
||||
/** @var \Illuminate\Database\Eloquent\Collection $companyModels List of published companies. */
|
||||
/** @var array<\App\Models\Company> $companyModels List of published companies. */
|
||||
public $companyModels;
|
||||
|
||||
/** @var \Illuminate\Database\Eloquent\Collection $companyActivityModels List of published company activities. */
|
||||
/** @var array<\App\Models\CompanyActivity> $companyActivityModels List of published company activities. */
|
||||
public $companyActivityModels;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ return Application::configure(basePath: dirname(__DIR__))
|
|||
__DIR__ . '/../routes/web-front.php',
|
||||
__DIR__ . '/../routes/web-back.php',
|
||||
],
|
||||
api: __DIR__.'/../routes/api.php',
|
||||
health: '/up',
|
||||
)
|
||||
->withMiddleware(function (Middleware $middleware) {
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
module.exports = require('@uwil/husky-config/commitlint.config.cjs');
|
||||
|
|
@ -24,12 +24,10 @@
|
|||
"sentry/sentry-laravel": "^4.18",
|
||||
"spatie/laravel-translatable": "^6.11",
|
||||
"tightenco/ziggy": "^2.5",
|
||||
"uwil/admin-secure-laravel": "^5.1",
|
||||
"uwil/admin-secure-laravel": "^5.0",
|
||||
"uwil/k8s-laravel": "^2.0",
|
||||
"uwil/laravel-backend": "^3.0",
|
||||
"uwil/laravel-common": "^4.1",
|
||||
"uwil/sitemap-generator": "^6.0",
|
||||
"verschuur/laravel-robotstxt": "*"
|
||||
"uwil/laravel-common": "^4.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.23",
|
||||
|
|
|
|||
1218
composer.lock
generated
1218
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -14,7 +14,7 @@ return [
|
|||
*
|
||||
*/
|
||||
|
||||
'default' => env('MAIL_MAILER', 'smtp'),
|
||||
'default' => env('MAIL_MAILER', 'log'),
|
||||
|
||||
/**
|
||||
*--------------------------------------------------------------------------
|
||||
|
|
@ -114,14 +114,4 @@ return [
|
|||
'name' => env('MAIL_FROM_NAME', 'Example'),
|
||||
],
|
||||
|
||||
'to' => [
|
||||
'breeder' => explode(',', env('MAIL_LIST_BREEDER')) ?? [],
|
||||
'commitments' => explode(',', env('MAIL_LIST_COMMITMENTS')) ?? [],
|
||||
'export' => explode(',', env('MAIL_LIST_EXPORT')) ?? [],
|
||||
'finance' => explode(',', env('MAIL_LIST_FINANCE')) ?? [],
|
||||
'info' => explode(',', env('MAIL_LIST_INFO')) ?? [],
|
||||
'press' => explode(',', env('MAIL_LIST_PRESS')) ?? [],
|
||||
'restauration' => explode(',', env('MAIL_LIST_RESTAURATION')) ?? [],
|
||||
]
|
||||
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
<?php
|
||||
return [
|
||||
'environments' => [
|
||||
'production' => [
|
||||
'paths' => [
|
||||
'*' => [
|
||||
'disallow' => [
|
||||
'/admin',
|
||||
'*.pdf$'
|
||||
],
|
||||
'allow' => []
|
||||
],
|
||||
],
|
||||
'sitemaps' => [
|
||||
'sitemap.xml'
|
||||
]
|
||||
],
|
||||
'staging' => [
|
||||
'paths' => [
|
||||
'*' => [
|
||||
'disallow' => [
|
||||
'/'
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
]
|
||||
];
|
||||
|
|
@ -20,7 +20,7 @@ return [
|
|||
|
|
||||
*/
|
||||
|
||||
'driver' => env('SCOUT_DRIVER', null),
|
||||
'driver' => env('SCOUT_DRIVER', 'meilisearch'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -37,14 +37,5 @@ return [
|
|||
|
||||
'google' => [
|
||||
'maps' => env('GOOGLE_MAPS_KEY'),
|
||||
'recaptcha' => [
|
||||
'public' => env('GOOGLE_RECAPTCHA_PUBLIC'),
|
||||
'private' => env('GOOGLE_RECAPTCHA_PRIVATE'),
|
||||
'version' => env('GOOGLE_RECAPTCHA_VERSION', "3") === "3" ? true : false
|
||||
]
|
||||
],
|
||||
|
||||
'matomo' => [
|
||||
'site_id' => env('MATOMO_SITE_ID')
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,74 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
|
||||
|
||||
return [
|
||||
|
||||
/**
|
||||
* Single route names
|
||||
*
|
||||
* Ex:
|
||||
*
|
||||
* 'singlePages' => [
|
||||
* 'homepage',
|
||||
* ],
|
||||
*/
|
||||
'singlePages' => [
|
||||
'front.search',
|
||||
],
|
||||
|
||||
/**
|
||||
* Model namespaces with filters
|
||||
*
|
||||
* Ex: (modelFilters & relationFilters are not necessaries)
|
||||
* 'cruds' => [
|
||||
* [
|
||||
* 'model' => 'App\Models\Product',
|
||||
* 'modelFilters' => [
|
||||
* ['published', '=', true]
|
||||
* ],
|
||||
* 'relationFilters' => [
|
||||
* 'range' => fn(Builder $q) => $q->where('status', true),
|
||||
* ],
|
||||
* ],
|
||||
* [
|
||||
* 'model' => 'App\Models\Article',
|
||||
* ]
|
||||
* ],
|
||||
*/
|
||||
'cruds' => [
|
||||
[
|
||||
'model' => 'App\Models\News',
|
||||
'filters' => [
|
||||
['status', '=', \App\Enums\News\NewsStatusEnum::published]
|
||||
],
|
||||
],
|
||||
[
|
||||
'model' => 'App\Models\DynamicPage',
|
||||
'filters' => [
|
||||
['status', '=', \App\Enums\DynamicPages\PageStatusEnum::published]
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
/**
|
||||
* Enable or disable schedule for the job
|
||||
* If set to true the sitemap generator will be run
|
||||
* using the 'cron' instruction
|
||||
*/
|
||||
'schedule' => true,
|
||||
|
||||
/**
|
||||
* If you want to set specific
|
||||
* instruction for when to schedule job
|
||||
* you can set this with a cron instruction
|
||||
* You can generate one using https://crontab.guru/
|
||||
*
|
||||
* schedule must be set to true
|
||||
*
|
||||
* Default is every day at 15:45
|
||||
*/
|
||||
'cron' => '45 15 * * *',
|
||||
|
||||
'supported_locales' => array_keys(config('laravellocalization.supportedLocales', ['fr' => "Fr"]))
|
||||
];
|
||||
|
|
@ -192,7 +192,7 @@ return [
|
|||
"delete" => "delete the color",
|
||||
],
|
||||
"wysiwyg" => [
|
||||
"undo" => "Undo",
|
||||
"undo" => "Undo",
|
||||
"redo" => "Redo",
|
||||
"bold" => "Bold",
|
||||
"italic" => "Italic",
|
||||
|
|
@ -371,40 +371,4 @@ return [
|
|||
"select_value" => "select a value from the list",
|
||||
],
|
||||
"associated_model" => "associated :model|associated :model",
|
||||
"input_video" => [
|
||||
"placeholder" => "Click to add a new video",
|
||||
"title" => "Insert an video",
|
||||
"subtitle" => "Add a new video to your content.",
|
||||
"insert" => "Insert",
|
||||
"cancel" => "Cancel",
|
||||
"tooltip_cancel" => "Cancel adding this video",
|
||||
"edit_title" => "Update a video",
|
||||
"edit_subtitle" => "Edit the attributes associated with the video.",
|
||||
"edit_apply" => "Apply",
|
||||
"edit_cancel" => "Cancel",
|
||||
"position" => "Image position",
|
||||
"format" => "Image format",
|
||||
"video" => "Image",
|
||||
"alt" => "ALT attribute of the video",
|
||||
"caption" => "Caption of the video",
|
||||
"has_caption" => "Presence of a legend",
|
||||
"landscape" => "Landscape",
|
||||
"portrait" => "Portrait",
|
||||
"square" => "Square",
|
||||
"align-left" => "Align left",
|
||||
"align-center" => "Align center",
|
||||
"align-right" => "Align right",
|
||||
"wrap-left" => "Wrap left",
|
||||
"wrap-right" => "Wrap right",
|
||||
"youtube" => "Youtube",
|
||||
"vimeo" => "Vimeo",
|
||||
"tooltip" => [
|
||||
"title" => "video",
|
||||
"delete" => "delete the video",
|
||||
"reset" => "reset to original state",
|
||||
"insert" => "add this video",
|
||||
"edit_cancel" => "Cancel updating the video attributes",
|
||||
"edit_apply" => "Update the video attributes",
|
||||
]
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -31,7 +31,47 @@ return [
|
|||
'model' => 'Model',
|
||||
'staticroute' => "Static route",
|
||||
'position' => 'Element position',
|
||||
'contactform' => 'Contact form type',
|
||||
],
|
||||
'contactFormType' => [
|
||||
'collaborator' => [
|
||||
'label' => 'join us as an employee',
|
||||
'slug' => 'join-us-as-an-employee'
|
||||
],
|
||||
'breeder' => [
|
||||
'label' => 'join us as a farmer',
|
||||
'slug' => 'join-us-as-a-farmer'
|
||||
],
|
||||
'professional' => [
|
||||
'label' => 'a request as a professional'
|
||||
],
|
||||
'restauration' => [
|
||||
'label' => 'foodservice, Industry, Retailer France & Overseas',
|
||||
'slug' => 'foodservice-industry-retailer-distributor',
|
||||
'subtitle' => 'a request as a customer / retailer / distributor'
|
||||
],
|
||||
'export' => [
|
||||
'label' => 'other countries / Export',
|
||||
'slug' => 'export'
|
||||
],
|
||||
'finance' => [
|
||||
'label' => 'finance',
|
||||
'slug' => 'finance-2' #FIXME: revoir le slug
|
||||
],
|
||||
'commitments' => [
|
||||
'label' => 'our commitments',
|
||||
'slug' => 'our-commitments-2' #FIXME: revoir le slug
|
||||
],
|
||||
'product' => [
|
||||
'label' => 'product information',
|
||||
'slug' => 'product-information'
|
||||
],
|
||||
'info' => [
|
||||
'label' => 'other general information',
|
||||
'slug' => 'other-general-information'
|
||||
],
|
||||
'press' => [
|
||||
'label' => 'a press request'
|
||||
],
|
||||
],
|
||||
'breedType' => [
|
||||
'chicken' => 'Chickens / turkeys / guinea fowl',
|
||||
|
|
@ -88,25 +128,4 @@ return [
|
|||
'asc' => 'From oldest to newest.',
|
||||
'desc' => 'From the most recent to the oldest.'
|
||||
],
|
||||
'exportAskingType' => [
|
||||
"customer" => "Customer",
|
||||
"provider" => "Supplier",
|
||||
"other" => "Other"
|
||||
],
|
||||
'contactFormType' => [
|
||||
'collaborator' => 'join us as an employee',
|
||||
'breeder' => 'join us as a farmer',
|
||||
'professional' => 'a request as a professional',
|
||||
'restauration' => 'foodservice, Industry, Retailer France & Overseas',
|
||||
'export' => 'other countries / Export',
|
||||
'finance' => 'finance',
|
||||
'commitments' => 'our commitments',
|
||||
'product' => 'product information',
|
||||
'info' => 'other general information',
|
||||
'press' => 'a press request',
|
||||
],
|
||||
"videoDisplayFormat" => [
|
||||
"landscape" => "landscape",
|
||||
"portrait" => "portrait"
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -145,11 +145,5 @@ return [
|
|||
'subtitle' => 'jobs, internships and apprenticeships',
|
||||
'link_text' => 'access our recruitment portal'
|
||||
],
|
||||
'discover_our_jobs' => 'discover our broad range of jobs',
|
||||
'newsletter' => [
|
||||
'title' => 'Subscribe to our newsletter !',
|
||||
'placeholder' => 'Enter your email',
|
||||
'validate' => 'Confirm',
|
||||
'policy_message' => 'For any additional information regarding your personal data and your rights, please consult our '
|
||||
],
|
||||
'discover_our_jobs' => 'discover our broad range of jobs'
|
||||
];
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
return [
|
||||
"classes" => [
|
||||
"user" => "user|users",
|
||||
"user" => "user",
|
||||
"dynamic-page" => "dynamic page|dynamic pages",
|
||||
"page-config" => "page configuration|page configurations",
|
||||
"activity-log" => "activity log",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'front' => [
|
||||
'news' => 'news/{news}',
|
||||
'search' => 'search'
|
||||
],
|
||||
'contact' => 'contact-us/{slug}',
|
||||
'contact_index' => 'contact-us',
|
||||
'news' => 'news/{news}',
|
||||
'search' => 'search',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -271,15 +271,6 @@ return [
|
|||
"value" => "value",
|
||||
"path" => "path",
|
||||
"issuu_path" => "link of the Issuu preview",
|
||||
"is_issuu" => "is an Issuu preview ?",
|
||||
"video" => "vidéo",
|
||||
"video_" => [
|
||||
"isMuted" => "muted",
|
||||
"hasControls" => "controls enabled",
|
||||
"canFullScreen" => "full screen allowed",
|
||||
"alt" => "alternative text",
|
||||
"title" => "title",
|
||||
"caption" => "caption"
|
||||
]
|
||||
"is_issuu" => "is an Issuu preview ?"
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -372,45 +372,4 @@ return [
|
|||
"select_value" => "sélectionnez une valeur dans la liste",
|
||||
],
|
||||
"associated_model" => ":model associés|:model associées",
|
||||
"input_video" => [
|
||||
"placeholder" => "Cliquer pour ajouter une nouvelle vidéo",
|
||||
"title" => "Insérer une vidéo",
|
||||
"subtitle" => "Ajouter une nouvelle vidéo à votre contenu.",
|
||||
"insert" => "Insérer",
|
||||
"cancel" => "Annuler",
|
||||
"edit_title" => "Mise à jour d'une vidéo",
|
||||
"edit_subtitle" => "Modifier les attributs associés à la vidéo.",
|
||||
"edit_apply" => "Appliquer",
|
||||
"edit_cancel" => "Annuler",
|
||||
"position" => "Position de la vidéo",
|
||||
"format" => "Format de la vidéo",
|
||||
"image" => "Vidéo",
|
||||
"alt" => "Texte alternatif de la vidéo",
|
||||
"caption" => "Légende de la vidéo",
|
||||
"has_caption" => "Présence d'une légende",
|
||||
"landscape" => "Paysage",
|
||||
"portrait" => "Portrait",
|
||||
"align-left" => "Aligner à gauche",
|
||||
"align-center" => "Aligner au centre",
|
||||
"align-right" => "Aligner à droite",
|
||||
"wrap-left" => "Flottant à gauche",
|
||||
"wrap-right" => "Flottant à droite",
|
||||
"youtube" => "Youtube",
|
||||
"vimeo" => "Viméo",
|
||||
"is_muted" => "muter la vidéo ?",
|
||||
"has_controls" => "permettre de controler la vidéo ?",
|
||||
"can_fullScreen" => "autoriser le plein écran ?",
|
||||
"provider" => "hébergeur de la vidéo",
|
||||
'invalid_youtube_id' => "vidéo YOUTUBE invalide",
|
||||
"invalid_vimeo_id" => "vidéo VIMEO invalide",
|
||||
"tooltip" => [
|
||||
"title" => "vidéo",
|
||||
"delete" => "supprimer la vidéo",
|
||||
"reset" => "remettre à l'état d'origine",
|
||||
"insert" => "Ajouter cette vidéo",
|
||||
"cancel" => "Annuler l'ajout de cette vidéo",
|
||||
"edit_apply" => "Mettre à jour les attributs de la vidéo",
|
||||
"edit_cancel" => "Annuler la mise à jour des attributs de la vidéo",
|
||||
]
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -31,7 +31,47 @@ return [
|
|||
'model' => 'Modèle',
|
||||
'staticroute' => "Route statique",
|
||||
'position' => 'Positionnement de l\'élement',
|
||||
'contactform' => 'Type de formulaire de contact',
|
||||
],
|
||||
'contactFormType' => [
|
||||
'collaborator' => [
|
||||
'label' => 'nous rejoindre en tant que collaborateur',
|
||||
'slug' => 'nous-rejoindre-en-tant-que-collaborateur'
|
||||
],
|
||||
'breeder' => [
|
||||
'label' => 'nous rejoindre en tant qu’éleveur',
|
||||
'slug' => 'nous-rejoindre-en-tant-queleveur'
|
||||
],
|
||||
'professional' => [
|
||||
'label' => 'une demande en tant que professionnel'
|
||||
],
|
||||
'restauration' => [
|
||||
'label' => 'restaurations, Distributeurs et Détaillants France',
|
||||
'subtitle' => 'une demande en tant que client / détaillant / distributeur',
|
||||
'slug' => 'une-demande-en-tant-que-client-detaillant-distributeur'
|
||||
],
|
||||
'export' => [
|
||||
'label' => 'l’export',
|
||||
'slug' => 'lexport'
|
||||
],
|
||||
'finance' => [
|
||||
'label' => 'la finance',
|
||||
'slug' => 'la-finance'
|
||||
],
|
||||
'commitments' => [
|
||||
'label' => 'nos engagements',
|
||||
'slug' => 'nos-engagements'
|
||||
],
|
||||
'product' => [
|
||||
'label' => 'une information produit',
|
||||
'slug' => 'une-information-produit'
|
||||
],
|
||||
'info' => [
|
||||
'label' => 'une autre information générale',
|
||||
'slug' => 'une-autre-information-generale'
|
||||
],
|
||||
'press' => [
|
||||
'label' => 'une demande presse'
|
||||
],
|
||||
],
|
||||
'breedType' => [
|
||||
'chicken' => 'Poulets/dindes/pintades',
|
||||
|
|
@ -88,25 +128,4 @@ return [
|
|||
'asc' => 'du plus ancien au plus récent.',
|
||||
'desc' => 'du plus récent au plus ancien.'
|
||||
],
|
||||
'exportAskingType' => [
|
||||
"customer" => "Client",
|
||||
"provider" => "Fournisseur",
|
||||
"other" => "Autres"
|
||||
],
|
||||
'contactFormType' => [
|
||||
'collaborator' => 'nous rejoindre en tant que collaborateur',
|
||||
'breeder' => 'nous rejoindre en tant qu’éleveur',
|
||||
'professional' => 'une demande en tant que professionnel',
|
||||
'restauration' => 'restaurations, Distributeurs et Détaillants France',
|
||||
'export' => 'l’export',
|
||||
'finance' => 'la finance',
|
||||
'commitments' => 'nos engagements',
|
||||
'product' => 'une information produit',
|
||||
'info' => 'une autre information générale',
|
||||
'press' => 'une demande presse',
|
||||
],
|
||||
"videoDisplayFormat" => [
|
||||
"landscape" => "paysage",
|
||||
"portrait" => "portrait"
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -146,11 +146,5 @@ return [
|
|||
'subtitle' => 'd\'emploi, de stage et d\'alternance',
|
||||
'link_text' => 'accédez à notre portail de recrutement'
|
||||
],
|
||||
'discover_our_jobs' => 'découvrez nos métiers',
|
||||
'newsletter' => [
|
||||
'title' => 'Inscrivez-vous à notre newsletter !',
|
||||
'placeholder' => 'Renseignez votre email',
|
||||
'validate' => 'Valider',
|
||||
'policy_message' => 'Pour toute information complémentaire concernant vos données personnelles et vos droits, merci de consulter notre'
|
||||
],
|
||||
'discover_our_jobs' => 'découvrez nos métiers'
|
||||
];
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
return [
|
||||
"classes" => [
|
||||
"user" => "utilisateur|utilisateurs",
|
||||
"user" => "utilisateur",
|
||||
"dynamic-page" => "page dynamique|pages dynamiques",
|
||||
"page-config" => "configuration de page|configurations de page",
|
||||
"activity-log" => "journal d'activité",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'front' => [
|
||||
'news' => 'actualites/{news}',
|
||||
'search' => 'recherche'
|
||||
],
|
||||
'contact' => 'nous-contacter/{slug}',
|
||||
'contact_index' => 'nous-contacter',
|
||||
'news' => 'actualites/{news}',
|
||||
'search' => 'recherche',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -270,17 +270,6 @@ return [
|
|||
"value" => "valeur",
|
||||
"path" => "chemin d'accès",
|
||||
"issuu_path" => "lien du fichier Issuu",
|
||||
"is_issuu" => "est-ce un fichier Issuu ?",
|
||||
"video" => "vidéo",
|
||||
"video_" => [
|
||||
"isMuted" => "désactiver le son",
|
||||
"hasControls" => "activer les contrôles",
|
||||
"canFullScreen" => "autoriser le plein écran",
|
||||
"alt" => "texte alernatif",
|
||||
"title" => "titre",
|
||||
"caption" => "légende",
|
||||
"provider" => "hébergeur",
|
||||
"videoId" => "ID de la vidéo"
|
||||
]
|
||||
"is_issuu" => "est-ce un fichier Issuu ?"
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ data:
|
|||
APP_ENV: "${APP_APP_ENV}"
|
||||
APP_KEY: "${APP_APP_KEY}"
|
||||
APP_DEBUG: "${APP_APP_DEBUG}"
|
||||
APP_URL: "https://${REDIRECT}${APP_DOMAIN}"
|
||||
APP_URL: "https://${APP_DOMAIN}"
|
||||
LOG_CHANNEL: "k8s"
|
||||
CACHE_STORE: "${APP_CACHE_STORE}"
|
||||
DB_HOST: "${APP_DB_HOST}"
|
||||
|
|
@ -23,13 +23,6 @@ data:
|
|||
MAIL_ENCRYPTION: "${APP_MAIL_ENCRYPTION}"
|
||||
MAIL_FROM_ADDRESS: "${APP_MAIL_FROM_ADDRESS}"
|
||||
MAIL_FROM_NAME: "${APP_APP_NAME}"
|
||||
MAIL_LIST_BREEDER: "${APP_MAIL_LIST_BREEDER}"
|
||||
MAIL_LIST_COMMITMENTS: "${APP_MAIL_LIST_COMMITMENTS}"
|
||||
MAIL_LIST_EXPORT: "${APP_MAIL_LIST_EXPORT}"
|
||||
MAIL_LIST_FINANCE: "${APP_MAIL_LIST_FINANCE}"
|
||||
MAIL_LIST_INFO: "${APP_MAIL_LIST_INFO}"
|
||||
MAIL_LIST_PRESS: "${APP_MAIL_LIST_PRESS}"
|
||||
MAIL_LIST_RESTAURATION: "${APP_MAIL_LIST_RESTAURATION}"
|
||||
SENTRY_LARAVEL_DSN: "${APP_SENTRY_LARAVEL_DSN}"
|
||||
TELESCOPE_ENABLED: "${APP_TELESCOPE_ENABLED}"
|
||||
CRM_ENDPOINT: "${APP_CRM_ENDPOINT}"
|
||||
|
|
@ -63,18 +56,6 @@ spec:
|
|||
requests:
|
||||
storage: $APP_PVC_SIZE
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: ${CI_PROJECT_PATH_SLUG}-wp-uploads-pvc-storage
|
||||
spec:
|
||||
storageClassName: "csi-cinder-classic"
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: $APP_WP_UPLOADS_PVC_SIZE
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
|
|
@ -105,8 +86,6 @@ spec:
|
|||
volumeMounts:
|
||||
- name: storage
|
||||
mountPath: /app/srcs/storage
|
||||
- name: wp-uploads-storage
|
||||
mountPath: /app/srcs/public/app/uploads
|
||||
- name: ${CI_PROJECT_PATH_SLUG}-queue-worker
|
||||
image: $IMAGE_TAG
|
||||
lifecycle:
|
||||
|
|
@ -141,9 +120,6 @@ spec:
|
|||
- name: storage
|
||||
persistentVolumeClaim:
|
||||
claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage
|
||||
- name: wp-uploads-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: ${CI_PROJECT_PATH_SLUG}-wp-uploads-pvc-storage
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
|
|
@ -165,29 +141,14 @@ spec:
|
|||
- web
|
||||
- websecure
|
||||
routes:
|
||||
- match: Host(`${APP_DOMAIN}`) || Host(`www.${APP_DOMAIN}`)
|
||||
- match: Host(`${APP_DOMAIN}`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: ${CI_PROJECT_PATH_SLUG}-service
|
||||
port: 80
|
||||
middlewares:
|
||||
- name: redirect-no-www-to-www
|
||||
- name: redirect-ldc-rgpd-to-rgpd
|
||||
|
||||
tls:
|
||||
secretName: ${CRT_TLS_NAME}
|
||||
---
|
||||
# Redirect with domain replacement
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: redirect-ldc-rgpd-to-rgpd
|
||||
spec:
|
||||
redirectRegex:
|
||||
regex: ^https://${REDIRECT}${APP_DOMAIN}/rgpd/(professionnels|salaries|consommateurs)(/(en|de))?
|
||||
replacement: https://rgpd.ldc.fr/fr/${1}
|
||||
permanent: true
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
|
|
|
|||
645
package-lock.json
generated
645
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -33,6 +33,7 @@
|
|||
"@typescript-eslint/parser": "^8.39.0",
|
||||
"@vitejs/plugin-react": "^4.7.0",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"baseline-browser-mapping": "^2.9.19",
|
||||
"concurrently": "^9.2.0",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
|
|
@ -103,7 +104,6 @@
|
|||
"@types/pluralize": "^0.0.33",
|
||||
"@types/react": "^19.1.9",
|
||||
"@types/react-dom": "^19.1.7",
|
||||
"@uwil/husky-config": "^1.0.1",
|
||||
"axios": "^1.13.2",
|
||||
"chart.js": "^4.5.1",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@ parameters:
|
|||
paths:
|
||||
- app/
|
||||
|
||||
level: 7
|
||||
level: 5
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ metadata:
|
|||
spec:
|
||||
dnsNames:
|
||||
- $APP_DOMAIN
|
||||
- www.${APP_DOMAIN}
|
||||
secretName: $APP_DOMAIN
|
||||
issuerRef:
|
||||
name: $APP_CERT_ISSUER
|
||||
|
|
|
|||
174
public/.htaccess
174
public/.htaccess
|
|
@ -18,182 +18,8 @@
|
|||
RewriteCond %{REQUEST_URI} (.+)/$
|
||||
RewriteRule ^ %1 [L,R=301]
|
||||
|
||||
# Redirect /index.php/anything to /anything
|
||||
RewriteCond %{THE_REQUEST} /index\.php/([^\s?]*) [NC]
|
||||
RewriteRule ^index\.php/(.*)$ /$1 [L,R=301,NC]
|
||||
|
||||
# Send Requests To Front Controller...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [L]
|
||||
|
||||
# Redirection from old website
|
||||
Redirect 301 "/category/news" "/actualites"
|
||||
Redirect 301 "/100%des-elevages-nature-deleveurs-dici-a-2025" "/actualites/100-des-elevages-nature-deleveurs-dici-a-2025"
|
||||
Redirect 301 "/acquisition-de-la-societe-asia-general-food" "/actualites/acquisition-de-la-societe-asia-general-food"
|
||||
Redirect 301 "/big-bang-de-lemploi-2023-rencontrons-nous-dans-des-conditions-exceptionnelles" "/actualites/big-bang-de-lemploi-2023-rencontrons-nous-dans-des-conditions-exceptionnelles"
|
||||
Redirect 301 "/bonne-annee-2024-a-tous" "/actualites/bonne-annee-2024-a-tous"
|
||||
Redirect 301 "/decouvrez-notre-nouvelle-plaquette-rse" "/actualites/decouvrez-notre-nouvelle-plaquette-rse"
|
||||
Redirect 301 "/decouvrez-notre-rapport-annuel-2020-2021" "/actualites/decouvrez-notre-rapport-annuel-2020-2021"
|
||||
Redirect 301 "/decouvrez-notre-rapport-annuel-2021-2022" "/actualites/decouvrez-notre-rapport-annuel-2021-2022"
|
||||
Redirect 301 "/echanges-entre-les-etudiants-de-lessca-et-le-raf-du-pole-volaille-ldc" "/actualites/echanges-entre-les-etudiants-de-lessca-et-le-raf-du-pole-volaille-ldc"
|
||||
Redirect 301 "/echanges-entre-les-etudiants-unilasalle-et-des-collaborateurs-ldc" "/actualites/echanges-entre-les-etudiants-unilasalle-et-des-collaborateurs-ldc"
|
||||
Redirect 301 "/entree-en-negociation-exclusive-en-vue-de-lacquisition-de-la-societe-indykpol-sa-2" "/actualites/entree-en-negociation-exclusive-en-vue-de-lacquisition-de-la-societe-indykpol-sa"
|
||||
Redirect 301 "/entree-en-negociation-exclusive-en-vue-de-lacquisition-de-la-societe-indykpol-sa-3" "/actualites/entree-en-negociation-exclusive-en-vue-de-lacquisition-de-la-societe-indykpol-sa"
|
||||
Redirect 301 "/entree-en-negociation-exclusive-en-vue-de-lacquisition-de-lusine-konspol-de-nowy-sacz-en-pologne-2" "/actualites/entree-en-negociation-exclusive-en-vue-de-lacquisition-de-lusine-konspol-de-nowy-sacz-en-pologne"
|
||||
Redirect 301 "/entree-en-negociation-exclusive-en-vue-de-lacquisition-potentielle-de-100-du-capital-du-groupe-pierre-martinet-2" "/actualites/entree-en-negociation-exclusive-en-vue-de-lacquisition-potentielle-de-100-du-capital-du-groupe-pierre-martinet"
|
||||
Redirect 301 "/entree-en-negociation-exclusive-en-vue-de-lacquisition-potentielle-de-100-du-capital-du-groupe-pierre-martinet-3" "/actualites/entree-en-negociation-exclusive-en-vue-de-lacquisition-potentielle-de-100-du-capital-du-groupe-pierre-martinet"
|
||||
Redirect 301 "/entree-en-partenariat-avec-la-famille-buchanan-au-royaume-uni-2" "/actualites/entree-en-partenariat-avec-la-famille-buchanan-au-royaume-uni"
|
||||
Redirect 301 "/feu-vert-de-lautorite-de-la-concurrence-au-rachat-du-groupe-ronsard-2" "/actualites/feu-vert-de-lautorite-de-la-concurrence-au-rachat-du-groupe-ronsard"
|
||||
Redirect 301 "/feu-vert-de-lautorite-de-la-concurrence-au-rachat-du-groupe-ronsard-3" "/actualites/feu-vert-de-lautorite-de-la-concurrence-au-rachat-du-groupe-ronsard"
|
||||
Redirect 301 "/interview-philippe-gelin-sur-la-chaine-youtube-meilleurtaux-placement" "/actualites/interview-philippe-gelin-sur-la-chaine-youtube-meilleurtaux-placement"
|
||||
Redirect 301 "/journee-mondiale-de-leau" "/actualites/journee-mondiale-de-leau"
|
||||
Redirect 301 "/journee-mondiale-du-recyclage-%e2%99%bb" "/actualites/journee-mondiale-du-recyclage"
|
||||
Redirect 301 "/journee-portes-ouvertes-ldc-sable-le-1er-avril-2023" "/actualites/journee-portes-ouvertes-ldc-sable-le-1er-avril-2023"
|
||||
Redirect 301 "/joyeux-nouvel-an-chinois" "/actualites/joyeux-nouvel-an-chinois"
|
||||
Redirect 301 "/lancement-campagne-alternance-2024" "/actualites/lancement-campagne-alternance-2024"
|
||||
Redirect 301 "/ldc-a-la-reconquete-du-marche-national" "/actualites/ldc-a-la-reconquete-du-marche-national"
|
||||
Redirect 301 "/ldc-partage-sa-politique-alimentation-des-volailles" "/actualites/ldc-partage-sa-politique-dalimentation-durable-des-volailles"
|
||||
Redirect 301 "/ldc-participe-a-la-semaine-nationale-de-lemploi-agroalimentaire-100-digital" "/actualites/ldc-participe-a-la-semaine-nationale-de-lemploi-agroalimentaire-100-digital"
|
||||
Redirect 301 "/ldc-participe-au-campus-des-metiers-et-des-qualifications" "/actualites/ldc-participe-au-campus-des-metiers-et-des-qualifications"
|
||||
Redirect 301 "/ldc-sable-lance-sa-premiere-formation-qualifiante-post-bac" "/actualites/ldc-sable-lance-sa-premiere-formation-qualifiante-post-bac"
|
||||
Redirect 301 "/ldc-sable-le-gaulois-signe-un-partenariat-avec-coolplanet-pour-optimiser-ses-consommations-denergie-et-accelerer-sa-feuille-de-route-en-matiere-de-decarbonation" "/actualites/ldc-sable-le-gaulois-signe-un-partenariat-avec-coolplanet-pour-optimiser-ses-consommations-denergie-et-accelerer-sa-feuille-de-route-en-matiere-de-decarbonation"
|
||||
Redirect 301 "/le-cavol-a-la-reconquete-de-la-rhd" "/actualites/le-cavol-a-la-reconquete-de-la-rhd"
|
||||
Redirect 301 "/le-gaulois-maitre-coq-loue-il-est-le-champion-du-poulet-toutes-categories" "/actualites/le-gaulois-maitre-coq-loue-il-est-le-champion-du-poulet-toutes-categories"
|
||||
Redirect 301 "/le-gaulois-professionnel-lance-son-site-internet" "/actualites/le-gaulois-professionnel-lance-son-site-internet"
|
||||
Redirect 301 "/le-gaulois-signe-un-partenariat-avec-programme-malin" "/actualites/le-gaulois-signe-un-partenariat-avec-programme-malin"
|
||||
Redirect 301 "/le-groupe-ldc-a-participe-au-forum-uni-la-salle-de-beauvais-le-7-octobre-2021" "/actualites/le-groupe-ldc-a-participe-au-forum-uni-la-salle-de-beauvais-le-7-octobre-2021"
|
||||
Redirect 301 "/le-groupe-ldc-cree-un-partenariat-avec-citeo-pour-le-developpement-dune-filiere-de-recyclage-du-polystyrene-en-france" "/actualites/le-groupe-ldc-cree-un-partenariat-avec-citeo-pour-le-developpement-dune-filiere-de-recyclage-du-polystyrene-en-france"
|
||||
Redirect 301 "/le-groupe-ldc-officialise-sa-strategie-climat-biodiversite-2030-%f0%9f%8c%8d" "/actualites/le-groupe-ldc-officialise-sa-strategie-climat-biodiversite-2030"
|
||||
Redirect 301 "/le-groupe-ldc-participe-a-la-semaine-de-lagro-grand-ouest-du-12-au-20-avril" "/actualites/le-groupe-ldc-participe-a-la-semaine-de-lagro-grand-ouest-du-12-au-20-avril"
|
||||
Redirect 301 "/le-groupe-ldc-participe-a-la-semaine-nationale-de-lemploi-agroalimentaire" "/actualites/le-groupe-ldc-participe-a-la-semaine-nationale-de-lemploi-agroalimentaire"
|
||||
Redirect 301 "/anuga-2023" "/actualites/le-groupe-ldc-present-a-lanuga-2023"
|
||||
Redirect 301 "/le-groupe-ldc-present-au-forum-oniris-le-18-novembre-2021" "/actualites/le-groupe-ldc-present-au-forum-oniris-le-18-novembre-2021"
|
||||
Redirect 301 "/le-groupe-ldc-present-au-jobfest-du-mans-le-30-mars-2023" "/actualites/le-groupe-ldc-present-au-jobfest-du-mans-le-30-mars-2023"
|
||||
Redirect 301 "/le-groupe-ldc-present-aux-forums-ecoles-de-lesa-angers-et-agrosup-dijon" "/actualites/le-groupe-ldc-present-aux-forums-ecoles-de-lesa-angers-et-agrosup-dijon"
|
||||
Redirect 301 "/le-groupe-ldc-present-aux-forums-ecoles-de-linstitut-agro-dijon-esa-angers-oniris-nantes-esaip-angers" "/actualites/le-groupe-ldc-present-aux-forums-ecoles-de-linstitut-agro-dijon-esa-angers-oniris-nantes-esaip-angers"
|
||||
Redirect 301 "/le-groupe-ldc-present-aux-forums-polytech-angers-et-agro-campus-rennes-le-18-octobre-2022" "/actualites/le-groupe-ldc-present-aux-forums-polytech-angers-et-agro-campus-rennes-le-18-octobre-2022"
|
||||
Redirect 301 "/le-groupe-ldc-reagit-face-aux-nouvelles-attaques-de-l214" "/actualites/le-groupe-ldc-reagit-face-aux-nouvelles-attaques-de-l214"
|
||||
Redirect 301 "/le-groupe-ldc-renforce-ses-engagements-et-son-objectif-soja-zero-deforestation" "/actualites/le-groupe-ldc-reagit-face-aux-nouvelles-attaques-de-l214"
|
||||
Redirect 301 "/le-groupe-ldc-renforce-ses-engagements-et-son-objectif-soja-zero-deforestation-2" "/actualites/le-groupe-ldc-renforce-ses-engagements-et-son-objectif-soja-zero-deforestation"
|
||||
Redirect 301 "/les-industries-de-la-transformation-des-volailles-offrent-une-diversite-de-metiers-et-de-nombreuses-opportunites-demploi" "/actualites/les-industries-de-la-transformation-des-volailles-offrent-une-diversite-de-metiers-et-de-nombreuses-opportunites-demploi"
|
||||
Redirect 301 "/les-talents-de-la-sarthe-2019" "/actualites/les-talents-de-la-sarthe-2019"
|
||||
Redirect 301 "/les-talents-de-la-sarthe-2019-2" "/actualites/les-talents-de-la-sarthe-2019"
|
||||
Redirect 301 "/maitre-coq-devient-partenaire-officiel-dangers-sco-handball" "/actualites/maitre-coq-devient-partenaire-officiel-dangers-sco-handball"
|
||||
Redirect 301 "/marie-surgeles-organise-ses-job-dating-en-entreprise" "/actualites/marie-surgeles-organise-ses-job-dating-en-entreprise"
|
||||
Redirect 301 "/nos-equipes-volena-et-sbv-etaient-presentes-au-food-talent-du-cfia-expo-rennes-ce-14-mars" "/actualites/nos-equipes-volena-et-sbv-etaient-presentes-au-food-talent-du-cfia-expo-rennes-ce-14-mars"
|
||||
Redirect 301 "/note-dinformation-deces-de-monsieur-chancereul-gerard" "/actualites/note-dinformation-deces-de-monsieur-chancereul-gerard"
|
||||
Redirect 301 "/partenariat-ecole-les-etudiants-uni-la-salle-en-visite-chez-ldc-groupe" "/actualites/partenariat-ecole-les-etudiants-unilasalle-en-visite-chez-ldc-groupe"
|
||||
Redirect 301 "/partenariat-ecole-visite-de-lesa-sur-lunite-dinde-ldc-sable" "/actualites/partenariat-ecole-visite-de-lesa-sur-lunite-dinde-ldc-sable"
|
||||
Redirect 301 "/publication-de-notre-rapport-annuel-2022-2023" "/actualites/publication-de-notre-rapport-annuel-2022-2023"
|
||||
Redirect 301 "/recrutement-en-alternance-plus-de-100-opportunites-dans-tous-les-metiers" "/actualites/recrutement-en-alternance-plus-de-100-opportunites-dans-tous-les-metiers"
|
||||
Redirect 301 "/reprise-de-kiplama-en-belgique" "/actualites/reprise-de-kiplama-en-belgique"
|
||||
Redirect 301 "/reprise-de-luche-tradition-volailles-a-luche-pringe-sarthe" "/actualites/reprise-de-luche-tradition-volailles-a-luche-pringe-sarthe"
|
||||
Redirect 301 "/reprise-de-marnevall-en-hongrie" "/actualites/reprise-de-marnevall-en-hongrie"
|
||||
Redirect 301 "/resultats-annuels-2021-2022-2" "/actualites/resultats-annuels-2021-2022"
|
||||
Redirect 301 "/resultats-semestriels-2020-2021-3" "/actualites/resultats-semestriels-2020-2021"
|
||||
Redirect 301 "/resultats-semestriels-2023-2024-2" "/actualites/resultats-semestriels-20232024"
|
||||
Redirect 301 "/retour-en-video-sur-le-space-rennes-2024" "/actualites/retour-en-video-sur-le-space-rennes-2024"
|
||||
Redirect 301 "/retour-en-video-sur-notre-evenement-interne-challenge-remy-lambert" "/actualites/retour-en-video-sur-notre-evenement-interne-challenge-remy-lambert"
|
||||
Redirect 301 "/retrospective-2024-retrouvez-les-entreprises-qui-ont-rejoint-le-groupe-en-2024" "/actualites/retrospective-2024-retrouvez-les-entreprises-qui-ont-rejoint-le-groupe-en-2024"
|
||||
Redirect 301 "/retrouvez-nous-aux-forums-ecoles-en-fevrier-2025" "/actualites/retrouvez-nous-aux-forums-ecoles-en-fevrier-2025"
|
||||
Redirect 301 "/retrouvez-nous-aux-forums-ecoles-en-mars-2025" "/actualites/retrouvez-nous-aux-forums-ecoles-en-mars-2025"
|
||||
Redirect 301 "/signature-de-conventions-avec-les-banques-alimentaires" "/actualites/signature-de-conventions-avec-les-banques-alimentaires"
|
||||
Redirect 301 "/sirha-lyon-2025-le-groupe-ldc-et-ses-marques-restauration-seront-presents-du-23-au-27-janvier-2025" "/actualites/sirha-lyon-2025-le-groupe-ldc-et-ses-marques-restauration-seront-presents-du-23-au-27-janvier-2025"
|
||||
Redirect 301 "/sponsoring-sportif-maitre-coq-et-yannick-bestaven" "/actualites/sponsoring-sportif-maitre-coq-et-yannick-bestaven"
|
||||
Redirect 301 "/synthese-rse-du-groupe-ldc-2020" "/actualites/synthese-rse-du-groupe-ldc-2020"
|
||||
Redirect 301 "/teasing-retrouvez-le-pole-amont-au-space-du-17-au-19-septembre-2024" "/actualites/teasing-retrouvez-le-pole-amont-au-space-du-17-au-19-septembre-2024"
|
||||
Redirect 301 "/top-depart-pour-le-vendee-globe-avec-maitre-coq" "/actualites/top-depart-pour-le-vendee-globe-avec-maitre-coq"
|
||||
Redirect 301 "/tous-derriere-yannick-et-julien-pour-la-transat-jacques-vabre" "/actualites/tous-derriere-yannick-et-julien-pour-la-transat-jacques-vabre"
|
||||
Redirect 301 "/une-annee-de-plus-ou-nos-produits-ont-ete-recompenses-par-le-concours-general-agricole-2024" "/actualites/une-annee-de-plus-ou-nos-produits-ont-ete-recompenses-par-le-concours-general-agricole-2024"
|
||||
Redirect 301 "/venez-nous-rencontrer-au-salon-work-in-agro-2023" "/actualites/venez-nous-rencontrer-au-salon-work-in-agro-2023"
|
||||
Redirect 301 "/victoire-de-yannick-bestaven-et-son-maitre-coq-iv-de-la-9eme-edition-du-vendee-globe" "/actualites/victoire-de-yannick-bestaven-et-son-maitre-coq-iv-de-la-9eme-edition-du-vendee-globe"
|
||||
Redirect 301 "/victoire-de-yannick-bestaven-et-son-maitre-coq-iv-de-la-9eme-edition-du-vendee-globe-2" "/actualites/victoire-de-yannick-bestaven-et-son-maitre-coq-iv-de-la-9eme-edition-du-vendee-globe"
|
||||
Redirect 301 "/ldc-sable-lance-sa-premiere-formation-qualifiante-post-bac-pour-devenir-conducteur-de-ligne" "/actualites/video-ldc-sable-lance-sa-premiere-formation-qualifiante-post-bac-pour-devenir-conducteur-de-ligne"
|
||||
Redirect 301 "/volena-volaillers-engages-pour-lavenir-le-nouveau-nom-du-pole-normandie" "/actualites/volena-volaillers-engages-pour-lavenir-le-nouveau-nom-du-pole-normandie"
|
||||
Redirect 301 "/webinaire-entre-les-etudiants-doniris-et-des-collaborateurs-ldc" "/actualites/webinaire-entre-les-etudiants-doniris-et-des-collaborateurs-ldc"
|
||||
Redirect 301 "/en/100-of-nature-deleveurs-farms-by-2025" "/en/news/100-of-nature-deleveurs-farms-by-2025"
|
||||
Redirect 301 "/en/acquisition-of-asia-general-food" "/en/news/acquisition-of-asia-general-food"
|
||||
Redirect 301 "/en/cavol-to-re-conquer-hrd" "/en/news/cavol-to-re-conquer-hrd"
|
||||
Redirect 301 "/en/entry-into-partnership-with-the-buchanan-family-2" "/en/news/entry-into-partnership-with-the-buchanan-family"
|
||||
Redirect 301 "/en/ldc-participates-in-the-trades-and-skills-campus" "/en/news/ldc-participates-in-the-trades-and-skills-campus"
|
||||
Redirect 301 "/en/ldc-to-regain-the-national-market" "/en/news/ldc-to-regain-the-national-market"
|
||||
Redirect 301 "/en/le-gaulois-maitre-coq-loue-the-chicken-champion-across-the-categories" "/en/news/le-gaulois-maitre-coq-loue-the-chicken-champion-across-the-categories"
|
||||
Redirect 301 "/en/le-gaulois-signs-a-partnership-with-programme-malin" "/en/news/le-gaulois-signs-a-partnership-with-programme-malin"
|
||||
Redirect 301 "/en/maitre-coq-becomes-an-official-partner-of-angers-sco-handball" "/en/news/maitre-coq-becomes-an-official-partner-of-angers-sco-handball"
|
||||
Redirect 301 "/en/signature-of-agreements-with-food-banks" "/en/news/signature-of-agreements-with-food-banks"
|
||||
Redirect 301 "/en/take-over-of-kiplama-in-belgium" "/en/news/take-over-of-kiplama-in-belgium"
|
||||
Redirect 301 "/en/takeover-of-luche-tradition-volailles-in-luche-pringe-sarthe-2" "/en/news/takeover-of-luche-tradition-volailles-in-luche-pringe-sarthe"
|
||||
Redirect 301 "/en/takeover-of-marnevall-in-hungary" "/en/news/takeover-of-marnevall-in-hungary"
|
||||
Redirect 301 "/en/les-talents-de-la-sarthe-2019-2" "/en/news/talents-in-the-sarthe-2019"
|
||||
Redirect 301 "/en/talents-in-the-sarthe-2019" "/en/news/talents-in-the-sarthe-2019"
|
||||
Redirect 301 "/en/the-ldc-group-creates-a-partnership-with-citeo-for-the-development-of-a-polystyrene-recycling-industry-in-france" "/en/news/the-ldc-group-creates-a-partnership-with-citeo-for-the-development-of-a-polystyrene-recycling-industry-in-france"
|
||||
Redirect 301 "/en/top-start-for-the-vendee-globe-with-maitre-coq" "/en/news/top-start-for-the-vendee-globe-with-maitre-coq"
|
||||
Redirect 301 "/search" "/recherche"
|
||||
Redirect 301 "/nous-contacter/nos-engagements" "/nous-contacter/engagements"
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_expires.c>
|
||||
ExpiresActive On
|
||||
|
||||
# Images
|
||||
ExpiresByType image/jpg "access plus 1 year"
|
||||
ExpiresByType image/jpeg "access plus 1 year"
|
||||
ExpiresByType image/png "access plus 1 year"
|
||||
ExpiresByType image/gif "access plus 1 year"
|
||||
ExpiresByType image/webp "access plus 1 year"
|
||||
ExpiresByType image/svg+xml "access plus 1 year"
|
||||
|
||||
# CSS / JS
|
||||
ExpiresByType text/css "access plus 1 year"
|
||||
ExpiresByType text/javascript "access plus 1 year"
|
||||
ExpiresByType application/javascript "access plus 1 year"
|
||||
ExpiresByType application/x-javascript "access plus 1 year"
|
||||
|
||||
# WOFF / WOFF2 / Fonts
|
||||
ExpiresByType application/font-woff "access plus 1 year"
|
||||
ExpiresByType font/woff "access plus 1 year"
|
||||
ExpiresByType application/font-woff2 "access plus 1 year"
|
||||
ExpiresByType font/woff2 "access plus 1 year"
|
||||
|
||||
# Favicon
|
||||
ExpiresByType image/x-icon "access plus 1 year"
|
||||
</IfModule>
|
||||
|
||||
<FilesMatch "\.(jpe?g|png|gif|webp|css|js|woff|woff2|ico)$">
|
||||
Header set Cache-Control "public, max-age=31536000, immutable"
|
||||
</FilesMatch>
|
||||
|
||||
<IfModule mod_brotli.c>
|
||||
AddOutputFilterByType BROTLI_COMPRESS text/html text/css text/plain text/xml text/javascript application/javascript application/x-javascript
|
||||
AddType text/plain .br
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_deflate.c>
|
||||
AddOutputFilterByType DEFLATE text/html
|
||||
AddOutputFilterByType DEFLATE text/plain
|
||||
AddOutputFilterByType DEFLATE text/xml
|
||||
AddOutputFilterByType DEFLATE text/css
|
||||
AddOutputFilterByType DEFLATE text/javascript
|
||||
AddOutputFilterByType DEFLATE application/javascript
|
||||
AddOutputFilterByType DEFLATE application/x-javascript
|
||||
AddOutputFilterByType DEFLATE application/xml
|
||||
AddOutputFilterByType DEFLATE application/xhtml+xml
|
||||
AddOutputFilterByType DEFLATE application/rss+xml
|
||||
AddOutputFilterByType DEFLATE image/svg+xml
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_mime.c>
|
||||
AddType application/javascript .js
|
||||
AddType font/woff2 .woff2
|
||||
AddType application/font-woff2 .woff2
|
||||
AddType application/font-woff .woff
|
||||
AddType font/woff .woff
|
||||
AddType image/svg+xml .svg
|
||||
</IfModule>
|
||||
|
||||
<FilesMatch "\.(css|js|jpg|jpeg|gif|png|ico|svg|woff|woff2)$">
|
||||
FileETag None
|
||||
Header unset ETag
|
||||
Header unset Set-Cookie
|
||||
</FilesMatch>
|
||||
|
|
|
|||
|
|
@ -20,21 +20,6 @@
|
|||
.image-border_bottom {
|
||||
top: auto;
|
||||
}
|
||||
.textblock__container_swap > .image-content-size img {
|
||||
width: 100% !important;
|
||||
object-fit: cover !important;
|
||||
}
|
||||
|
||||
.textblock__container_row > .image-content-size img {
|
||||
width: 100% !important;
|
||||
height: 300px !important;
|
||||
object-fit: cover !important;
|
||||
}
|
||||
|
||||
.textblock__container_side > .image-content-size img {
|
||||
width: 100% !important;
|
||||
object-fit: cover !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1600px) {
|
||||
.wrapper {
|
||||
|
|
@ -103,11 +88,6 @@
|
|||
.textblock__container_swap .textblock__image {
|
||||
margin-left: 70px;
|
||||
}
|
||||
.textblock__container_row > .image-content-size img {
|
||||
width: 100% !important;
|
||||
height: 300px !important;
|
||||
object-fit: cover !important;
|
||||
}
|
||||
.breadcrumbs {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
|
@ -266,35 +246,10 @@
|
|||
width: 310px;
|
||||
margin: 0px 11px 35px;
|
||||
}
|
||||
|
||||
.image-border-wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.textblock__container_side > .image-content-size img {
|
||||
width: 100% !important;
|
||||
height: 425px !important;
|
||||
object-fit: cover !important;
|
||||
}
|
||||
.textblock__container_swap_left > .image-content-size img {
|
||||
width: 100% !important;
|
||||
height: 425px !important;
|
||||
object-fit: cover !important;
|
||||
}
|
||||
|
||||
.textblock__container_row > .image-content-size {
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
.textblock__container_row > .image-content-size img {
|
||||
height: 210px !important;
|
||||
object-fit: cover !important;
|
||||
}
|
||||
|
||||
|
||||
.values {
|
||||
padding-bottom: 55px;
|
||||
}
|
||||
|
|
@ -448,6 +403,7 @@
|
|||
padding-left: 10px;
|
||||
}
|
||||
[data-menu="submenu-2951"] .mobile-menu__level {
|
||||
padding-top: 0;
|
||||
min-height: calc(100vh - 80px);
|
||||
}
|
||||
.offer-form {
|
||||
|
|
@ -962,7 +918,7 @@
|
|||
font-size: 34px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
|
||||
.engagements__wrapper {
|
||||
text-align: center;
|
||||
}
|
||||
|
|
@ -1023,30 +979,8 @@
|
|||
border: 1px solid #a0a0a0;
|
||||
}
|
||||
.image-border-wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.textblock__container_swap > .image-content-size img {
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
object-fit: cover !important;
|
||||
}
|
||||
.textblock__container_side > .image-content-size img {
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
object-fit: cover !important;
|
||||
}
|
||||
.textblock__container_row > .image-content-size {
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
height: 210px !important;
|
||||
}
|
||||
|
||||
.image-content-size img {
|
||||
height: 100% !important;
|
||||
object-fit: cover !important;
|
||||
}
|
||||
.list-item__title {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.9 KiB |
BIN
public/assets/img/logo_en.png
Normal file
BIN
public/assets/img/logo_en.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
public/news/26_01_07/img/header.jpg
Normal file
BIN
public/news/26_01_07/img/header.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 368 KiB |
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue