Compare commits
175 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7f93bb47b | ||
|
|
db840f94a9 | ||
|
|
b058a1a8e2 | ||
|
|
60d9bda89f | ||
|
|
99d2df7711 | ||
|
|
d3e4075dc7 | ||
|
|
9081187949 | ||
|
|
2dc3dd08aa | ||
|
|
af077eb74a | ||
|
|
7f71e3550d | ||
|
|
2bc0d1b30d | ||
|
|
a7fa202f4c | ||
|
|
9cd61a1c6e | ||
|
|
b061599ab1 | ||
|
|
0a94df329a | ||
|
|
2f99b0f5fa | ||
|
|
04910c331e | ||
|
|
d6b77b6a50 | ||
|
|
1152dcb995 | ||
|
|
608ede77e2 | ||
|
|
7875d41a7b | ||
|
|
5f72787e37 | ||
|
|
1f84322ea9 | ||
|
|
a7896ef3fa | ||
|
|
0c03ee97e7 | ||
|
|
0eaf145401 | ||
|
|
344389b5b5 | ||
|
|
c3dd439ea0 | ||
|
|
affddeea9f | ||
|
|
9e83930c18 | ||
|
|
6ac4d8b7df | ||
|
|
3838c7eab6 | ||
|
|
e17135a7af | ||
|
|
8df51ef55d | ||
|
|
12fb5dfd12 | ||
|
|
ef41add69a | ||
|
|
ee1a56e232 | ||
|
|
3e8e6cb40b | ||
|
|
60fcd21ca1 | ||
|
|
e29f423e98 | ||
|
|
b4188ba963 | ||
|
|
2e3d03e53b | ||
|
|
3fc041d9a8 | ||
|
|
6f2ebfb4b6 | ||
|
|
c1713e38a2 | ||
|
|
d7e5f7b4ab | ||
|
|
7a14c0542f | ||
|
|
20366f7f14 | ||
|
|
4a9bfd1a31 | ||
|
|
073ff3da04 | ||
|
|
68cc0d1581 | ||
|
|
6dbedc0af9 | ||
|
|
c33ad114f0 | ||
|
|
0ffce35844 | ||
|
|
2284d3ca0f | ||
|
|
6f02efb2d9 | ||
|
|
c836b36751 | ||
|
|
aa66e8977e | ||
|
|
2dc7a1ee86 | ||
|
|
3b50fc3923 | ||
|
|
c1f966bdd4 | ||
|
|
9fcf5f8c08 | ||
|
|
a30b3b5ca4 | ||
|
|
18839e26ed | ||
|
|
4324dd1e8a | ||
|
|
1bb3c146b3 | ||
|
|
9339abd082 | ||
|
|
eeff942229 | ||
|
|
db54ff36f9 | ||
|
|
1062fe432a | ||
|
|
fba3a18795 | ||
|
|
14d536f58d | ||
|
|
a562ecf249 | ||
|
|
b234ecefab | ||
|
|
dfa574c548 | ||
|
|
9ef2204305 | ||
|
|
08480aed92 | ||
|
|
5c08d0c34c | ||
|
|
9787710128 | ||
|
|
1c735f1200 | ||
|
|
8278419606 | ||
|
|
fb062e11aa | ||
|
|
a5f4d522c4 | ||
|
|
55e5871096 | ||
|
|
d75d51af8c | ||
|
|
07be96c762 | ||
|
|
170f1b2552 | ||
|
|
566ff421aa | ||
|
|
0943b300d1 | ||
|
|
821cf7eabd | ||
|
|
93ec9f9396 | ||
|
|
61675911f0 | ||
|
|
d71530cb3d | ||
|
|
85ffb4e762 | ||
|
|
bfcffbb223 | ||
|
|
60557ccba6 | ||
|
|
4e7268ae44 | ||
|
|
6128e763eb | ||
|
|
4de27ac36c | ||
|
|
739e863667 | ||
|
|
f1c1f185e3 | ||
|
|
0878350923 | ||
|
|
90040f9fb4 | ||
|
|
1716fb8adf | ||
|
|
80c5b7d916 | ||
|
|
470f64e5ca | ||
|
|
e580f7f56f | ||
|
|
7f7596ba2c | ||
|
|
1811553c79 | ||
|
|
eafaffe116 | ||
|
|
2c8335dfbd | ||
|
|
206438ffc3 | ||
|
|
38ad8c8d0b | ||
|
|
ff44ac613b | ||
|
|
4afa7eb1e8 | ||
|
|
428e92ca44 | ||
|
|
1867442f98 | ||
|
|
ba2de1bd90 | ||
|
|
cb3f61501b | ||
|
|
1c67975317 | ||
|
|
334431bb5a | ||
|
|
af13501909 | ||
|
|
0a7809ed7f | ||
|
|
a1424d0348 | ||
|
|
4a609d8285 | ||
|
|
613d853229 | ||
|
|
95e0d8841e | ||
|
|
d495c928c8 | ||
|
|
d4c9c96173 | ||
|
|
7be8c8fc17 | ||
|
|
befd6848e0 | ||
|
|
ba94a40144 | ||
|
|
984746ce41 | ||
|
|
59b3db0ae1 | ||
|
|
ac7335c312 | ||
|
|
849a21be60 | ||
|
|
9177972a4c | ||
|
|
dec24e1342 | ||
|
|
6204166b00 | ||
|
|
949c80e6d3 | ||
|
|
a37537b48b | ||
|
|
49c0bac402 | ||
|
|
d1ff745707 | ||
|
|
52f144d96e | ||
|
|
1917f514b5 | ||
|
|
937d267b74 | ||
|
|
689fe2b23d | ||
|
|
ecb359a73a | ||
|
|
994834d812 | ||
|
|
bef0cc1cc7 | ||
|
|
0284861336 | ||
|
|
2c94a47891 | ||
|
|
9b1908fc97 | ||
|
|
3f853dd746 | ||
|
|
60deae8b64 | ||
|
|
f4cf0fe26d | ||
|
|
d932c7125c | ||
|
|
cf3945c939 | ||
|
|
aeb80ba7e8 | ||
|
|
86c82c4015 | ||
|
|
3dce4ee563 | ||
|
|
ac9726632c | ||
|
|
1bb2a3fe61 | ||
|
|
56e3583d19 | ||
|
|
f7250ca0b7 | ||
|
|
8a49d0296c | ||
|
|
79a4e573cb | ||
|
|
80294115f6 | ||
|
|
506bf2f90b | ||
|
|
77780724cc | ||
|
|
e78738ead9 | ||
|
|
bed321e492 | ||
|
|
57638149d3 | ||
|
|
879197c215 | ||
|
|
6bf8bd2c31 |
14
.env.example
|
|
@ -43,5 +43,15 @@ GOOGLE_RECAPTCHA_PUBLIC=
|
|||
GOOGLE_RECAPTCHA_PRIVATE=
|
||||
GOOGLE_RECAPTCHA_VERSION=
|
||||
|
||||
# LDC Web Admin Secure
|
||||
LDC_WEB_API_KEY="MY_KEY"
|
||||
# UWIL ADMIN SECURE
|
||||
# - LIST SEPARATED WITH ',' (Required)
|
||||
UWIL_ADMIN_SECURE_CIDR_LIST=""
|
||||
# - LIST SEPARATED WITH ',' (Optional)
|
||||
UWIL_ADMIN_SECURE_CIDR_PROJECT_ALLOWED_LIST=""
|
||||
|
||||
# SAML
|
||||
SAML2_DEFAULT_TENANT_UUID=
|
||||
SAML2_SP_CERT_x509=
|
||||
SAML2_SP_CERT_PRIVATEKEY=
|
||||
SAML2_CONTACT_TECHNICAL_EMAIL=
|
||||
SAML2_CONTACT_SUPPORT_EMAIL=
|
||||
|
|
|
|||
2
.gitignore
vendored
|
|
@ -6,6 +6,8 @@
|
|||
/public/uploads
|
||||
/public/cache
|
||||
/public/sitemap.xml
|
||||
/public/marker-icon.png
|
||||
/public/marker-shadow.png
|
||||
/storage/*.key
|
||||
/vendor
|
||||
.env
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ include:
|
|||
file: 'security/security.yml'
|
||||
- project: 'ldc-web/shared-ci'
|
||||
ref: 'main'
|
||||
file: 'build/build.yml'
|
||||
file: 'build/docker-multistage.yml'
|
||||
- project: 'ldc-web/shared-ci'
|
||||
ref: 'main'
|
||||
file: 'test/test.yml'
|
||||
|
|
|
|||
46
Dockerfile
|
|
@ -1,5 +1,45 @@
|
|||
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/ldcweb-production-8.2:latest
|
||||
COPY --chown=www-data:www-data . /app/srcs
|
||||
FROM composer:2.8 AS vendor
|
||||
|
||||
ARG GITLAB_USER
|
||||
ARG GITLAB_PASSWORD
|
||||
|
||||
COPY database/ database/
|
||||
|
||||
COPY composer.json composer.json
|
||||
COPY composer.lock composer.lock
|
||||
|
||||
RUN composer config gitlab-token.lab.s-web.fr ${GITLAB_USER} ${GITLAB_PASSWORD}
|
||||
RUN composer install \
|
||||
--ignore-platform-reqs \
|
||||
--no-interaction \
|
||||
--no-plugins \
|
||||
--no-scripts \
|
||||
--no-dev \
|
||||
--prefer-dist
|
||||
|
||||
FROM node:20.18 AS frontend
|
||||
|
||||
ARG GITLAB_PASSWORD
|
||||
|
||||
RUN mkdir -p /app/public/build
|
||||
|
||||
COPY package*.json tsconfig.json vite.config.ts .eslintrc.json .stylelintrc.json /app/
|
||||
COPY resources/ /app/resources/
|
||||
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 ci && npm run prod
|
||||
|
||||
ARG PHP_8_5_TAG=latest
|
||||
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/uwil-production-8.5:${PHP_8_5_TAG}
|
||||
|
||||
ARG USER=www-data
|
||||
|
||||
COPY --chown=${USER}:${USER} . /app/srcs
|
||||
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/
|
||||
|
||||
USER root
|
||||
RUN chmod -R 755 /app/srcs/storage
|
||||
USER www-data
|
||||
USER ${USER}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ php artisan schedule:run
|
|||
```
|
||||
ldcweb:admin-secure-sync
|
||||
```
|
||||
### Refresh-Sitemap
|
||||
#### Available Commands
|
||||
```
|
||||
sitemap:refresh --dry-run
|
||||
```
|
||||
|
||||
## TODO
|
||||
Après le 30 juin 2024, retirer le code de la modal concernant le jeu (cf [ce commit](https://lab.s-web.fr/ldc-web/projets/lionor/-/commit/befd6848e0bb31bf9d79bac2a1f30d3015d8b14b))
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ class HtmlColor implements CastsAttributes
|
|||
/**
|
||||
* Cast the given value.
|
||||
*
|
||||
* @param Model $model
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.TypeHintMissing
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.ScalarTypeHintMissing
|
||||
|
|
@ -32,10 +32,10 @@ class HtmlColor implements CastsAttributes
|
|||
/**
|
||||
* Prepare the given value for storage.
|
||||
*
|
||||
* @param Model $model
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @return integer
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.TypeHintMissing
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.ScalarTypeHintMissing
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ class RgbaColor extends HtmlColor
|
|||
/**
|
||||
* Cast the given value.
|
||||
*
|
||||
* @param Model $model
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.TypeHintMissing
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.ScalarTypeHintMissing
|
||||
|
|
@ -24,6 +24,7 @@ class RgbaColor extends HtmlColor
|
|||
public function get($model, $key, $value, $attributes)
|
||||
{
|
||||
// phpcs:enable
|
||||
/** @var \Illuminate\Support\Collection<array-key, float> */
|
||||
$intValues = collect(\str_split($this->zeropad(\dechex(\intval($value)), 8), 2))->map(function ($hex) {
|
||||
return intval(\hexdec($hex));
|
||||
});
|
||||
|
|
@ -35,10 +36,10 @@ class RgbaColor extends HtmlColor
|
|||
/**
|
||||
* Prepare the given value for storage.
|
||||
*
|
||||
* @param Model $model
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @return integer
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.TypeHintMissing
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.ScalarTypeHintMissing
|
||||
|
|
|
|||
|
|
@ -1,177 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CreateAdmin extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'user:create';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create a backend admin user';
|
||||
|
||||
/**
|
||||
* The firstname of the new user.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $firstname;
|
||||
|
||||
/**
|
||||
* The lastname of the new user.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $lastname;
|
||||
|
||||
/**
|
||||
* The email of the new user.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $email;
|
||||
|
||||
/**
|
||||
* The password of the new user.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $password;
|
||||
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$this->firstname = null;
|
||||
$this->addFirstname();
|
||||
|
||||
$this->lastname = null;
|
||||
$this->addLastname();
|
||||
|
||||
$this->email = null;
|
||||
$this->addEmail();
|
||||
|
||||
$this->password = null;
|
||||
$this->addPassword();
|
||||
|
||||
$user = new User([
|
||||
'firstname' => $this->firstname,
|
||||
'lastname' => $this->lastname,
|
||||
'email' => $this->email,
|
||||
'password' => $this->password,
|
||||
]);
|
||||
$user->saveOrFail();
|
||||
|
||||
$this->info('User created 👌');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a firstname to the user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addFirstname(): void
|
||||
{
|
||||
while (is_null($this->firstname)) {
|
||||
try {
|
||||
$tmp = $this->ask('Type the wanted user firstname', 'Admin');
|
||||
$validator = Validator::make(['firstname' => $tmp], [
|
||||
'firstname' => 'required|min:3|max:255'
|
||||
]);
|
||||
$validator->validate();
|
||||
$this->firstname = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please provide a valid firstname %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
} //end try
|
||||
}; //end while
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a lastname to the user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addLastname(): void
|
||||
{
|
||||
while (is_null($this->lastname)) {
|
||||
try {
|
||||
$tmp = $this->ask('Type the wanted user lastname', 'Saïtama');
|
||||
$validator = Validator::make(['lastname' => $tmp], [
|
||||
'lastname' => 'required|min:3|max:255'
|
||||
]);
|
||||
$validator->validate();
|
||||
$this->lastname = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please provide a valid lastname %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
} //end try
|
||||
}; //end while
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an email to the user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addEmail(): void
|
||||
{
|
||||
while (is_null($this->email)) {
|
||||
try {
|
||||
$tmp = $this->ask('Type the wanted user email', 'equipe.web@ldc.fr');
|
||||
$validator = Validator::make(['email' => $tmp], [
|
||||
'email' => 'required|unique:users,email|email:rfc,dns'
|
||||
]);
|
||||
$validator->validate();
|
||||
$this->email = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please provide a valid email %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
} //end try
|
||||
}; //end while
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a password to the user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addPassword(): void
|
||||
{
|
||||
while (
|
||||
($this->password = $this->secret(
|
||||
(!\is_null($this->password) ? 'Failed to confirm, ' : '') . 'Type the wanted user password'
|
||||
)) !== $this->secret('Confirm the password')
|
||||
) {
|
||||
continue;
|
||||
}; //end while
|
||||
}
|
||||
}
|
||||
204
app/Console/Commands/UserCreate.php
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Enums\Users\RoleEnum;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class UserCreate extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'uwil:user:create';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create a backend admin user';
|
||||
|
||||
/**
|
||||
* The first name of the new user.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $first_name;
|
||||
|
||||
/**
|
||||
* The last name of the new user.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $last_name;
|
||||
|
||||
/**
|
||||
* The email of the new user.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $email;
|
||||
|
||||
/**
|
||||
* The role of the new user.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $role;
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
$this->first_name = null;
|
||||
$this->addFirstName();
|
||||
|
||||
$this->last_name = null;
|
||||
$this->addLastName();
|
||||
|
||||
$this->email = null;
|
||||
$this->addEmail();
|
||||
|
||||
$this->role = null;
|
||||
$this->addRole();
|
||||
|
||||
$user = new User([
|
||||
'first_name' => $this->first_name,
|
||||
'last_name' => $this->last_name,
|
||||
'email' => $this->email,
|
||||
'role' => $this->role,
|
||||
'published' => true,
|
||||
]);
|
||||
$user->saveOrFail();
|
||||
|
||||
$this->info('User created 👌');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a first name to the user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addFirstName(): void
|
||||
{
|
||||
while (is_null($this->first_name)) {
|
||||
try {
|
||||
$tmp = $this->ask('Type the wanted user first name', 'Admin');
|
||||
$validator = Validator::make(['first_name' => $tmp], [
|
||||
'first_name' => 'required|min:3|max:255'
|
||||
]);
|
||||
$validator->validate();
|
||||
$this->first_name = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please provide a valid first name %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
} //end try
|
||||
}; //end while
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a last name to the user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addLastName(): void
|
||||
{
|
||||
while (is_null($this->last_name)) {
|
||||
try {
|
||||
$tmp = $this->ask('Type the wanted user last name', 'Saïtama');
|
||||
$validator = Validator::make(['last_name' => $tmp], [
|
||||
'last_name' => 'required|min:3|max:255'
|
||||
]);
|
||||
$validator->validate();
|
||||
$this->last_name = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please provide a valid last_name %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
} //end try
|
||||
}; //end while
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an email to the user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addEmail(): void
|
||||
{
|
||||
while (is_null($this->email)) {
|
||||
try {
|
||||
$tmp = $this->ask('Type the wanted user email', 'equipe.web@ldc.fr');
|
||||
$validator = Validator::make(['email' => $tmp], [
|
||||
'email' => 'required|unique:users,email|email:rfc,dns'
|
||||
]);
|
||||
$validator->validate();
|
||||
$this->email = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please provide a valid email %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
} //end try
|
||||
}; //end while
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a role to the user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addRole(): void
|
||||
{
|
||||
while (is_null($this->role)) {
|
||||
try {
|
||||
$tmp = $this->choice(
|
||||
'Select his role',
|
||||
[
|
||||
Str::ucFirst(RoleEnum::conceptor->label()),
|
||||
Str::ucFirst(RoleEnum::admin->label()),
|
||||
Str::ucFirst(RoleEnum::visitor->label())
|
||||
],
|
||||
Str::ucFirst(RoleEnum::visitor->label()),
|
||||
);
|
||||
if ($tmp === Str::ucFirst(RoleEnum::conceptor->label())) {
|
||||
$tmp = RoleEnum::conceptor;
|
||||
}
|
||||
if ($tmp === Str::ucFirst(RoleEnum::admin->label())) {
|
||||
$tmp = RoleEnum::admin;
|
||||
}
|
||||
if ($tmp === Str::ucFirst(RoleEnum::visitor->label())) {
|
||||
$tmp = RoleEnum::visitor;
|
||||
}
|
||||
$validator = Validator::make(['role' => $tmp], [
|
||||
'role' => 'required'
|
||||
]);
|
||||
$validator->validate();
|
||||
$this->role = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please choose from the selection %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
} //end try
|
||||
}; //end while
|
||||
}
|
||||
}
|
||||
48
app/Enums/ActivityLogs/ActivityLogsEventEnum.php
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\ActivityLogs;
|
||||
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
enum ActivityLogsEventEnum: int
|
||||
{
|
||||
use BaseEnum;
|
||||
|
||||
case created = 1;
|
||||
case updated = 2;
|
||||
case duplicated = 3;
|
||||
case deleted = 4;
|
||||
|
||||
/**
|
||||
* Optionnal labels definition
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::created->name => 'Création',
|
||||
self::updated->name => 'Mise à jour',
|
||||
self::duplicated->name => 'Duplication',
|
||||
self::deleted->name => 'Suppression',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Custom added classes definition
|
||||
*/
|
||||
private const BOOTSTRAPCLASS = [
|
||||
self::created->name => 'success',
|
||||
self::updated->name => 'warning',
|
||||
self::duplicated->name => 'secondary',
|
||||
self::deleted->name => 'danger',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get Class
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function bootstrapClass(): string
|
||||
{
|
||||
return self::BOOTSTRAPCLASS[$this->name];
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ enum CookingModeEnum: int
|
|||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::withoutCooking->name => 'Sans cuisson',
|
||||
|
|
|
|||
|
|
@ -12,6 +12,12 @@ enum DifficultyEnum: int
|
|||
case medium = 2;
|
||||
case hard = 3;
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::easy->name => 'Facile',
|
||||
self::medium->name => 'Moyen',
|
||||
|
|
|
|||
|
|
@ -15,6 +15,12 @@ enum NutriscoreEnum: int
|
|||
case dLetter = 5;
|
||||
case eLetter = 6;
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::noLetter->name => 'N/A',
|
||||
self::aLetter->name => 'A',
|
||||
|
|
@ -24,6 +30,11 @@ enum NutriscoreEnum: int
|
|||
self::eLetter->name => 'E'
|
||||
];
|
||||
|
||||
/**
|
||||
* Enum stickers
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private const STICKERS = [
|
||||
self::noLetter->name => '',
|
||||
self::aLetter->name => 'resources/assets/images/nutriscore/logo-nutriscore-A.png',
|
||||
|
|
|
|||
16
app/Enums/Pagination/ItemsPerPaginationEnum.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Pagination;
|
||||
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
enum ItemsPerPaginationEnum: int
|
||||
{
|
||||
use BaseEnum;
|
||||
|
||||
case five = 5;
|
||||
case twelve = 12;
|
||||
case twentyfive = 25;
|
||||
case fifty = 50;
|
||||
case onehundred = 100;
|
||||
}
|
||||
|
|
@ -13,6 +13,12 @@ enum PreparationTimeEnum: int
|
|||
case interval3 = 3;
|
||||
case interval4 = 4;
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::interval1->name => '0-30 min',
|
||||
self::interval2->name => '30min - 2h',
|
||||
|
|
@ -20,6 +26,11 @@ enum PreparationTimeEnum: int
|
|||
self::interval4->name => '> 4h',
|
||||
];
|
||||
|
||||
/**
|
||||
* Enum times
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private const TIMES = [
|
||||
self::interval1->name => ['min' => 0, 'max' => 30],
|
||||
self::interval2->name => ['min' => 31, 'max' => 120],
|
||||
|
|
@ -40,7 +51,7 @@ enum PreparationTimeEnum: int
|
|||
/**
|
||||
* Get enum images
|
||||
*
|
||||
* @return array<string>
|
||||
* @return array<string, array<string, int>>
|
||||
*/
|
||||
public static function toTimes(): array
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,6 +20,12 @@ enum SignsEnum: int
|
|||
case uexpress = 10;
|
||||
case netto = 11;
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::leclerc->name => 'Leclerc',
|
||||
self::auchan->name => 'Auchan',
|
||||
|
|
|
|||
31
app/Enums/StaticPageType.php
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
enum StaticPageType: int
|
||||
{
|
||||
use BaseEnum;
|
||||
|
||||
case legals = 1;
|
||||
case confidentiality = 2;
|
||||
case homepage = 3;
|
||||
case our_products = 4;
|
||||
case our_commitments = 5;
|
||||
case banner_section = 6;
|
||||
|
||||
/**
|
||||
* Optionnal labels definition.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::legals->name => 'Mentions légales',
|
||||
self::confidentiality->name => 'Confidentialité',
|
||||
self::homepage->name => 'Accueil',
|
||||
self::our_products->name => 'Nos produits',
|
||||
self::our_commitments->name => 'Nos engagements',
|
||||
self::banner_section->name => 'Section bannière',
|
||||
];
|
||||
}
|
||||
25
app/Enums/Users/RoleEnum.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Users;
|
||||
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
enum RoleEnum: int
|
||||
{
|
||||
use BaseEnum;
|
||||
|
||||
case conceptor = 1;
|
||||
case admin = 2;
|
||||
case visitor = 99;
|
||||
|
||||
/**
|
||||
* Optionnal labels definition.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::conceptor->name => 'enums.user-role.conceptor',
|
||||
self::admin->name => 'enums.user-role.admin',
|
||||
self::visitor->name => 'enums.user-role.visitor',
|
||||
];
|
||||
}
|
||||
71
app/Http/Controllers/Bo/ActivityLogController.php
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\ActivityLog;
|
||||
use App\Traits\Controllers\ChangesModelOrder;
|
||||
use App\Traits\Controllers\UpdateModelPublished;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ActivityLogController extends Controller
|
||||
{
|
||||
use ChangesModelOrder;
|
||||
use UpdateModelPublished;
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$this->authorize('isConceptor');
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $query */
|
||||
$query = ActivityLog::query()->with('user');
|
||||
|
||||
/** @var string $search Search field */
|
||||
$search = $request->search;
|
||||
if ($search) {
|
||||
$this->searchQuery(
|
||||
$query,
|
||||
$search,
|
||||
null,
|
||||
'model_class',
|
||||
);
|
||||
}
|
||||
$searchFields = \implode(', ', [
|
||||
trans('validation.custom.target'),
|
||||
]);
|
||||
|
||||
/** Sort columns with a query */
|
||||
$this->sortQuery($query);
|
||||
|
||||
/** Custom pagination */
|
||||
$activitylogModels = $this->paginate($query);
|
||||
|
||||
return view('bo.pages.activity_logs.index', compact('activitylogModels', 'search', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\ActivityLog $activity_log
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(ActivityLog $activity_log): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$this->authorize('isConceptor');
|
||||
$targetModelClass = $activity_log->model_class;
|
||||
$targetModel = $activity_log->model_class::where(
|
||||
(new $targetModelClass())->getRouteKeyName(),
|
||||
$activity_log->model_id
|
||||
)->first();
|
||||
|
||||
return view('bo.pages.activity_logs.show', [
|
||||
'activitylogModel' => $activity_log,
|
||||
'targetModel' => $targetModel,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -16,9 +16,9 @@ class CertificationController extends Controller
|
|||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $certifications */
|
||||
$certifications = Certification::query();
|
||||
|
|
@ -43,9 +43,9 @@ class CertificationController extends Controller
|
|||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create()
|
||||
public function create(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('bo.pages.certifications.create');
|
||||
}
|
||||
|
|
@ -54,9 +54,9 @@ class CertificationController extends Controller
|
|||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Certifications\StoreCertificationRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(StoreCertificationRequest $request)
|
||||
public function store(StoreCertificationRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$certification = new Certification();
|
||||
|
|
@ -84,9 +84,9 @@ class CertificationController extends Controller
|
|||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Certification $certification
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(Certification $certification)
|
||||
public function edit(Certification $certification): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('bo.pages.certifications.edit', [
|
||||
'certificationModel' => $certification,
|
||||
|
|
@ -98,10 +98,12 @@ class CertificationController extends Controller
|
|||
*
|
||||
* @param \App\Http\Requests\Bo\Certifications\UpdateCertificationRequest $request
|
||||
* @param \App\Models\Certification $certification
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateCertificationRequest $request, Certification $certification)
|
||||
{
|
||||
public function update(
|
||||
UpdateCertificationRequest $request,
|
||||
Certification $certification
|
||||
): \Illuminate\Http\RedirectResponse {
|
||||
return DB::transaction(function () use ($request, $certification) {
|
||||
$certification->fill($request->validated());
|
||||
|
||||
|
|
@ -126,9 +128,9 @@ class CertificationController extends Controller
|
|||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Certification $certification
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(Certification $certification)
|
||||
public function destroy(Certification $certification): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if ($certification->deleteOrFail()) {
|
||||
return redirect()
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
|
|
@ -12,7 +11,7 @@ class DashboardController extends Controller
|
|||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(): View
|
||||
public function index(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('bo.pages.dashboard');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,9 +22,9 @@ class ProductController extends Controller
|
|||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $products */
|
||||
$products = Product::query();
|
||||
|
|
@ -50,9 +50,9 @@ class ProductController extends Controller
|
|||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create()
|
||||
public function create(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$ranges = Range::all();
|
||||
$certifications = Certification::all();
|
||||
|
|
@ -65,9 +65,9 @@ class ProductController extends Controller
|
|||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Products\StoreProductRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(StoreProductRequest $request)
|
||||
public function store(StoreProductRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$product = new Product();
|
||||
|
|
@ -97,9 +97,9 @@ class ProductController extends Controller
|
|||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Product $product
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(Product $product)
|
||||
public function edit(Product $product): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$ranges = Range::all();
|
||||
$certifications = Certification::all();
|
||||
|
|
@ -118,9 +118,9 @@ class ProductController extends Controller
|
|||
*
|
||||
* @param \App\Http\Requests\Bo\Products\UpdateProductRequest $request
|
||||
* @param \App\Models\Product $product
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateProductRequest $request, Product $product)
|
||||
public function update(UpdateProductRequest $request, Product $product): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request, $product) {
|
||||
$product->fill($request->validated());
|
||||
|
|
@ -148,9 +148,9 @@ class ProductController extends Controller
|
|||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Product $product
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(Product $product)
|
||||
public function destroy(Product $product): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if ($product->deleteOrFail()) {
|
||||
return redirect()
|
||||
|
|
|
|||
|
|
@ -6,23 +6,21 @@ use App\Http\Controllers\Controller;
|
|||
use App\Http\Requests\Bo\Ranges\UpdateRangeRequest;
|
||||
use App\Models\Range;
|
||||
use App\Traits\Controllers\UpdateModelStatus;
|
||||
use App\Traits\Controllers\ChangesModelOrder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class RangeController extends Controller
|
||||
{
|
||||
use ChangesModelOrder;
|
||||
use UpdateModelStatus;
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $ranges */
|
||||
$ranges = Range::query();
|
||||
|
|
@ -48,9 +46,9 @@ class RangeController extends Controller
|
|||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Range $range
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(Range $range)
|
||||
public function edit(Range $range): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('bo.pages.ranges.edit', [
|
||||
'rangeModel' => $range
|
||||
|
|
@ -62,9 +60,9 @@ class RangeController extends Controller
|
|||
*
|
||||
* @param \App\Http\Requests\Bo\Ranges\UpdateRangeRequest $request
|
||||
* @param \App\Models\Range $range
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateRangeRequest $request, Range $range)
|
||||
public function update(UpdateRangeRequest $request, Range $range): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request, $range) {
|
||||
$range->fill($request->validated());
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ class RecipeController extends Controller
|
|||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $recipes */
|
||||
$recipes = Recipe::query();
|
||||
|
|
@ -48,9 +48,9 @@ class RecipeController extends Controller
|
|||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create()
|
||||
public function create(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$products = Product::all();
|
||||
$recipes = Recipe::all();
|
||||
|
|
@ -65,9 +65,9 @@ class RecipeController extends Controller
|
|||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Recipes\StoreRecipeRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(StoreRecipeRequest $request)
|
||||
public function store(StoreRecipeRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$recipe = new Recipe();
|
||||
|
|
@ -98,12 +98,12 @@ class RecipeController extends Controller
|
|||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Recipe $recipe
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(Recipe $recipe)
|
||||
public function edit(Recipe $recipe): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$products = Product::all();
|
||||
$recipes = Recipe::where('id', '!=', $recipe->id)->get();
|
||||
$recipes = Recipe::query()->where('id', '!=', $recipe->id)->get();
|
||||
|
||||
return view('bo.pages.recipes.edit', [
|
||||
'recipeModel' => $recipe,
|
||||
|
|
@ -117,9 +117,9 @@ class RecipeController extends Controller
|
|||
*
|
||||
* @param \App\Http\Requests\Bo\Recipes\UpdateRecipeRequest $request
|
||||
* @param \App\Models\Recipe $recipe
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateRecipeRequest $request, Recipe $recipe)
|
||||
public function update(UpdateRecipeRequest $request, Recipe $recipe): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request, $recipe) {
|
||||
$recipe->products()->sync($request->product_list);
|
||||
|
|
@ -149,9 +149,9 @@ class RecipeController extends Controller
|
|||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Recipe $recipe
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(Recipe $recipe)
|
||||
public function destroy(Recipe $recipe): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
DB::table('recipe_recipe')->where($recipe->recipes()->getRelatedPivotKeyName(), $recipe->id)->delete();
|
||||
$recipe->products()->sync([]);
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ class ShopController extends Controller
|
|||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $shops */
|
||||
$shops = Shop::query();
|
||||
|
|
@ -46,9 +46,9 @@ class ShopController extends Controller
|
|||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create()
|
||||
public function create(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('bo.pages.shops.create');
|
||||
}
|
||||
|
|
@ -57,9 +57,9 @@ class ShopController extends Controller
|
|||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Shops\StoreShopRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(StoreShopRequest $request)
|
||||
public function store(StoreShopRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$shop = new Shop();
|
||||
|
|
@ -87,9 +87,9 @@ class ShopController extends Controller
|
|||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Shop $shop
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(Shop $shop)
|
||||
public function edit(Shop $shop): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('bo.pages.shops.edit', [
|
||||
'shopModel' => $shop,
|
||||
|
|
@ -101,9 +101,9 @@ class ShopController extends Controller
|
|||
*
|
||||
* @param \App\Http\Requests\Bo\Shops\UpdateShopRequest $request
|
||||
* @param \App\Models\Shop $shop
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateShopRequest $request, Shop $shop)
|
||||
public function update(UpdateShopRequest $request, Shop $shop): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request, $shop) {
|
||||
$shop->fill($request->validated());
|
||||
|
|
@ -129,9 +129,9 @@ class ShopController extends Controller
|
|||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Shop $shop
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(Shop $shop)
|
||||
public function destroy(Shop $shop): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if ($shop->deleteOrFail()) {
|
||||
return redirect()
|
||||
|
|
|
|||
104
app/Http/Controllers/Bo/StaticPageController.php
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\StaticPages\UpdateStaticPageRequest;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class StaticPageController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create the controller instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->authorizeResource(StaticPage::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $query */
|
||||
$query = StaticPage::query();
|
||||
|
||||
/** @var string $search Search field */
|
||||
$search = $request->search;
|
||||
if ($search) {
|
||||
$this->searchQuery(
|
||||
$query,
|
||||
$search,
|
||||
null,
|
||||
'title',
|
||||
);
|
||||
}
|
||||
$searchFields = \implode(', ', [
|
||||
trans('validation.attributes.title'),
|
||||
]);
|
||||
|
||||
/** Sort columns with a query */
|
||||
$this->sortQuery($query);
|
||||
|
||||
/** Custom pagination */
|
||||
$staticPageModelList = $this->paginate($query);
|
||||
|
||||
return view('bo.pages.static_pages.index', compact('staticPageModelList', 'search', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\StaticPage $static_page
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(StaticPage $static_page): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('bo.pages.static_pages.edit', ['staticPageModel' => $static_page]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\StaticPages\UpdateStaticPageRequest $request
|
||||
* @param \App\Models\StaticPage $static_page
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateStaticPageRequest $request, StaticPage $static_page): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request, $static_page) {
|
||||
$validated = $request->validated();
|
||||
$data = $static_page->data;
|
||||
|
||||
foreach ($validated['data'] as $key => $input) {
|
||||
if (isset($input['value']) && is_array($input['value'])) {
|
||||
$data[$key]['value'] = $input['value'];
|
||||
}
|
||||
}
|
||||
|
||||
$static_page->data = $data;
|
||||
$static_page->fill(array_replace_recursive(
|
||||
$static_page->getFillableFields($static_page),
|
||||
$validated
|
||||
));
|
||||
|
||||
if ($static_page->saveOrFail()) {
|
||||
return redirect()->route('bo.static_pages.edit', $static_page)
|
||||
->with('success', __('crud.messages.has_been_updated', [
|
||||
'model' => Str::ucfirst(\trans_choice('models.classes.static_page', 1))
|
||||
]));
|
||||
}
|
||||
return redirect()->route('bo.static_pages.edit', $static_page)
|
||||
->with('error', __('crud.messages.cannot_be_updated', [
|
||||
'model' => Str::ucfirst(\trans_choice('models.classes.static_page', 1))
|
||||
]));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -2,12 +2,16 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Enums\Pagination\ItemsPerPaginationEnum;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
|
|
@ -29,7 +33,7 @@ class Controller extends BaseController
|
|||
protected function searchQuery(
|
||||
Builder $query,
|
||||
string $search,
|
||||
callable $searchQuery = null,
|
||||
?callable $searchQuery = null,
|
||||
string ...$fields
|
||||
): Builder {
|
||||
if (count($fields)) {
|
||||
|
|
@ -107,10 +111,7 @@ class Controller extends BaseController
|
|||
Session::remove("$rName.sort_way");
|
||||
}
|
||||
if (request()->sort_col and request()->sort_way and Schema::hasColumn($table, request()->sort_col)) {
|
||||
if (
|
||||
!isset($ignore) or
|
||||
(isset($ignore) and !in_array(request()->sort_col, $ignore))
|
||||
) {
|
||||
if (!in_array(request()->sort_col, $ignore)) {
|
||||
$query = $query->orderBy(\sprintf("$table.%s", request()->sort_col), request()->sort_way);
|
||||
}
|
||||
} elseif (Schema::hasColumn($table, 'order')) {
|
||||
|
|
@ -120,4 +121,30 @@ class Controller extends BaseController
|
|||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Customize pagination with cache or config (default).
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \App\Enums\Pagination\ItemsPerPaginationEnum|null $pagination
|
||||
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||||
*/
|
||||
protected function paginate(
|
||||
Builder $query,
|
||||
?ItemsPerPaginationEnum $pagination = null
|
||||
): \Illuminate\Contracts\Pagination\LengthAwarePaginator {
|
||||
$currentRoutePath = Str::slug(request()->route()->getName());
|
||||
$cacheKey = "pagination.{$currentRoutePath}";
|
||||
$pagination = $pagination ?? ItemsPerPaginationEnum::twelve;
|
||||
$pagination = ToolboxHelper::getValidatedEnum(
|
||||
Cache::get($cacheKey, $pagination->value()),
|
||||
'pagination',
|
||||
'\App\Enums\Pagination\ItemsPerPaginationEnum',
|
||||
);
|
||||
if (Cache::get($cacheKey) !== $pagination) {
|
||||
Cache::put($cacheKey, $pagination);
|
||||
}
|
||||
$query = $query->paginate($pagination);
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
22
app/Http/Controllers/Fo/CommitmentController.php
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\StaticPage;
|
||||
|
||||
class CommitmentController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$staticPageModel = StaticPage::query()->where('type', StaticPageType::our_commitments)->first();
|
||||
|
||||
return view('fo.pages.engagments', compact('staticPageModel'));
|
||||
}
|
||||
}
|
||||
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Range;
|
||||
use App\Models\Recipe;
|
||||
use App\Models\StaticPage;
|
||||
|
||||
class HomeController extends Controller
|
||||
{
|
||||
|
|
@ -15,16 +17,19 @@ class HomeController extends Controller
|
|||
*/
|
||||
public function index()
|
||||
{
|
||||
$staticPageModel = StaticPage::query()->where('type', StaticPageType::homepage)->first();
|
||||
|
||||
// Gammes.
|
||||
$ranges = Range::where('status', true)
|
||||
$ranges = Range::query()->where('status', true)
|
||||
->get();
|
||||
|
||||
// 3 Recettes.
|
||||
$publishedRecipes = Recipe::where('status', true)
|
||||
$publishedRecipes = Recipe::query()
|
||||
->where('status', true)
|
||||
->inRandomOrder()
|
||||
->take(3)
|
||||
->get();
|
||||
|
||||
return view('fo.pages.home', compact('ranges', 'publishedRecipes'));
|
||||
return view('fo.pages.home', compact('staticPageModel', 'ranges', 'publishedRecipes'));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Product;
|
||||
use App\Models\Range;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class ProductsController extends Controller
|
||||
|
|
@ -16,11 +18,13 @@ class ProductsController extends Controller
|
|||
*/
|
||||
public function index()
|
||||
{
|
||||
$staticPageModel = StaticPage::query()->where('type', StaticPageType::our_products)->first();
|
||||
|
||||
// Gammes.
|
||||
$ranges = Range::where('status', true)
|
||||
$ranges = Range::query()->where('status', true)
|
||||
->get();
|
||||
|
||||
return view('fo.pages.products.index', compact('ranges'));
|
||||
return view('fo.pages.products.index', compact('staticPageModel', 'ranges'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -35,7 +39,7 @@ class ProductsController extends Controller
|
|||
$q->where('id', $publishedRange->id);
|
||||
})
|
||||
->where('status', true)
|
||||
->paginate(9);
|
||||
->paginate(9);
|
||||
|
||||
return view('fo.pages.products.range-products', [
|
||||
'products' => $products,
|
||||
|
|
@ -51,6 +55,7 @@ class ProductsController extends Controller
|
|||
*/
|
||||
public function show(Product $publishedProduct)
|
||||
{
|
||||
$publishedProduct->load('range');
|
||||
$certifications = $publishedProduct->certifications()->where('status', true)->get();
|
||||
$associatedRecipes = $publishedProduct->recipes()->where('status', true)->take(3)->get();
|
||||
$productModel = $publishedProduct;
|
||||
|
|
|
|||
|
|
@ -2,54 +2,64 @@
|
|||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Enums\CookingModeEnum;
|
||||
use App\Enums\DifficultyEnum;
|
||||
use App\Enums\PreparationTimeEnum;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Fo\RecipesIndexRequest;
|
||||
use App\Models\Recipe;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use App\Http\Resources\Fo\Recipes\RecipeResource;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class RecipesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Return a list of filtered recipes.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \App\Http\Requests\Fo\RecipesIndexRequest $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(RecipesIndexRequest $request)
|
||||
{
|
||||
// Get recipes.
|
||||
$filters_activated = $request->filtered_infos;
|
||||
$query = Recipe::query();
|
||||
|
||||
$publishedRecipes = Recipe::when(
|
||||
isset($filters_activated),
|
||||
function ($query) use ($filters_activated) {
|
||||
if ($filters_activated[0] >= 0) {
|
||||
$diff_oper = '=';
|
||||
} else {
|
||||
$diff_oper = '>';
|
||||
}
|
||||
if ($filters_activated[1] >= 0) {
|
||||
$min_time = PreparationTimeEnum::from($filters_activated[1])->time()['min'];
|
||||
$max_time = PreparationTimeEnum::from($filters_activated[1])->time()['max'];
|
||||
} else {
|
||||
$min_time = 0;
|
||||
$max_time = 9999;
|
||||
}
|
||||
if ($filters_activated[2] >= 0) {
|
||||
$cook_oper = '=';
|
||||
} else {
|
||||
$cook_oper = '>';
|
||||
}
|
||||
$query->where('difficulty', $diff_oper, $filters_activated[0])
|
||||
->whereBetween('preparation_time', [$min_time, $max_time])
|
||||
->where('cooking_mode', $cook_oper, $filters_activated[2]);
|
||||
}
|
||||
)
|
||||
/** @var \App\Enums\CookingModeEnum|null */
|
||||
$cooking_mode_enum = !empty($request->get('cooking_mode_enum')) ?
|
||||
CookingModeEnum::make($request->get('cooking_mode_enum')) :
|
||||
null;
|
||||
/** @var \App\Enums\PreparationTimeEnum|null */
|
||||
$preparation_time_enum = !empty($request->get('preparation_time_enum')) ?
|
||||
PreparationTimeEnum::make($request->get('preparation_time_enum')) :
|
||||
null;
|
||||
/** @var \App\Enums\DifficultyEnum|null */
|
||||
$difficulty_enum = !empty($request->get('difficulty_enum')) ?
|
||||
DifficultyEnum::make($request->get('difficulty_enum')) :
|
||||
null;
|
||||
|
||||
if ($cooking_mode_enum) {
|
||||
$query->where('cooking_mode', $cooking_mode_enum);
|
||||
}
|
||||
|
||||
if ($preparation_time_enum) {
|
||||
/** @var integer */
|
||||
$min_time = Arr::get($preparation_time_enum->time(), 'min', 0);
|
||||
/** @var integer */
|
||||
$max_time = Arr::get($preparation_time_enum->time(), 'max', 9999);
|
||||
|
||||
$query->whereBetween('preparation_time', [$min_time, $max_time]);
|
||||
}
|
||||
|
||||
if ($difficulty_enum) {
|
||||
$query->where('difficulty', $difficulty_enum);
|
||||
}
|
||||
|
||||
$publishedRecipes = $query
|
||||
->where('status', true)
|
||||
->orderBy('created_at')
|
||||
->paginate(9);
|
||||
|
||||
return view('fo.pages.recipes.index', compact('publishedRecipes', 'filters_activated'));
|
||||
return view('fo.pages.recipes.index', compact('publishedRecipes'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -64,7 +74,8 @@ class RecipesController extends Controller
|
|||
$relatedRecipes = $publishedRecipe->recipes()->where('status', true)->get();
|
||||
|
||||
// 3 Recettes.
|
||||
$publishedRecipes = Recipe::where('status', true)
|
||||
$publishedRecipes = Recipe::query()
|
||||
->where('status', true)
|
||||
->where('id', '!=', $publishedRecipe->id)
|
||||
->take(3)
|
||||
->get();
|
||||
|
|
@ -76,4 +87,102 @@ class RecipesController extends Controller
|
|||
compact('recipeModel', 'products', 'relatedRecipes')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print recipe informations
|
||||
*
|
||||
* @param \App\Models\Recipe $publishedRecipe
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function printRecipe(Recipe $publishedRecipe): \Symfony\Component\HttpFoundation\Response
|
||||
{
|
||||
$title = trans('Fiche commerciale du produit : :label - :appname', [
|
||||
'label' => $publishedRecipe->name,
|
||||
'appname' => \config('app.name', 'Lionor')
|
||||
]);
|
||||
$filename = trans('fiche-commerciale-:slug-:date', [
|
||||
'slug' => Str::slug($publishedRecipe->name),
|
||||
'date' => \now()->format('Y-m-d')
|
||||
]);
|
||||
|
||||
/**
|
||||
* ! Réponse mano car en fait \Mccarlosen\LaravelMpdf\LaravelMpdf
|
||||
* ! ne retourne pas vraiemnt une http response, mais provoque une 500
|
||||
* ! apres avoir header et echo dans le corps de la réponse php (Nasty trick)
|
||||
*
|
||||
* (From LeGauloisPro)
|
||||
*/
|
||||
return \response(
|
||||
$this->generateRecipePdf($publishedRecipe, $title)->download($filename),
|
||||
200,
|
||||
[
|
||||
'Content-Type' => 'application/pdf',
|
||||
'Content-disposition' => "inline; filename=\"{$filename}\"",
|
||||
'Cache-Control' => 'public, must-revalidate, max-age=0',
|
||||
'Pragma' => 'public',
|
||||
// * For glory
|
||||
'X-Generator' => 'mPDF',
|
||||
'Expires' => 'Sat, 26 Jul 1997 05:00:00 GMT',
|
||||
'Last-Modified' => gmdate('D, d M Y H:i:s') . ' GMT',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate recipe PDF
|
||||
*
|
||||
* @param \App\Models\Recipe $recipe
|
||||
* @param string $title
|
||||
* @return \Mccarlosen\LaravelMpdf\LaravelMpdf
|
||||
*/
|
||||
private function generateRecipePdf(Recipe $recipe, string $title): \Mccarlosen\LaravelMpdf\LaravelMpdf
|
||||
{
|
||||
$tabRecipe = \json_decode(\json_encode(new RecipeResource($recipe)));
|
||||
|
||||
$mpdf = app('laravel-mpdf');
|
||||
/** @var \Mccarlosen\LaravelMpdf\LaravelMpdf */
|
||||
$pdf = $mpdf->loadView(
|
||||
'fo.documents.recipe',
|
||||
// * Dirty convert to object.
|
||||
[
|
||||
'title' => $title,
|
||||
'recipe' => $tabRecipe
|
||||
],
|
||||
[],
|
||||
[
|
||||
'mode' => 'utf-8',
|
||||
'format' => 'A4',
|
||||
'default_font_size' => '12',
|
||||
'default_font' => 'sans-serif',
|
||||
|
||||
// Recto Verso.
|
||||
'margin_left' => 10,
|
||||
'margin_right' => 10,
|
||||
'mirrorMargins' => true,
|
||||
|
||||
'margin_top' => 25,
|
||||
'margin_bottom' => 20,
|
||||
'margin_header' => 0,
|
||||
'margin_footer' => 0,
|
||||
'orientation' => 'P',
|
||||
'title' => $title,
|
||||
'author' => \config('app.name', 'Lionor'),
|
||||
'watermark' => '',
|
||||
'show_watermark' => false,
|
||||
'watermark_font' => 'sans-serif',
|
||||
'display_mode' => 'fullpage',
|
||||
'watermark_text_alpha' => 0.1,
|
||||
'custom_font_dir' => '',
|
||||
'custom_font_data' => [],
|
||||
'auto_language_detection' => false,
|
||||
'temp_dir' => rtrim(
|
||||
ini_get('upload_tmp_dir') ? ini_get('upload_tmp_dir') : sys_get_temp_dir(),
|
||||
DIRECTORY_SEPARATOR
|
||||
),
|
||||
'pdfa' => false,
|
||||
'pdfaauto' => false,
|
||||
]
|
||||
);
|
||||
return $pdf;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ class ShopController extends Controller
|
|||
/**
|
||||
* Get all shops
|
||||
*
|
||||
* @return json
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index()
|
||||
public function index(): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
if (request()->wantsJson()) {
|
||||
return response()
|
||||
|
|
@ -28,10 +28,10 @@ class ShopController extends Controller
|
|||
/**
|
||||
* Get the 5 nearest shops with the given coords in the request.
|
||||
*
|
||||
* @param App\Http\Requests\Fo\Shop\GetNearestShopRequest $request
|
||||
* @return json
|
||||
* @param \App\Http\Requests\Fo\Shop\GetNearestShopRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getNearest(GetNearestShopRequest $request)
|
||||
public function getNearest(GetNearestShopRequest $request): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
if (!$request->wantsJson()) {
|
||||
return abort(404);
|
||||
|
|
|
|||
34
app/Http/Controllers/Fo/StaticPageController.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\StaticPage;
|
||||
|
||||
class StaticPageController extends Controller
|
||||
{
|
||||
/**
|
||||
* Legal show
|
||||
*
|
||||
* @param \App\Models\StaticPage $legalPage
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function legals(StaticPage $legalPage)
|
||||
{
|
||||
$legalPage = StaticPage::query()->where('type', StaticPageType::legals)->first();
|
||||
return view('fo.pages.legals', ['staticPageModel' => $legalPage]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Policies show
|
||||
*
|
||||
* @param \App\Models\StaticPage $policiesPage
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function policies(StaticPage $policiesPage)
|
||||
{
|
||||
$policiesPage = StaticPage::query()->where('type', StaticPageType::confidentiality)->first();
|
||||
return view('fo.pages.policies', ['staticPageModel' => $policiesPage]);
|
||||
}
|
||||
}
|
||||
|
|
@ -40,6 +40,12 @@ class Kernel extends HttpKernel
|
|||
\App\Http\Middleware\SecureHeaders::class
|
||||
],
|
||||
|
||||
'saml' => [
|
||||
\App\Http\Middleware\EncryptCookies::class,
|
||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
],
|
||||
|
||||
'api' => [
|
||||
\Illuminate\Routing\Middleware\ThrottleRequests::class . ':api',
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use Illuminate\Http\Request;
|
|||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Illuminate\Support\Facades\Vite;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class SecureHeaders
|
||||
{
|
||||
|
|
@ -31,7 +30,7 @@ class SecureHeaders
|
|||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
public function handle(Request $request, Closure $next): \Symfony\Component\HttpFoundation\Response
|
||||
{
|
||||
// phpcs:enable
|
||||
View::share('nonce', $nonce = Vite::useCspNonce());
|
||||
|
|
@ -51,12 +50,20 @@ class SecureHeaders
|
|||
"default-src 'none';",
|
||||
"manifest-src 'self';",
|
||||
// * CKEDITOR Specific https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/csp.html
|
||||
"connect-src 'self' blob:;",
|
||||
"img-src * data: blob:;",
|
||||
"connect-src 'self' blob: " . implode(' ', [
|
||||
'https://yl.s-web.fr',
|
||||
'https://api-adresse.data.gouv.fr'
|
||||
]) . ';',
|
||||
"img-src 'self' data: blob: " . implode(' ', [
|
||||
'https://tile.openstreetmap.org/'
|
||||
]) . ';',
|
||||
// ! Blob required for printjs
|
||||
'frame-src ' . implode(' ', [
|
||||
'https://www.google.com/recaptcha/',
|
||||
'https://recaptcha.google.com/recaptcha/',
|
||||
'https://www.google.com/maps/'
|
||||
'https://www.google.com/maps/',
|
||||
'https://www.youtube.com/',
|
||||
'blob:',
|
||||
]) . ';',
|
||||
"font-src 'self' data: https://fonts.gstatic.com;",
|
||||
// ! Using CKEditor will must have unsafe-inline style
|
||||
|
|
@ -67,7 +74,7 @@ class SecureHeaders
|
|||
'https://fonts.googleapis.com',
|
||||
'https://cdn.jsdelivr.net',
|
||||
'https://use.fontawesome.com',
|
||||
'https://fonts.googleapis.com'
|
||||
'https://fonts.googleapis.com',
|
||||
]) . ';',
|
||||
// ! If you dont use ckeditor use this
|
||||
// "style-src 'self' 'nonce-$nonce';",
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class StoreCertificationRequest extends FormRequest
|
|||
protected function prepareForValidation()
|
||||
{
|
||||
$this->merge([
|
||||
'status' => $this->status ? true : false
|
||||
'status' => $this->boolean('status')
|
||||
]);
|
||||
$this->mergePicture('sticker');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class ChangeOrderRequest extends FormRequest
|
|||
protected function prepareForValidation()
|
||||
{
|
||||
$this->merge([
|
||||
'direction' => $this->action === 'up' ? true : false
|
||||
'direction' => $this->direction === 'up' ? true : false
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -36,7 +36,6 @@ class ChangeOrderRequest extends FormRequest
|
|||
public function rules()
|
||||
{
|
||||
return [
|
||||
'action' => 'required|string|in:up,down',
|
||||
'direction' => 'required|boolean',
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use App\Enums\NutriscoreEnum;
|
|||
use App\Traits\Requests\HasPicture;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rules\Enum;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class StoreProductRequest extends FormRequest
|
||||
{
|
||||
|
|
@ -30,14 +31,15 @@ class StoreProductRequest extends FormRequest
|
|||
protected function prepareForValidation()
|
||||
{
|
||||
$this->merge([
|
||||
'status' => $this->status ? true : false,
|
||||
'nutritional_values' => $this->nutritional_values ?? [],
|
||||
'status' => $this->boolean('status'),
|
||||
'nutritional_values' => $this->input('nutritional_values') ?? [],
|
||||
'certification_list' => \collect($this->certifications)->map(function ($value) {
|
||||
return \is_array($value) ? ($value['value'] ?? null) : null;
|
||||
})->filter()->all(),
|
||||
'recipe_list' => \collect($this->recipes)->map(function ($value) {
|
||||
return \is_array($value) ? ($value['value'] ?? null) : null;
|
||||
})->filter()->all(),
|
||||
'description' => (string)Str::of($this->input('description'))
|
||||
]);
|
||||
$this->mergePicture('picture');
|
||||
$this->mergePicture('sticker');
|
||||
|
|
@ -60,7 +62,7 @@ class StoreProductRequest extends FormRequest
|
|||
'sticker_alt' => 'required|min:3|max:255',
|
||||
'sticker_title' => 'required|min:3|max:255',
|
||||
|
||||
'description' => 'required|string|min:15',
|
||||
'description' => 'present|string',
|
||||
'preparation' => 'nullable|string|min:15',
|
||||
'ingredients' => 'required|string|min:15',
|
||||
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ class UpdateRangeRequest extends FormRequest
|
|||
protected function prepareForValidation()
|
||||
{
|
||||
$this->merge([
|
||||
'slug' => Str::slug(strip_tags($this->name)),
|
||||
'status' => $this->status ? true : false
|
||||
'slug' => Str::slug(strip_tags($this->input('name'))),
|
||||
'status' => $this->boolean('status')
|
||||
]);
|
||||
$this->mergePicture('picture');
|
||||
$this->mergePicture('banner');
|
||||
|
|
|
|||
|
|
@ -31,12 +31,12 @@ class StoreRecipeRequest extends FormRequest
|
|||
protected function prepareForValidation()
|
||||
{
|
||||
$this->merge([
|
||||
'slug' => Str::slug(strip_tags($this->title)),
|
||||
'status' => $this->status ? true : false,
|
||||
'ingredients' => $this->ingredients ?? [],
|
||||
'products' => $this->products ?? [],
|
||||
'recipes' => $this->recipes ?? [],
|
||||
'cooking_time' => $this->cooking_time ?? 0,
|
||||
'slug' => Str::slug(strip_tags($this->input('title'))),
|
||||
'status' => $this->boolean('status'),
|
||||
'ingredients' => $this->input('ingredients') ?? [],
|
||||
'products' => $this->input('products') ?? [],
|
||||
'recipes' => $this->input('recipes') ?? [],
|
||||
'cooking_time' => $this->input('cooking_time') ?? 0,
|
||||
// * For sync relations
|
||||
'product_list' => \collect($this->products)->map(function ($value) {
|
||||
return \is_array($value) ? ($value['value'] ?? null) : null;
|
||||
|
|
@ -75,7 +75,7 @@ class StoreRecipeRequest extends FormRequest
|
|||
'difficulty' => ['required', new Enum(DifficultyEnum::class)],
|
||||
'cooking_mode' => [
|
||||
'required_with:cooking_time',
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||
function ($attribute, $value, $fail) {
|
||||
if ($this->cooking_time == 0 and $value != 0) {
|
||||
$fail(\trans(":attribute doit être à :enumValue quand temps de cuisson est à 0.", [
|
||||
|
|
@ -97,7 +97,7 @@ class StoreRecipeRequest extends FormRequest
|
|||
'preparation_time' => 'required|numeric|min:1|max:1440',
|
||||
'status' => 'required|boolean',
|
||||
'products' => [
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||
'present', 'array', function ($attribute, array $value, $fail) {
|
||||
if (count($value) < 1 || count($value) > 3) {
|
||||
$fail(\trans('Vous devez associer 1 à 3 produits.'));
|
||||
|
|
@ -108,7 +108,7 @@ class StoreRecipeRequest extends FormRequest
|
|||
'products.*.value' => 'required|exists:products,id',
|
||||
'products.*.label' => 'required|string',
|
||||
'recipes' => [
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||
'present', 'array', function ($attribute, array $value, $fail) {
|
||||
if (count($value) > 3) {
|
||||
$fail(\trans('Vous devez associer au maximum 3 recettes.'));
|
||||
|
|
|
|||
75
app/Http/Requests/Bo/StaticPages/UpdateStaticPageRequest.php
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Bo\StaticPages;
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class UpdateStaticPageRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth('backend')->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'content' => $this->input('content') ? Str::of($this->input('content'))->value() : null
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'seo_title' => 'nullable',
|
||||
'seo_description' => 'nullable',
|
||||
'title' => 'required|min:3|max:255',
|
||||
'content' => 'nullable',
|
||||
'data' => 'present|array',
|
||||
'data.*' => 'required|array',
|
||||
];
|
||||
|
||||
/** @var \App\Models\StaticPage $staticPageModel */
|
||||
$staticPageModel = request()->route()->parameter('static_page');
|
||||
if (!$staticPageModel->type->equals(StaticPageType::banner_section)) {
|
||||
$rules = \array_merge(
|
||||
$rules,
|
||||
[
|
||||
'seo_title' => 'required|min:45|max:70',
|
||||
'seo_description' => 'required|min:50|max:160',
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!$staticPageModel->type->equals(StaticPageType::homepage) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::our_products) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::our_commitments) &&
|
||||
!$staticPageModel->type->equals(StaticPageType::banner_section)
|
||||
) {
|
||||
$rules = \array_merge(
|
||||
$rules,
|
||||
['content' => ['present']],
|
||||
);
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
|
|
@ -109,7 +109,7 @@ abstract class UpdateMiniCrudRequest extends FormRequest
|
|||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value" => [
|
||||
function (string $attribute, $value, callable $fail) use ($sizes) {
|
||||
return ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
|
||||
ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
|
||||
}
|
||||
],
|
||||
$this->compileValidate(
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class ContactRequest extends FormRequest
|
|||
return [
|
||||
'civility' => [
|
||||
'required',
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||
function ($attribute, $value, $fail) {
|
||||
if (!in_array($value, CivilityEnum::toValues())) {
|
||||
$fail(__('Veuillez choisir entre :values', [
|
||||
|
|
@ -48,7 +48,6 @@ class ContactRequest extends FormRequest
|
|||
'city' => 'required|string|max:255',
|
||||
'subject' => 'required|string|max:255',
|
||||
'message' => 'required|string|min:20|max:255',
|
||||
'rgpd' => 'accepted'
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +87,6 @@ class ContactRequest extends FormRequest
|
|||
'city' => trans('ville'),
|
||||
'subject' => trans('objet e la demande'),
|
||||
'message' => trans('message'),
|
||||
'rgpd' => trans('condition d\'utilisation'),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
65
app/Http/Requests/Fo/RecipesIndexRequest.php
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Fo;
|
||||
|
||||
use App\Enums\CookingModeEnum;
|
||||
use App\Enums\DifficultyEnum;
|
||||
use App\Enums\PreparationTimeEnum;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class RecipesIndexRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'cooking_mode_enum' => $this->makeEnum(CookingModeEnum::class, $this->get('cooking_mode_enum')),
|
||||
'preparation_time_enum' => $this->makeEnum(PreparationTimeEnum::class, $this->get('preparation_time_enum')),
|
||||
'difficulty_enum' => $this->makeEnum(DifficultyEnum::class, $this->get('difficulty_enum'))
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'cooking_mode_enum' => ['nullable', Rule::enum(CookingModeEnum::class)],
|
||||
'preparation_time_enum' => ['nullable', Rule::enum(PreparationTimeEnum::class)],
|
||||
'difficulty_enum' => ['nullable', Rule::enum(DifficultyEnum::class)]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Make enum handle nullable case.
|
||||
*
|
||||
* @param string $enum_class
|
||||
* @param string|null $query_index
|
||||
* @return string|integer|null
|
||||
*/
|
||||
private function makeEnum(string $enum_class, ?string $query_index): string|int|null
|
||||
{
|
||||
if (!$query_index) {
|
||||
return null;
|
||||
}
|
||||
return optional(call_user_func([$enum_class, 'make'], $query_index))->value();
|
||||
}
|
||||
}
|
||||
81
app/Http/Resources/Fo/Recipes/RecipeResource.php
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Resources\Fo\Recipes;
|
||||
|
||||
use App\Models\Recipe;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class RecipeResource extends JsonResource
|
||||
{
|
||||
/** @var \App\Models\Recipe */
|
||||
private $recipe;
|
||||
|
||||
/** @var array */
|
||||
private static $skeleton = [
|
||||
'id' => '',
|
||||
'name' => '',
|
||||
'slug' => '',
|
||||
'picture' => '',
|
||||
'description' => '',
|
||||
'preparation' => '',
|
||||
'ingredients' => [],
|
||||
'portions' => '',
|
||||
'difficulty' => [
|
||||
'label' => 'none',
|
||||
'value' => 0
|
||||
],
|
||||
'preparation_time' => '',
|
||||
'cooking_time' => '',
|
||||
];
|
||||
|
||||
/**
|
||||
* RecipeResource
|
||||
*
|
||||
* @param \App\Models\Recipe $recipe
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Recipe $recipe)
|
||||
{
|
||||
$this->recipe = $recipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request|null $request
|
||||
* @return array
|
||||
*
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
*/
|
||||
public function toArray(?Request $request = null): array
|
||||
{
|
||||
// phpcs:enable
|
||||
return array_intersect_key(
|
||||
[
|
||||
'id' => $this->recipe->id,
|
||||
'name' => $this->recipe->name,
|
||||
'slug' => $this->recipe->slug,
|
||||
'picture' => $this->recipe->picture,
|
||||
'description' => $this->recipe->description,
|
||||
'preparation' => $this->recipe->preparation,
|
||||
'ingredients' => $this->recipe->ingredients,
|
||||
'portions' => $this->recipe->portions,
|
||||
'difficulty' => $this->recipe->difficulty,
|
||||
'preparation_time' => $this->recipe->preparation_time,
|
||||
'cooking_time' => $this->recipe->cooking_time,
|
||||
],
|
||||
$this->getSkeleton()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource skeletton
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getSkeleton(): array
|
||||
{
|
||||
return self::$skeleton;
|
||||
}
|
||||
}
|
||||
|
|
@ -145,7 +145,7 @@ class ExceptionsHelper
|
|||
$traceStr .= self::handleArgs($stack);
|
||||
}
|
||||
$traceStr .= ")\n";
|
||||
} elseif (isset($stack['function'])) {
|
||||
} else {
|
||||
$traceStr .= "{$stack['function']}(";
|
||||
if (isset($stack['args'])) {
|
||||
$traceStr .= self::handleArgs($stack);
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ class FileStorageHelper
|
|||
Model $model,
|
||||
$file,
|
||||
bool $slugify = false,
|
||||
string $filename = null,
|
||||
?string $filename = null,
|
||||
bool $private = false
|
||||
): string {
|
||||
// phpcs:enable
|
||||
|
|
@ -118,7 +118,7 @@ class FileStorageHelper
|
|||
);
|
||||
|
||||
return str_replace('/private/', '', $newPath);
|
||||
}//end if
|
||||
} //end if
|
||||
if (\is_object($file) and $file instanceof \SplFileInfo) {
|
||||
/** @var \SplFileInfo $file */
|
||||
$filename = $filename ?: $file->getBaseName();
|
||||
|
|
@ -152,7 +152,7 @@ class FileStorageHelper
|
|||
public static function storeModelFilesFromHtml(
|
||||
Model $model,
|
||||
string $htmlString,
|
||||
string $oldHtmlString = null
|
||||
?string $oldHtmlString = null
|
||||
): string {
|
||||
\collect(self::onlyUploadedFilesWithFileManager(self::findFilesInHtml($htmlString)))
|
||||
->each(function (string $path) use ($model, &$htmlString) {
|
||||
|
|
@ -309,7 +309,6 @@ class FileStorageHelper
|
|||
$private ? 'app/private/modelfiles' : 'app/public/modelfiles',
|
||||
$tableName,
|
||||
$filename,
|
||||
$private
|
||||
);
|
||||
$filename = self::getFileUniqueName($folderPath, $filename);
|
||||
return "{$folderPath}/{$filename}";
|
||||
|
|
@ -404,7 +403,7 @@ class FileStorageHelper
|
|||
$filename = Str::of($filename)->ltrim('.-');
|
||||
// * Optional beautification
|
||||
if ($beautify) {
|
||||
$filename = static::beautifyFilename($filename);
|
||||
$filename = self::beautifyFilename($filename);
|
||||
}
|
||||
// * Maximize filename length to 255 bytes http://serverfault.com/a/9548/44086
|
||||
/** @var string */
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use Illuminate\Support\Facades\Route;
|
|||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\Rules\Enum;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
|
|
@ -169,11 +170,10 @@ class ToolboxHelper
|
|||
$url = $match;
|
||||
try {
|
||||
$request = Request::create($url);
|
||||
// If a route is match then it do not throws exception.
|
||||
if (
|
||||
\parse_url(config('app.url'), \PHP_URL_HOST) === \parse_url($url, \PHP_URL_HOST) &&
|
||||
$routes->match($request)
|
||||
) {
|
||||
// Assert route matches existing routes.
|
||||
$routes->match($request);
|
||||
// ? Is url internal ?
|
||||
if (\parse_url(config('app.url'), \PHP_URL_HOST) === \parse_url($url, \PHP_URL_HOST)) {
|
||||
// Removes the matched url.
|
||||
throw ValidationException::withMessages([
|
||||
$field => trans(
|
||||
|
|
@ -199,14 +199,14 @@ class ToolboxHelper
|
|||
* @param array|string $replace
|
||||
* @param array|string $subject
|
||||
* @param integer $count
|
||||
* @return array|string
|
||||
* @return array|string|false
|
||||
*/
|
||||
public static function mbReplace(
|
||||
array|string $search,
|
||||
array|string $replace,
|
||||
array|string $subject,
|
||||
int &$count = 0
|
||||
): array|string {
|
||||
): array|string|false {
|
||||
if (!is_array($search) && is_array($replace)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -283,9 +283,12 @@ class ToolboxHelper
|
|||
public static function getOriginal(Model $model, string $attribute): mixed
|
||||
{
|
||||
if (\in_array('Spatie\Translatable\HasTranslations', \class_uses_recursive($model))) {
|
||||
// @phpstan-ignore-next-line
|
||||
return $model->getTranslation(
|
||||
$attribute,
|
||||
// @phpstan-ignore-next-line
|
||||
$model->getLocale(),
|
||||
// @phpstan-ignore-next-line
|
||||
$model->useFallbackLocale()
|
||||
);
|
||||
}
|
||||
|
|
@ -309,7 +312,7 @@ class ToolboxHelper
|
|||
): Builder {
|
||||
$currentLocale = app()->currentLocale();
|
||||
$locales = collect(config('app.locales'))
|
||||
->mapWithKeys(fn (string $locale) => [$locale => $locale]);
|
||||
->mapWithKeys(fn (string $locale) => [$locale => $locale]);
|
||||
if (!$locales->has($defaultLocale)) {
|
||||
// * Remove default locale.
|
||||
$locales->pull($defaultLocale);
|
||||
|
|
@ -355,55 +358,55 @@ class ToolboxHelper
|
|||
/**
|
||||
* Convert deeply an object to array
|
||||
*
|
||||
* @param array|object $input
|
||||
* @param mixed $input
|
||||
* @return array
|
||||
* @throws \RuntimeException If $input var is a scalar value.
|
||||
*/
|
||||
public static function objectToArray($input): array
|
||||
public static function objectToArray(mixed $input): array
|
||||
{
|
||||
// Only process if it's an object or array being passed to the function.
|
||||
if (is_object($input) or is_array($input)) {
|
||||
$ret = (array)$input;
|
||||
foreach ($ret as &$item) {
|
||||
// Recursively process EACH element only if not scalar.
|
||||
$item = (is_object($item) or is_array($item)) ?
|
||||
self::objectToArray($item) : $item;
|
||||
}
|
||||
return $ret;
|
||||
} else {
|
||||
if (!(is_object($input) or is_array($input))) {
|
||||
throw new \RuntimeException('Cannot handle $input of type ' . \gettype($input));
|
||||
}
|
||||
$ret = (array)$input;
|
||||
foreach ($ret as &$item) {
|
||||
// Recursively process EACH element only if not scalar.
|
||||
$item = (is_object($item) or is_array($item)) ?
|
||||
self::objectToArray($item) : $item;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert deeply an array to object
|
||||
*
|
||||
* @param array|object $input
|
||||
* @param mixed $input
|
||||
* @return object
|
||||
* @throws \RuntimeException If $input var is a scalar value.
|
||||
*/
|
||||
public static function arrayToObject($input): object
|
||||
public static function arrayToObject(mixed $input): object
|
||||
{
|
||||
// Only process if it's an object or array being passed to the function.
|
||||
if (is_object($input) or is_array($input)) {
|
||||
$ret = (object)$input;
|
||||
foreach ($ret as &$item) {
|
||||
// Recursively process EACH element only if not scalar.
|
||||
$item = (is_object($item) or is_array($item)) ?
|
||||
self::arrayToObject($item) : $item;
|
||||
}
|
||||
return $ret;
|
||||
} else {
|
||||
if (!(is_object($input) or is_array($input))) {
|
||||
throw new \RuntimeException('Cannot handle $input of type ' . \gettype($input));
|
||||
}
|
||||
$ret = (object)$input;
|
||||
foreach ($ret as &$item) {
|
||||
// Recursively process EACH element only if not scalar.
|
||||
$item = (is_object($item) or is_array($item)) ?
|
||||
self::arrayToObject($item) : $item;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate picture
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param string|null $value
|
||||
* @param callback $fail
|
||||
* @param callable $fail
|
||||
* @param object $sizes
|
||||
* @return void
|
||||
*/
|
||||
|
|
@ -426,7 +429,7 @@ class ToolboxHelper
|
|||
'attribute' => $attribute
|
||||
]));
|
||||
}
|
||||
if (!($dimensions = \getimagesize($fileFullPath)) or !isset($dimensions[0]) or !isset($dimensions[1])) {
|
||||
if (!($dimensions = \getimagesize($fileFullPath))) {
|
||||
$fail(trans(':attribute impossible de valider les dimensions', [
|
||||
'attribute' => $attribute
|
||||
]));
|
||||
|
|
@ -481,4 +484,24 @@ class ToolboxHelper
|
|||
{
|
||||
return !$useStorage ? File::mimeType($value) : Storage::mimeType($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get validated pagination from request.
|
||||
*
|
||||
* @param integer $default
|
||||
* @param string $field
|
||||
* @param string $enumPath
|
||||
* @return integer
|
||||
*/
|
||||
public static function getValidatedEnum(int $default, string $field, string $enumPath): int
|
||||
{
|
||||
try {
|
||||
return \intval(Validator::make(
|
||||
[$field => \request()->get($field)],
|
||||
[$field => new Enum($enumPath)]
|
||||
)->validated()[$field]);
|
||||
} catch (ValidationException $e) {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
179
app/Models/ActivityLog.php
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\ActivityLogs\ActivityLogsEventEnum;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @property string $model Target model.
|
||||
* @property string $model_id Id of the target model.
|
||||
* @property \App\Enums\ActivityLogs\ActivityLogsEventEnum $event Event of this activity (ActivityLogsEventEnum).
|
||||
* @property array $data Changes.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Created date.
|
||||
*
|
||||
* @property-read \App\Models\User $user User BelongsTo relation.
|
||||
*/
|
||||
class ActivityLog extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use Notifiable;
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'is_anonymous',
|
||||
'model_class',
|
||||
'model_id',
|
||||
'event',
|
||||
'data',
|
||||
'created_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'is_anonymous' => 'bool',
|
||||
'event' => ActivityLogsEventEnum::class,
|
||||
'data' => 'json',
|
||||
'created_at' => 'datetime',
|
||||
];
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Add new activity to the activity logs list.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param \App\Enums\ActivityLogs\ActivityLogsEventEnum $eventEnum
|
||||
* @return void
|
||||
*/
|
||||
public static function addActivity(Model $model, ActivityLogsEventEnum $eventEnum): void
|
||||
{
|
||||
$isAnonymous = true;
|
||||
/** @var \Illuminate\Database\Eloquent\Model|null */
|
||||
$userModel = auth('backend')->user();
|
||||
if (is_object($userModel)) {
|
||||
$userModel = $userModel->getKeyForSelectQuery();
|
||||
$isAnonymous = false;
|
||||
}
|
||||
$activity = new self();
|
||||
$activity->user_id = $userModel;
|
||||
$activity->is_console = app()->runningInConsole();
|
||||
$activity->is_anonymous = $isAnonymous;
|
||||
$activity->model_class = \get_class($model);
|
||||
$activity->model_id = $model->getKey();
|
||||
$activity->event = $eventEnum;
|
||||
$activity->data = static::getChangedColumns($activity, $model, $eventEnum);
|
||||
// @phpstan-ignore-next-line
|
||||
$activity->created_at = now();
|
||||
$activity->saveOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get old, new columns that has changed.
|
||||
*
|
||||
* @param self $activity
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param \App\Enums\ActivityLogs\ActivityLogsEventEnum $eventEnum
|
||||
* @return array
|
||||
*/
|
||||
public static function getChangedColumns(self $activity, Model $model, ActivityLogsEventEnum $eventEnum): array
|
||||
{
|
||||
$modelClassName = $activity->model_class;
|
||||
/** Get type of each fields of the target model */
|
||||
/** @var \Illuminate\Database\Eloquent\Model|null $targetModel */
|
||||
$targetModel = $activity->model_class::where(
|
||||
(new $modelClassName())->getRouteKeyName(),
|
||||
$activity->model_id
|
||||
)->first();
|
||||
|
||||
if (\is_null($targetModel)) {
|
||||
return [];
|
||||
}
|
||||
$targetModelTypes = collect($targetModel->toArray())
|
||||
->map(fn ($value) => self::getValueType($value))
|
||||
->toArray();
|
||||
/** Return old, new and type of values changed */
|
||||
return match ($eventEnum) {
|
||||
ActivityLogsEventEnum::created => array_intersect_key($targetModelTypes, $model->toArray()),
|
||||
ActivityLogsEventEnum::duplicated => array_intersect_key($targetModelTypes, $model->toArray()),
|
||||
ActivityLogsEventEnum::updated => array_intersect_key($targetModelTypes, $model->getChanges()),
|
||||
default => []
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a value type as a string
|
||||
* ! Use this for display purpose only
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
* @throws \RuntimeException If type is unhlanded.
|
||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.MaxExceeded
|
||||
*/
|
||||
private static function getValueType(mixed $value): string
|
||||
{
|
||||
// phpcs:enable
|
||||
$type = \gettype($value);
|
||||
switch ($type) {
|
||||
// phpcs:ignore PSR2.ControlStructures.SwitchDeclaration.TerminatingComment
|
||||
case 'string':
|
||||
return match (true) {
|
||||
Str::length(\strip_tags($value)) !== Str::length($value) => 'html',
|
||||
Str::startsWith($value, 'storage/modelfiles') => 'file',
|
||||
Str::isUuid($value) => 'uuid',
|
||||
Str::isUlid($value) => 'ulid',
|
||||
Str::isUrl($value) => 'url',
|
||||
Str::isMatch('/^[0-9A-Za-z_-]{10}[048AEIMQUYcgkosw]$/', $value) => 'youtube_video_id',
|
||||
\is_numeric($value) => 'numeric',
|
||||
Str::isJson($value) and
|
||||
(Str::startsWith($value, '[') or Str::startsWith($value, '{')) => 'json',
|
||||
default => 'string'
|
||||
};
|
||||
case 'NULL':
|
||||
case 'object':
|
||||
case 'array':
|
||||
case 'integer':
|
||||
case 'boolean':
|
||||
return $type;
|
||||
case 'double':
|
||||
return is_float($value) ? 'float' : 'double';
|
||||
case 'resource (closed)':
|
||||
case 'resource':
|
||||
throw new \RuntimeException('Laravel model properties should not contain resources !');
|
||||
case 'unknown type':
|
||||
default:
|
||||
throw new \RuntimeException('Unhandled Type ' . \gettype($value));
|
||||
} //end switch
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
* User BelongsTo relation.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -25,7 +25,7 @@ class Certification extends Model
|
|||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
|
|
@ -38,7 +38,7 @@ class Certification extends Model
|
|||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'status' => 'bool'
|
||||
|
|
@ -61,7 +61,7 @@ class Certification extends Model
|
|||
$model->sticker = FileStorageHelper::storeFile($model, $model->sticker, true);
|
||||
});
|
||||
static::updated(function (self $model) {
|
||||
$model->sticker = FileStorageHelper::removeOldFile($model, 'sticker');
|
||||
FileStorageHelper::removeOldFile($model, 'sticker');
|
||||
self::flashStatus($model, true);
|
||||
});
|
||||
static::deleting(function (self $model) {
|
||||
|
|
|
|||
|
|
@ -10,8 +10,11 @@ use App\Traits\Models\HasFlashStatus;
|
|||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\Sitemap\Contracts\Sitemapable;
|
||||
use Spatie\Sitemap\Tags\Url;
|
||||
use Uwil\SitemapGenerator\Lib\SitemapHelper;
|
||||
|
||||
class Product extends Model
|
||||
class Product extends Model implements Sitemapable
|
||||
{
|
||||
use HasFactory;
|
||||
use HasFlashStatus;
|
||||
|
|
@ -19,7 +22,7 @@ class Product extends Model
|
|||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
|
|
@ -47,7 +50,7 @@ class Product extends Model
|
|||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
/** @var array<ingredient> */
|
||||
|
|
@ -67,7 +70,7 @@ class Product extends Model
|
|||
// * EVENT CLOSURES.
|
||||
static::creating(function (self $model) {
|
||||
// * ASSERTIONS
|
||||
static::assertFieldIsUnique('name', $model->name);
|
||||
self::assertFieldIsUnique('name', $model->name);
|
||||
ToolboxHelper::assertNoInternalBoUrls('description', $model->description);
|
||||
ToolboxHelper::assertNoInternalBoUrls('preparation', $model->preparation ?? '');
|
||||
ToolboxHelper::assertNoInternalBoUrls('ingredients', $model->ingredients);
|
||||
|
|
@ -82,7 +85,7 @@ class Product extends Model
|
|||
});
|
||||
static::updating(function (self $model) {
|
||||
// * ASSERTIONS
|
||||
static::assertFieldIsUnique('name', $model->name, $model->id);
|
||||
self::assertFieldIsUnique('name', $model->name, $model->id);
|
||||
ToolboxHelper::assertNoInternalBoUrls('description', $model->description);
|
||||
ToolboxHelper::assertNoInternalBoUrls('preparation', $model->preparation ?? '');
|
||||
ToolboxHelper::assertNoInternalBoUrls('ingredients', $model->ingredients);
|
||||
|
|
@ -152,6 +155,19 @@ class Product extends Model
|
|||
return $this->belongsToMany(Certification::class, 'product_certification');
|
||||
}
|
||||
|
||||
/**
|
||||
* toSitemapTag method
|
||||
*
|
||||
* @return Url|string|array
|
||||
*/
|
||||
public function toSitemapTag(): Url | string | array
|
||||
{
|
||||
$model = $this->loadMissing('range');
|
||||
$route = 'products.show';
|
||||
$params = ['publishedProduct' => $model->slug];
|
||||
return SitemapHelper::generateUrl($route, $params, $model);
|
||||
}
|
||||
|
||||
/**
|
||||
* BelongsTo certifications relation
|
||||
*
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Spatie\Sitemap\Contracts\Sitemapable;
|
||||
use Spatie\Sitemap\Tags\Url;
|
||||
use Uwil\SitemapGenerator\Lib\SitemapHelper;
|
||||
|
||||
/**
|
||||
* Gamme
|
||||
|
|
@ -40,7 +43,7 @@ use Illuminate\Validation\ValidationException;
|
|||
*
|
||||
* @package App\Models
|
||||
*/
|
||||
class Range extends Model
|
||||
class Range extends Model implements Sitemapable
|
||||
{
|
||||
use HasFactory;
|
||||
use HasFlashStatus;
|
||||
|
|
@ -48,7 +51,7 @@ class Range extends Model
|
|||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
|
|
@ -80,8 +83,8 @@ class Range extends Model
|
|||
});
|
||||
static::updating(function (self $model) {
|
||||
// * ASSERTIONS
|
||||
static::assertFieldIsUnique('name', $model->name, $model->id);
|
||||
static::assertAtLeastOneIsPublished($model);
|
||||
self::assertFieldIsUnique('name', $model->name, $model->id);
|
||||
self::assertAtLeastOneIsPublished($model);
|
||||
|
||||
// * TRANSFORMATIONS
|
||||
$model->slug = Str::slug($model->name);
|
||||
|
|
@ -90,9 +93,9 @@ class Range extends Model
|
|||
$model->sticker = FileStorageHelper::storeFile($model, $model->sticker, true);
|
||||
});
|
||||
static::updated(function (self $model) {
|
||||
$model->picture = FileStorageHelper::removeOldFile($model, 'picture');
|
||||
$model->banner = FileStorageHelper::removeOldFile($model, 'banner');
|
||||
$model->banner = FileStorageHelper::removeOldFile($model, 'sticker');
|
||||
FileStorageHelper::removeOldFile($model, 'picture');
|
||||
FileStorageHelper::removeOldFile($model, 'banner');
|
||||
FileStorageHelper::removeOldFile($model, 'sticker');
|
||||
static::flashStatus($model, true);
|
||||
});
|
||||
static::deleting(function () {
|
||||
|
|
@ -134,6 +137,19 @@ class Range extends Model
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* toSitemapTag method
|
||||
*
|
||||
* @return Url|string|array
|
||||
*/
|
||||
public function toSitemapTag(): Url | string | array
|
||||
{
|
||||
$model = $this->loadMissing('products');
|
||||
$route = 'ranges.products';
|
||||
$params = ['publishedRange' => $model->slug, 'publishedProduct' => $model];
|
||||
return SitemapHelper::generateUrl($route, $params, $model);
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -10,8 +10,11 @@ use App\Traits\Models\HasFlashStatus;
|
|||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\Sitemap\Contracts\Sitemapable;
|
||||
use Spatie\Sitemap\Tags\Url;
|
||||
use Uwil\SitemapGenerator\Lib\SitemapHelper;
|
||||
|
||||
class Recipe extends Model
|
||||
class Recipe extends Model implements Sitemapable
|
||||
{
|
||||
use HasFactory;
|
||||
use HasFlashStatus;
|
||||
|
|
@ -19,7 +22,7 @@ class Recipe extends Model
|
|||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
|
|
@ -47,7 +50,7 @@ class Recipe extends Model
|
|||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'ingredients' => 'array',
|
||||
|
|
@ -65,14 +68,14 @@ class Recipe extends Model
|
|||
{
|
||||
// * EVENT CLOSURES.
|
||||
static::creating(function (self $model) {
|
||||
static::assertFieldIsUnique('name', $model->name);
|
||||
self::assertFieldIsUnique('name', $model->name);
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::created(function (self $model) {
|
||||
self::flashStatus($model);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
static::assertFieldIsUnique('name', $model->name, $model->id);
|
||||
self::assertFieldIsUnique('name', $model->name, $model->id);
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updated(function (self $model) {
|
||||
|
|
@ -91,10 +94,10 @@ class Recipe extends Model
|
|||
/**
|
||||
* Manage fields on this model event.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param self $model
|
||||
* @return void
|
||||
*/
|
||||
private static function manageFields(Model $model)
|
||||
private static function manageFields(self $model)
|
||||
{
|
||||
// * ASSERTIONS
|
||||
ToolboxHelper::assertNoInternalBoUrls('description', $model->description);
|
||||
|
|
@ -161,6 +164,19 @@ class Recipe extends Model
|
|||
return "{$nbHours}H {$nbMinutes}M";
|
||||
}
|
||||
|
||||
/**
|
||||
* toSitemapTag method
|
||||
*
|
||||
* @return Url|string|array
|
||||
*/
|
||||
public function toSitemapTag(): Url | string | array
|
||||
{
|
||||
$model = $this->loadMissing('recipes');
|
||||
$route = 'recipes.show';
|
||||
$params = ['publishedRecipe' => $model->slug, 'publishedProduct' => $model];
|
||||
return SitemapHelper::generateUrl($route, $params, $model);
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class Shop extends Model
|
|||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
|
|
@ -29,7 +29,7 @@ class Shop extends Model
|
|||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'signs' => SignsEnum::class,
|
||||
|
|
@ -45,11 +45,11 @@ class Shop extends Model
|
|||
// * EVENT CLOSURES.
|
||||
static::creating(function (self $model) {
|
||||
// * ASSERTIONS
|
||||
static::assertFieldIsUnique('name', $model->name);
|
||||
self::assertFieldIsUnique('name', $model->name);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
// * ASSERTIONS
|
||||
static::assertFieldIsUnique('name', $model->name, $model->id);
|
||||
self::assertFieldIsUnique('name', $model->name, $model->id);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
118
app/Models/StaticPage.php
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use App\Traits\Models\ActivityLog;
|
||||
use App\Traits\Models\MiniCrudModel;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @property \App\Enums\StaticPageType $type Page type (StaticPageEnum).
|
||||
* @property string $seo_title Seo title about 70 chars as recommended.
|
||||
* @property string $seo_description Seo description about 160 chars as recommended.
|
||||
* @property string $title Title for the page.
|
||||
* @property string $slug Slug of the title for the page.
|
||||
* @property string $content WYSIWYG text content using ckeditor.
|
||||
* @property array<string, array<string, mixed>> $data Static page json data.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Created date.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
|
||||
*/
|
||||
class StaticPage extends Model
|
||||
{
|
||||
use ActivityLog;
|
||||
use HasFactory;
|
||||
use MiniCrudModel;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'seo_title',
|
||||
'seo_description',
|
||||
'title',
|
||||
'content',
|
||||
'data'
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'type' => StaticPageType::class,
|
||||
'data' => 'object',
|
||||
];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
// * ASSERTIONS
|
||||
self::assertTitleIsUnique($model->title);
|
||||
|
||||
// * CHANGES
|
||||
$model->slug = Str::slug($model->title);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
// * ASSERTIONS
|
||||
self::assertTitleIsUnique($model->title, $model->id);
|
||||
|
||||
// * CHANGES
|
||||
$model->slug = Str::slug($model->title);
|
||||
});
|
||||
}
|
||||
|
||||
// * ROUTABLE
|
||||
|
||||
/**
|
||||
* Get the value of the model's route key.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRouteKey()
|
||||
{
|
||||
/** @var \App\Enums\StaticPageType */
|
||||
$enum = $this->getAttribute($this->getRouteKeyName());
|
||||
return $enum->value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the route key for the model.
|
||||
*
|
||||
* ! Type is the routable parameter
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRouteKeyName(): string
|
||||
{
|
||||
return 'type';
|
||||
}
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Asserts using validation that the title is unique
|
||||
*
|
||||
* @param string|null $title
|
||||
* @param integer|null $id
|
||||
* @return void
|
||||
* @throws \Illuminate\Validation\ValidationException If an actu title already exists.
|
||||
*/
|
||||
private static function assertTitleIsUnique(string|null $title, ?int $id = null)
|
||||
{
|
||||
$table = (new self())->getTable();
|
||||
ToolboxHelper::assertFieldIsUnique($table, 'title', $title, $id);
|
||||
ToolboxHelper::assertFieldIsUnique($table, 'slug', Str::slug($title), $id);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,14 +2,29 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\Users\RoleEnum;
|
||||
use App\Traits\Models\ActivityLog;
|
||||
use Illuminate\Auth\Access\AuthorizationException;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @property string $first_name Firstname.
|
||||
* @property string $last_name Lastname.
|
||||
* @property string $email Email.
|
||||
* @property string $remember_token Remember_token.
|
||||
* @property \App\Enums\Users\RoleEnum $role Role.
|
||||
* @property \Illuminate\Support\Carbon $last_connection Last_connection.
|
||||
* @property \Illuminate\Support\Carbon $published Published status.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Created date.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
|
||||
*
|
||||
* @property-read \App\Models\ActivityLog $activityLogs Activities logs HasMany relationship.
|
||||
*/
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use ActivityLog;
|
||||
use HasFactory;
|
||||
use Notifiable;
|
||||
|
||||
|
|
@ -19,10 +34,11 @@ class User extends Authenticatable
|
|||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'firstname',
|
||||
'lastname',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'email',
|
||||
'password',
|
||||
'role',
|
||||
'published',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -31,7 +47,6 @@ class User extends Authenticatable
|
|||
* @var array<int, string>
|
||||
*/
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
];
|
||||
|
||||
|
|
@ -41,8 +56,9 @@ class User extends Authenticatable
|
|||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'email_verified_at' => 'datetime',
|
||||
'last_connection' => 'datetime',
|
||||
'role' => RoleEnum::class,
|
||||
'last_connection' => 'date',
|
||||
'published' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -50,20 +66,28 @@ class User extends Authenticatable
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
protected static function booted(): void
|
||||
{
|
||||
// * EVENT CLOSURES.
|
||||
static::creating(function (self $user) {
|
||||
if (Hash::needsRehash($user->password)) {
|
||||
$user->password = Hash::make($user->password);
|
||||
}
|
||||
$user->remember_token = Str::random(10);
|
||||
static::creating(function (self $model) {
|
||||
// * Prevent user elevation privileges
|
||||
throw_if(
|
||||
auth('backend')->user() and auth('backend')->user()->role->value() > $model->role->value(),
|
||||
AuthorizationException::class
|
||||
);
|
||||
});
|
||||
static::updating(function (self $user) {
|
||||
if (Hash::needsRehash($user->password)) {
|
||||
$user->password = Hash::make($user->password);
|
||||
static::updating(function (self $model) {
|
||||
if (optional(auth('backend')->user())->getKey() === $model->getKey()) {
|
||||
\validator(
|
||||
['published' => $model->published],
|
||||
['published' => 'required|boolean|accepted'],
|
||||
['published.accepted' => trans('crud.messages.user_unpublished')],
|
||||
)->validate();
|
||||
}
|
||||
$user->remember_token = Str::random(10);
|
||||
// * Prevent user elevation privileges
|
||||
throw_if(
|
||||
auth('backend')->user() and auth('backend')->user()->role->value() > $model->role->value(),
|
||||
AuthorizationException::class
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
54
app/Observers/ModelObserver.php
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Enums\ActivityLogs\ActivityLogsEventEnum;
|
||||
use App\Models\ActivityLog;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ModelObserver
|
||||
{
|
||||
/**
|
||||
* Handle the model "created" event.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return void
|
||||
*/
|
||||
public static function created(Model $model): void
|
||||
{
|
||||
ActivityLog::addActivity($model, ActivityLogsEventEnum::created);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the model "updated" event.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return void
|
||||
*/
|
||||
public static function updated(Model $model): void
|
||||
{
|
||||
ActivityLog::addActivity($model, ActivityLogsEventEnum::updated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the model "duplicated" event.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return void
|
||||
*/
|
||||
public static function duplicated(Model $model): void
|
||||
{
|
||||
ActivityLog::addActivity($model, ActivityLogsEventEnum::duplicated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the model "deleted" event.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return void
|
||||
*/
|
||||
public static function deleted(Model $model): void
|
||||
{
|
||||
ActivityLog::addActivity($model, ActivityLogsEventEnum::deleted);
|
||||
}
|
||||
}
|
||||
36
app/Policies/StaticPagePolicy.php
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\StaticPage;
|
||||
use App\Models\User;
|
||||
|
||||
class StaticPagePolicy
|
||||
{
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @return boolean
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.Found
|
||||
*/
|
||||
public function viewAny(User $authUser): bool
|
||||
{
|
||||
// phpcs:enable
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*
|
||||
* @param \App\Models\User $authUser
|
||||
* @param \App\Models\StaticPage $static_page
|
||||
* @return boolean
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
|
||||
*/
|
||||
public function update(User $authUser, StaticPage $static_page): bool
|
||||
{
|
||||
// phpcs:enable
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,14 +2,16 @@
|
|||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Models\Range;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
|
@ -38,7 +40,7 @@ class AppServiceProvider extends ServiceProvider
|
|||
return request()->getClientIp();
|
||||
} else {
|
||||
return request()->server('HTTP_X_FORWARDED_FOR') ??
|
||||
request()->getClientIp();
|
||||
request()->getClientIp();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -71,9 +73,14 @@ class AppServiceProvider extends ServiceProvider
|
|||
// * GAMMES
|
||||
if (Schema::hasTable('ranges')) {
|
||||
// On partage les ranges (gammes produit).
|
||||
$ranges = Range::where('status', true)->get();
|
||||
$ranges = Range::query()->where('status', true)->get();
|
||||
View::share('PublishedRangesGlobal', $ranges);
|
||||
}
|
||||
|
||||
if (Schema::hasTable('static_pages')) {
|
||||
$bannerSection = StaticPage::query()->where('type', StaticPageType::banner_section->value())->get();
|
||||
View::share('bannerSection', $bannerSection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,13 @@ namespace App\Providers;
|
|||
use Illuminate\Auth\Events\Registered;
|
||||
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Slides\Saml2\Events\SignedIn;
|
||||
use Slides\Saml2\Events\SignedOut;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
|
@ -19,15 +26,6 @@ class EventServiceProvider extends ServiceProvider
|
|||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Register any events for your application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if events and listeners should be automatically discovered.
|
||||
*
|
||||
|
|
@ -37,4 +35,49 @@ class EventServiceProvider extends ServiceProvider
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register any events for your application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
Event::listen('Slides\Saml2\Events\SignedIn', function (SignedIn $event) {
|
||||
|
||||
$messageId = $event->getAuth()->getLastMessageId();
|
||||
|
||||
$fromCache = Cache::get(config('cache.prefix') . "_saml_message_id_" . $messageId);
|
||||
if ($fromCache) {
|
||||
logger()->error(
|
||||
'SAML MESSAGE ID HANDLER',
|
||||
['error' => 'Message ID : ' . $messageId . " replayed !"]
|
||||
);
|
||||
abort(403);
|
||||
} else {
|
||||
Cache::put(config('cache.prefix') . "_saml_message_id_" . $messageId, $messageId, 28800);
|
||||
// Cache for 8h.
|
||||
}
|
||||
|
||||
$user = $event->getSaml2User();
|
||||
$email = $user->getNameId();
|
||||
|
||||
$lUser = User::where('email', '=', $email)->first();
|
||||
|
||||
if (!$lUser) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
Auth::guard('backend')->login($lUser);
|
||||
session(['sessionIndex' => $user->getSessionIndex()]);
|
||||
$lUser->last_connection = now();
|
||||
$lUser->saveQuietly();
|
||||
});
|
||||
|
||||
//phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
|
||||
Event::listen('Slides\Saml2\Events\SignedOut', function (SignedOut $event) {
|
||||
Auth::guard('backend')->logout();
|
||||
Session::save();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class TranslationServiceProvider extends ServiceProvider
|
|||
/**
|
||||
* Gather provided langs checking from files
|
||||
*
|
||||
* @return \Illuminate\Support\Collection<string, string>
|
||||
* @return \Illuminate\Support\Collection<int, string>
|
||||
*/
|
||||
private function collectLocalesStrings(): Collection
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,59 +3,56 @@
|
|||
namespace App\Traits\Controllers;
|
||||
|
||||
use App\Http\Requests\Bo\ChangeOrderRequest;
|
||||
use App\Traits\Models\IsCachedAsCollection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
trait ChangesModelOrder
|
||||
{
|
||||
/**
|
||||
* Change order
|
||||
*
|
||||
* ! requires x64 server + order column as unique integer
|
||||
* Change order.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\ChangeOrderRequest $request
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \RuntimeException Si le nom du parametre de la route ne correspond pas au model utilisé.
|
||||
*/
|
||||
public function changeOrder(ChangeOrderRequest $request, Model $model): RedirectResponse
|
||||
public function changeOrder(ChangeOrderRequest $request, Model $model): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request, $model) {
|
||||
$params = collect(request()->route()->parameterNames);
|
||||
$className = Str::ucfirst(Str::lower($params->get($params->count() - 2)));
|
||||
$className = "\\App\\Models\\$className";
|
||||
|
||||
if (!class_exists($className)) {
|
||||
throw new \RuntimeException("The $className class doesn't exist.");
|
||||
}
|
||||
|
||||
/** @var \Illuminate\Database\Eloquent\Model|null */
|
||||
$model = $className::query()->where($model->getRouteKeyName(), $model->getRouteKey())->first();
|
||||
|
||||
if (!$model) {
|
||||
return back()->with('error', trans('crud.messages.order_not_changed'));
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($request, $className, $model) {
|
||||
/** @var \Illuminate\Database\Eloquent\Model|null */
|
||||
$tmp = (\get_class($model))::where('order', $request->direction ? '<' : '>', $model->order)
|
||||
$tmp = $className::query()->where('order', $request->direction ? '<' : '>', $model->getOriginal('order'))
|
||||
->orderBy('order', $request->direction ? 'DESC' : 'ASC')->first();
|
||||
|
||||
if (!$tmp) {
|
||||
return back()->with('bo.error', trans('L\'ordre n\'a pas pu être modifié'));
|
||||
return back()->with('error', trans('crud.messages.order_not_changed'));
|
||||
}
|
||||
$oldOrder = $model->order;
|
||||
$newOrder = $tmp->order;
|
||||
|
||||
// * Silent update timestamps.
|
||||
$tmp->timestamps = false;
|
||||
$model->timestamps = false;
|
||||
$newOrder = $tmp->getOriginal('order');
|
||||
// Didn't use ->update() because it didn't work with Models which use MiniCrudModel.
|
||||
$tmp->fill(['order' => $model->getOriginal('order')]);
|
||||
$tmp->save();
|
||||
$model->fill(['order' => $newOrder]);
|
||||
$model->save();
|
||||
|
||||
$saveOk = false;
|
||||
Session::flash('success', trans('crud.messages.order_changed'));
|
||||
|
||||
// ! Fake value to prevent unique SQL key to trigger.
|
||||
$tmp->order = 4294967295;
|
||||
$saveOk = $tmp->saveQuietly();
|
||||
$model->order = $newOrder;
|
||||
$saveOk = $model->saveQuietly() & $saveOk;
|
||||
$tmp->order = $oldOrder;
|
||||
$saveOk = $tmp->saveQuietly() & $saveOk;
|
||||
if (\in_array(IsCachedAsCollection::class, class_uses_recursive(\get_class($model)))) {
|
||||
$model::removeCached();
|
||||
}
|
||||
if (!$saveOk) {
|
||||
throw ValidationException::withMessages([
|
||||
'error' => \trans('L\'ordre n\'a pas pu être modifié')
|
||||
]);
|
||||
}
|
||||
Session::flash('bo.success', trans('L\'ordre a été modifié'));
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
25
app/Traits/Controllers/UpdateModelPublished.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Traits\Controllers;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* This trait works with Route::bind in App service provider
|
||||
* to resolve the model and the DB row
|
||||
* It does not work with binder Service
|
||||
*/
|
||||
trait UpdateModelPublished
|
||||
{
|
||||
/**
|
||||
* Change model published.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function changePublished(Model $model)
|
||||
{
|
||||
$model->update(['published' => !$model->getOriginal('published')]);
|
||||
return redirect()->back()->with('success', trans(__('crud.messages.publish_status_saved')));
|
||||
}
|
||||
}
|
||||
|
|
@ -12,19 +12,14 @@ use Illuminate\Database\Eloquent\Model;
|
|||
trait UpdateModelStatus
|
||||
{
|
||||
/**
|
||||
* Change model published
|
||||
* Change model published.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function changePublished(Model $model)
|
||||
{
|
||||
$model->status = !$model->status;
|
||||
$model->saveOrFail();
|
||||
|
||||
if (!$model->saveOrFail()) {
|
||||
return redirect()->back()->with('error', __('The status could not be changed'));
|
||||
}
|
||||
return redirect()->back()->with('success', __('The status has been changed'));
|
||||
$model->update(['published' => !$model->getOriginal('published')]);
|
||||
return redirect()->back()->with('success', trans(__('crud.messages.publish_status_saved')));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,8 +120,8 @@ trait BaseEnum
|
|||
/**
|
||||
* Fetch enum using value
|
||||
*
|
||||
* @param \App\Traits\Enums\BaseEnum|integer|string $value
|
||||
* @return \App\Traits\Enums\BaseEnum|null
|
||||
* @param self|integer|string $value
|
||||
* @return self|null
|
||||
*/
|
||||
public static function make(self|int|string $value): self|null
|
||||
{
|
||||
|
|
|
|||
23
app/Traits/Models/ActivityLog.php
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace App\Traits\Models;
|
||||
|
||||
use App\Observers\ModelObserver;
|
||||
|
||||
/**
|
||||
* If there is a static function in a trait (named boot[TraitName]),
|
||||
* it will be executed as the boot() function would on an Eloquent model.
|
||||
* Futhermore, event in the Model observer doesn't erase actual events in the model,
|
||||
* but adds them.
|
||||
*/
|
||||
trait ActivityLog
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function bootActivityLog(): void
|
||||
{
|
||||
static::observe(ModelObserver::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,8 @@ use Illuminate\Support\Facades\Cache;
|
|||
/**
|
||||
* ! Use this only on limited elements, (not on tags, or products, or posts for ex.)
|
||||
*
|
||||
* @property private static array $cacheConditions Eloquent condition to cache elements (to be used in where statement).
|
||||
* @property array<string,string|integer|float|boolean> $cacheConditions
|
||||
* Eloquent condition to cache elements (to be used in where statement).
|
||||
*/
|
||||
trait IsCachedAsCollection
|
||||
{
|
||||
|
|
@ -52,7 +53,7 @@ trait IsCachedAsCollection
|
|||
{
|
||||
$conditions = [];
|
||||
if (property_exists(get_called_class(), 'cacheConditions')) {
|
||||
$conditions = collect(static::${'cacheConditions'})->all();
|
||||
$conditions = collect(get_called_class()::${'cacheConditions'})->all();
|
||||
}
|
||||
Cache::put(static::getCacheKeyName(), static::queryCached(static::query())
|
||||
->where($conditions)->get()
|
||||
|
|
|
|||
|
|
@ -11,18 +11,20 @@ trait MiniCrudModel
|
|||
/**
|
||||
* Fill the model with an array of attributes.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return void
|
||||
* @param array<string, mixed> $attributes
|
||||
* @return $this
|
||||
* @throws \Illuminate\Database\Eloquent\MassAssignmentException If fill prop is not allowed.
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.EmptyThrows
|
||||
*/
|
||||
public function fill(array $attributes)
|
||||
public function fill(array $attributes): static
|
||||
{
|
||||
// phpcs:enable
|
||||
parent::fill($attributes);
|
||||
if (isset($attributes['data'])) {
|
||||
$this->setData($attributes['data']);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -62,7 +64,6 @@ trait MiniCrudModel
|
|||
*/
|
||||
public function minicrudUpdated()
|
||||
{
|
||||
/** @var array */
|
||||
foreach ($this->data as $index => $input) {
|
||||
switch ($input['inputType']) {
|
||||
case InputType::text->value:
|
||||
|
|
@ -177,4 +178,21 @@ trait MiniCrudModel
|
|||
} //end foreach
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fillable properties and their values from the model.
|
||||
*
|
||||
* @param self $model
|
||||
* @return array
|
||||
*/
|
||||
public function getFillableFields(self $model): array
|
||||
{
|
||||
$datas = [];
|
||||
foreach ($model->toArray() as $property => $value) {
|
||||
if (in_array($property, $model->getFillable())) {
|
||||
$datas = array_merge($datas, [$property => $value]);
|
||||
}
|
||||
}
|
||||
return $datas;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ trait HasPicture
|
|||
$name => [
|
||||
!$nullable ? 'required' : 'nullable',
|
||||
function (string $attribute, $value, callable $fail) use ($sizes) {
|
||||
return ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
|
||||
ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
|
||||
}
|
||||
]
|
||||
];
|
||||
|
|
@ -101,7 +101,7 @@ trait HasPicture
|
|||
"{$name}Validate.*" => [
|
||||
'required',
|
||||
function (string $attribute, $value, callable $fail) use ($sizes) {
|
||||
return $this->validatePicture($attribute, $value, $fail, $sizes);
|
||||
ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
|
||||
}
|
||||
]
|
||||
];
|
||||
|
|
|
|||
33
app/View/Components/LocalBlockComponent.php
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Models\StaticPage;
|
||||
use Closure;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class LocalBlockComponent extends Component
|
||||
{
|
||||
/** @var \App\Models\StaticPage $staticPageModel */
|
||||
private $staticPageModel;
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->staticPageModel = StaticPage::query()->where('type', StaticPageType::our_commitments)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.local-block-component', [
|
||||
'staticPageModel' => $this->staticPageModel
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,32 +3,34 @@
|
|||
"type": "project",
|
||||
"description": "Site de la marque Lionor",
|
||||
"require": {
|
||||
"php": "^8.2",
|
||||
"php": "^8.5",
|
||||
"scaler-tech/laravel-saml2": "^2.5",
|
||||
"axlon/laravel-postal-code-validation": "^3.3",
|
||||
"diglactic/laravel-breadcrumbs": "^8.1.1",
|
||||
"carlos-meneses/laravel-mpdf": "^2.1",
|
||||
"diglactic/laravel-breadcrumbs": "^9.0",
|
||||
"guzzlehttp/guzzle": "^7.2",
|
||||
"kaishiyoku/laravel-color-validation": "^2.1.1",
|
||||
"kwaadpepper/image-resizer": "^2.1",
|
||||
"kwaadpepper/refresh-sitemap": "^2.0",
|
||||
"laravel/framework": "^10.0",
|
||||
"kaishiyoku/laravel-color-validation": "^3.2",
|
||||
"kwaadpepper/image-resizer": "^3.1",
|
||||
"laravel/framework": "^11.0",
|
||||
"laravel/tinker": "^2.8",
|
||||
"laravel/ui": "^4.2",
|
||||
"ldc/web-admin-secure-laravel": "^2.0.0",
|
||||
"mews/purifier": "^3.4",
|
||||
"propaganistas/laravel-phone": "^5.0.3",
|
||||
"sentry/sentry-laravel": "*",
|
||||
"uwil/k8s-laravel": "1.1.0"
|
||||
"uwil/laravel-admin-secure": "^6.0",
|
||||
"uwil/k8s-laravel": "^1.4",
|
||||
"uwil/sitemap-generator": "^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/dbal": "^3.3",
|
||||
"fakerphp/faker": "^1.9.1",
|
||||
"kitloong/laravel-migrations-generator": "^6.8",
|
||||
"krlove/eloquent-model-generator": "dev-l10-compatibility",
|
||||
"kitloong/laravel-migrations-generator": "^7.0",
|
||||
"larastan/larastan": "^2.6",
|
||||
"laravel-lang/lang": "10.0",
|
||||
"laravel/pint": "^1.0",
|
||||
"laravel/sail": "^1.18",
|
||||
"mockery/mockery": "^1.4.4",
|
||||
"nunomaduro/collision": "^7.0",
|
||||
"nunomaduro/collision": "^8.1",
|
||||
"phpunit/phpunit": "^10.0",
|
||||
"slevomat/coding-standard": "^8.10",
|
||||
"spatie/laravel-ignition": "^2.0",
|
||||
|
|
|
|||
6766
composer.lock
generated
|
|
@ -56,8 +56,6 @@ return [
|
|||
|
||||
'url' => env('APP_URL', 'http://localhost'),
|
||||
|
||||
'asset_url' => env('ASSET_URL'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Timezone
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ return [
|
|||
|
|
||||
*/
|
||||
|
||||
'view' => 'modules/breadcrumb/breadcrumb-layout',
|
||||
'view' => 'modules.breadcrumbs.breadcrumb-layout',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1,106 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Spatie\Sitemap\Tags\Url;
|
||||
|
||||
return [
|
||||
|
||||
/**
|
||||
* A list of url to ignore
|
||||
* These are hard coded
|
||||
* Each url does not have to be exhaustive
|
||||
*
|
||||
* For example, if you want to ignore all routes
|
||||
* of the backoffice group
|
||||
* just add '/backoffice' into this table
|
||||
*/
|
||||
'ignoreRoutes' => [
|
||||
'/bo',
|
||||
],
|
||||
|
||||
/**
|
||||
* This table is needed to resolve models matching
|
||||
* routes
|
||||
*
|
||||
* it has to be filled like following
|
||||
*
|
||||
* 'products.meat-type' => [
|
||||
* 'slugMeatType' => [MeatTypes::class, 'slug']
|
||||
* ],
|
||||
* 'kitchen-side.health-nutrition.balanced-menu.menu' => [
|
||||
* 'type' => [BalancedMenuType::class, 'type']
|
||||
* ]
|
||||
*
|
||||
* The index is the complete route name, the array content is an array
|
||||
* within index is the argument name with its model class.
|
||||
* This will allow the generator to generate a route for each of the models
|
||||
* in this table
|
||||
*/
|
||||
'routesBinder' => [],
|
||||
|
||||
/**
|
||||
* You can put route conditions here
|
||||
* These will be used to decide whether the route should appear
|
||||
* in the sitemap or not
|
||||
*
|
||||
* These are called in Eloquent where
|
||||
*
|
||||
* example
|
||||
*
|
||||
* 'queryConditions' => [
|
||||
* 'status' => true,
|
||||
* 'ocbStatus' => EleveurOcbStatus::yes()->value,
|
||||
* 'star_moment' => true
|
||||
* ]
|
||||
*
|
||||
*/
|
||||
'queryConditions' => [
|
||||
'status' => true,
|
||||
],
|
||||
|
||||
/**
|
||||
* The default route frequency to use with sitemap generator
|
||||
*/
|
||||
'routeDefaultFrequency' => Url::CHANGE_FREQUENCY_DAILY,
|
||||
|
||||
/**
|
||||
* The default route priority to use with sitemap generator
|
||||
*
|
||||
* priority should be a number between 0 and 1
|
||||
* https://www.sitemaps.org/protocol.html
|
||||
*/
|
||||
'routeDefaultPriority' => 0.5,
|
||||
|
||||
/**
|
||||
* Frequencies for routes
|
||||
* use the full or partial route name as index
|
||||
* and a frequency within \Spatie\Sitemap\Tags\Url constants
|
||||
*/
|
||||
'routeFrequencies' => [],
|
||||
|
||||
/**
|
||||
* Priorities for routes
|
||||
* use the full or partial route name as index
|
||||
* and a priority number between 0 and 1
|
||||
*/
|
||||
'routePriorities' => [],
|
||||
|
||||
/**
|
||||
* 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/
|
||||
* https://laravel.com/docs/8.x/scheduling#schedule-frequency-options
|
||||
*
|
||||
* schedule must be set to true
|
||||
*
|
||||
* Default is every day at 15:45
|
||||
*/
|
||||
'cron' => '45 15 * * *'
|
||||
];
|
||||
397
config/saml2.php
Normal file
|
|
@ -0,0 +1,397 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Tenant Model
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This will allow you to override the tenant model with your own.
|
||||
|
|
||||
*/
|
||||
|
||||
'tenantModel' => \Slides\Saml2\Models\Tenant::class,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Use built-in routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If "useRoutes" set to true, the package defines five new routes:
|
||||
|
|
||||
| Method | URI | Name
|
||||
| -------|---------------------------------|------------------
|
||||
| POST | {routesPrefix}/{uuid}/acs | saml.acs
|
||||
| GET | {routesPrefix}/{uuid}/login | saml.login
|
||||
| GET | {routesPrefix}/{uuid}/logout | saml.logout
|
||||
| GET | {routesPrefix}/{uuid}/metadata | saml.metadata
|
||||
| GET | {routesPrefix}/{uuid}/sls | saml.sls
|
||||
|
|
||||
*/
|
||||
|
||||
'useRoutes' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Built-in routes prefix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define the prefix for built-in routes.
|
||||
|
|
||||
*/
|
||||
|
||||
'routesPrefix' => '/saml2',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Middle groups to use for the SAML routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Note, Laravel 5.2 requires a group which includes StartSession
|
||||
|
|
||||
*/
|
||||
|
||||
'routesMiddleware' => ['saml'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Signature validation
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Set to true if you want to use parameters from $_SERVER to validate the signature.
|
||||
|
|
||||
*/
|
||||
|
||||
'retrieveParametersFromServer' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Login redirection URL.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The redirection URL after successful login.
|
||||
|
|
||||
*/
|
||||
|
||||
'loginRoute' => '/bo',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Logout redirection URL.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The redirection URL after successful logout.
|
||||
|
|
||||
*/
|
||||
|
||||
'logoutRoute' => '/bo',
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Login error redirection URL.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The redirection URL after login failing.
|
||||
|
|
||||
*/
|
||||
|
||||
'errorRoute' => '/bo/login-error',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Strict mode.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If 'strict' is True, then the PHP Toolkit will reject unsigned
|
||||
| or unencrypted messages if it expects them signed or encrypted
|
||||
| Also will reject the messages if not strictly follow the SAML
|
||||
| standard: Destination, NameId, Conditions... are validated too.
|
||||
|
|
||||
*/
|
||||
|
||||
'strict' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Debug mode.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When enabled, errors must be printed.
|
||||
|
|
||||
*/
|
||||
|
||||
'debug' => env('SAML2_DEBUG', env('APP_DEBUG', false)),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Whether to use `X-Forwarded-*` headers to determine port/domain/protocol.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If 'proxyVars' is True, then the Saml lib will trust proxy headers
|
||||
| e.g X-Forwarded-Proto / HTTP_X_FORWARDED_PROTO. This is useful if
|
||||
| your application is running behind a load balancer which terminates SSL.
|
||||
|
|
||||
*/
|
||||
|
||||
'proxyVars' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Service Provider configuration.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| General setting of the service provider.
|
||||
|
|
||||
*/
|
||||
|
||||
'sp' => [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| NameID format.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specifies constraints on the name identifier to be used to
|
||||
| represent the requested subject.
|
||||
|
|
||||
*/
|
||||
|
||||
'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| SP Certificates.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Usually x509cert and privateKey of the SP are provided by files placed at
|
||||
| the certs folder. But we can also provide them with the following parameters.
|
||||
|
|
||||
*/
|
||||
|
||||
'x509cert' => env('SAML2_SP_CERT_x509', ''),
|
||||
'privateKey' => env('SAML2_SP_CERT_PRIVATEKEY', ''),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Identifier (URI) of the SP entity.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Leave blank to use the 'saml.metadata' route.
|
||||
|
|
||||
*/
|
||||
|
||||
'entityId' => env('SAML2_SP_ENTITYID', ''),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| The Assertion Consumer Service (ACS) URL.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| URL Location where the <Response> from the IdP will be returned, using HTTP-POST binding.
|
||||
| Leave blank to use the 'saml.acs' route.
|
||||
|
|
||||
*/
|
||||
|
||||
'assertionConsumerService' => [
|
||||
'url' => '',
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| The Single Logout Service URL.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specifies info about where and how the <Logout Response> message MUST be
|
||||
| returned to the requester, in this case our SP.
|
||||
|
|
||||
| URL Location where the <Response> from the IdP will be returned, using HTTP-Redirect binding.
|
||||
| Leave blank to use the 'saml.sls' route.
|
||||
|
|
||||
*/
|
||||
|
||||
'singleLogoutService' => [
|
||||
'url' => ''
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| OneLogin security settings.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
|
|
||||
|
|
||||
*/
|
||||
|
||||
'security' => [
|
||||
|
||||
'signatureAlgorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
|
||||
'digestAlgorithm' => 'http://www.w3.org/2001/04/xmlenc#sha256',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| NameId encryption
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Indicates that the nameID of the <samlp:logoutRequest> sent by this SP
|
||||
| will be encrypted.
|
||||
|
|
||||
*/
|
||||
|
||||
'nameIdEncrypted' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| AuthnRequest signage
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Indicates whether the <samlp:AuthnRequest> messages sent by
|
||||
| this SP will be signed. The Metadata of the SP will offer this info
|
||||
|
|
||||
*/
|
||||
|
||||
'authnRequestsSigned' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Logout request signage
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Indicates whether the <samlp:logoutRequest> messages sent by this SP
|
||||
| will be signed.
|
||||
|
|
||||
*/
|
||||
|
||||
'logoutRequestSigned' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Logout response signage
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Indicates whether the <samlp:logoutResponse> messages sent by this SP
|
||||
| will be signed.
|
||||
|
|
||||
*/
|
||||
|
||||
'logoutResponseSigned' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Whether need to sign metadata.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The possible values:
|
||||
| - false
|
||||
| - true (use certs)
|
||||
| - array:
|
||||
| ```
|
||||
| [
|
||||
| 'keyFileName' => 'metadata.key',
|
||||
| 'certFileName' => 'metadata.crt'
|
||||
| ]
|
||||
| ```
|
||||
|
|
||||
*/
|
||||
|
||||
'signMetadata' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Requirement to sign messages.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Indicates a requirement for the <samlp:Response>, <samlp:LogoutRequest> and
|
||||
| <samlp:LogoutResponse> elements received by this SP to be signed.
|
||||
|
|
||||
*/
|
||||
|
||||
'wantMessagesSigned' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Requirement to sign assertion elements.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Indicates a requirement for the <saml:Assertion> elements received by
|
||||
| this SP to be signed.
|
||||
|
|
||||
*/
|
||||
|
||||
'wantAssertionsSigned' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Requirement to encrypt NameID.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Indicates a requirement for the NameID received by this SP to be encrypted.
|
||||
|
|
||||
*/
|
||||
|
||||
'wantNameIdEncrypted' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication context.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Set to false and no AuthContext will be sent in the AuthNRequest,
|
||||
|
|
||||
| Set true or don't present this parameter and you will get an
|
||||
| AuthContext 'exact' 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'
|
||||
|
|
||||
| Set an array with the possible auth context values:
|
||||
| ['urn:oasis:names:tc:SAML:2.0:ac:classes:Password', 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509']
|
||||
|
|
||||
*/
|
||||
|
||||
'requestedAuthnContext' => true,
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Contact information.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| It is recommended to supply a technical and support contacts.
|
||||
|
|
||||
*/
|
||||
|
||||
'contactPerson' => [
|
||||
'technical' => [
|
||||
'givenName' => env('SAML2_CONTACT_TECHNICAL_NAME', env('APP_NAME', 'Technical')),
|
||||
'emailAddress' => env('SAML2_CONTACT_TECHNICAL_EMAIL', 'no@reply.com')
|
||||
],
|
||||
'support' => [
|
||||
'givenName' => env('SAML2_CONTACT_SUPPORT_NAME', env('APP_NAME', 'Support')),
|
||||
'emailAddress' => env('SAML2_CONTACT_SUPPORT_EMAIL', 'no@reply.com')
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Organization information.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The info in en_US lang is recommended, add more if required.
|
||||
|
|
||||
*/
|
||||
|
||||
'organization' => [
|
||||
'en-US' => [
|
||||
'name' => env('SAML2_ORGANIZATION_NAME', env('APP_NAME', 'Name')),
|
||||
'displayname' => env('SAML2_ORGANIZATION_NAME', env('APP_NAME', 'Name')),
|
||||
'url' => env('SAML2_ORGANIZATION_URL', env('APP_URL', 'http://url'))
|
||||
],
|
||||
],
|
||||
|
||||
/**
|
||||
* Default tenant UUID
|
||||
*/
|
||||
|
||||
'default_tenant_uuid' => env('SAML2_DEFAULT_TENANT_UUID', null)
|
||||
|
||||
];
|
||||
82
config/sitemap-generator.php
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/**
|
||||
* Single route names
|
||||
*
|
||||
* Ex:
|
||||
*
|
||||
* 'singlePages' => [
|
||||
* 'homepage',
|
||||
* ],
|
||||
*/
|
||||
'singlePages' => [
|
||||
'home',
|
||||
'engagments',
|
||||
'local',
|
||||
'recipes.index',
|
||||
'ranges.index',
|
||||
'contact.show',
|
||||
'map',
|
||||
'policies',
|
||||
'legals'
|
||||
],
|
||||
|
||||
/**
|
||||
* Model namespaces with filters
|
||||
*
|
||||
* Ex:
|
||||
* 'cruds' => [
|
||||
* [
|
||||
* 'model' => 'App\Models\Product',
|
||||
* 'filters' => [
|
||||
* ['published', '=', true]
|
||||
* ]
|
||||
* ],
|
||||
* [
|
||||
* 'model' => 'App\Models\Article',
|
||||
* 'filters' => []
|
||||
* ]
|
||||
* ],
|
||||
*/
|
||||
'cruds' => [
|
||||
[
|
||||
'model' => 'App\Models\Product',
|
||||
'filters' => [
|
||||
['status', '=', true]
|
||||
],
|
||||
],
|
||||
[
|
||||
'model' => 'App\Models\Recipe',
|
||||
'filters' => [
|
||||
['status', '=', true]
|
||||
],
|
||||
],
|
||||
[
|
||||
'model' => 'App\Models\Range',
|
||||
'filters' => [
|
||||
['status', '=', true]
|
||||
],
|
||||
]
|
||||
],
|
||||
|
||||
/**
|
||||
* 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 * * *',
|
||||
];
|
||||
|
|
@ -15,8 +15,8 @@ class UserFactory extends Factory
|
|||
public function definition()
|
||||
{
|
||||
return [
|
||||
'firstname' => $this->faker->firstName(),
|
||||
'lastname' => $this->faker->lastName(),
|
||||
'first_name' => $this->faker->firstName(),
|
||||
'last_name' => $this->faker->lastName(),
|
||||
'email' => $this->faker->unique()->safeEmail(),
|
||||
'email_verified_at' => now(),
|
||||
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('static_pages', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedTinyInteger('type')->unique()->comment('Page type (StaticPageEnum)');
|
||||
$table->string('seo_title')->comment('Seo title about 70 chars as recommended');
|
||||
$table->string('seo_description')->comment('Seo description about 160 chars as recommended');
|
||||
$table->string('title')->comment('Title for the page');
|
||||
$table->string('slug')->unique()->comment('Unique title slug');
|
||||
$table->text('content')->comment('WYSIWYG text content using ckeditor');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('static_pages');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('activity_logs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('user_id')->nullable()->constrained('users')->nullOnDelete()
|
||||
->comment('Id of the user associated, or nullable for a deleted user.');
|
||||
$table->boolean('is_anonymous')->comment('If there is no user connected when action was realised.');
|
||||
$table->boolean('is_console')->comment('If the action was realised in console.');
|
||||
$table->string('model_class')->comment('Target model.');
|
||||
$table->integer('model_id')->comment('Id of the target model.');
|
||||
$table->integer('event')->comment('Event of this activity (ActivityLogsEventEnum).');
|
||||
$table->json('data')->nullable()->comment('List of changes (old and new values).');
|
||||
$table->timestamp('created_at')->comment('The date on which the user was published.');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('activity_logs');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
// Drop.
|
||||
$table->dropColumn('email_verified_at');
|
||||
$table->dropColumn('password');
|
||||
// Rename.
|
||||
$table->renameColumn('firstname', 'first_name');
|
||||
$table->renameColumn('lastname', 'last_name');
|
||||
// New columns.
|
||||
$table->unsignedTinyInteger('role')->after('remember_token')
|
||||
->comment('Role of the user who defines the rights/access.');
|
||||
$table->boolean('published')->after('role')
|
||||
->comment('Is the user published ?');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
// New columns.
|
||||
$table->timestamp('email_verified_at')->nullable()->after('email');
|
||||
$table->string('password')->after('email_verified_at');
|
||||
// Rename.
|
||||
$table->renameColumn('first_name', 'firstname');
|
||||
$table->renameColumn('last_name', 'lastname');
|
||||
// Drop.
|
||||
$table->dropColumn('role');
|
||||
$table->dropColumn('published');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('static_pages', function (Blueprint $table) {
|
||||
$table->text('seo_title')->nullable()->comment('Seo title about 70 chars as recommended')->change();
|
||||
$table->text('seo_description')->nullable()->comment('Seo description about 160 chars as recommended')->change();
|
||||
$table->text('content')->nullable()->comment('WYSIWYG text content using ckeditor')->change();
|
||||
$table->mediumText('data')->nullable()->after('content')->comment('Static page data.');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
<?php
|
||||
|
||||
use App\Enums\InputType;
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// HOMEPAGE
|
||||
$data = [
|
||||
'left_title' => [
|
||||
'label' => 'Titre de la section de gauche',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Des produits bien élevés qui ont le goût de la qualité',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'left_subtitle' => [
|
||||
'label' => 'Sous-titre de la section de gauche',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Garantis Poulet 100% local',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'left_button_text' => [
|
||||
'label' => 'Texte du bouton de la section de gauche',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Nous Découvrir >',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'right_title' => [
|
||||
'label' => 'Titre de la section de droite',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Des produits de qualité bons et accessibles',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'right_subtitle' => [
|
||||
'label' => 'Sous-titre de la section de droite',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Pour manger sain et régional',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'right_button_text' => [
|
||||
'label' => 'Texte du bouton de la section de gauche',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Voir nos recettes >',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'container_title' => [
|
||||
'label' => 'Titre de la section n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Chez Lionor le',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'container_title_2' => [
|
||||
'label' => 'Titre n°2 de la section n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Poulet 100% local',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'container_title_3' => [
|
||||
'label' => 'Titre n°3 de la section n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'C\'est...',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'container_item_1' => [
|
||||
'label' => 'Texte n°1 de la section n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Des Volailles nées, élevées et préparées en Hauts-de-France.',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'container_item_2' => [
|
||||
'label' => 'Texte n°2 de la section n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Des éleveurs animés par le développement de leur région.',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'container_item_3' => [
|
||||
'label' => 'Texte n°3 de la section n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Des volailles bien élevées qui assurent des produits bons et accessibles.',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'container_item_4' => [
|
||||
'label' => 'Texte n°4 de la section n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Une filière soucieuse de la santé des hommes, des animaux et de la terre.',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'product_title' => [
|
||||
'label' => 'Titre de la section n°3',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Découvrez nos volailles bien élevées',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'product_subtitle' => [
|
||||
'label' => 'Titre n°2 de la section n°3',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'qui ont le goût de la qualité',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
];
|
||||
|
||||
$staticPage = StaticPage::where('type', StaticPageType::homepage)->first();
|
||||
if ($staticPage) {
|
||||
$staticPage->data = $data;
|
||||
$staticPage->saveQuietly();
|
||||
} else {
|
||||
StaticPage::query()->forceCreateQuietly(
|
||||
[
|
||||
'type' => StaticPageType::homepage->value(),
|
||||
'seo_title' => 'Lionor, des volailles en Nord',
|
||||
'seo_description' => '100% local, des produits bien élevés, de qualité et accessibles.',
|
||||
'title' => 'Accueil',
|
||||
'slug' => 'accueil',
|
||||
'data' => $data
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('static_pages', function () {
|
||||
$staticPage = StaticPage::query()->where('type', StaticPageType::homepage)->first();
|
||||
$staticPage->data = [];
|
||||
$staticPage->saveQuietly();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
|
||||
use App\Enums\InputType;
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// OUR PRODUCTS
|
||||
$data = [
|
||||
'page_title' => [
|
||||
'label' => 'Titre de la section n°1',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Nos volailles bien élevées',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'page_title_2' => [
|
||||
'label' => 'Titre n°2 de la section n°1',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'qui ont le goût de la qualité',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'left_title_1' => [
|
||||
'label' => 'Titre n°1 de la section de gauche',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Trouvez l\'inspiration',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'left_title_2' => [
|
||||
'label' => 'Titre n°2 de la section de gauche',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'avec nos recettes',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'left_title_3' => [
|
||||
'label' => 'Titre n°3 de la section de gauche',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'de volailles bonnes',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'left_title_4' => [
|
||||
'label' => 'Titre n°4 de la section de gauche',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'et accessibles',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'right_title_1' => [
|
||||
'label' => 'Titre n°1 de la section de droite',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Découvrez les engagements',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'right_title_2' => [
|
||||
'label' => 'Titre n°2 de la section de droite',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'd\'une filière engagée',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'right_title_3' => [
|
||||
'label' => 'Titre n°3 de la section de droite',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'pour manger bon, sain',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'right_title_4' => [
|
||||
'label' => 'Titre n°4 de la section de droite',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'et Poulet 100% local',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
];
|
||||
|
||||
$staticPage = StaticPage::where('type', StaticPageType::our_products)->first();
|
||||
if ($staticPage) {
|
||||
$staticPage->data = $data;
|
||||
$staticPage->saveQuietly();
|
||||
} else {
|
||||
StaticPage::query()->forceCreateQuietly(
|
||||
[
|
||||
'type' => StaticPageType::our_products->value(),
|
||||
'seo_title' => 'Nos volailles bien élevées qui ont le goût de la qualité',
|
||||
'seo_description' => 'Liste de toutes nos gammes de produits.',
|
||||
'title' => 'Nos produits',
|
||||
'slug' => 'gammes',
|
||||
'data' => $data
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('static_pages', function () {
|
||||
$staticPage = StaticPage::query()->where('type', StaticPageType::our_products)->first();
|
||||
$staticPage->data = [];
|
||||
$staticPage->saveQuietly();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
<?php
|
||||
|
||||
use App\Enums\InputType;
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// OUR PRODUCTS
|
||||
$data = [
|
||||
'commitment_title_1' => [
|
||||
'label' => 'Titre de l\'engagement n°1',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Des produits de qualité bons et accessibles',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'commitment_subtitle_1' => [
|
||||
'label' => 'Sous-titre de l\'engagement n°1',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Garantis Poulet 100% Hauts-De-France',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'commitment_text_1' => [
|
||||
'label' => 'Texte de l\'engagement n°1',
|
||||
'inputType' => InputType::text->value,
|
||||
'value' => '<p>Avec notre label Poulet 100% LOCAL, certifié et contrôlé par un cahier des charges précis, nous garantissons l\'origine de nos produits issus de poulets nés, élevés et préparés en région des Hauts de France.</p>',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'commitment_title_2' => [
|
||||
'label' => 'Titre de l\'engagement n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Une filière soucieuse de la santé',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'commitment_subtitle_2' => [
|
||||
'label' => 'Sous-titre de l\'engagement n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Des hommes, des animaux et de la terre',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'commitment_text_2' => [
|
||||
'label' => 'Texte de l\'engagement n°2',
|
||||
'inputType' => InputType::text->value,
|
||||
'value' => '<p>LIONOR, c\'est une filière qui s\'engage pour élever des volailles dans le respect du vivant et qui favorise l\'économie locale. Fiers de nos 70 éleveurs et de nos 235 salariés, unis par la passion de leur métier, nous participons activement à la vie sociale et économique de notre région.</p>',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'commitment_title_3' => [
|
||||
'label' => 'Titre de l\'engagement n°3',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Des femmes et des hommes',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'commitment_subtitle_3' => [
|
||||
'label' => 'Sous-titre de l\'engagement n°3',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Qui maîtrisent la filière du grain à l\'assiette',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'commitment_text_3' => [
|
||||
'label' => 'Texte de l\'engagement n°3',
|
||||
'inputType' => InputType::text->value,
|
||||
'value' => '<p>Grâce à la maitrise totale de notre filière, allant de l\'alimentation aux produits régionaux de qualité, en passant pas nos élevages se situant dans un rayon de 50kms autour de notre entreprise, nous garantissons aux consommateurs finaux, une qualité et une traçabilité irréprochables. Notre crédo : "élever bien pour manger sain en région des Hauts de France."</p>',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
|
||||
'container_title' => [
|
||||
'label' => 'Titre de la section n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Chez Lionor le',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'container_title_2' => [
|
||||
'label' => 'Titre n°2 de la section n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Poulet 100% local',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'container_title_3' => [
|
||||
'label' => 'Titre n°3 de la section n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'C\'est...',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'container_item_1' => [
|
||||
'label' => 'Texte n°1 de la section n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Des Volailles nées, élevées et préparées en Hauts-de-France.',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'container_item_2' => [
|
||||
'label' => 'Texte n°2 de la section n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Des éleveurs animés par le développement de leur région.',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'container_item_3' => [
|
||||
'label' => 'Texte n°3 de la section n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Des volailles bien élevées qui assurent des produits bons et accessibles.',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'container_item_4' => [
|
||||
'label' => 'Texte n°4 de la section n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Une filière soucieuse de la santé des hommes, des animaux et de la terre.',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
];
|
||||
|
||||
$staticPage = StaticPage::where('type', StaticPageType::our_commitments)->first();
|
||||
if ($staticPage) {
|
||||
$staticPage->data = $data;
|
||||
$staticPage->saveQuietly();
|
||||
} else {
|
||||
StaticPage::query()->forceCreateQuietly(
|
||||
[
|
||||
'type' => StaticPageType::our_commitments->value(),
|
||||
'seo_title' => 'Les engagements Lionor',
|
||||
'seo_description' => 'Des produits de qualité, une filière soucieuse de la santé, maîtrise la filière du grain à l\'assiette',
|
||||
'title' => 'Nos engagements',
|
||||
'slug' => 'nos-engagements',
|
||||
'data' => $data
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('static_pages', function () {
|
||||
$staticPage = StaticPage::query()->where('type', StaticPageType::our_commitments)->first();
|
||||
$staticPage->data = [];
|
||||
$staticPage->saveQuietly();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
|
||||
use App\Enums\InputType;
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// BANNER SECTION
|
||||
$data = [
|
||||
'banner_title_1' => [
|
||||
'label' => 'Titre n°1 du bandeau',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Choisir',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'banner_title_2' => [
|
||||
'label' => 'Titre n°2 du bandeau',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'les volailles',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'banner_title_3' => [
|
||||
'label' => 'Titre n°3 du bandeau',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Lionor, c\'est...',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'banner_item_title_1' => [
|
||||
'label' => 'Titre de l\'élément n°1',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Soutenir',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'banner_item_text_1' => [
|
||||
'label' => 'Texte de l\'élément n°1',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'L\'emploi local et les éleveurs régionaux',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'banner_item_title_2' => [
|
||||
'label' => 'Titre de l\'élément n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Choisir la fraîcheur',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'banner_item_text_2' => [
|
||||
'label' => 'Texte de l\'élément n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Et consommer des produits de proximité',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'banner_item_title_3' => [
|
||||
'label' => 'Titre de l\'élément n°3',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Goûter la qualité',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'banner_item_text_3' => [
|
||||
'label' => 'Texte de l\'élément n°3',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'D\'un bout à l\'autre de la filière',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
];
|
||||
|
||||
$staticPage = StaticPage::where('type', StaticPageType::banner_section)->first();
|
||||
if ($staticPage) {
|
||||
$staticPage->data = $data;
|
||||
$staticPage->saveQuietly();
|
||||
} else {
|
||||
StaticPage::query()->forceCreateQuietly(
|
||||
[
|
||||
'type' => StaticPageType::banner_section->value(),
|
||||
'title' => 'Bannière',
|
||||
'slug' => 'banner',
|
||||
'data' => $data
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('static_pages', function () {
|
||||
$staticPage = StaticPage::query()->where('type', StaticPageType::banner_section)->first();
|
||||
$staticPage->data = [];
|
||||
$staticPage->saveQuietly();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Database\Seeders\StaticPageSeeder;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
|
|
@ -19,6 +20,7 @@ class DatabaseSeeder extends Seeder
|
|||
ProductSeeder::class,
|
||||
RecipeSeeder::class,
|
||||
ShopSeeder::class,
|
||||
StaticPageSeeder::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
148
database/seeders/StaticPageSeeder.php
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class StaticPageSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
// Legals.
|
||||
StaticPage::query()->updateOrCreate(
|
||||
[
|
||||
'type' => StaticPageType::legals,
|
||||
],
|
||||
[
|
||||
'seo_title' => 'Mentions légales et CGU',
|
||||
'seo_description' => 'Mentions légales et conditions générales d\'utilisation du site internet du site internet Lionor',
|
||||
'title' => 'Mentions légales',
|
||||
'type' => StaticPageType::legals,
|
||||
'content' => "
|
||||
<h2>Introduction</h2>
|
||||
<p>Nous vous remercions de lire ces conditions générales d'utilisation qui régissent les conditions d'accès et d'utilisation du site <a target='_blank' href='https://lionor.s-web.test' rel='noreferrer noopener'>lionor.fr</a>
|
||||
<br><br>
|
||||
<strong>Nous vous invitons à consulter régulièrement cette rubrique car la société Lionor peut être amenée à la modifier à tout moment.</strong>
|
||||
<br><br>
|
||||
<strong>Tout utilisateur déclare avoir lu et accepté les mentions légales et les conditions générales d'utilisation et s'engage à s'y conformer.</strong><br><br><br>
|
||||
Mise à jour le 15/03/2023.</p>
|
||||
<h2>Mentions légales</h2>
|
||||
<p>Lionor RTE DE LA GARE 59189 STEENBECQUE<br>Tél : +33(0)328436055 SAS au capital de 1 646 400 euros - RCS de Dunkerque sous le numéro 305 507 303<br><br>
|
||||
<strong>Editeur du Site</strong> : LDC Services 98 à 102 Rue Albert Einstein 72000 Le Mans<br>
|
||||
<strong>Directeur de la publication</strong> : Sylvain Gouet, Responsable Web Marketing Groupe LDC<br>
|
||||
<strong>Conception du site et réalisation</strong> : LDC Services 98 à 102 Rue Albert Einstein 72000 Le Mans<br>
|
||||
<strong>Illustrations</strong> : Médiapole 2020<br>
|
||||
<strong>Le site est hébergé par</strong> : OVH, via LDC, SAS au capital de 10 069 020 euros, RCS Lille Métropole 537 407 926, 2 rue Kellermann - 59100 Roubaix, Tel : 09 72 10 10 07, Mail : hosting@ml.ovh.net<br></p>
|
||||
<h2>Droit d'auteur - Droit des marques - Protection des bases de données</h2>
|
||||
<p>La présentation et le contenu du site constituent, ensemble, une œuvre protégée par les lois en vigueur des droits d'auteur, de la propriété intellectuelle et industrielle.
|
||||
<br><br>
|
||||
Les créations apparaissant sur le site (dessins, photographies, images, textes, séquences animées sonores ou non et autres documentations représentées), sont objets de droits d'auteur, de propriété industrielle et/ou intellectuelle et sont, selon les cas, propriété de la société Lionor ou de tiers ayant autorisé la société Lionor à les utiliser.
|
||||
<br>Aucune exploitation commerciale, reproduction, représentation, utilisation, adaptation, modification, incorporation, traduction, commercialisation, partielle ou intégrale de ces éléments (y compris ceux téléchargeables ou copiables) ne pourra en être faite sans l'accord préalable et écrit de la société Lionor, à l'exception de l'utilisation pour un usage privé sous réserve des dispositions différentes voire plus restrictives du Code de la propriété intellectuelle.
|
||||
<br>Toute utilisation non expressément autorisée peut engager la responsabilité civile et/ou pénale de son auteur. Lionor se réserve le droit d'engager des poursuites judiciaires à l'encontre de toute personne qui n'aurait pas respecté cette interdiction.</p>
|
||||
<h2>Vie privée - Données personnelles - Cookies</h2>
|
||||
<p>Nous vous invitons à vous reporter à notre Charte de confidentialité en <a target='_blank' href='https://lionor.s-web.test/politique-de-donnees-personnelles' rel='noreferrer noopener'>cliquant ici</a>.</p>
|
||||
<h2>Mentions Sanitaires :</h2>
|
||||
<p>Pour votre santé :<br>- mangez au moins cinq fruits et légumes par jour<br>- pratiquez une activité physique régulière<br>- évitez de manger trop gras, trop sucré, trop salé<br>- évitez de grignoter entre les repas</p>
|
||||
<p>Pour toute information complémentaire, consultez le site <a target='_blank' href='https://www.mangerbouger.fr' rel='noreferrer noopener'>www.mangerbouger.fr</a></p>
|
||||
<h2>Responsabilité</h2>
|
||||
<p>Lionor a déployé ses meilleurs efforts pour s'assurer de l'exactitude des informations présentes sur son site internet (ci-après le Site). Cependant, Lionor n'est responsable ni de l'exactitude, ni des erreurs, ni des omissions contenues sur le Site. L'utilisateur est seul responsable de l'utilisation de telles informations.
|
||||
<br>Lionor ne donne aucune garantie, explicite ou implicite, et n'assume aucune responsabilité qui pourrait résulter de l'accès ou de l'utilisation de ce Site incluant toutes détériorations ou virus qui pourraient infecter l'équipement informatique ou tout autre bien de l'utilisateur.
|
||||
<br>Par ailleurs.
|
||||
<br>Lionor pourra unilatéralement et à tout moment interrompre temporairement ou définitivement l'accès à tout ou partie du Site, y compris notamment le contenu, les fonctionnalités ou les heures de disponibilité, sans que sa responsabilité ne puisse être recherchée et sans que cela ne puisse donner lieu à l'allocation de dommages et intérêts de quelque nature que ce soit.
|
||||
<br>Les pages du Site peuvent contenir des liens hypertextes renvoyant vers d'autres sites internet gérés par des sociétés distinctes de Lionor, et sur lesquels Lionor n'exerce aucune sorte de contrôle. Lionor n'est pas responsable du contenu de tout autre site auquel vous pourriez avoir accès via le Site ou les autres sites internet du groupe LDC. Tout utilisateur ou visiteur du Site ne peut mettre en place un lien hypertexte en direction de ce Site sans l'autorisation expresse préalable de Lionor.</p>",
|
||||
]
|
||||
);
|
||||
// Policies.
|
||||
StaticPage::query()->updateOrCreate(
|
||||
[
|
||||
'type' => StaticPageType::confidentiality,
|
||||
],
|
||||
[
|
||||
'seo_title' => 'Politique des données personnelles',
|
||||
'seo_description' => 'Lionor vous informe sur les données que nous collectons, comment nous les traitons, dans quelles finalités.',
|
||||
'title' => 'Politique des données personnelles',
|
||||
'type' => StaticPageType::confidentiality,
|
||||
'content' => "
|
||||
<h2>Introduction</h2>
|
||||
<p>Le nouveau Règlement Général de l'Union Européenne sur la Protection des Données (RGPD), entré en vigueur le 25 mai 2018, vise à mieux encadrer la collecte, le traitement et l'utilisation de vos données personnelles.<br>Lionor, en sa qualité de responsable du traitement, renforce ses engagements pour garantir la protection et la sécurité des données à caractère personnel que vous lui confiez.<br><br></p>
|
||||
<p>A ce titre, la présente Charte de confidentialité vous informe sur le type de données que nous collectons, comment nous les traitons, dans quelles finalités, de manière à rendre leur utilisation la plus adaptée à vos besoins.<br><br>
|
||||
Le responsable de traitement, qui collecte et gère vos données, est la société Lionor, SA au capital social de 1 646 400 immatriculée au registre du commerce et des sociétés de Dunkerque sous le numéro 305 507 303, dont le siège social est RTE DE LA GARE 59189 STEENBECQUE.<br><br>
|
||||
Pour toute question relative à notre Charte de confidentialité, merci de nous contacter via le formulaire de contact suivant:<br><a target='_blank' href='https://www.ldc.fr/rgpd/professionnels/' rel='noreferrer noopener'>https://www.ldc.fr/rgpd/professionnels/</a><br><a target='_blank' href='https://www.ldc.fr/rgpd/consommateurs/' rel='noreferrer noopener'>https://www.ldc.fr/rgpd/consommateurs/</a>
|
||||
<br><a target='_blank' href='https://www.ldc.fr/rgpd/salaries/' rel='noreferrer noopener'>https://www.ldc.fr/rgpd/salaries/</a><br><br>Nous vous invitons à consulter régulièrement cette rubrique car Lionor peut être amené à la modifier à tout moment.
|
||||
<br>La présente Charte de confidentialité a été mise à jour le 15/03/2023.</p>
|
||||
<h2>Nos Engagements</h2>
|
||||
<p>Conformément à la réglementation relative à la protection des données personnelles et à la vie privée, notamment la loi n°78-17 du 6 janvier 1978 relative à l'informatique, aux fichiers et aux libertés dite loi « Informatique et Libertés » et au Règlement (UE) 2016/679 du 25 mai 2018 relatif à la protection des personnes physiques à l'égard du traitement des données à caractère personnel et à la libre circulation de ces données, (ci-après le « Règlement RGPD»), Lionor s'engage à respecter les principes suivants : <br><br>
|
||||
<strong>Consentement</strong>: vous devez avoir consenti à la collecte et au traitement de vos données. Si tel n'était pas le cas ou si vous avez changé d'avis, merci de vous reporter à l'article ci-dessous relatif à vos droits.<br><br>
|
||||
<strong>Limitation des données collectées</strong>: nous ne collectons que les données qui sont strictement nécessaires au traitement et à l'utilisation envisagée. Nous vous rappelons qu'il n'y a aucune obligation à nous transmettre ces données. Toutefois certains services ou opérations promotionnelles nécessitent certaines données, faute de quoi vous ne pourriez y accéder.<br><br>
|
||||
<strong>Limitation des finalités</strong>: les données que nous collectons sont traitées uniquement dans les finalités décrites ci-dessous.<br><br>
|
||||
<strong>Limitation des durées de conservation</strong>: vos données sont conservées uniquement le temps nécessaire aux finalités de traitement pour lequel elles ont été collectées. Au-delà de cette durée si aucune obligation légale impose leur conservation, nous veillerons à ce que vos données soient supprimées, détruites ou anonymisées.<br><br>
|
||||
<strong>Protection des données</strong>: en vue de sécuriser vos données et leur traitement, nous avons mis en place des mesures techniques et organisationnelles détaillées ci-dessous.<br><br>
|
||||
<strong>Transparence et loyauté</strong>: lorsque Lionor collecte une donnée vous concernant, nous vous informons de l'utilisation qui en sera faite. C'est pourquoi nous vous conseillons de lire attentivement les informations qui vous sont transmises à travers notre site internet.</p>
|
||||
<h2>Quelles données personnelles sont collectées ?</h2>
|
||||
<p>Au sens du Règlement RGPD, une donnée à caractère personnel désigne toute information relative à une personne physique identifiée ou identifiable.<br><br>Les données personnelles collectées varient en fonction du but de la collecte et du service dont vous souhaitez bénéficier.<br>
|
||||
<br>La société Lionor est amenée à collecter les catégories de données personnelles suivantes:<br><br>- coordonnées personnelles (civilité, nom, prénom, adresse e-mail, adresse postale) ; <br>- coordonnées personnelles non obligatoires (date de naissance, numéro de téléphone); <br>- identifiants utilisés pour accéder à votre compte en ligne (adresse IP, adresse e-mail et mot de passe);<br>- données relatives aux tickets de caisse de l'utilisateur ainsi que son RIB ou son compte Paypal;<br>- historiques de navigation, telles que les pages visitées et actions sur le site.<br>
|
||||
<br>Vous vous engagez à fournir des données personnelles actualisées et valides et garantissez ne faire aucune fausse déclaration et ne donner aucune information erronée.</p>
|
||||
<h2>Pourquoi vos données personnelles sont collectées ?</h2><p>Vos données peuvent être collectées dans la mesure où vous avez consenti de manière spécifique, libre et éclairée. Elles peuvent également être collectées pour satisfaire à l'exécution d'une obligation légale ou dans le cadre de la relation contractuelle construite avec vous (notamment conditions générales d'utilisation, conditions générales de vente) ou encore dans l'intérêt légitime de Lionor (par exemple pour assurer la sécurité des transactions).<br>
|
||||
<br>Nous collectons vos données personnelles afin de vous fournir la meilleure expérience utilisateur à travers notre site internet.<br><br><strong>Ces données sont collectées aux fins suivantes </strong><br>- Gestion des fonctionnalités et de la qualité du site internet<br>- Gestion de votre inscription à notre Newsletter et de votre Compte utilisateur<br>- Accès à votre Compte utilisateur<br>- Gestion du recrutement<br>- Traitement de vos demandes de renseignements<br>- Communication des informations (promotions, nouveaux produits, activité de la marque)<br>- Gestion de votre participation à nos jeux, tirages au sort, activités promotionnelles<br>- Développement et amélioration des produits Lionor<br>- Statistiques<br>- Proposition de produits personnalisés et de communications adaptées ou pour recommandation de produits en fonction des besoins de consommateurs<br>- Partages sur les réseaux sociaux</p>
|
||||
<h2>Quels sont vos droits ?</h2><p>Vous disposez d'un certain nombre de droits concernant vos données personnelles listés ci-dessous. <br><br>
|
||||
<strong>Droit d'accès</strong> Vous pouvez demander la communication de vos données sous une forme accessible, la confirmation que vos données font ou ne font plus l'objet d'un traitement ainsi que la communication des informations relatives à vos données. Afin que vos données personnelles soient exactes, complètes, pertinentes et à jour, vous avez le droit d'accéder, de corriger ou de mettre à jour vos données personnelles à tout moment.<br><br>
|
||||
<strong>Droit de rectification</strong><br>Vous êtes en droit de demander à ce que vos données soient rectifiées, complétées ou mises à jour lorsqu'elles sont inexactes, incomplètes, équivoques ou périmées.<br><br>
|
||||
<strong>Droit à l'effacement </strong><br>Vous avez le droit de demander la suppression de vos données personnelles notamment lorsqu'elles ne sont plus nécessaires aux finalités pour lesquelles elles ont été collectées. Si les données personnelles collectées ne sont plus nécessaires à aucune finalité et qu'aucune obligation légale nous impose de les conserver, nous mettrons tout en œuvre pour supprimer, détruire ou anonymiser ces données.<br><br>
|
||||
<strong>Droit à la limitation du traitement</strong><br>Vous avez le droit de demander la limitation du traitement de vos données personnelles si : <br><br>- vous contestez l'exactitude des données;<br>- vous souhaitez limiter le traitement des données qui n'avaient pas été traitées de manière licite plutôt que leur suppression; <br>- nous n'avons plus besoin de vos données personnelles mais celles-ci sont nécessaires pour la constatation, l'exercice ou la défense de vos droits en justice; <br>- vous vous êtes opposés au traitement de vos données personnelles et attendez de savoir si vos intérêts liés à cette objection l'emportent sur les motifs légitimes que nous poursuivons. <br><br>
|
||||
<strong>Droit à la portabilité de vos données </strong><br>Lorsque le traitement est effectué à partir de procédés automatisés et que vous avez librement consenti au traitement de vos données personnelles pour une finalité que nous vous avions communiqué au préalable; ou lorsque nous traitons vos données dans le cadre d'une opération commerciale (ex: vous fournir un produit) vous avez le droit de demander:<br>- à recevoir vos données personnelles dans un format structuré, couramment utilisé et lisible par une machine;<br>- à ce que vos données personnelles soient transmises directement à une autre responsable de traitement, lorsque que cela est techniquement possible.<br><br>
|
||||
<strong>Droit d'opposition</strong><br>Lorsque vos données sont traitées à des fins de prospection commerciale, vous avez le droit, à tout moment, de vous opposer au traitement de vos données personnelles et ce sans motif.</p>
|
||||
<h2>Droit de porter réclamation auprès de la CNIL</h2>
|
||||
<p>Si vous estimez que le traitement de vos données personnelles constitue une violation de la réglementation, vous pouvez introduire une réclamation auprès d'une autorité de contrôle, telle que la CNIL.<br><br>
|
||||
<strong>Vous pouvez exercer ces droits à tout moment en nous contactant via le formulaire suivant :</strong><br><a target='_blank' href='https://www.ldc.fr/rgpd/professionnels/' rel='noreferrer noopener'>https://www.ldc.fr/rgpd/professionnels/</a><br><a target='_blank' href='https://www.ldc.fr/rgpd/consommateurs/' rel='noreferrer noopener'>https://www.ldc.fr/rgpd/consommateurs/</a><br><a target='_blank' href='https://www.ldc.fr/rgpd/salaries/' rel='noreferrer noopener'>https://www.ldc.fr/rgpd/salaries/</a><br><br>
|
||||
<strong>Vous recevrez une réponse de notre part dans un délai d'un mois à compter de la réception de la demande. En cas de demande complexe ou du nombre important de demandes, le délai peut être prolongé de deux mois. </strong><br><br>
|
||||
<strong>L'exercice des droits se fait à titre gratuit. Si toutefois la demande était manifestement infondée ou excessive, Lionor se réserve la possibilité d'appliquer des frais administratifs ou de refuser de donner suite à la demande. </strong></p>
|
||||
<h2>Comment vos données personnelles sont protégées ?</h2>
|
||||
<p>Afin d'assurer la sécurité de vos données personnelles nous avons mis en place des mesures de sécurité, notamment des contrôles d'accès, des pare-feux, des serveurs sécurisés.<br><br>Ces mesures visent à protéger vos données personnelles contre toute perte, détournement, mauvaise utilisation, divulgation, modification, interférence, dommage, accès non autorisé des données.<br><br>En cas de violation de vos données personnelles susceptible d'engendrer un risque pour vos droits et libertés, Lionor en notifie la violation à la CNIL dans les meilleurs délais et, si possible, 72 heures au plus tard après en avoir pris connaissance. Lionor vous en informera dans les meilleurs délais.</p>
|
||||
<h2>Accès à vos données personnelles :</h2>
|
||||
<p>Vos données personnelles sont destinées au personnel de Lionor habilité à les traiter, notamment le service marketing, développement durable, informatique, commercial, qualité et administratif.</p>
|
||||
<h2>Partage de vos données personnelles :</h2>
|
||||
<p>Conformément à la règlementation, quand nous sommes amenés à partager vos données personnelles avec des sous-traitants pour certaines finalités décrites dans la présente Charte, nous nous assurons que leur dispositif en matière de sécurité des données et de leur stockage est au moins aussi important que celui de notre organisation. Nous veillons également à ce qu'ils respectent les lois relatives à la protection des données personnelles dans des conditions au moins équivalentes à celles que nous respectons.<br>
|
||||
<br>Par ailleurs, les sous-traitants étant amenés à traiter de vos données personnelles pour notre compte et sur nos instructions, nous nous engageons à ce que vos données personnelles ne soient pas partagées ou divulguées pour des finalités autres que celles décrites dans la présente Charte. Nous pouvons cependant être amenés à transmettre vos données, pour des finalités autres que celles prévues dans la Charte, dans les cas où leur communication est requise par la loi et les autorités gouvernementales.</p>
|
||||
<h2>Transfert de vos données en dehors de l'espace économique Européen :</h2>
|
||||
<p>Nous nous informons que vos données personnelles ne sont pas traitées en dehors de l'Espace Economique Européen (EEE). En cas de changement, nous vous en avertirons et mettrons tout en œuvre pour que ce transfert international de données dispose d'un niveau et de garanties de sécurité adéquats.</p>
|
||||
<h2>Utilisation des cookies</h2>
|
||||
<p>Les cookies sont des petits fichiers textes contenant des informations propres vous concernant stockés sur le disque dur de l'équipement informatique avec lequel vous vous êtes connectés sur le site internet et pouvant être lus seulement par le serveur qui l'a fourni. Les cookies sont gérés par votre navigateur internet.<br><br>Les cookies indiquent la fréquentation des pages que vous visitez, ce qui nous aide à connaître les informations qui vous intéressent. Cela permet de vous offrir plus de contenu qui vous intéresse et moins de contenu qui ne vous intéresse pas. <br><br>Les cookies vous permettent de stocker des préférences et les noms des utilisateurs, enregistrer des produits et des services, personnaliser des pages ou faire de la publicité ciblée.<br>
|
||||
<br>A travers ces cookies, vos données personnelles peuvent être recueilles telles que :<br>
|
||||
<br>- des informations concernant le navigateur de votre appareil et le système d'exploitation que vous utilisez;
|
||||
<br>- l'adresse IP de l'appareil que vous utilisez;
|
||||
<br>- les pages Web que vous consultez;
|
||||
<br>- les liens sur lesquelles vous cliquez pendant que vous êtes en interaction avec nos services.<br>
|
||||
<br>Le site internet <a target='_blank' href='https://lionor.s-web.test' rel='noreferrer noopener'>lionor.fr</a> utilise trois types de cookies qui ont des finalités différentes. Tous les cookies de type non techniques doivent recueillir votre consentement avant d'être installés. Vous pouvez donner votre consentement sur la page d'accueil du site internet, en cliquant sur « accepter ».<br>
|
||||
<br>- Les cookies strictement nécessaires et fonctionnels Ces cookies sont nécessaires au bon fonctionnement du site internet. Ils vous permettent d'utiliser les principales fonctionnalités. Sans ces cookies, vous ne pourrez pas utiliser normalement le site internet.
|
||||
<br>- Les cookies analytiques Ces cookies nous permettent de connaître l'utilisation et les performances du site internet et d'en améliorer son fonctionnement. <br>
|
||||
<br>- Les cookies de ciblage<br>
|
||||
<br>Ces cookies sont utilisés pour vous présenter des publicités ou vous adresser des informations adaptées à vos centres d'intérêts en dehors du site <a target='_blank' href='https://lionor.s-web.test' rel='noreferrer noopener'>lionor.fr</a> lors de votre navigation sur Internet. Le refus de ces cookies publicitaires n'a pas d'impact sur l'utilisation du site internet. Cependant, le fait de refuser les cookies publicitaires n'entraînera pas l'arrêt de la publicité sur Internet. Cela aura seulement pour effet d'afficher une publicité qui ne tiendra pas compte de vos centres d'intérêt ou de vos préférences.<br><br>
|
||||
<strong>Vous avez le choix :</strong><br>
|
||||
<br><strong>- d'accepter</strong> ces cookies en cliquant sur le bouton «Accepter» présent sur le bandeau Cookies, apparaissant au bas de votre page internet. Tant que vous n'avez pas accepté, les cookies ne pourront être stockés sur votre appareil; ou<br><br>
|
||||
<strong>de refuser</strong> ces cookies via le bouton «Paramétrer» présent sur le bandeau Cookies ou les paramètres de votre navigateur internet.<br>
|
||||
<br>Lorsque vous cliquez sur le bouton «Paramétrer» du bandeau Cookies, une liste s'affiche présentant les différents types de cookies par finalité. Si vous consentez au dépôt des cookies, il vous suffit de les activer puis de cliquer sur le bouton «Enregistrer» en bas de la fenêtre. Si vous refusez le dépôt des cookies, il vous suffit de cliquer sur le bouton «Enregistrer», le dépôt des cookies étant par défaut désactivé.<br>
|
||||
<br>Pour en savoir plus sur la désactivation des cookies via votre navigateur internet :<br>
|
||||
<br>Internet Explorer: <a target='_blank' href='http://windows.microsoft.com/fr-FR/windows-vista/Block-or-allow-cookies' rel='noreferrer noopener'>http://windows.microsoft.com/fr-FR/windows-vista/Block-or-allow-cookies</a>
|
||||
<br>Chrome: <a target='_blank' href='http://support.google.com/chrome/bin/answer.py?hl=fr&hlrm=en&answer=95647' rel='noreferrer noopener'>http://support.google.com/chrome/bin/answer.py?hl=fr&hlrm=en&answer=95647</a>
|
||||
<br>Firefox: <a target='_blank' href='https://support.mozilla.org/fr/kb/protection-renforcee-contre-pistage-firefox-ordinateur' rel='noreferrer noopener'>https://support.mozilla.org/fr/kb/protection-renforcee-contre-pistage-firefox-ordinateur</a>
|
||||
<br>Safari: <a target='_blank' href='https://support.apple.com/fr-fr/guide/safari/sfri11471/mac' rel='noreferrer noopener'>https://support.apple.com/fr-fr/guide/safari/sfri11471/mac</a><br>
|
||||
<br>La durée de conservation de ces informations dans votre appareil est d'une durée maximale de 13 mois. A l'expiration de ce délai, nous recueillerons de nouveau votre consentement. <br>Pour plus d'informations sur le paramétrage de vos cookies, vous pouvez consulter :<br><a target='_blank' href='http://www.youronlinechoices.com/fr/' rel='noreferrer noopener'>http://www.youronlinechoices.com/fr/</a><br><a target='_blank' href='https://www.allaboutcookies.org/' rel='noreferrer noopener'>https://www.allaboutcookies.org/</a></p>
|
||||
<h2>Sites internet de tiers</h2>
|
||||
<p>Le site internet Lionor peut être associé à des sites internet tiers. Les sites hébergés par des tiers sont hors de notre contrôle. Lorsque vous renseignez des données personnelles sur un site internet tiers, le traitement de ces données n'est pas effectué sur notre site internet, mais sur le site internet tiers concerné. Toute donnée personnelle que vous fournissez sera collectée et traitée conformément à la politique relative à la confidentialité des données du tiers concerné.<br>
|
||||
<br>Par conséquent, nous n'assumons aucune responsabilité concernant les pratiques exercées par lesdits tiers en matière de protection des données.</p>
|
||||
<h2>Droit applicable</h2>
|
||||
<p>La présente Charte de confidentialité est régie et sera interprétée conformément au droit français.</p>
|
||||
<h2>Nous contacter</h2>
|
||||
<p>Si vous avez des questions, remarques ou réclamations relatives à la présente Charte de confidentialité, ou le traitement de vos données personnelles, veuillez-nous contacter à l'adresse :<br><br><a target='_blank' href='https://www.ldc.fr/rgpd/professionnels/' rel='noreferrer noopener'>https://www.ldc.fr/rgpd/professionnels/</a><br><a target='_blank' href='https://www.ldc.fr/rgpd/consommateurs/' rel='noreferrer noopener'>https://www.ldc.fr/rgpd/consommateurs/</a><br><a target='_blank' href='https://www.ldc.fr/rgpd/salaries/' rel='noreferrer noopener'>https://www.ldc.fr/rgpd/salaries/</a></p>
|
||||
",
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,9 +8,9 @@ data:
|
|||
APP_ENV: "${APP_APP_ENV}"
|
||||
APP_KEY: "${APP_APP_KEY}"
|
||||
APP_DEBUG: "${APP_APP_DEBUG}"
|
||||
APP_URL: "https://www.${APP_DOMAIN}"
|
||||
APP_URL: "https://${REDIRECT}${APP_DOMAIN}"
|
||||
LOG_CHANNEL: "k8s"
|
||||
DB_HOST: "mariadb-service.common-services"
|
||||
DB_HOST: "${APP_DB_HOST}"
|
||||
DB_DATABASE: "${APP_DB_DATABASE}"
|
||||
DB_USERNAME: "${APP_DB_USERNAME}"
|
||||
DB_PASSWORD: "${APP_DB_PASSWORD}"
|
||||
|
|
@ -28,6 +28,12 @@ data:
|
|||
GOOGLE_RECAPTCHA_VERSION: "${APP_GOOGLE_RECAPTCHA_VERSION}"
|
||||
SENTRY_LARAVEL_DSN: "${APP_SENTRY_LARAVEL_DSN}"
|
||||
MATOMO_SITE_ID: "${APP_MATOMO_SITE_ID}"
|
||||
SAML2_SP_CERT_x509: "${APP_SAML2_SP_CERT_x509}"
|
||||
SAML2_SP_CERT_PRIVATEKEY: "${APP_SAML2_SP_CERT_PRIVATEKEY}"
|
||||
SAML2_CONTACT_TECHNICAL_EMAIL: "${APP_SAML2_CONTACT_TECHNICAL_EMAIL}"
|
||||
SAML2_CONTACT_SUPPORT_EMAIL: "${APP_SAML2_CONTACT_SUPPORT_EMAIL}"
|
||||
SAML2_DEFAULT_TENANT_UUID: "${APP_SAML2_DEFAULT_TENANT_UUID}"
|
||||
UWIL_ADMIN_SECURE_CIDR_LIST: "${APP_GLOBAL_UWIL_ADMIN_SECURE_CIDR_LIST}"
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
|
|
@ -63,15 +69,22 @@ spec:
|
|||
envFrom:
|
||||
- configMapRef:
|
||||
name: ${CI_PROJECT_PATH_SLUG}-config-map
|
||||
resources:
|
||||
limits:
|
||||
cpu: "${APP_CI_CPU_LIMIT}"
|
||||
memory: "${APP_CI_MEMORY_LIMIT}"
|
||||
requests:
|
||||
cpu: "${APP_CI_CPU_REQUEST}"
|
||||
memory: "${APP_CI_MEMORY_REQUEST}"
|
||||
volumeMounts:
|
||||
- name: storage
|
||||
mountPath: /app/srcs/storage
|
||||
imagePullSecrets:
|
||||
- name: docker-registry-credentials
|
||||
securityContext:
|
||||
runAsUser: 33
|
||||
runAsGroup: 33
|
||||
fsGroup: 33
|
||||
runAsUser: 82
|
||||
runAsGroup: 82
|
||||
fsGroup: 82
|
||||
fsGroupChangePolicy: "OnRootMismatch"
|
||||
volumes:
|
||||
- name: storage
|
||||
|
|
@ -89,10 +102,10 @@ spec:
|
|||
app: ${CI_PROJECT_PATH_SLUG}-app
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 443
|
||||
targetPort: 80
|
||||
|
||||
---
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: ${CI_PROJECT_PATH_SLUG}-ingress-route
|
||||
|
|
@ -101,30 +114,15 @@ spec:
|
|||
- web
|
||||
- websecure
|
||||
routes:
|
||||
- match: Host(`${APP_DOMAIN}`, `www.${APP_DOMAIN}`)
|
||||
- match: Host(`${APP_DOMAIN}`) || Host(`www.${APP_DOMAIN}`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: ${CI_PROJECT_PATH_SLUG}-service
|
||||
port: 80
|
||||
middlewares:
|
||||
- name: redirect-no-www-to-www
|
||||
namespace: common-services
|
||||
tls:
|
||||
secretName: $APP_DOMAIN
|
||||
|
||||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: $APP_DOMAIN
|
||||
spec:
|
||||
dnsNames:
|
||||
- $APP_DOMAIN
|
||||
- www.${APP_DOMAIN}
|
||||
secretName: $APP_DOMAIN
|
||||
issuerRef:
|
||||
name: $APP_CERT_ISSUER
|
||||
kind: ClusterIssuer
|
||||
secretName: ${CRT_TLS_NAME}
|
||||
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
|
|
@ -133,6 +131,9 @@ metadata:
|
|||
name: ${CI_PROJECT_PATH_SLUG}-cronjob
|
||||
spec:
|
||||
schedule: "* * * * *"
|
||||
successfulJobsHistoryLimit: 1
|
||||
failedJobsHistoryLimit: 1
|
||||
concurrencyPolicy: Forbid
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
|
|
@ -151,7 +152,7 @@ spec:
|
|||
containers:
|
||||
- name: ${CI_PROJECT_PATH_SLUG}-scheduled
|
||||
image: $IMAGE_TAG
|
||||
imagePullPolicy: Always
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- "php"
|
||||
args:
|
||||
|
|
@ -170,8 +171,8 @@ spec:
|
|||
persistentVolumeClaim:
|
||||
claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage
|
||||
securityContext:
|
||||
runAsUser: 33
|
||||
runAsGroup: 33
|
||||
fsGroup: 33
|
||||
runAsUser: 82
|
||||
runAsGroup: 82
|
||||
fsGroup: 82
|
||||
fsGroupChangePolicy: "OnRootMismatch"
|
||||
restartPolicy: OnFailure
|
||||
|
|
|
|||
307
package-lock.json
generated
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "lionor",
|
||||
"name": "srcs",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
"@fortawesome/free-regular-svg-icons": "latest",
|
||||
"@fortawesome/free-solid-svg-icons": "latest",
|
||||
"@fortawesome/vue-fontawesome": "^3.0.3",
|
||||
"@ldc-web/cookie-notice": "^3.0.8",
|
||||
"@ldc-web/cookie-notice": "^6.0.3",
|
||||
"@rushstack/eslint-patch": "^1.3.2",
|
||||
"@sipec/vue3-tags-input": "^3.0.4",
|
||||
"@types/bootstrap": "^5.2.7",
|
||||
|
|
@ -31,10 +31,11 @@
|
|||
"fslightbox": "^3.4.1",
|
||||
"laravel-vite-plugin": "latest",
|
||||
"leaflet": "^1.9.4",
|
||||
"meow": "^9.0.0",
|
||||
"postcss-discard-comments": "^5.1.2",
|
||||
"prettier": "latest",
|
||||
"print-js": "^1.6.0",
|
||||
"resolve-url-loader": "^5.0.0",
|
||||
"rollup-plugin-copy": "^3.5.0",
|
||||
"sass": "latest",
|
||||
"slugify": "^1.6.6",
|
||||
"stylelint-config-idiomatic-order": "github:ream88/stylelint-config-idiomatic-order",
|
||||
|
|
@ -75,12 +76,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.22.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
|
||||
"integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
|
||||
"version": "7.23.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
|
||||
"integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/highlight": "^7.22.13",
|
||||
"@babel/highlight": "^7.23.4",
|
||||
"chalk": "^2.4.2"
|
||||
},
|
||||
"engines": {
|
||||
|
|
@ -127,12 +128,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/generator": {
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
|
||||
"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
|
||||
"version": "7.23.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz",
|
||||
"integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.23.0",
|
||||
"@babel/types": "^7.23.6",
|
||||
"@jridgewell/gen-mapping": "^0.3.2",
|
||||
"@jridgewell/trace-mapping": "^0.3.17",
|
||||
"jsesc": "^2.5.1"
|
||||
|
|
@ -406,9 +407,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/helper-string-parser": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
|
||||
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
|
||||
"version": "7.23.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz",
|
||||
"integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
|
|
@ -461,9 +462,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/highlight": {
|
||||
"version": "7.22.20",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
|
||||
"integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
|
||||
"version": "7.23.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz",
|
||||
"integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.22.20",
|
||||
|
|
@ -475,9 +476,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
|
||||
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
|
||||
"version": "7.23.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz",
|
||||
"integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
|
|
@ -1684,20 +1685,20 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/traverse": {
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz",
|
||||
"integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==",
|
||||
"version": "7.23.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz",
|
||||
"integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.22.13",
|
||||
"@babel/generator": "^7.23.0",
|
||||
"@babel/code-frame": "^7.23.5",
|
||||
"@babel/generator": "^7.23.6",
|
||||
"@babel/helper-environment-visitor": "^7.22.20",
|
||||
"@babel/helper-function-name": "^7.23.0",
|
||||
"@babel/helper-hoist-variables": "^7.22.5",
|
||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||
"@babel/parser": "^7.23.0",
|
||||
"@babel/types": "^7.23.0",
|
||||
"debug": "^4.1.0",
|
||||
"@babel/parser": "^7.23.6",
|
||||
"@babel/types": "^7.23.6",
|
||||
"debug": "^4.3.1",
|
||||
"globals": "^11.1.0"
|
||||
},
|
||||
"engines": {
|
||||
|
|
@ -1705,12 +1706,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
|
||||
"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
|
||||
"version": "7.23.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz",
|
||||
"integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.22.5",
|
||||
"@babel/helper-string-parser": "^7.23.4",
|
||||
"@babel/helper-validator-identifier": "^7.22.20",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
},
|
||||
|
|
@ -2435,9 +2436,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@ldc-web/cookie-notice": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://lab.s-web.fr/api/v4/projects/50/packages/npm/@ldc-web/cookie-notice/-/@ldc-web/cookie-notice-3.0.8.tgz",
|
||||
"integrity": "sha1-FOc6hEv1L9NOnRDOdyBnbIsd31A=",
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://lab.s-web.fr/api/v4/projects/50/packages/npm/@ldc-web/cookie-notice/-/@ldc-web/cookie-notice-6.0.3.tgz",
|
||||
"integrity": "sha1-mW2DD+8ipWkmvKhZ3m9h5wemAHI=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
|
|
@ -2551,12 +2552,31 @@
|
|||
"integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/fs-extra": {
|
||||
"version": "8.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz",
|
||||
"integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/geojson": {
|
||||
"version": "7946.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.11.tgz",
|
||||
"integrity": "sha512-L7A0AINMXQpVwxHJ4jxD6/XjZ4NDufaRlUJHjNIFKYUFBH1SvOW+neaqb0VTRSLW5suSrSu19ObFEFnfNcr+qg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/glob": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
|
||||
"integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/minimatch": "*",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz",
|
||||
|
|
@ -2572,19 +2592,32 @@
|
|||
"@types/geojson": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/minimatch": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
|
||||
"integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/minimist": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.3.tgz",
|
||||
"integrity": "sha512-ZYFzrvyWUNhaPomn80dsMNgMeXxNWZBdkuG/hWlUvXvbdUH8ZERNBGXnU87McuGcWDsyzX2aChCv/SVN348k3A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz",
|
||||
"integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/normalize-package-data": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.2.tgz",
|
||||
"integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.5.3",
|
||||
|
|
@ -3270,7 +3303,6 @@
|
|||
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
|
||||
"integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -3292,9 +3324,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz",
|
||||
"integrity": "sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==",
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.3.tgz",
|
||||
"integrity": "sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
|
|
@ -3464,8 +3496,6 @@
|
|||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
|
|
@ -3475,8 +3505,6 @@
|
|||
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz",
|
||||
"integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"camelcase": "^5.3.1",
|
||||
"map-obj": "^4.0.0",
|
||||
|
|
@ -3584,6 +3612,12 @@
|
|||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/colorette": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
|
||||
"integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
|
|
@ -3755,7 +3789,6 @@
|
|||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -3765,7 +3798,6 @@
|
|||
"resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz",
|
||||
"integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"decamelize": "^1.1.0",
|
||||
"map-obj": "^1.0.0"
|
||||
|
|
@ -3782,7 +3814,6 @@
|
|||
"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
|
||||
"integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -3853,7 +3884,6 @@
|
|||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"is-arrayish": "^0.2.1"
|
||||
}
|
||||
|
|
@ -4558,7 +4588,6 @@
|
|||
"resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
|
||||
"integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
|
|
@ -4595,7 +4624,6 @@
|
|||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
|
||||
"integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
|
|
@ -4608,7 +4636,6 @@
|
|||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
|
|
@ -4620,8 +4647,7 @@
|
|||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/html-tags": {
|
||||
"version": "3.3.1",
|
||||
|
|
@ -4697,8 +4723,6 @@
|
|||
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
|
||||
"integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
|
@ -4730,8 +4754,7 @@
|
|||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
||||
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
|
|
@ -4811,7 +4834,6 @@
|
|||
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
|
||||
"integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -4872,8 +4894,7 @@
|
|||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
|
||||
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
|
|
@ -4925,7 +4946,6 @@
|
|||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
|
||||
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -4975,8 +4995,7 @@
|
|||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/loader-utils": {
|
||||
"version": "2.0.4",
|
||||
|
|
@ -5064,7 +5083,6 @@
|
|||
"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz",
|
||||
"integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
|
|
@ -5095,8 +5113,6 @@
|
|||
"resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz",
|
||||
"integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/minimist": "^1.2.0",
|
||||
"camelcase-keys": "^6.2.2",
|
||||
|
|
@ -5123,8 +5139,6 @@
|
|||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz",
|
||||
"integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
|
|
@ -5180,7 +5194,6 @@
|
|||
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
|
||||
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
|
|
@ -5202,7 +5215,6 @@
|
|||
"resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
|
||||
"integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"arrify": "^1.0.1",
|
||||
"is-plain-obj": "^1.1.0",
|
||||
|
|
@ -5259,7 +5271,6 @@
|
|||
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
|
||||
"integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"hosted-git-info": "^4.0.1",
|
||||
"is-core-module": "^2.5.0",
|
||||
|
|
@ -5275,7 +5286,6 @@
|
|||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
|
|
@ -5288,7 +5298,6 @@
|
|||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
|
|
@ -5303,8 +5312,7 @@
|
|||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
|
|
@ -5400,8 +5408,6 @@
|
|||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
|
|
@ -5423,7 +5429,6 @@
|
|||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
|
||||
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"error-ex": "^1.3.1",
|
||||
|
|
@ -5654,12 +5659,6 @@
|
|||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/print-js": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/print-js/-/print-js-1.6.0.tgz",
|
||||
"integrity": "sha512-BfnOIzSKbqGRtO4o0rnj/K3681BSd2QUrsIZy/+WdCIugjIswjmx3lDEZpXB2ruGf9d4b3YNINri81+J0FsBWg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/process": {
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||
|
|
@ -5709,8 +5708,6 @@
|
|||
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
|
||||
"integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
|
@ -5720,8 +5717,6 @@
|
|||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
|
||||
"integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/normalize-package-data": "^2.4.0",
|
||||
"normalize-package-data": "^2.5.0",
|
||||
|
|
@ -5737,8 +5732,6 @@
|
|||
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
|
||||
"integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"find-up": "^4.1.0",
|
||||
"read-pkg": "^5.2.0",
|
||||
|
|
@ -5756,8 +5749,6 @@
|
|||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"locate-path": "^5.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
|
|
@ -5771,8 +5762,6 @@
|
|||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"p-locate": "^4.1.0"
|
||||
},
|
||||
|
|
@ -5785,8 +5774,6 @@
|
|||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"p-try": "^2.0.0"
|
||||
},
|
||||
|
|
@ -5802,8 +5789,6 @@
|
|||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"p-limit": "^2.2.0"
|
||||
},
|
||||
|
|
@ -5816,8 +5801,6 @@
|
|||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
|
||||
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
|
@ -5826,17 +5809,13 @@
|
|||
"version": "2.8.9",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
|
||||
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/read-pkg/node_modules/normalize-package-data": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
|
||||
"integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"hosted-git-info": "^2.1.4",
|
||||
"resolve": "^1.10.0",
|
||||
|
|
@ -5849,8 +5828,6 @@
|
|||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver"
|
||||
}
|
||||
|
|
@ -5860,8 +5837,6 @@
|
|||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
|
||||
"integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
|
@ -5883,8 +5858,6 @@
|
|||
"resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
|
||||
"integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"indent-string": "^4.0.0",
|
||||
"strip-indent": "^3.0.0"
|
||||
|
|
@ -6070,6 +6043,82 @@
|
|||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup-plugin-copy": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.5.0.tgz",
|
||||
"integrity": "sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/fs-extra": "^8.0.1",
|
||||
"colorette": "^1.1.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
"globby": "10.0.1",
|
||||
"is-plain-object": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.3"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup-plugin-copy/node_modules/fs-extra": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6 <7 || >=8"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup-plugin-copy/node_modules/globby": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz",
|
||||
"integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/glob": "^7.1.1",
|
||||
"array-union": "^2.1.0",
|
||||
"dir-glob": "^3.0.1",
|
||||
"fast-glob": "^3.0.3",
|
||||
"glob": "^7.1.3",
|
||||
"ignore": "^5.1.1",
|
||||
"merge2": "^1.2.3",
|
||||
"slash": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup-plugin-copy/node_modules/is-plain-object": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz",
|
||||
"integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup-plugin-copy/node_modules/jsonfile": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||
"integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
|
||||
"dev": true,
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup-plugin-copy/node_modules/universalify": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/run-parallel": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||
|
|
@ -6258,7 +6307,6 @@
|
|||
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
|
||||
"integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"spdx-expression-parse": "^3.0.0",
|
||||
"spdx-license-ids": "^3.0.0"
|
||||
|
|
@ -6268,15 +6316,13 @@
|
|||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
|
||||
"integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/spdx-expression-parse": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
|
||||
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"spdx-exceptions": "^2.1.0",
|
||||
"spdx-license-ids": "^3.0.0"
|
||||
|
|
@ -6286,8 +6332,7 @@
|
|||
"version": "3.0.16",
|
||||
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz",
|
||||
"integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
|
|
@ -6321,8 +6366,6 @@
|
|||
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
|
||||
"integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"min-indent": "^1.0.0"
|
||||
},
|
||||
|
|
@ -6830,9 +6873,9 @@
|
|||
"peer": true
|
||||
},
|
||||
"node_modules/sweetalert2": {
|
||||
"version": "11.7.32",
|
||||
"resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.7.32.tgz",
|
||||
"integrity": "sha512-44tNNe2oLe7T94mT6dus4hc9G7qg6jZU/K5qZzpNS6e5HGPrSF6Kie6oZ7B5puIJydB34V2h/8f5EhIFivYo4A==",
|
||||
"version": "11.10.2",
|
||||
"resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.10.2.tgz",
|
||||
"integrity": "sha512-BYlIxGw6OF9Rw2z1wlnh1U+fvHHkvtg4BGyimV9nZxQRGvCBfx9uonxgwuYpJuYqCtM+2W1KOm8iMIEb/2v7Hg==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
|
|
@ -6948,8 +6991,6 @@
|
|||
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
|
||||
"integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
|
@ -7003,6 +7044,12 @@
|
|||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/unicode-canonical-property-names-ecmascript": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
|
||||
|
|
@ -7117,16 +7164,15 @@
|
|||
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
||||
"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"spdx-correct": "^3.0.0",
|
||||
"spdx-expression-parse": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "4.4.11",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-4.4.11.tgz",
|
||||
"integrity": "sha512-ksNZJlkcU9b0lBwAGZGGaZHCMqHsc8OpgtoYhsQ4/I2v5cnpmmmqe5pM4nv/4Hn6G/2GhTdj0DhZh2e+Er1q5A==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz",
|
||||
"integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
|
|
@ -7745,7 +7791,6 @@
|
|||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
|
||||
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
"@fortawesome/free-regular-svg-icons": "latest",
|
||||
"@fortawesome/free-solid-svg-icons": "latest",
|
||||
"@fortawesome/vue-fontawesome": "^3.0.3",
|
||||
"@ldc-web/cookie-notice": "^3.0.8",
|
||||
"@ldc-web/cookie-notice": "^6.0.3",
|
||||
"@rushstack/eslint-patch": "^1.3.2",
|
||||
"@sipec/vue3-tags-input": "^3.0.4",
|
||||
"@types/bootstrap": "^5.2.7",
|
||||
|
|
@ -38,10 +38,11 @@
|
|||
"fslightbox": "^3.4.1",
|
||||
"laravel-vite-plugin": "latest",
|
||||
"leaflet": "^1.9.4",
|
||||
"meow": "^9.0.0",
|
||||
"postcss-discard-comments": "^5.1.2",
|
||||
"prettier": "latest",
|
||||
"print-js": "^1.6.0",
|
||||
"resolve-url-loader": "^5.0.0",
|
||||
"rollup-plugin-copy": "^3.5.0",
|
||||
"sass": "latest",
|
||||
"slugify": "^1.6.6",
|
||||
"stylelint-config-idiomatic-order": "github:ream88/stylelint-config-idiomatic-order",
|
||||
|
|
|
|||
10
phpstan.neon
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
includes:
|
||||
- vendor/larastan/larastan/extension.neon
|
||||
|
||||
parameters:
|
||||
|
||||
paths:
|
||||
- app/
|
||||
|
||||
# Level 9 is the highest level
|
||||
level: 5
|
||||
13
production-resources.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: $APP_DOMAIN
|
||||
spec:
|
||||
dnsNames:
|
||||
- $APP_DOMAIN
|
||||
- www.${APP_DOMAIN}
|
||||
secretName: $APP_DOMAIN
|
||||
issuerRef:
|
||||
name: $APP_CERT_ISSUER
|
||||
kind: ClusterIssuer
|
||||
|
|
@ -1,2 +1,13 @@
|
|||
User-agent: *
|
||||
Disallow:
|
||||
Disallow: /bo
|
||||
|
||||
User-agent: GPTBot
|
||||
Disallow: /
|
||||
|
||||
User-agent: Amazonbot
|
||||
Disallow: /
|
||||
|
||||
User-agent: ClaudeBot
|
||||
Disallow: /
|
||||
|
||||
Sitemap: https://www.lionor.fr/sitemap.xml
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 112 KiB |
BIN
resources/assets/images/2024-ad.png
Normal file
|
After Width: | Height: | Size: 294 KiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 284 KiB |
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 219 KiB |
|
Before Width: | Height: | Size: 1.9 MiB |