Compare commits

...
Sign in to create a new pull request.

146 commits
2.0.0 ... trunk

Author SHA1 Message Date
Noah Lancien
8b9977b779 Merge branch 'develop' into trunk 2026-10-26 12:03:02 +01:00
Noah Lancien
6315c452cb ci: 👷 Replaced user 33 with 82 2026-10-26 12:02:54 +01:00
Noah Lancien
fa9ca6000d Merge branch 'develop' into trunk 2026-10-22 17:44:12 +02:00
Noix
7b7b456ef2 Merge branch 'bump' into 'develop'
chore: ⬆️ bump php 8.5 + laravel 12 + meow

See merge request ldc-web/projets/agis!50
2026-10-22 15:41:56 +00:00
Corentin Huet
8d3d646403 chore: ⬆️ bump php 8.5 + laravel 12 + meow 2026-10-22 17:35:06 +02:00
K Muller
436e196f8b Merge branch 'develop' into trunk 2026-06-18 14:50:22 +02:00
karl.muller
666d79b32f Merge branch 'fix-86' into 'develop'
Closes #86 wording change

See merge request ldc-web/projets/agis!48
2026-06-18 12:50:00 +00:00
Jeremy Munsch
3ed4e6a99f
refactor: Closes #86 wording change in order to be law compliant on page explorer and gastro.. 2026-06-18 14:43:01 +02:00
Jeremy Munsch
80e21dabb7
fix: UserFactory was not upto date 2026-06-18 14:30:38 +02:00
Noah Lancien
4a8691c3ab Merge branch 'develop' into trunk 2026-01-23 14:40:23 +01:00
Noah Lancien
f6b5dcb42c ci: migrate to mysql + limit cronjobs 2026-01-23 14:40:06 +01:00
Noah Lancien
056c265aad Merge branch 'develop' into trunk 2026-01-12 12:42:01 +01:00
Noah Lancien
df39b81e40 feat: updated admin-secure 2026-01-12 12:40:48 +01:00
Noah Lancien
dd2f3877a2 Merge branch 'develop' into trunk 2026-01-09 14:43:32 +01:00
Noah Lancien
e86852de81 ci: updated image version + target port 80 2026-01-09 14:39:44 +01:00
Noah Lancien
4b78418ce4 Merge branch 'develop' into trunk 2026-01-08 14:39:23 +01:00
Noah Lancien
d7c69379c1 ci: added staging-resources.yaml 2026-01-08 14:38:51 +01:00
Noah Lancien
27d200ecb0 Merge branch 'develop' into trunk 2026-01-08 14:19:44 +01:00
Noah Lancien
9b2e54a6a3 ci: added ci variables to define pod resources 2026-01-08 12:59:15 +01:00
Noah Lancien
7a5d666b0e Merge branch 'develop' into trunk 2025-06-16 15:14:48 +02:00
noah.lancien
9bf67ce627 Merge branch 'issue-84' into 'develop'
feat: ✨ add desired location in joins us formulary #84

See merge request ldc-web/projets/agis!46
2025-06-16 13:13:27 +00:00
Alexis Gousseau
83cd90096e fix: 🚨 resolve errors for php 8.4 2025-06-16 12:26:32 +02:00
Alexis Gousseau
4656dd598e feat: ✨ add desired location in joins us formulary #84 2025-06-16 12:24:01 +02:00
Vincent BRIDIER
7333c9faf7
Merge branch 'develop' into trunk 2025-05-02 10:41:36 +02:00
Vincent BRIDIER
6bca2d4a13 feat: Add br in text on explorer page - Close #82 2025-05-02 08:41:05 +00:00
Karl Muller
e40e70aaff Merge branch 'develop' into trunk 2025-04-29 12:06:26 +00:00
Karl Muller
aefaf9a0b1 CI: 👷 add multistage Docker build 2025-04-29 07:44:26 +00:00
Vincent BRIDIER
8ada25191a
Merge branch 'develop' into trunk 2025-04-29 08:59:45 +02:00
Vincent BRIDIER
5f16591b85
feat: Add text on explorer page - Close #82 2025-04-29 08:59:34 +02:00
Noah Lancien
ee7c1dc2d5 Merge branch 'develop' into trunk 2025-03-06 16:50:39 +01:00
Noah Lancien
aa7715c19c ci: Updated the docker image version to 8.3 2025-03-06 16:50:24 +01:00
Noah Lancien
348836b1ef Merge branch 'develop' into trunk 2025-03-06 16:18:47 +01:00
noah.lancien
53fa87fa17 Merge branch 'bump-and-saml' into 'develop'
Bump and saml

See merge request ldc-web/projets/agis!43
2025-03-06 15:16:36 +00:00
Noah Lancien
ecaff7a068 feat: Added SAML authentication 2025-03-06 16:06:54 +01:00
Noah Lancien
ab85b33052 chore: Bump Laravel-11 + sitemap-generator v2 -> v4 2025-03-06 14:28:42 +01:00
Noah Lancien
b0b836c5b9 Merge branch 'develop' into trunk 2025-01-13 11:15:03 +01:00
Noah Lancien
cb8eae4a18 fix: composer update to fix CVE 2025-01-13 11:14:52 +01:00
Noah Lancien
ec29df898b Merge branch 'develop' into trunk 2025-01-13 11:09:53 +01:00
Noah Lancien
d13760ce4f ci: Added 'concurrencyPolicy: Forbid' in cron jobs 2025-01-13 11:08:27 +01:00
Noah Lancien
8358e75212 Merge branch 'develop' into trunk 2024-11-06 09:55:47 +01:00
noah.lancien
e418f01712 Merge branch 'issue-22' into 'develop'
fix: 🐛 add condition in news, product and range controller in filtered...

See merge request ldc-web/projets/agis!42
2024-11-06 08:49:47 +00:00
Nicolas Demangeat
5eb1df950a fix: 🐛 add condition in news, product and range controller in filtered method for the paginatemanually 2024-11-06 09:18:13 +01:00
Vincent BRIDIER
5d7309e21c Merge branch 'develop' into trunk 2024-10-08 09:50:20 +02:00
Vincent BRIDIER
a56e9a3e63 Merge branch 'fix-issue-78' into 'develop'
fix: 💄 center recaptcha btn

See merge request ldc-web/projets/agis!41
2024-10-08 07:46:29 +00:00
Sebastien Hattry
3b6801dc35 fix: 💄 center recaptcha btn 2024-10-08 09:40:26 +02:00
Vincent BRIDIER
46828fa2e5
Merge branch 'develop' into trunk 2024-10-07 17:28:57 +02:00
Vincent BRIDIER
84c28399ab
feat: Add customer service email for contactForm - Close #81 2024-10-07 17:28:44 +02:00
Vincent BRIDIER
1b0ec6a3d8
feat: Bump php deps for PHP8.3 2024-10-07 16:48:53 +02:00
Vincent BRIDIER
ea6bc03cbe
Merge branch 'develop' into trunk 2024-10-07 16:45:57 +02:00
Vincent BRIDIER
4338023e59 Merge branch 'issue-79' into 'develop'
Issue 79

See merge request ldc-web/projets/agis!40
2024-10-07 14:44:28 +00:00
Sebastien Hattry
7b9e6cc094 feat: change contact page according to cn 6.0.3 2024-09-10 12:20:38 +02:00
Sebastien Hattry
0cbf60cf03 chore: bump CN to 6.0.3 2024-09-10 11:59:20 +02:00
Sebastien Hattry
94156c7db0 chore: npm audit fix 2024-09-09 15:57:36 +02:00
Noah Lancien
466881fe9b Merge branch 'develop' into trunk 2024-07-31 09:42:52 +02:00
Noah Lancien
59752b3b2e Updated manifest.yaml 2024-07-31 09:42:36 +02:00
Louis Rossignol
42db4816ea Merge branch 'develop' into 'trunk'
Develop

See merge request ldc-web/projets/agis!38
2024-07-03 14:01:12 +00:00
Louis Rossignol
29108f8e28 Merge branch 'lor-migration' into 'develop'
Preparation migration

See merge request ldc-web/projets/agis!37
2024-07-03 14:00:20 +00:00
LOR
bc96ef44b0 Preparation migration 2024-07-03 15:59:18 +02:00
Jérémy Munsch
69fd4a00df
Merge branch 'develop' into trunk 2024-04-24 15:30:57 +02:00
Jérémy Munsch
b4159f0c83 Merge branch 'issue-74' into 'develop'
Fixes #74

See merge request ldc-web/projets/agis!36
2024-04-24 13:30:31 +00:00
Jérémy Munsch
eed1ce86d5
Fixes #74 2024-04-24 15:29:28 +02:00
Jérémy Munsch
37913f0206
Merge branch 'develop' into trunk 2024-04-24 14:56:02 +02:00
Jérémy Munsch
6e3f65b9ea Merge branch 'issue-76' into 'develop'
Closes #76

See merge request ldc-web/projets/agis!34
2024-04-24 12:53:20 +00:00
Jérémy Munsch
72c0652434 Merge branch '77-typo-header' into 'develop'
Issue 77

See merge request ldc-web/projets/agis!35
2024-04-24 12:51:16 +00:00
lucasschreiner
6f33b697e6 Fix FO typo into the header logo 2024-04-18 13:43:24 +02:00
Jérémy Munsch
4e596fb2b9
Closes #76 2024-03-20 13:54:37 +01:00
Jérémy Munsch
8f7a91faa9
Merge branch 'develop' into trunk 2024-03-14 15:42:56 +01:00
Jérémy Munsch
3fef79fa72
Ajout de redirections post MEP oubliés par Sylvain 2024-03-14 15:42:15 +01:00
Jérémy Munsch
45e298f2a9
Fix wrong throttles applied 2024-03-14 15:25:40 +01:00
Jérémy Munsch
8351c315cd
Merge branch 'develop' into trunk 2024-03-13 09:53:24 +01:00
Jérémy Munsch
ec39bb4f6f
Closes #72 2024-03-13 09:46:45 +01:00
Jérémy Munsch
0b8b1bff0a
#Closes 71 2024-03-13 09:30:34 +01:00
Jérémy Munsch
79b1435c92
Merge branch 'develop' into trunk 2024-03-05 11:54:11 +01:00
Jérémy Munsch
b0508da89d
Closes #66 2024-03-05 11:53:25 +01:00
Jérémy Munsch
fb94fcb1f6
Closes #67 2024-03-05 11:47:23 +01:00
Jérémy Munsch
8de072695b
Closes #69, #68 2024-03-05 11:46:26 +01:00
Jérémy Munsch
3db48686ee
Closes #70 2024-03-05 11:36:09 +01:00
Vincent BRIDIER
b0a427df59
Merge branch 'develop' into trunk 2024-02-09 13:02:08 +01:00
Vincent BRIDIER
28625f2bf2 Merge branch 'issue-32' into 'develop'
Fixes #32 Add Home video vimeo possibility playing as loop except for youtube (need playlist)

See merge request ldc-web/projets/agis!33
2024-02-09 12:01:42 +00:00
Jérémy Munsch
b658db5bf7 Fixes #32 Add Home video vimeo possibility playing as loop except for youtube (need playlist) 2024-02-09 12:01:42 +00:00
Vincent BRIDIER
95d552c429 Merge branch 'issue-63' into 'develop'
clean blades - #63

See merge request ldc-web/projets/agis!32
2024-02-08 15:00:43 +00:00
Alexis Gousseau
76b8b61288 clean blades - #63 2024-02-07 12:15:42 +01:00
Vincent BRIDIER
88beb346a8
Merge branch 'develop' into trunk 2024-02-02 11:44:15 +01:00
Vincent BRIDIER
e8871467c0 Merge branch 'products-images' into 'develop'
fix product images dimensions - #62

See merge request ldc-web/projets/agis!31
2024-02-02 10:43:43 +00:00
Alexis Gousseau
77ad125ad2 fix product images dimensions - #62 2024-02-02 09:50:06 +01:00
Vincent BRIDIER
c210e95782 Merge branch 'develop' into trunk 2024-01-30 11:50:02 +01:00
Vincent BRIDIER
dcf995bdc6 Merge branch 'issue-38' into 'develop'
bump cookies notice to v4.0.1 - #38

See merge request ldc-web/projets/agis!29
2024-01-30 10:49:14 +00:00
Alexis Gousseau
29016ad3ba bump cookies notice to v4.0.1 - #38 2024-01-30 09:46:31 +01:00
Jérémy Munsch
d3c04bebd9
Merge branch 'develop' into trunk 2024-01-29 17:09:36 +01:00
Jérémy Munsch
e1961fab93
disable executeJavascript for sitemap as no puppeteer 2024-01-29 17:08:57 +01:00
Vincent BRIDIER
54237e0f78 Merge branch 'develop' into trunk 2024-01-29 13:03:40 +01:00
Vincent BRIDIER
fa7d44d03d Merge branch 'mulitple-issues' into 'develop'
Mulitple issues

See merge request ldc-web/projets/agis!28
2024-01-29 11:58:53 +00:00
Jérémy Munsch
4d363f8fac
Fix navlink active on ranges 2024-01-29 12:36:34 +01:00
Jérémy Munsch
80a394691c
Closes #48 2024-01-29 12:33:12 +01:00
Jérémy Munsch
1648636bfa
npm update 2024-01-29 12:25:46 +01:00
Jérémy Munsch
159cbbebe7
Closes #56 Fix phone number 2024-01-29 12:13:48 +01:00
Vincent BRIDIER
a53cfc7d55 Merge branch 'issue-60-nutrionnal-values-labels' into 'develop'
Updated nutrionnal values labels

See merge request ldc-web/projets/agis!27
2024-01-29 11:11:31 +00:00
Noah Lancien
c498e298d8 Updated nutrionnal values labels 2024-01-29 11:24:12 +01:00
Vincent BRIDIER
c1eed482da Merge branch 'develop' into trunk 2024-01-29 09:52:25 +01:00
Vincent BRIDIER
e2d3d7ec28 Merge branch 'php-stan-issues-48-57' into 'develop'
Php stan issues 48 57

See merge request ldc-web/projets/agis!26
2024-01-29 08:40:19 +00:00
Noah Lancien
bed9d9dde6 phpstan 2024-01-26 16:08:12 +01:00
Noah Lancien
19f6454ea3 Merge branch 'issue-57' into php-stan-issues-48-57 2024-01-26 13:09:38 +01:00
Noah Lancien
ffdd886ddc Merge remote-tracking branch 'origin/issue-48' into php-stan-issues-48-57 2024-01-26 13:03:07 +01:00
Vincent BRIDIER
0d17174052 Merge branch 'issue-51' into 'develop'
Added a BackToTop button

See merge request ldc-web/projets/agis!25
2024-01-26 11:14:50 +00:00
Vincent BRIDIER
50a99c7344 Merge branch 'issue-58' into 'develop'
paËlla

See merge request ldc-web/projets/agis!23
2024-01-26 11:13:50 +00:00
Vincent BRIDIER
41dba737cb Merge branch 'issue-59' into 'develop'
Added youtube channel link in join-us page

See merge request ldc-web/projets/agis!22
2024-01-26 11:13:27 +00:00
Vincent BRIDIER
ae4ab562dc Merge branch 'issue-52' into 'develop'
Issue 52, 53, 54, 55, 56 - Typos + footer link

See merge request ldc-web/projets/agis!21
2024-01-26 11:12:29 +00:00
Vincent BRIDIER
a04a65c232 Merge branch 'issue-36-seo-package' into 'develop'
Added the SEO package

See merge request ldc-web/projets/agis!20
2024-01-26 11:11:44 +00:00
Vincent BRIDIER
fd987180bb Merge branch 'fix-news-show' into 'develop'
apply text-center for news subtitle in news show blade

See merge request ldc-web/projets/agis!19
2024-01-26 11:10:21 +00:00
Vincent BRIDIER
58d359155f Merge branch 'issue-44' into 'develop'
Decorative picture is now aligned with the cooking advice part in produt.show

See merge request ldc-web/projets/agis!17
2024-01-26 11:06:57 +00:00
Vincent BRIDIER
1532e3a31d Merge branch 'issue-41' into 'develop'
Ranges title in homepage are now with different colors

See merge request ldc-web/projets/agis!16
2024-01-26 11:05:41 +00:00
Vincent BRIDIER
8e9f7f8419 Merge branch 'issue-32' into 'develop'
Issue 32 Fix Trait HasPicture (Blame pas possible à cause du squash), les parametres...

See merge request ldc-web/projets/agis!15
2024-01-26 11:04:33 +00:00
Vincent BRIDIER
d5c0c06294 Merge branch 'issue-46' into 'develop'
The width of black strip is now the same as title in about-us page

See merge request ldc-web/projets/agis!14
2024-01-26 11:02:59 +00:00
Vincent BRIDIER
0333649f48 Merge branch 'issue-35' into 'develop'
Issue 35

See merge request ldc-web/projets/agis!13
2024-01-26 11:02:19 +00:00
Vincent BRIDIER
6d482c4631 Merge branch 'develop' into issue-35 2024-01-26 12:01:21 +01:00
Noah Lancien
14b0382cdb Added a BackToTop button 2024-01-23 11:53:45 +01:00
Noah Lancien
54e501cd03 In contact form, dates are now dates inpiuts instead of string 2024-01-22 09:56:19 +00:00
Noah Lancien
d162f87f3e Some wording in the contact form 2024-01-22 09:55:27 +00:00
Noah Lancien
1f1d691cbe paËlla 2024-01-22 09:01:28 +01:00
Noah Lancien
be80ca6c6a Added youtube channel link in join-us page 2024-01-22 08:59:16 +01:00
Noah Lancien
bf365eadca Fix #53, added 'convictions' link in footer 2024-01-19 09:51:43 +01:00
Noah Lancien
28a8390c41 Fix #55, wording on ranges page 2024-01-19 09:48:29 +01:00
Noah Lancien
6ee0986b48 Fix #56, renamed civilities 2024-01-19 09:47:34 +01:00
Noah Lancien
239307c1b1 Fixed footer typo 2024-01-19 09:46:41 +01:00
Noah Lancien
81089b8e12 Fixed header typo 2024-01-19 09:45:25 +01:00
Noah Lancien
30ee51d9d1 Added the SEO package 2024-01-08 10:54:20 +01:00
Nicolas Demangeat
398c762b33 apply text-center for news subtitle in news show blade 2023-12-29 15:18:09 +01:00
Jérémy Munsch
a952ea6ac6
Fixes #48 Add style to ck-content + fix all front WYSIWYG taht where missing ck-content 2023-12-22 11:46:21 +01:00
Jérémy Munsch
8318e83d0b
Update secure header with vite config form base project 2023-12-22 11:23:25 +01:00
Jérémy Munsch
25d9e1cac6
Fix commitments responsive on products.show 2023-12-22 11:05:14 +01:00
Jérémy Munsch
cffa0f34a8
Closes #37 add sitemap 2023-12-22 09:49:02 +01:00
Noah Lancien
9a8e0f8f9a Decorative picture is now aligned with the cooking advice part in produt.show 2023-12-21 16:10:31 +01:00
Noah Lancien
5854fc274b Ranges title in homepage are now with different colors 2023-12-21 15:51:00 +01:00
Jérémy Munsch
608629307f
Closes #32 Add youtube video on Homepage
+ remove Unused video Frame
+ FIX  Video Inlaid in Cookie Notice
2023-12-21 15:42:36 +01:00
Noah Lancien
b32f5161b3 The width of black strip is now the same as title in about-us page 2023-12-21 15:22:05 +01:00
Jérémy Munsch
f06e87daf5
Update HasPicture 2023-12-21 15:18:27 +01:00
Jérémy Munsch
13d998ac9c
Fix Trait HasPicture (Blame pas possible à cause du squash), les parametres ajoutés doivent être à la fin pour ne pas niquer le reste du code 2023-12-21 14:41:27 +01:00
Jérémy Munsch
fed7a112c2
Bump inputs form base project 2023-12-21 13:56:34 +01:00
Jérémy Munsch
f34bb70504
cookie notice bump to 4.0.0 2023-12-21 12:09:47 +01:00
Jérémy Munsch
53ccbb5af8
Closes #35 Change civility labels 2023-12-21 10:59:50 +01:00
Jérémy Munsch
8949c3b427
bump front stack + add favicon Fixes #40 2023-12-21 10:45:43 +01:00
Jérémy Munsch
1963b827d8
composer update 2023-12-21 09:28:30 +01:00
Vincent BRIDIER
256a8b5542 Add foreach for contactformé 2023-12-19 16:50:48 +01:00
Vincent BRIDIER
ee1622e1d8 Merge branch 'develop' into trunk 2023-12-19 16:12:19 +01:00
Vincent BRIDIER
6c63d52996 Merge branch '2.0.0' into 'develop'
2.0.0

See merge request ldc-web/projets/agis!1
2023-12-19 15:09:12 +00:00
noah.lancien
b557533b72 2.0.0 with Laravel 2023-12-19 15:09:12 +00:00
8902 changed files with 198966 additions and 619193 deletions

5
.browserslistrc Normal file
View file

@ -0,0 +1,5 @@
# Browsers that we support
last 3 version
> 0.3%
not dead # no browsers without security updates

2
.dockerignore Normal file
View file

@ -0,0 +1,2 @@
.git
*.md

21
.editorconfig Normal file
View file

@ -0,0 +1,21 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
[docker-compose.yml]
indent_size = 4
[*.vue]
indent_size = 2

60
.env.example Normal file
View file

@ -0,0 +1,60 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MAIL_MAILER=smtp
MAIL_HOST=mailpit
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
MAIL_CONTACTFORM_RECEIVER=
MAIL_CONTACTFORM_CUSTOMER_SERVICE_RECEIVER=
# Sentry
SENTRY_LARAVEL_DSN=
# MATOMO
MATOMO_SITE_ID=
# GOOGLE
# - RECAPTCHA
GOOGLE_RECAPTCHA_PUBLIC=
GOOGLE_RECAPTCHA_PRIVATE=
GOOGLE_RECAPTCHA_VERSION=
# 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=

62
.eslintrc.json Normal file
View file

@ -0,0 +1,62 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:vue/vue3-strongly-recommended",
"@vue/eslint-config-typescript"
],
"overrides": [
{
"files": ["*.ts", "*.vue"],
"rules": {
"no-undef": "off"
}
},
{
"files": ["*.vue"],
"rules": {
"indent": "off"
}
}
],
"parser": "vue-eslint-parser",
"parserOptions": {
"parser": "@typescript-eslint/parser",
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["vue", "@typescript-eslint"],
"ignorePatterns": [
"webpack.mix.js",
"**/*.php",
"**/*.svg",
"**/vendor/*.js",
"**/vendor/**/*.js",
"**/vendor/**/*.scss"
],
"rules": {
"indent": ["error", 4, { "SwitchCase": 1 }],
"linebreak-style": ["error", "unix"],
"quotes": ["error", "double"],
"semi": ["error", "always"],
"vue/script-indent": ["error", 2, { "baseIndent": 0, "switchCase": 1 }],
"vue/one-component-per-file": "off"
},
"settings": {
"import/resolver": {
"node": {
"extensions": [".js", ".vue", ".ts", ".d.ts"]
},
"alias": {
"extensions": [".vue", ".js", ".ts", ".scss", ".d.ts"],
"map": [
["~", "./resources/assets"],
["@", "./node_modules"]
]
}
}
}
}

11
.gitattributes vendored Normal file
View file

@ -0,0 +1,11 @@
* text=auto eol=lf
*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php
/.github export-ignore
CHANGELOG.md export-ignore
.styleci.yml export-ignore

58
.gitignore vendored Executable file → Normal file
View file

@ -1,20 +1,38 @@
app/cache/*
app/logs/*
app/config/parameters.yml
*.orig
*.bak
*.zip
.buildpath
.project
.settings
web/bundles/*
web/js/*
web/css/*
web/img-cache/*
web/uploads/offres/
web/uploads/images/original/*
*.php\~
/*.gitmodules
.idea/*
.DS_Store
web/.htaccess
.env
.env.backup
.env.production
.phpunit.result.cache
.stylelintcache
/.fleet
/.idea
/.phpunit.cache
/.vscode
/node_modules
/bootstrap
/public/build
/public/cache
/public/hot
/public/sitemap.xml
/public/storage
/storage/*.key
/vendor
auth.json
docker-compose.override.yml
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
.npmrc
# Ignore public favicon
/public/android-chrome-192x192.png
/public/android-chrome-512x512.png
/public/apple-touch-icon.png
/public/browserconfig.xml
/public/browserconfig.xml
/public/favicon-16x16.png
/public/favicon-32x32.png
/public/favicon.ico
/public/mstile-150x150.png
/public/safari-pinned-tab.svg
/public/site.webmanifest

24
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,24 @@
include:
- project: 'ldc-web/shared-ci'
ref: 'main'
file: 'lint/lint.yml'
- project: 'ldc-web/shared-ci'
ref: 'main'
file: 'security/security.yml'
- project: 'ldc-web/shared-ci'
ref: 'main'
file: 'build/docker-multistage.yml'
- project: 'ldc-web/shared-ci'
ref: 'main'
file: 'test/test.yml'
- project: 'ldc-web/shared-ci'
ref: 'main'
file: 'deploy/deploy.yml'
stages:
- lint
- security
- build
- test
- deploy

45
.stylelintrc.json Normal file
View file

@ -0,0 +1,45 @@
{
"extends": [
"stylelint-config-standard-scss",
"stylelint-config-sass-guidelines",
"stylelint-config-idiomatic-order"
],
"plugins": [
"stylelint-scss"
],
"files": [
"**/*.css",
"**/*.scss"
],
"ignoreFiles": [
"**/vendor/*.css",
"**/vendor/**/*.css",
"**/vendor/*.scss",
"**/vendor/**/*.scss",
"**/vendor/*.sass",
"**/vendor/**/*.sass",
"**/vendor/*.less",
"**/vendor/**/*.less"
],
"customSyntax": "postcss-scss",
"rules": {
"declaration-property-value-no-unknown": true,
"selector-max-id": null,
"color-no-invalid-hex": true,
"order/properties-alphabetical-order": null,
"max-nesting-depth": 5,
"selector-max-compound-selectors": 5,
"declaration-colon-newline-after": null,
"value-list-comma-newline-after": null,
"scss/double-slash-comment-empty-line-before": [
"always",
{
"ignore": [
"between-comments",
"stylelint-commands",
"inside-block"
]
}
]
}
}

View file

@ -1,10 +0,0 @@
language: php
php:
- 5.3.3
- 5.3
- 5.4
before_script: composer install
script: phpunit -c app

22
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,22 @@
{
"workbench.colorCustomizations": {
"activityBar.activeBackground": "#9898da",
"activityBar.background": "#9898da",
"activityBar.foreground": "#15202b",
"activityBar.inactiveForeground": "#15202b99",
"activityBarBadge.background": "#f7e8e8",
"activityBarBadge.foreground": "#15202b",
"commandCenter.border": "#e7e7e799",
"sash.hoverBorder": "#9898da",
"statusBar.background": "#7373cc",
"statusBar.foreground": "#e7e7e7",
"statusBarItem.hoverBackground": "#9898da",
"statusBarItem.remoteBackground": "#7373cc",
"statusBarItem.remoteForeground": "#e7e7e7",
"titleBar.activeBackground": "#7373cc",
"titleBar.activeForeground": "#e7e7e7",
"titleBar.inactiveBackground": "#7373cc99",
"titleBar.inactiveForeground": "#e7e7e799"
},
"peacock.remoteColor": "#7373cc"
}

45
Dockerfile Normal file
View file

@ -0,0 +1,45 @@
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 ${USER}

19
LICENSE
View file

@ -1,19 +0,0 @@
Copyright (c) 2004-2013 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

181
README.md Executable file → Normal file
View file

@ -1,176 +1,7 @@
Symfony Standard Edition
========================
# Agis
Welcome to the Symfony Standard Edition - a fully-functional Symfony2
application that you can use as the skeleton for your new applications.
This document contains information on how to download, install, and start
using Symfony. For a more detailed explanation, see the [Installation][1]
chapter of the Symfony Documentation.
1) Installing the Standard Edition
----------------------------------
When it comes to installing the Symfony Standard Edition, you have the
following options.
### Use Composer (*recommended*)
As Symfony uses [Composer][2] to manage its dependencies, the recommended way
to create a new project is to use it.
If you don't have Composer yet, download it following the instructions on
http://getcomposer.org/ or just run the following command:
curl -s https://getcomposer.org/installer | php
Then, use the `create-project` command to generate a new Symfony application:
php composer.phar create-project symfony/framework-standard-edition path/to/install 2.1.x-dev
For an exact version, replace 2.1.x-dev with the latest Symfony version (e.g. 2.1.1).
Composer will install Symfony and all its dependencies under the
`path/to/install` directory.
### Download an Archive File
To quickly test Symfony, you can also download an [archive][3] of the Standard
Edition and unpack it somewhere under your web server root directory.
If you downloaded an archive "without vendors", you also need to install all
the necessary dependencies. Download composer (see above) and run the
following command:
php composer.phar install
2) Checking your System Configuration
-------------------------------------
Before starting coding, make sure that your local system is properly
configured for Symfony.
Execute the `check.php` script from the command line:
php app/check.php
Access the `config.php` script from a browser:
http://localhost/path/to/symfony/app/web/config.php
If you get any warnings or recommendations, fix them before moving on.
3) Browsing the Demo Application
--------------------------------
Congratulations! You're now ready to use Symfony.
From the `config.php` page, click the "Bypass configuration and go to the
Welcome page" link to load up your first Symfony page.
You can also use a web-based configurator by clicking on the "Configure your
Symfony Application online" link of the `config.php` page.
To see a real-live Symfony page in action, access the following page:
web/app_dev.php/demo/hello/Fabien
4) Getting started with Symfony
-------------------------------
This distribution is meant to be the starting point for your Symfony
applications, but it also contains some sample code that you can learn from
and play with.
A great way to start learning Symfony is via the [Quick Tour][4], which will
take you through all the basic features of Symfony2.
Once you're feeling good, you can move onto reading the official
[Symfony2 book][5].
A default bundle, `AcmeDemoBundle`, shows you Symfony2 in action. After
playing with it, you can remove it by following these steps:
* delete the `src/Acme` directory;
* remove the routing entries referencing AcmeBundle in
`app/config/routing_dev.yml`;
* remove the AcmeBundle from the registered bundles in `app/AppKernel.php`;
* remove the `web/bundles/acmedemo` directory;
* remove the `security.providers`, `security.firewalls.login` and
`security.firewalls.secured_area` entries in the `security.yml` file or
tweak the security configuration to fit your needs.
What's inside?
---------------
The Symfony Standard Edition is configured with the following defaults:
* Twig is the only configured template engine;
* Doctrine ORM/DBAL is configured;
* Swiftmailer is configured;
* Annotations for everything are enabled.
It comes pre-configured with the following bundles:
* **FrameworkBundle** - The core Symfony framework bundle
* [**SensioFrameworkExtraBundle**][6] - Adds several enhancements, including
template and routing annotation capability
* [**DoctrineBundle**][7] - Adds support for the Doctrine ORM
* [**TwigBundle**][8] - Adds support for the Twig templating engine
* [**SecurityBundle**][9] - Adds security by integrating Symfony's security
component
* [**SwiftmailerBundle**][10] - Adds support for Swiftmailer, a library for
sending emails
* [**MonologBundle**][11] - Adds support for Monolog, a logging library
* [**AsseticBundle**][12] - Adds support for Assetic, an asset processing
library
* [**JMSSecurityExtraBundle**][13] - Allows security to be added via
annotations
* [**JMSDiExtraBundle**][14] - Adds more powerful dependency injection
features
* **WebProfilerBundle** (in dev/test env) - Adds profiling functionality and
the web debug toolbar
* **SensioDistributionBundle** (in dev/test env) - Adds functionality for
configuring and working with Symfony distributions
* [**SensioGeneratorBundle**][15] (in dev/test env) - Adds code generation
capabilities
* **AcmeDemoBundle** (in dev/test env) - A demo bundle with some example
code
Enjoy!
[1]: http://symfony.com/doc/2.1/book/installation.html
[2]: http://getcomposer.org/
[3]: http://symfony.com/download
[4]: http://symfony.com/doc/2.1/quick_tour/the_big_picture.html
[5]: http://symfony.com/doc/2.1/index.html
[6]: http://symfony.com/doc/2.1/bundles/SensioFrameworkExtraBundle/index.html
[7]: http://symfony.com/doc/2.1/book/doctrine.html
[8]: http://symfony.com/doc/2.1/book/templating.html
[9]: http://symfony.com/doc/2.1/book/security.html
[10]: http://symfony.com/doc/2.1/cookbook/email.html
[11]: http://symfony.com/doc/2.1/cookbook/logging/monolog.html
[12]: http://symfony.com/doc/2.1/cookbook/assetic/asset_management.html
[13]: http://jmsyst.com/bundles/JMSSecurityExtraBundle/master
[14]: http://jmsyst.com/bundles/JMSDiExtraBundle/master
[15]: http://symfony.com/doc/2.1/bundles/SensioGeneratorBundle/index.html
## CRON
Put every min in PROD :
```
php artisan schedule:run
```

View file

@ -1,262 +0,0 @@
Symfony Standard Edition Upgrade
================================
From Symfony 2.0 to Symfony 2.1
-------------------------------
### Project Dependencies
As of Symfony 2.1, project dependencies are managed by
[Composer](http://getcomposer.org/):
* The `bin/vendors` script can be removed as `composer.phar` does all the work
now (it is recommended to install it globally on your machine).
* The `deps` file need to be replaced with the `composer.json` one.
* The `composer.lock` is the equivalent of the generated `deps.lock` file and
it is automatically generated by Composer.
Download the default
[`composer.json`](https://raw.github.com/symfony/symfony-standard/2.1/composer.json)
and
[`composer.lock`](https://raw.github.com/symfony/symfony-standard/2.1/composer.lock)
files for Symfony 2.1 and put them into the main directory of your project. If
you have customized your `deps` file, move the added dependencies to the
`composer.json` file (many bundles and PHP libraries are already available as
Composer packages -- search for them on [Packagist](http://packagist.org/)).
Remove your current `vendor` directory.
Finally, run Composer:
$ composer.phar install
Note: You must complete the upgrade steps below so composer can successfully generate the autoload files.
### `app/autoload.php`
The default `autoload.php` reads as follows (it has been simplified a lot as
autoloading for libraries and bundles declared in your `composer.json` file is
automatically managed by the Composer autoloader):
<?php
use Doctrine\Common\Annotations\AnnotationRegistry;
$loader = include __DIR__.'/../vendor/autoload.php';
// intl
if (!function_exists('intl_get_error_code')) {
require_once __DIR__.'/../vendor/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs/functions.php';
$loader->add('', __DIR__.'/../vendor/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs');
}
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
return $loader;
### `app/config/config.yml`
The `framework.charset` setting must be removed. If you are not using `UTF-8`
for your application, override the `getCharset()` method in your `AppKernel`
class instead:
class AppKernel extends Kernel
{
public function getCharset()
{
return 'ISO-8859-1';
}
// ...
}
You might want to add the new `strict_requirements` parameter to
`framework.router` (it avoids fatal errors in the production environment when
a link cannot be generated):
framework:
router:
strict_requirements: "%kernel.debug%"
The `default_locale` parameter is now a setting of the main `framework`
configuration (it was under the `framework.session` in 2.0):
framework:
default_locale: "%locale%"
The `auto_start` setting under `framework.session` must be removed as it is
not used anymore (the session is now always started on-demand). If
`auto_start` was the only setting under the `framework.session` entry, don't
remove it entirely, but set its value to `~` (`~` means `null` in YAML)
instead:
framework:
session: ~
The `trust_proxy_headers` setting was added in the default configuration file
(as it should be set to `true` when you install your application behind a
reverse proxy):
framework:
trust_proxy_headers: false
An empty `bundles` entry was added to the `assetic` configuration:
assetic:
bundles: []
The default `swiftmailer` configuration now has the `spool` setting configured
to the `memory` type to defer email sending after the response is sent to the
user (recommended for better end-user performance):
swiftmailer:
spool: { type: memory }
The `jms_security_extra` configuration was moved to the `security.yml`
configuration file.
### `app/config/config_dev.yml`
An example of how to send all emails to a unique address was added:
#swiftmailer:
# delivery_address: me@example.com
### `app/config/config_test.yml`
The `storage_id` setting must be changed to `session.storage.mock_file`:
framework:
session:
storage_id: session.storage.mock_file
### `app/config/parameters.ini`
The file has been converted to a YAML file which reads as follows:
parameters:
database_driver: pdo_mysql
database_host: localhost
database_port: ~
database_name: symfony
database_user: root
database_password: ~
mailer_transport: smtp
mailer_host: localhost
mailer_user: ~
mailer_password: ~
locale: en
secret: ThisTokenIsNotSoSecretChangeIt
Note that if you convert your parameters file to YAML, you must also change
its reference in `app/config/config.yml`.
### `app/config/routing_dev.yml`
The `_assetic` entry was removed:
#_assetic:
# resource: .
# type: assetic
### `app/config/security.yml`
Under `security.access_control`, the default rule for internal routes was changed:
security:
access_control:
#- { path: ^/_internal/secure, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
Under `security.providers`, the `in_memory` example was updated to the following:
security:
providers:
in_memory:
memory:
users:
user: { password: userpass, roles: [ 'ROLE_USER' ] }
admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
### `app/AppKernel.php`
The following bundles have been added to the list of default registered bundles:
new JMS\AopBundle\JMSAopBundle(),
new JMS\DiExtraBundle\JMSDiExtraBundle($this),
You must also rename the DoctrineBundle from:
new Symfony\Bundle\DoctrineBundle\DoctrineBundle(),
to:
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
### `web/app.php`
The default `web/app.php` file now reads as follows:
<?php
use Symfony\Component\ClassLoader\ApcClassLoader;
use Symfony\Component\HttpFoundation\Request;
$loader = require_once __DIR__.'/../app/bootstrap.php.cache';
// Use APC for autoloading to improve performance
// Change 'sf2' by the prefix you want in order to prevent key conflict with another application
/*
$loader = new ApcClassLoader('sf2', $loader);
$loader->register(true);
*/
require_once __DIR__.'/../app/AppKernel.php';
//require_once __DIR__.'/../app/AppCache.php';
$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
//$kernel = new AppCache($kernel);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
### `web/app_dev.php`
The default `web/app_dev.php` file now reads as follows:
<?php
use Symfony\Component\HttpFoundation\Request;
// If you don't want to setup permissions the proper way, just uncomment the following PHP line
// read http://symfony.com/doc/current/book/installation.html#configuration-and-setup for more information
//umask(0000);
// This check prevents access to debug front controllers that are deployed by accident to production servers.
// Feel free to remove this, extend it, or make something more sophisticated.
if (isset($_SERVER['HTTP_CLIENT_IP'])
|| isset($_SERVER['HTTP_X_FORWARDED_FOR'])
|| !in_array(@$_SERVER['REMOTE_ADDR'], array(
'127.0.0.1',
'::1',
))
) {
header('HTTP/1.0 403 Forbidden');
exit('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.');
}
$loader = require_once __DIR__.'/../app/bootstrap.php.cache';
require_once __DIR__.'/../app/AppKernel.php';
$kernel = new AppKernel('dev', true);
$kernel->loadClassCache();
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

View file

@ -1 +0,0 @@
deny from all

View file

@ -1,9 +0,0 @@
<?php
require_once __DIR__.'/AppKernel.php';
use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache;
class AppCache extends HttpCache
{
}

View file

@ -1,43 +0,0 @@
<?php
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = array(
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
new Symfony\Bundle\AsseticBundle\AsseticBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new JMS\AopBundle\JMSAopBundle(),
new JMS\DiExtraBundle\JMSDiExtraBundle($this),
new JMS\SecurityExtraBundle\JMSSecurityExtraBundle(),
new FOS\UserBundle\FOSUserBundle(),
new Agis\FO\AgisBundle\AgisFOAgisBundle(),
new Agis\BO\AgisBundle\AgisBOAgisBundle(),
new Agis\BO\UserBundle\AgisBoUserBundle(),
new Agis\Commun\CommunBundle\AgisCommunCommunBundle(),
new Arson\elFinderBundle\ArsonElFinderBundle()
);
if (in_array($this->getEnvironment(), array('dev', 'test', 'local'))) {
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
}
return $bundles;
}
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
}
}

View file

@ -0,0 +1,35 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Mail;
class TestMail extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'uwil:mail:test';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Send test email to equipe.web@ldc.fr';
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
Mail::raw(sprintf('UWIL mail-test from %s %s', \config('app.name'), \config('app.url')), function ($msg) {
$msg->to('equipe.web@ldc.fr')->subject('Test Email');
});
}
}

View file

@ -0,0 +1,33 @@
<?php
namespace App\Console\Commands;
use App\Jobs\NewsStatusUpdate;
use Illuminate\Console\Command;
class UpdateNewsStatus extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'uwil:updatestatus:news';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Update news status according to the publish and unpublish dates';
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
\dispatch(new NewsStatusUpdate());
}
}

View file

@ -0,0 +1,33 @@
<?php
namespace App\Console\Commands;
use App\Jobs\SeasonalSectionStatusUpdate;
use Illuminate\Console\Command;
class UpdateSeasonalSectionsStatus extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'uwil:updatestatus:seasonalsections';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Update seasonal sections status according to the publish and unpublish dates';
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
\dispatch(new SeasonalSectionStatusUpdate());
}
}

View file

@ -0,0 +1,200 @@
<?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;
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 integer
*/
public function handle(): int
{
$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,
'published_at' => Carbon::now(),
]);
$user->saveOrFail();
$this->info('User created 👌');
return 0;
}
/**
* 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',
[RoleEnum::conceptor->label(), RoleEnum::admin->label(), RoleEnum::visitor->label()],
RoleEnum::visitor->label(),
);
if ($tmp === RoleEnum::conceptor->label()) {
$tmp = RoleEnum::conceptor;
} elseif ($tmp === RoleEnum::admin->label()) {
$tmp = RoleEnum::admin;
} elseif ($tmp === 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
}
}

35
app/Console/Kernel.php Normal file
View file

@ -0,0 +1,35 @@
<?php
namespace App\Console;
use App\Jobs\NewsStatusUpdate;
use App\Jobs\SeasonalSectionStatusUpdate;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->job(NewsStatusUpdate::class)->everyMinute();
$schedule->job(SeasonalSectionStatusUpdate::class)->everyMinute();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__ . '/Commands');
require base_path('routes/console.php');
}
}

View file

@ -0,0 +1,47 @@
<?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];
}
}

View file

@ -0,0 +1,23 @@
<?php
namespace App\Enums\Contact;
use App\Traits\Enums\BaseEnum;
enum CivilityEnum: int
{
use BaseEnum;
case man = 1;
case woman = 2;
/**
* Optionnal labels definition
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::man->name => 'Monsieur',
self::woman->name => 'Madame',
];
}

View file

@ -0,0 +1,27 @@
<?php
namespace App\Enums\Contact;
use App\Traits\Enums\BaseEnum;
enum ObjectEnum: int
{
use BaseEnum;
case customerService = 1;
case ideasSuggestions = 2;
case informationRequest = 3;
case other = 4;
/**
* Optionnal labels definition
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::customerService->name => 'Service consommateurs',
self::ideasSuggestions->name => 'Idées & suggestions',
self::informationRequest->name => 'Demande d’informations',
self::other->name => 'Divers',
];
}

625
app/Enums/Country.php Normal file
View file

@ -0,0 +1,625 @@
<?php
namespace App\Enums;
use App\Traits\Enums\BaseEnum;
enum Country: int
{
use BaseEnum;
case afghanistan = 1;
case alandIslands = 2;
case albania = 3;
case algeria = 4;
case americanSamoa = 5;
case andorra = 6;
case angola = 7;
case anguilla = 8;
case antarctica = 9;
case antiguaAndBarbuda = 10;
case argentina = 11;
case armenia = 12;
case aruba = 13;
case australia = 14;
case austria = 15;
case azerbaijan = 16;
case bahrain = 17;
case bahamas = 18;
case bangladesh = 19;
case barbados = 20;
case belarus = 21;
case belgium = 22;
case belize = 23;
case benin = 24;
case bermuda = 25;
case bhutan = 26;
case boliviaPlurinationalStateOf = 27;
case bonaireSintEustatiusAndSaba = 28;
case bosniaAndHerzegovina = 29;
case botswana = 30;
case bouvetIsland = 31;
case brazil = 32;
case britishIndianOceanTerritory = 33;
case bruneiDarussalam = 34;
case bulgaria = 35;
case burkinaFaso = 36;
case burundi = 37;
case cambodia = 38;
case cameroon = 39;
case canada = 40;
case capeVerde = 41;
case caymanIslands = 42;
case centralAfricanRepublic = 43;
case chad = 44;
case chile = 45;
case china = 46;
case christmasIsland = 47;
case cocosKeelingIslands = 48;
case colombia = 49;
case comoros = 50;
case congo = 51;
case congoTheDemocraticRepublicOfThe = 52;
case cookIslands = 53;
case costaRica = 54;
case coteDivoire = 55;
case croatia = 56;
case cuba = 57;
case curacao = 58;
case cyprus = 59;
case czechRepublic = 60;
case denmark = 61;
case djibouti = 62;
case dominica = 63;
case dominicanRepublic = 64;
case ecuador = 65;
case egypt = 66;
case elSalvador = 67;
case equatorialGuinea = 68;
case eritrea = 69;
case estonia = 70;
case ethiopia = 71;
case falklandIslandsMalvinas = 72;
case faroeIslands = 73;
case fiji = 74;
case finland = 75;
case france = 76;
case frenchGuiana = 77;
case frenchPolynesia = 78;
case frenchSouthernTerritories = 79;
case gabon = 80;
case gambia = 81;
case georgia = 82;
case germany = 83;
case ghana = 84;
case gibraltar = 85;
case greece = 86;
case greenland = 87;
case grenada = 88;
case guadeloupe = 89;
case guam = 90;
case guatemala = 91;
case guernsey = 92;
case guinea = 93;
case guineaBissau = 94;
case guyana = 95;
case haiti = 96;
case heardIslandAndMcdonaldIslands = 97;
case holySeeVaticanCityState = 98;
case honduras = 99;
case hongKong = 100;
case hungary = 101;
case iceland = 102;
case india = 103;
case indonesia = 104;
case iranIslamicRepublicOf = 105;
case iraq = 106;
case ireland = 107;
case isleOfMan = 108;
case israel = 109;
case italy = 110;
case jamaica = 111;
case japan = 112;
case jersey = 113;
case jordan = 114;
case kazakhstan = 115;
case kenya = 116;
case kiribati = 117;
case koreaDemocraticPeoplesRepublicOf = 118;
case koreaRepublicOf = 119;
case kuwait = 120;
case kyrgyzstan = 121;
case laoPeoplesDemocraticRepublic = 122;
case latvia = 123;
case lebanon = 124;
case lesotho = 125;
case liberia = 126;
case libya = 127;
case liechtenstein = 128;
case lithuania = 129;
case luxembourg = 130;
case macao = 131;
case macedoniaTheFormerYugoslavRepublicOf = 132;
case madagascar = 133;
case malawi = 134;
case malaysia = 135;
case maldives = 136;
case mali = 137;
case malta = 138;
case marshallIslands = 139;
case martinique = 140;
case mauritania = 141;
case mauritius = 142;
case mayotte = 143;
case mexico = 144;
case micronesiaFederatedStatesOf = 145;
case moldovaRepublicOf = 146;
case monaco = 147;
case mongolia = 148;
case montenegro = 149;
case montserrat = 150;
case morocco = 151;
case mozambique = 152;
case myanmar = 153;
case namibia = 154;
case nauru = 155;
case nepal = 156;
case netherlands = 157;
case newCaledonia = 158;
case newZealand = 159;
case nicaragua = 160;
case niger = 161;
case nigeria = 162;
case niue = 163;
case norfolkIsland = 164;
case northernMarianaIslands = 165;
case norway = 166;
case oman = 167;
case pakistan = 168;
case palau = 169;
case palestineStateOf = 170;
case panama = 171;
case papuaNewGuinea = 172;
case paraguay = 173;
case peru = 174;
case philippines = 175;
case pitcairn = 176;
case poland = 177;
case portugal = 178;
case puertoRico = 179;
case qatar = 180;
case reunion = 181;
case romania = 182;
case russianFederation = 183;
case rwanda = 184;
case saintBarthelemy = 185;
case saintHelenaAscensionAndTristanDaCunha = 186;
case saintKittsAndNevis = 187;
case saintLucia = 188;
case saintMartinFrenchPart = 189;
case saintPierreAndMiquelon = 190;
case saintVincentAndTheGrenadines = 191;
case samoa = 192;
case sanMarino = 193;
case saoTomeAndPrincipe = 194;
case saudiArabia = 195;
case senegal = 196;
case serbia = 197;
case seychelles = 198;
case sierraLeone = 199;
case singapore = 200;
case sintMaartenDutchPart = 201;
case slovakia = 202;
case slovenia = 203;
case solomonIslands = 204;
case somalia = 205;
case southAfrica = 206;
case southGeorgiaAndTheSouthSandwichIslands = 207;
case southSudan = 208;
case spain = 209;
case sriLanka = 210;
case sudan = 211;
case suriname = 212;
case svalbardAndJanMayen = 213;
case swaziland = 214;
case sweden = 215;
case switzerland = 216;
case syrianArabRepublic = 217;
case taiwanProvinceOfChina = 218;
case tajikistan = 219;
case tanzaniaUnitedRepublicOf = 220;
case thailand = 221;
case timorLeste = 222;
case togo = 223;
case tokelau = 224;
case tonga = 225;
case trinidadAndTobago = 226;
case tunisia = 227;
case turkey = 228;
case turkmenistan = 229;
case turksAndCaicosIslands = 230;
case tuvalu = 231;
case uganda = 232;
case ukraine = 233;
case unitedArabEmirates = 234;
case unitedKingdom = 235;
case unitedStates = 236;
case unitedStatesMinorOutlyingIslands = 237;
case uruguay = 238;
case uzbekistan = 239;
case vanuatu = 240;
case venezuelaBolivarianRepublicOf = 241;
case vietNam = 242;
case virginIslandsBritish = 243;
case virginIslandsUs = 244;
case wallisAndFutuna = 245;
case westernSahara = 246;
case yemen = 247;
case zambia = 248;
case zimbabwe = 249;
/**
* Optionnal labels definition
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::afghanistan->name => 'Afghanistan',
self::alandIslands->name => 'Åland Islands',
self::albania->name => 'Albania',
self::algeria->name => 'Algeria',
self::americanSamoa->name => 'American Samoa',
self::andorra->name => 'Andorra',
self::angola->name => 'Angola',
self::anguilla->name => 'Anguilla',
self::antarctica->name => 'Antarctica',
self::antiguaAndBarbuda->name => 'Antigua and Barbuda',
self::argentina->name => 'Argentina',
self::armenia->name => 'Armenia',
self::aruba->name => 'Aruba',
self::australia->name => 'Australia',
self::austria->name => 'Austria',
self::azerbaijan->name => 'Azerbaijan',
self::bahrain->name => 'Bahrain',
self::bahamas->name => 'Bahamas',
self::bangladesh->name => 'Bangladesh',
self::barbados->name => 'Barbados',
self::belarus->name => 'Belarus',
self::belgium->name => 'Belgium',
self::belize->name => 'Belize',
self::benin->name => 'Benin',
self::bermuda->name => 'Bermuda',
self::bhutan->name => 'Bhutan',
self::boliviaPlurinationalStateOf->name => 'Bolivia, Plurinational State of',
self::bonaireSintEustatiusAndSaba->name => 'Bonaire, Sint Eustatius and Saba',
self::bosniaAndHerzegovina->name => 'Bosnia and Herzegovina',
self::botswana->name => 'Botswana',
self::bouvetIsland->name => 'Bouvet Island',
self::brazil->name => 'Brazil',
self::britishIndianOceanTerritory->name => 'British Indian Ocean Territory',
self::bruneiDarussalam->name => 'Brunei Darussalam',
self::bulgaria->name => 'Bulgaria',
self::burkinaFaso->name => 'Burkina Faso',
self::burundi->name => 'Burundi',
self::cambodia->name => 'Cambodia',
self::cameroon->name => 'Cameroon',
self::canada->name => 'Canada',
self::capeVerde->name => 'Cape Verde',
self::caymanIslands->name => 'Cayman Islands',
self::centralAfricanRepublic->name => 'Central African Republic',
self::chad->name => 'Chad',
self::chile->name => 'Chile',
self::china->name => 'China',
self::christmasIsland->name => 'Christmas Island',
self::cocosKeelingIslands->name => 'Cocos (Keeling) Islands',
self::colombia->name => 'Colombia',
self::comoros->name => 'Comoros',
self::congo->name => 'Congo',
self::congoTheDemocraticRepublicOfThe->name => 'Congo, the Democratic Republic of the',
self::cookIslands->name => 'Cook Islands',
self::costaRica->name => 'Costa Rica',
self::coteDivoire->name => 'Côte d\'Ivoire',
self::croatia->name => 'Croatia',
self::cuba->name => 'Cuba',
self::curacao->name => 'Curaçao',
self::cyprus->name => 'Cyprus',
self::czechRepublic->name => 'Czech Republic',
self::denmark->name => 'Denmark',
self::djibouti->name => 'Djibouti',
self::dominica->name => 'Dominica',
self::dominicanRepublic->name => 'Dominican Republic',
self::ecuador->name => 'Ecuador',
self::egypt->name => 'Egypt',
self::elSalvador->name => 'El Salvador',
self::equatorialGuinea->name => 'Equatorial Guinea',
self::eritrea->name => 'Eritrea',
self::estonia->name => 'Estonia',
self::ethiopia->name => 'Ethiopia',
self::falklandIslandsMalvinas->name => 'Falkland Islands (Malvinas)',
self::faroeIslands->name => 'Faroe Islands',
self::fiji->name => 'Fiji',
self::finland->name => 'Finland',
self::france->name => 'France',
self::frenchGuiana->name => 'French Guiana',
self::frenchPolynesia->name => 'French Polynesia',
self::frenchSouthernTerritories->name => 'French Southern Territories',
self::gabon->name => 'Gabon',
self::gambia->name => 'Gambia',
self::georgia->name => 'Georgia',
self::germany->name => 'Germany',
self::ghana->name => 'Ghana',
self::gibraltar->name => 'Gibraltar',
self::greece->name => 'Greece',
self::greenland->name => 'Greenland',
self::grenada->name => 'Grenada',
self::guadeloupe->name => 'Guadeloupe',
self::guam->name => 'Guam',
self::guatemala->name => 'Guatemala',
self::guernsey->name => 'Guernsey',
self::guinea->name => 'Guinea',
self::guineaBissau->name => 'GuineaBissau',
self::guyana->name => 'Guyana',
self::haiti->name => 'Haiti',
self::heardIslandAndMcdonaldIslands->name => 'Heard Island and McDonald Islands',
self::holySeeVaticanCityState->name => 'Holy See (Vatican City State)',
self::honduras->name => 'Honduras',
self::hongKong->name => 'Hong Kong',
self::hungary->name => 'Hungary',
self::iceland->name => 'Iceland',
self::india->name => 'India',
self::indonesia->name => 'Indonesia',
self::iranIslamicRepublicOf->name => 'Iran, Islamic Republic of',
self::iraq->name => 'Iraq',
self::ireland->name => 'Ireland',
self::isleOfMan->name => 'Isle of Man',
self::israel->name => 'Israel',
self::italy->name => 'Italy',
self::jamaica->name => 'Jamaica',
self::japan->name => 'Japan',
self::jersey->name => 'Jersey',
self::jordan->name => 'Jordan',
self::kazakhstan->name => 'Kazakhstan',
self::kenya->name => 'Kenya',
self::kiribati->name => 'Kiribati',
self::koreaDemocraticPeoplesRepublicOf->name => 'Korea, Democratic People\'s Republic of',
self::koreaRepublicOf->name => 'Korea, Republic of',
self::kuwait->name => 'Kuwait',
self::kyrgyzstan->name => 'Kyrgyzstan',
self::laoPeoplesDemocraticRepublic->name => 'Lao People\'s Democratic Republic',
self::latvia->name => 'Latvia',
self::lebanon->name => 'Lebanon',
self::lesotho->name => 'Lesotho',
self::liberia->name => 'Liberia',
self::libya->name => 'Libya',
self::liechtenstein->name => 'Liechtenstein',
self::lithuania->name => 'Lithuania',
self::luxembourg->name => 'Luxembourg',
self::macao->name => 'Macao',
self::macedoniaTheFormerYugoslavRepublicOf->name => 'Macedonia, the Former Yugoslav Republic of',
self::madagascar->name => 'Madagascar',
self::malawi->name => 'Malawi',
self::malaysia->name => 'Malaysia',
self::maldives->name => 'Maldives',
self::mali->name => 'Mali',
self::malta->name => 'Malta',
self::marshallIslands->name => 'Marshall Islands',
self::martinique->name => 'Martinique',
self::mauritania->name => 'Mauritania',
self::mauritius->name => 'Mauritius',
self::mayotte->name => 'Mayotte',
self::mexico->name => 'Mexico',
self::micronesiaFederatedStatesOf->name => 'Micronesia, Federated States of',
self::moldovaRepublicOf->name => 'Moldova, Republic of',
self::monaco->name => 'Monaco',
self::mongolia->name => 'Mongolia',
self::montenegro->name => 'Montenegro',
self::montserrat->name => 'Montserrat',
self::morocco->name => 'Morocco',
self::mozambique->name => 'Mozambique',
self::myanmar->name => 'Myanmar',
self::namibia->name => 'Namibia',
self::nauru->name => 'Nauru',
self::nepal->name => 'Nepal',
self::netherlands->name => 'Netherlands',
self::newCaledonia->name => 'New Caledonia',
self::newZealand->name => 'New Zealand',
self::nicaragua->name => 'Nicaragua',
self::niger->name => 'Niger',
self::nigeria->name => 'Nigeria',
self::niue->name => 'Niue',
self::norfolkIsland->name => 'Norfolk Island',
self::northernMarianaIslands->name => 'Northern Mariana Islands',
self::norway->name => 'Norway',
self::oman->name => 'Oman',
self::pakistan->name => 'Pakistan',
self::palau->name => 'Palau',
self::palestineStateOf->name => 'Palestine, State of',
self::panama->name => 'Panama',
self::papuaNewGuinea->name => 'Papua New Guinea',
self::paraguay->name => 'Paraguay',
self::peru->name => 'Peru',
self::philippines->name => 'Philippines',
self::pitcairn->name => 'Pitcairn',
self::poland->name => 'Poland',
self::portugal->name => 'Portugal',
self::puertoRico->name => 'Puerto Rico',
self::qatar->name => 'Qatar',
self::reunion->name => 'Réunion',
self::romania->name => 'Romania',
self::russianFederation->name => 'Russian Federation',
self::rwanda->name => 'Rwanda',
self::saintBarthelemy->name => 'Saint Barthélemy',
self::saintHelenaAscensionAndTristanDaCunha->name => 'Saint Helena, Ascension and Tristan da Cunha',
self::saintKittsAndNevis->name => 'Saint Kitts and Nevis',
self::saintLucia->name => 'Saint Lucia',
self::saintMartinFrenchPart->name => 'Saint Martin (French part)',
self::saintPierreAndMiquelon->name => 'Saint Pierre and Miquelon',
self::saintVincentAndTheGrenadines->name => 'Saint Vincent and the Grenadines',
self::samoa->name => 'Samoa',
self::sanMarino->name => 'San Marino',
self::saoTomeAndPrincipe->name => 'Sao Tome and Principe',
self::saudiArabia->name => 'Saudi Arabia',
self::senegal->name => 'Senegal',
self::serbia->name => 'Serbia',
self::seychelles->name => 'Seychelles',
self::sierraLeone->name => 'Sierra Leone',
self::singapore->name => 'Singapore',
self::sintMaartenDutchPart->name => 'Sint Maarten (Dutch part)',
self::slovakia->name => 'Slovakia',
self::slovenia->name => 'Slovenia',
self::solomonIslands->name => 'Solomon Islands',
self::somalia->name => 'Somalia',
self::southAfrica->name => 'South Africa',
self::southGeorgiaAndTheSouthSandwichIslands->name => 'South Georgia and the South Sandwich Islands',
self::southSudan->name => 'South Sudan',
self::spain->name => 'Spain',
self::sriLanka->name => 'Sri Lanka',
self::sudan->name => 'Sudan',
self::suriname->name => 'Suriname',
self::svalbardAndJanMayen->name => 'Svalbard and Jan Mayen',
self::swaziland->name => 'Swaziland',
self::sweden->name => 'Sweden',
self::switzerland->name => 'Switzerland',
self::syrianArabRepublic->name => 'Syrian Arab Republic',
self::taiwanProvinceOfChina->name => 'Taiwan, Province of China',
self::tajikistan->name => 'Tajikistan',
self::tanzaniaUnitedRepublicOf->name => 'Tanzania, United Republic of',
self::thailand->name => 'Thailand',
self::timorLeste->name => 'TimorLeste',
self::togo->name => 'Togo',
self::tokelau->name => 'Tokelau',
self::tonga->name => 'Tonga',
self::trinidadAndTobago->name => 'Trinidad and Tobago',
self::tunisia->name => 'Tunisia',
self::turkey->name => 'Turkey',
self::turkmenistan->name => 'Turkmenistan',
self::turksAndCaicosIslands->name => 'Turks and Caicos Islands',
self::tuvalu->name => 'Tuvalu',
self::uganda->name => 'Uganda',
self::ukraine->name => 'Ukraine',
self::unitedArabEmirates->name => 'United Arab Emirates',
self::unitedKingdom->name => 'United Kingdom',
self::unitedStates->name => 'United States',
self::unitedStatesMinorOutlyingIslands->name => 'United States Minor Outlying Islands',
self::uruguay->name => 'Uruguay',
self::uzbekistan->name => 'Uzbekistan',
self::vanuatu->name => 'Vanuatu',
self::venezuelaBolivarianRepublicOf->name => 'Venezuela, Bolivarian Republic of',
self::vietNam->name => 'Viet Nam',
self::virginIslandsBritish->name => 'Virgin Islands, British',
self::virginIslandsUs->name => 'Virgin Islands, U.S.',
self::wallisAndFutuna->name => 'Wallis and Futuna',
self::westernSahara->name => 'Western Sahara',
self::yemen->name => 'Yemen',
self::zambia->name => 'Zambia',
self::zimbabwe->name => 'Zimbabwe',
];
/**
* Get Valid Shipping Countries
*
* @return array
*/
public static function validShippingCountries(): array
{
return [
self::france,
/**
* // * DROM COM .
// self::guadeloupe,
// self::martinique,
// self::frenchGuiana,
// self::reunion,
// self::saintPierreAndMiquelon,
// self::mayotte,
// self::saintBarthelemy,
// self::saintMartinFrenchPart,
// self::wallisAndFutuna,
// self::frenchPolynesia,
// self::newCaledonia
*/
];
}
/**
* Get Valid Shipping Countries
*
* @return array
*/
public static function validBillingCountries(): array
{
return [
self::france,
// * DROM COM.
self::guadeloupe,
self::martinique,
self::frenchGuiana,
self::reunion,
self::saintPierreAndMiquelon,
self::mayotte,
self::saintBarthelemy,
self::saintMartinFrenchPart,
self::wallisAndFutuna,
self::frenchPolynesia,
self::newCaledonia
];
}
/**
* Get Alpha 2 ISO code of valid shipping countries
*
* @return array
*/
public static function getValidShippingCountriesIsoAplha2Codes(): array
{
return ['FR'];
}
/**
* Get Alpha 2 ISO code of valid billing countries
*
* @return array
*/
public static function getValidBillingCountriesIsoAplha2Codes(): array
{
return \array_values(self::ISOCODES);
}
/**
* Custom added ISOCODES definition
*/
private const ISOCODES = [
self::france->name => 'FR',
self::guadeloupe->name => 'GP',
self::martinique->name => 'MQ',
self::frenchGuiana->name => 'GF',
self::reunion->name => 'RE',
self::saintPierreAndMiquelon->name => 'PM',
self::mayotte->name => 'YT',
self::saintBarthelemy->name => 'BL',
self::saintMartinFrenchPart->name => 'MF',
self::wallisAndFutuna->name => 'WF',
self::frenchPolynesia->name => 'PF',
self::newCaledonia->name => 'NC',
];
/**
* Get ISOCODE
*
* @return string
*/
public function iso(): string
{
return self::ISOCODES[$this->name];
}
/**
* Get enum ISOCODES
*
* @return array<string>
*/
public static function toIsoCodes(): array
{
return self::ISOCODES;
}
}

View file

@ -0,0 +1,27 @@
<?php
namespace App\Enums;
use App\Traits\Enums\BaseEnum;
enum DesiredLocation: int
{
use BaseEnum;
case avignon = 1;
case herbignac = 2;
case tarare = 3;
case none = 4;
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::avignon->name => 'Avignon',
self::herbignac->name => 'Herbignac',
self::tarare->name => 'Tarare',
self::none->name => 'Indifférent',
];
}

30
app/Enums/InputType.php Normal file
View file

@ -0,0 +1,30 @@
<?php
namespace App\Enums;
use App\Traits\Enums\BaseEnum;
enum InputType: int
{
use BaseEnum;
case boolean = 1;
case dropdownArray = 2;
case email = 3;
case image = 4;
case imageArray = 5;
case labelArray = 6;
case miniblocArray = 7;
case number = 8;
case selectEnum = 9;
case password = 10;
case string = 11;
case text = 12;
case url = 13;
/** Vimeo only */
case videoVimeo = 14;
/** Youtube only */
case videoYoutube = 15;
/** Youtube or Vimeo. */
case video = 16;
}

View file

@ -0,0 +1,29 @@
<?php
namespace App\Enums\News;
use App\Traits\Enums\BaseEnum;
enum CategoryEnum: int
{
use BaseEnum;
case enterprise = 1;
case convictions = 2;
case recipes = 3;
case jobs = 4;
case communication = 5;
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::enterprise->name => 'La vie d\'Entreprise',
self::convictions->name => 'Nos convictions',
self::recipes->name => 'Nos recettes',
self::jobs->name => 'Nos métiers',
self::communication->name => 'Communication',
];
}

View 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;
}

View file

@ -0,0 +1,72 @@
<?php
namespace App\Enums\Products;
use App\Traits\Enums\BaseEnum;
enum CookingModeEnum: int
{
use BaseEnum;
case microwave = 1;
case furnace = 2;
case waterbath = 3;
case pan = 4;
case fresh = 5;
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::microwave->name => 'Micro-ondes',
self::furnace->name => 'Four traditionnel',
self::waterbath->name => 'Bain-marie',
self::pan->name => 'Poêle',
self::fresh->name => 'Se consomme frais',
];
/**
* Pictures paths.
*/
private const PICTURES = [
self::microwave->name => 'resources/assets/images/pictos/micro-wave.png',
self::furnace->name => 'resources/assets/images/pictos/furnace.png',
self::waterbath->name => 'resources/assets/images/pictos/water-bath.png',
self::pan->name => 'resources/assets/images/pictos/pan.png',
self::fresh->name => 'resources/assets/images/pictos/fresh.png',
];
/**
* Get picture path
*
* @return string
*/
public function picture(): string
{
return self::PICTURES[$this->name];
}
/**
* Alt attributes for pictures.
*/
private const ALTS = [
self::microwave->name => 'Pictogramme d\'un micro-ondes',
self::furnace->name => 'Pictogramme d\'un four traditionnel',
self::waterbath->name => 'Pictogramme d\'un bain-marie',
self::pan->name => 'Pictogramme d\'une poêle',
self::fresh->name => 'Pictogramme d\'une goutte d\'eau',
];
/**
* Get picture alt attribute
*
* @return string
*/
public function alt(): string
{
return self::ALTS[$this->name];
}
}

View file

@ -0,0 +1,44 @@
<?php
namespace App\Enums\SeasonalSections;
use App\Traits\Enums\BaseEnum;
enum BackgroundEnum: int
{
use BaseEnum;
case candlemas = 1;
case chinesenewyear = 2;
case endofyear = 3;
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::candlemas->name => 'Chandeleur',
self::chinesenewyear->name => 'Nouvel an chinois',
self::endofyear->name => 'Fin d\'année',
];
/**
* Custom added classes definition
*/
private const BOOTSTRAPCLASS = [
self::candlemas->name => 'seasonal-sections-candlemas',
self::chinesenewyear->name => 'seasonal-sections-chinesenewyear',
self::endofyear->name => 'seasonal-sections-endofyear',
];
/**
* Get Class
*
* @return string
*/
public function bootstrapClass(): string
{
return self::BOOTSTRAPCLASS[$this->name];
}
}

View file

@ -0,0 +1,39 @@
<?php
namespace App\Enums;
use App\Traits\Enums\BaseEnum;
enum StaticPageType: int
{
use BaseEnum;
case contact = 1;
case legals = 2;
case confidentiality = 3;
case home = 4;
case conviction = 5;
case explorer = 6;
case joinus = 7;
case ranges = 8;
case aboutus = 9;
case news = 10;
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::contact->name => 'Contact',
self::legals->name => 'Mentions légales et CGU',
self::confidentiality->name => 'Confidentialité',
self::home->name => 'Accueil',
self::conviction->name => 'Nos Convictions',
self::explorer->name => 'Explorateur & Gastronome',
self::joinus->name => 'Rejoignez-nous',
self::ranges->name => 'Nos Gammes de Produits',
self::aboutus->name => 'Nous Connaître',
self::news->name => 'Actualités',
];
}

View file

@ -0,0 +1,23 @@
<?php
namespace App\Enums\Theme;
use App\Traits\Enums\BaseEnum;
enum BootstrapThemeEnum: int
{
use BaseEnum;
case light = 1;
case dark = 2;
/**
* Optionnal labels definition
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::light->name => 'Light',
self::dark->name => 'Dark',
];
}

View 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 = 3;
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::conceptor->name => 'Concepteur',
self::admin->name => 'Administrateur',
self::visitor->name => 'Visiteur',
];
}

View file

@ -0,0 +1,48 @@
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* A list of exception types with their corresponding custom log levels.
*
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
*/
protected $levels = [];
/**
* A list of the exception types that are not reported.
*
* @var array<int, class-string<\Throwable>>
*/
protected $dontReport = [];
/**
* A list of the inputs that are never flashed to the session on validation exceptions.
*
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->reportable(function (Throwable $e) {
if (app()->bound('sentry')) {
app('sentry')->captureException($e);
}
});
}
}

View 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 ActivityLogsController 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,
]);
}
}

View file

@ -0,0 +1,72 @@
<?php
namespace App\Http\Controllers\Bo\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\Auth\StatefulGuard;
use Illuminate\Contracts\View\View;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
use AuthenticatesUsers;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest:backend')->except('logout');
}
/**
* Get the guard to be used during authentication.
*
* @return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard(): StatefulGuard
{
return Auth::guard('backend');
}
/**
* Show the application's login form.
*
* @return \Illuminate\Contracts\View\View
*/
public function showLoginForm(): View
{
return view('bo.auth.login');
}
/**
* Where to redirect users after login.
*
* @return string
*/
protected function redirectTo(): string
{
return response()->redirectToIntended()->getTargetUrl();
}
/**
* Attempt to log the user into the application.
*
* @param \Illuminate\Http\Request $request
* @return boolean
*/
protected function attemptLogin(Request $request)
{
$credentials = $this->credentials($request);
// * Attempt login only using published users.
$credentials['published'] = true;
return $this->guard()->attempt(
$credentials,
$request->boolean('remember')
);
}
}

View file

@ -0,0 +1,33 @@
<?php
namespace App\Http\Controllers\Bo\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\Auth\StatefulGuard;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Support\Facades\Auth;
class ResetPasswordController extends Controller
{
use ResetsPasswords;
/**
* Get the guard to be used during authentication.
*
* @return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard(): StatefulGuard
{
return Auth::guard('backend');
}
/**
* Where to redirect users after login.
*
* @return string
*/
protected function redirectTo(): string
{
return \route('bo.login');
}
}

View file

@ -0,0 +1,166 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Commitments\StoreCommitmentRequest;
use App\Http\Requests\Bo\Commitments\UpdateCommitmentRequest;
use App\Models\Commitment;
use App\Traits\Controllers\ChangesModelOrder;
use App\Traits\Controllers\UpdateModelPublished;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class CommitmentController extends Controller
{
use UpdateModelPublished;
use ChangesModelOrder;
/**
* Create the controller instance.
*/
public function __construct()
{
$this->authorizeResource(Commitment::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 $commitmentModels */
$commitmentModels = Commitment::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$commitmentModels,
$search,
null,
'title',
);
}
$searchFields = \implode(', ', [
Str::ucfirst(trans('validation.attributes.title'))
]);
/** Sort columns with a query */
$this->sortQuery($commitmentModels);
/** Custom pagination */
$commitmentModels = $this->paginate($commitmentModels);
return view('bo.pages.commitments.index', compact('commitmentModels', 'search', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Commitment $commitment
* @return \Illuminate\Contracts\View\View
*/
public function create(Commitment $commitment): \Illuminate\Contracts\View\View
{
return view('bo.pages.commitments.create', ['commitmentModel' => $commitment]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Commitments\StoreCommitmentRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreCommitmentRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$commitment = new Commitment();
if ($commitment->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.commitments.edit', $commitment)
->with('success', __('crud.messages.has_been_created', [
'model' => Str::ucfirst(__('models.classes.commitment'))
]));
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_created', [
'model' => Str::ucfirst(__('models.classes.commitment'))
]));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Commitment $commitment
* @return \Illuminate\Contracts\View\View
*/
public function edit(Commitment $commitment): \Illuminate\Contracts\View\View
{
return view('bo.pages.commitments.edit', ['commitmentModel' => $commitment]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Commitments\UpdateCommitmentRequest $request
* @param \App\Models\Commitment $commitment
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateCommitmentRequest $request, Commitment $commitment): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $commitment) {
if ($commitment->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.commitments.edit', $commitment)
->with('success', __('crud.messages.has_been_updated', [
'model' => Str::ucfirst(__('models.classes.commitment'))
]));
}
return redirect()->route('bo.commitments.edit', $commitment)
->with('error', __('crud.messages.cannot_be_updated', [
'model' => Str::ucfirst(__('models.classes.commitment'))
]));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Commitment $commitment
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Commitment $commitment): \Illuminate\Http\RedirectResponse
{
$commitment->products()->detach();
if ($commitment->explorerpage()->count() === 0) {
if ($commitment->deleteOrFail()) {
return redirect()->route('bo.commitments.index')
->with('success', __('crud.messages.has_been_deleted', [
'model' => Str::ucfirst(__('models.classes.commitment'))
]));
}
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_deleted', [
'model' => Str::ucfirst(__('models.classes.commitment'))
]));
}
/**
* Duplicate the specified resource.
*
* @param \App\Models\Commitment $commitment
* @return \Illuminate\Contracts\View\View
*/
public function duplicate(Commitment $commitment): \Illuminate\Contracts\View\View
{
return $this->create($commitment->replicate());
}
}

View file

@ -0,0 +1,54 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Convictionpages\UpdateConvictionpageRequest;
use App\Models\Convictionpage;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class ConvictionpageController extends Controller
{
/**
* Show the form for editing the specified resource.
*
* @return \Illuminate\Contracts\View\View
*/
public function edit(): \Illuminate\Contracts\View\View
{
$this->authorize('update', \App\Models\Convictionpage::class);
/** @var \App\Models\Convictionpage $convictionpageModel */
$convictionpageModel = Convictionpage::query()->firstOrFail();
return view('bo.pages.convictionpages.edit', compact('convictionpageModel'));
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Convictionpages\UpdateConvictionpageRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateConvictionpageRequest $request): \Illuminate\Http\RedirectResponse
{
$this->authorize('update', \App\Models\Convictionpage::class);
return DB::transaction(function () use ($request) {
/** @var \App\Models\Convictionpage $convictionpageModel */
$convictionpageModel = Convictionpage::query()->firstOrFail();
if (($convictionpageModel->fill($request->validated()))->saveOrFail()) {
return redirect()->route('bo.convictionpages.edit')
->with('success', __('crud.messages.has_been_updated', [
'model' => Str::ucfirst(__('models.classes.convictionpage'))
]));
}
return redirect()->route('bo.convictionpages.edit')
->with('error', __('crud.messages.cannot_be_updated', [
'model' => Str::ucfirst(__('models.classes.convictionpage'))
]));
});
}
}

View file

@ -0,0 +1,19 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\View\View;
class DashboardController extends Controller
{
/**
* Dashboard Page
*
* @return \Illuminate\Contracts\View\View
*/
public function index(): View
{
return view('bo.pages.dashboard');
}
}

View file

@ -0,0 +1,61 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Explorerpage\UpdateExplorerpageRequest;
use App\Models\Commitment;
use App\Models\Explorerpage;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class ExplorerpageController extends Controller
{
/**
* Show the form for editing the specified resource.
*
* @return \Illuminate\Contracts\View\View
*/
public function edit(): \Illuminate\Contracts\View\View
{
$this->authorize('update', \App\Models\Explorerpage::class);
/** @var \App\Models\Explorerpage $explorerpageModel */
$explorerpageModel = Explorerpage::query()->firstOrFail();
/** @var \Illuminate\Database\Eloquent\Collection<array-key, \App\Models\Commitment> */
$commitmentModels = Commitment::all();
return view('bo.pages.explorerpages.edit', compact('explorerpageModel', 'commitmentModels'));
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Explorerpage\UpdateExplorerpageRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateExplorerpageRequest $request): \Illuminate\Http\RedirectResponse
{
$this->authorize('update', \App\Models\Explorerpage::class);
return DB::transaction(function () use ($request) {
/** @var \App\Models\Explorerpage $explorerpageModel */
$explorerpageModel = Explorerpage::query()->firstOrFail();
$explorerpageModel->fill($request->safe()->except('commitments'));
$explorerpageModel->commitments()->sync(\collect($request->validated('commitments'))->pluck('id'));
if ($explorerpageModel->saveOrFail()) {
return redirect()->route('bo.explorerpages.edit')
->with('success', __('crud.messages.has_been_updated', [
'model' => Str::ucfirst(__('models.classes.explorerpage'))
]));
}
return redirect()->route('bo.explorerpages.edit')
->with('error', __('crud.messages.cannot_be_updated', [
'model' => Str::ucfirst(__('models.classes.explorerpage'))
]));
});
}
}

View file

@ -0,0 +1,54 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Homepage\UpdateHomepageRequest;
use App\Models\Homepage;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class HomepageController extends Controller
{
/**
* Show the form for editing the specified resource.
*
* @return \Illuminate\Contracts\View\View
*/
public function edit(): \Illuminate\Contracts\View\View
{
$this->authorize('update', \App\Models\Homepage::class);
/** @var \App\Models\Homepage $homepageModel */
$homepageModel = Homepage::query()->firstOrFail();
return view('bo.pages.homepages.edit', compact('homepageModel'));
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Homepage\UpdateHomepageRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateHomepageRequest $request): \Illuminate\Http\RedirectResponse
{
$this->authorize('update', \App\Models\Homepage::class);
return DB::transaction(function () use ($request) {
/** @var \App\Models\Homepage $homepageModel */
$homepageModel = Homepage::query()->firstOrFail();
if ($homepageModel->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.homepages.edit')
->with('success', __('crud.messages.has_been_updated', [
'model' => Str::ucfirst(__('models.classes.homepage'))
]));
}
return redirect()->route('bo.homepages.edit')
->with('error', __('crud.messages.cannot_be_updated', [
'model' => Str::ucfirst(__('models.classes.homepage'))
]));
});
}
}

View file

@ -0,0 +1,54 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Joinuspage\UpdateJoinuspageRequest;
use App\Models\Joinuspage;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class JoinuspageController extends Controller
{
/**
* Show the form for editing the specified resource.
*
* @return \Illuminate\Contracts\View\View
*/
public function edit(): \Illuminate\Contracts\View\View
{
$this->authorize('update', \App\Models\Joinuspage::class);
/** @var \App\Models\Joinuspage $joinuspageModel */
$joinuspageModel = Joinuspage::query()->firstOrFail();
return view('bo.pages.joinuspages.edit', compact('joinuspageModel'));
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Joinuspage\UpdateJoinuspageRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateJoinuspageRequest $request): \Illuminate\Http\RedirectResponse
{
$this->authorize('update', \App\Models\Joinuspage::class);
return DB::transaction(function () use ($request) {
/** @var \App\Models\Joinuspage $joinuspageModel */
$joinuspageModel = Joinuspage::query()->firstOrFail();
if ($joinuspageModel->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.joinuspages.edit')
->with('success', __('crud.messages.has_been_updated', [
'model' => Str::ucfirst(__('models.classes.joinuspage'))
]));
}
return redirect()->route('bo.joinuspages.edit')
->with('error', __('crud.messages.cannot_be_updated', [
'model' => Str::ucfirst(__('models.classes.joinuspage'))
]));
});
}
}

View file

@ -0,0 +1,168 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\News\StoreNewsRequest;
use App\Http\Requests\Bo\News\UpdateNewsRequest;
use App\Models\News;
use App\Traits\Controllers\ChangesModelOrder;
use App\Traits\Controllers\UpdateModelPublished;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class NewsController extends Controller
{
use UpdateModelPublished;
use ChangesModelOrder;
/**
* Create the controller instance.
*/
public function __construct()
{
$this->authorizeResource(News::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 $newsModels */
$newsModels = News::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$newsModels,
$search,
null,
'title',
'subtitle',
'content',
'category',
);
}
$searchFields = \implode(', ', [
Str::ucfirst(trans('validation.attributes.title')),
trans('validation.custom.subtitle'),
trans('validation.attributes.content'),
trans('validation.custom.category'),
]);
/** Sort columns with a query */
$this->sortQuery($newsModels);
/** Custom pagination */
$newsModels = $this->paginate($newsModels);
return view('bo.pages.news.index', compact('newsModels', 'search', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\News $news
* @return \Illuminate\Contracts\View\View
*/
public function create(News $news): \Illuminate\Contracts\View\View
{
return view('bo.pages.news.create', ['newsModel' => $news]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\News\StoreNewsRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreNewsRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$news = new News();
if ($news->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.news.edit', $news)
->with('success', __('crud.messages.has_been_created', [
'model' => Str::ucfirst(__('models.classes.news'))
]));
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_created', [
'model' => Str::ucfirst(__('models.classes.news'))
]));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\News $news
* @return \Illuminate\Contracts\View\View
*/
public function edit(News $news): \Illuminate\Contracts\View\View
{
return view('bo.pages.news.edit', ['newsModel' => $news]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\News\UpdateNewsRequest $request
* @param \App\Models\News $news
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateNewsRequest $request, News $news): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $news) {
if ($news->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.news.edit', $news)
->with('success', __('crud.messages.has_been_updated', [
'model' => Str::ucfirst(__('models.classes.news'))
]));
}
return redirect()->route('bo.news.edit', $news)
->with('error', __('crud.messages.cannot_be_updated', [
'model' => Str::ucfirst(__('models.classes.news'))
]));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\News $news
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(News $news): \Illuminate\Http\RedirectResponse
{
if ($news->deleteOrFail()) {
return redirect()->route('bo.news.index')
->with('success', __('crud.messages.has_been_deleted', [
'model' => Str::ucfirst(__('models.classes.news'))
]));
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_deleted', [
'model' => Str::ucfirst(__('models.classes.news'))
]));
}
/**
* Duplicate the specified resource.
*
* @param \App\Models\News $news
* @return \Illuminate\Contracts\View\View
*/
public function duplicate(News $news): \Illuminate\Contracts\View\View
{
return $this->create($news->replicate());
}
}

View file

@ -0,0 +1,191 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Products\StoreProductRequest;
use App\Http\Requests\Bo\Products\UpdateProductRequest;
use App\Models\Commitment;
use App\Models\Product;
use App\Models\Range;
use App\Traits\Controllers\ChangesModelOrder;
use App\Traits\Controllers\UpdateModelPublished;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class ProductController extends Controller
{
use UpdateModelPublished;
use ChangesModelOrder;
/**
* Create the controller instance.
*/
public function __construct()
{
$this->authorizeResource(Product::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 $productModels */
$productModels = Product::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$productModels,
$search,
null,
'title',
'subtitle',
'description',
);
}
$searchFields = \implode(', ', [
Str::ucfirst(trans('validation.attributes.title')),
trans('validation.custom.subtitle'),
trans('validation.custom.description'),
]);
/** Sort columns with a query */
$this->sortQuery($productModels);
/** Custom pagination */
$productModels = $this->paginate($productModels);
return view('bo.pages.products.index', compact('productModels', 'search', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Product $product
* @return \Illuminate\Contracts\View\View
*/
public function create(Product $product): \Illuminate\Contracts\View\View
{
$rangeModels = Range::all();
$commitmentModels = Commitment::all();
return view('bo.pages.products.create', [
'productModel' => $product,
'rangeModels' => $rangeModels,
'commitmentModels' => $commitmentModels,
]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Products\StoreProductRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreProductRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$product = new Product();
// Method safe() don't return formatted nutritionnal values, but we need this method to exclude commitments.
$product->fill($request->safe()->except(['commitments', 'nutritionnal_values']));
// We don't take $request->validated('nutritionnal_values') because it returned undesired datas.
$product->nutritionnal_values = $request->validated()['nutritionnal_values'];
if ($product->saveOrFail()) {
$product->commitments()->attach(collect($request->validated('commitments'))->pluck('id'));
return redirect()->route('bo.products.edit', $product)
->with('success', __('crud.messages.has_been_created', [
'model' => Str::ucfirst(__('models.classes.product'))
]));
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_created', [
'model' => Str::ucfirst(__('models.classes.product'))
]));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Product $product
* @return \Illuminate\Contracts\View\View
*/
public function edit(Product $product): \Illuminate\Contracts\View\View
{
$rangeModels = Range::all();
$commitmentModels = Commitment::all();
return view('bo.pages.products.edit', [
'productModel' => $product,
'rangeModels' => $rangeModels,
'commitmentModels' => $commitmentModels,
]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Products\UpdateProductRequest $request
* @param \App\Models\Product $product
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateProductRequest $request, Product $product): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $product) {
$product->fill($request->safe()->except('commitments'));
$product->commitments()->sync(collect($request->validated('commitments'))->pluck('id'));
$product->nutritionnal_values = $request->validated()['nutritionnal_values'];
if ($product->saveOrFail()) {
return redirect()->route('bo.products.edit', $product)
->with('success', __('crud.messages.has_been_updated', [
'model' => Str::ucfirst(__('models.classes.product'))
]));
}
return redirect()->route('bo.products.edit', $product)
->with('error', __('crud.messages.cannot_be_updated', [
'model' => Str::ucfirst(__('models.classes.product'))
]));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Product $product
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Product $product): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($product) {
$product->commitments()->detach();
if ($product->deleteOrFail()) {
return redirect()->route('bo.products.index')
->with('success', __('crud.messages.has_been_deleted', [
'model' => Str::ucfirst(__('models.classes.product'))
]));
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_deleted', [
'model' => Str::ucfirst(__('models.classes.product'))
]));
});
}
/**
* Duplicate the specified resource.
*
* @param \App\Models\Product $product
* @return \Illuminate\Contracts\View\View
*/
public function duplicate(Product $product): \Illuminate\Contracts\View\View
{
return $this->create($product->replicate());
}
}

View file

@ -0,0 +1,177 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Ranges\StoreRangeRequest;
use App\Http\Requests\Bo\Ranges\UpdateRangeRequest;
use App\Models\Range;
use App\Traits\Controllers\ChangesModelOrder;
use App\Traits\Controllers\UpdateModelPublished;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class RangeController extends Controller
{
use UpdateModelPublished;
use ChangesModelOrder;
/**
* Create the controller instance.
*/
public function __construct()
{
$this->authorizeResource(Range::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 $rangeModels */
$rangeModels = Range::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$rangeModels,
$search,
null,
'title',
'subtitle',
'tagline',
'description',
);
}
$searchFields = \implode(', ', [
Str::ucfirst(trans('validation.attributes.title')),
trans('validation.custom.subtitle'),
trans('validation.custom.tagline'),
trans('validation.custom.description'),
]);
/** Sort columns with a query */
$this->sortQuery($rangeModels);
/** Custom pagination */
$rangeModels = $this->paginate($rangeModels);
return view('bo.pages.ranges.index', compact('rangeModels', 'search', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Range $range
* @return \Illuminate\Contracts\View\View
*/
public function create(Range $range): \Illuminate\Contracts\View\View
{
return view('bo.pages.ranges.create', ['rangeModel' => $range]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Ranges\StoreRangeRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreRangeRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$range = new Range();
if ($range->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.ranges.edit', $range)
->with('success', __('crud.messages.has_been_created', [
'model' => Str::ucfirst(__('models.classes.range'))
]));
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_created', [
'model' => Str::ucfirst(__('models.classes.range'))
]));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Range $range
* @return \Illuminate\Contracts\View\View
*/
public function edit(Range $range): \Illuminate\Contracts\View\View
{
return view('bo.pages.ranges.edit', ['rangeModel' => $range]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Ranges\UpdateRangeRequest $request
* @param \App\Models\Range $range
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateRangeRequest $request, Range $range): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $range) {
if ($range->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.ranges.edit', $range)
->with('success', __('crud.messages.has_been_updated', [
'model' => Str::ucfirst(__('models.classes.range'))
]));
}
return redirect()->route('bo.ranges.edit', $range)
->with('error', __('crud.messages.cannot_be_updated', [
'model' => Str::ucfirst(__('models.classes.range'))
]));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Range $range
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Range $range): \Illuminate\Http\RedirectResponse
{
/** @var \Illuminate\Database\Eloquent\Collection $products*/
$products = $range->products;
if (!$products->isEmpty()) {
return redirect()->back()
->with('error', __('crud.messages.cannot_be_deleted_relation', [
'model' => Str::ucfirst(__('models.classes.range')),
'relations' => Str::plural(__('models.classes.product'))
]));
}
if ($range->deleteOrFail()) {
return redirect()->route('bo.ranges.index')
->with('success', __('crud.messages.has_been_deleted', [
'model' => Str::ucfirst(__('models.classes.range'))
]));
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_deleted', [
'model' => Str::ucfirst(__('models.classes.range'))
]));
}
/**
* Duplicate the specified resource.
*
* @param \App\Models\Range $range
* @return \Illuminate\Contracts\View\View
*/
public function duplicate(Range $range): \Illuminate\Contracts\View\View
{
return $this->create($range->replicate());
}
}

View file

@ -0,0 +1,164 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\SeasonalSections\StoreSeasonalSectionRequest;
use App\Http\Requests\Bo\SeasonalSections\UpdateSeasonalSectionRequest;
use App\Models\SeasonalSection;
use App\Traits\Controllers\UpdateModelPublished;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class SeasonalSectionController extends Controller
{
use UpdateModelPublished;
/**
* Create the controller instance.
*/
public function __construct()
{
$this->authorizeResource(SeasonalSection::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 $seasonalSectionModels */
$seasonalSectionModels = SeasonalSection::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$seasonalSectionModels,
$search,
null,
'title',
'text',
);
}
$searchFields = \implode(', ', [
Str::ucfirst(trans('validation.attributes.title')),
trans('validation.attributes.text'),
]);
/** Sort columns with a query */
$this->sortQuery($seasonalSectionModels);
/** Custom pagination */
$seasonalSectionModels = $this->paginate($seasonalSectionModels);
return view('bo.pages.seasonal_sections.index', compact('seasonalSectionModels', 'search', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\SeasonalSection $seasonalSection
* @return \Illuminate\Contracts\View\View
*/
public function create(SeasonalSection $seasonalSection): \Illuminate\Contracts\View\View
{
return view('bo.pages.seasonal_sections.create', ['seasonalSectionModel' => $seasonalSection]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\SeasonalSections\StoreSeasonalSectionRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreSeasonalSectionRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$seasonalSection = new SeasonalSection();
if ($seasonalSection->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.seasonalsections.edit', $seasonalSection)
->with('success', __('crud.messages.has_been_created', [
'model' => Str::ucfirst(trans_choice('models.classes.seasonal_section', 1))
]));
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_created', [
'model' => Str::ucfirst(trans_choice('models.classes.seasonal_section', 1))
]));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\SeasonalSection $seasonalSection
* @return \Illuminate\Contracts\View\View
*/
public function edit(SeasonalSection $seasonalSection): \Illuminate\Contracts\View\View
{
return view('bo.pages.seasonal_sections.edit', ['seasonalSectionModel' => $seasonalSection]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\SeasonalSections\UpdateSeasonalSectionRequest $request
* @param \App\Models\SeasonalSection $seasonalSection
* @return \Illuminate\Http\RedirectResponse
*/
public function update(
UpdateSeasonalSectionRequest $request,
SeasonalSection $seasonalSection
): \Illuminate\Http\RedirectResponse {
return DB::transaction(function () use ($request, $seasonalSection) {
if ($seasonalSection->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.seasonalsections.edit', $seasonalSection)
->with('success', __('crud.messages.has_been_updated', [
'model' => Str::ucfirst(trans_choice('models.classes.seasonal_section', 1))
]));
}
return redirect()->route('bo.seasonalsections.edit', $seasonalSection)
->with('error', __('crud.messages.cannot_be_updated', [
'model' => Str::ucfirst(trans_choice('models.classes.seasonal_section', 1))
]));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\SeasonalSection $seasonalSection
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(SeasonalSection $seasonalSection): \Illuminate\Http\RedirectResponse
{
if ($seasonalSection->deleteOrFail()) {
return redirect()->route('bo.seasonalsections.index')
->with('success', __('crud.messages.has_been_deleted', [
'model' => Str::ucfirst(trans_choice('models.classes.seasonal_section', 1))
]));
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_deleted', [
'model' => Str::ucfirst(trans_choice('models.classes.seasonal_section', 1))
]));
}
/**
* Duplicate the specified resource.
*
* @param \App\Models\SeasonalSection $seasonalSection
* @return \Illuminate\Contracts\View\View
*/
public function duplicate(SeasonalSection $seasonalSection): \Illuminate\Contracts\View\View
{
return $this->create($seasonalSection->replicate());
}
}

View file

@ -0,0 +1,162 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Stamps\StoreStampRequest;
use App\Http\Requests\Bo\Stamps\UpdateStampRequest;
use App\Models\Stamp;
use App\Traits\Controllers\UpdateModelPublished;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class StampController extends Controller
{
use UpdateModelPublished;
/**
* Create the controller instance.
*/
public function __construct()
{
$this->authorizeResource(Stamp::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 $stampModels */
$stampModels = Stamp::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$stampModels,
$search,
null,
'picture_alt',
'picture_title',
);
}
$searchFields = \implode(', ', [
Str::ucfirst(trans('validation.custom.attribute_alt')),
trans('validation.custom.attribute_title'),
]);
/** Sort columns with a query */
$this->sortQuery($stampModels);
/** Custom pagination */
$stampModels = $this->paginate($stampModels);
return view('bo.pages.stamps.index', compact('stampModels', 'search', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Stamp $stamp
* @return \Illuminate\Contracts\View\View
*/
public function create(Stamp $stamp): \Illuminate\Contracts\View\View
{
return view('bo.pages.stamps.create', ['stampModel' => $stamp]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Stamps\StoreStampRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreStampRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$stamp = new Stamp();
if ($stamp->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.stamps.edit', $stamp)
->with('success', __('crud.messages.has_been_created', [
'model' => Str::ucfirst(__('models.classes.stamp'))
]));
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_created', [
'model' => Str::ucfirst(__('models.classes.stamp'))
]));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Stamp $stamp
* @return \Illuminate\Contracts\View\View
*/
public function edit(Stamp $stamp): \Illuminate\Contracts\View\View
{
return view('bo.pages.stamps.edit', ['stampModel' => $stamp]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Stamps\UpdateStampRequest $request
* @param \App\Models\Stamp $stamp
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateStampRequest $request, Stamp $stamp): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $stamp) {
if ($stamp->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.stamps.edit', $stamp)
->with('success', __('crud.messages.has_been_updated', [
'model' => Str::ucfirst(__('models.classes.stamp'))
]));
}
return redirect()->route('bo.stamps.edit', $stamp)
->with('error', __('crud.messages.cannot_be_updated', [
'model' => Str::ucfirst(__('models.classes.stamp'))
]));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Stamp $stamp
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Stamp $stamp): \Illuminate\Http\RedirectResponse
{
if ($stamp->deleteOrFail()) {
return redirect()->route('bo.stamps.index')
->with('success', __('crud.messages.has_been_deleted', [
'model' => Str::ucfirst(__('models.classes.stamp'))
]));
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_deleted', [
'model' => Str::ucfirst(__('models.classes.stamp'))
]));
}
/**
* Duplicate the specified resource.
*
* @param \App\Models\Stamp $stamp
* @return \Illuminate\Contracts\View\View
*/
public function duplicate(Stamp $stamp): \Illuminate\Contracts\View\View
{
return $this->create($stamp->replicate());
}
}

View file

@ -0,0 +1,89 @@
<?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(', ', [
Str::ucfirst(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) {
if ($static_page->fill($request->validated())->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))
]));
});
}
}

View file

@ -0,0 +1,167 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Testimonials\StoreTestimonialRequest;
use App\Http\Requests\Bo\Testimonials\UpdateTestimonialRequest;
use App\Models\Testimonial;
use App\Traits\Controllers\ChangesModelOrder;
use App\Traits\Controllers\UpdateModelPublished;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class TestimonialController extends Controller
{
use UpdateModelPublished;
use ChangesModelOrder;
/**
* Create the controller instance.
*/
public function __construct()
{
$this->authorizeResource(Testimonial::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 $testimonialModels */
$testimonialModels = Testimonial::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$testimonialModels,
$search,
null,
'description',
'job'
);
}
$searchFields = \implode(', ', [
Str::ucfirst(trans('validation.custom.description')),
Str::ucfirst(trans('validation.custom.job'))
]);
/** Sort columns with a query */
$this->sortQuery($testimonialModels);
/** Custom pagination */
$testimonialModels = $this->paginate($testimonialModels);
return view('bo.pages.testimonials.index', compact('testimonialModels', 'search', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Testimonial $testimonial
* @return \Illuminate\Contracts\View\View
*/
public function create(Testimonial $testimonial): \Illuminate\Contracts\View\View
{
return view('bo.pages.testimonials.create', ['testimonialModel' => $testimonial]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Testimonials\StoreTestimonialRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreTestimonialRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$testimonial = new Testimonial();
if ($testimonial->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.testimonials.edit', $testimonial)
->with('success', __('crud.messages.has_been_created', [
'model' => Str::ucfirst(__('models.classes.testimonial'))
]));
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_created', [
'model' => Str::ucfirst(__('models.classes.testimonial'))
]));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Testimonial $testimonial
* @return \Illuminate\Contracts\View\View
*/
public function edit(Testimonial $testimonial): \Illuminate\Contracts\View\View
{
return view('bo.pages.testimonials.edit', ['testimonialModel' => $testimonial]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Testimonials\UpdateTestimonialRequest $request
* @param \App\Models\Testimonial $testimonial
* @return \Illuminate\Http\RedirectResponse
*/
public function update(
UpdateTestimonialRequest $request,
Testimonial $testimonial
): \Illuminate\Http\RedirectResponse {
return DB::transaction(function () use ($request, $testimonial) {
if ($testimonial->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.testimonials.edit', $testimonial)
->with('success', __('crud.messages.has_been_updated', [
'model' => Str::ucfirst(__('models.classes.testimonial'))
]));
}
return redirect()->route('bo.testimonials.edit', $testimonial)
->with('error', __('crud.messages.cannot_be_updated', [
'model' => Str::ucfirst(__('models.classes.testimonial'))
]));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Testimonial $testimonial
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Testimonial $testimonial): \Illuminate\Http\RedirectResponse
{
if ($testimonial->deleteOrFail()) {
return redirect()->route('bo.testimonials.index')
->with('success', __('crud.messages.has_been_deleted', [
'model' => Str::ucfirst(__('models.classes.testimonial'))
]));
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_deleted', [
'model' => Str::ucfirst(__('models.classes.testimonial'))
]));
}
/**
* Duplicate the specified resource.
*
* @param \App\Models\Testimonial $testimonial
* @return \Illuminate\Contracts\View\View
*/
public function duplicate(Testimonial $testimonial): \Illuminate\Contracts\View\View
{
return $this->create($testimonial->replicate());
}
}

View file

@ -0,0 +1,166 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Users\StoreUserRequest;
use App\Http\Requests\Bo\Users\UpdateUserRequest;
use App\Models\User;
use App\Traits\Controllers\UpdateModelPublished;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class UsersController extends Controller
{
use UpdateModelPublished;
/**
* Create the controller instance.
*/
public function __construct()
{
$this->authorizeResource(User::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 $userModels */
$userModels = User::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$userModels,
$search,
null,
'first_name',
'last_name',
'email',
'role',
);
}
$searchFields = \implode(', ', [
trans('validation.attributes.first_name'),
trans('validation.attributes.last_name'),
trans('validation.attributes.email'),
trans('validation.attributes.role'),
]);
/** Sort columns with a query */
$this->sortQuery($userModels);
/** Custom pagination */
$userModels = $this->paginate($userModels);
return view('bo.pages.users.index', compact('userModels', 'search', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\User $user
* @return \Illuminate\Contracts\View\View
*/
public function create(User $user): \Illuminate\Contracts\View\View
{
return view('bo.pages.users.create', ['userModel' => $user]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Users\StoreUserRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreUserRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$user = new User();
if ($user->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.users.edit', $user)
->with('success', __('crud.messages.has_been_created', [
'model' => Str::ucfirst(__('models.classes.user'))
]));
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_created', [
'model' => Str::ucfirst(__('models.classes.user'))
]));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\User $user
* @return \Illuminate\Contracts\View\View
*/
public function edit(User $user): \Illuminate\Contracts\View\View
{
return view('bo.pages.users.edit', ['userModel' => $user]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Users\UpdateUserRequest $request
* @param \App\Models\User $user
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateUserRequest $request, User $user): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $user) {
if ($user->fill($request->validated())->saveOrFail()) {
return redirect()->route('bo.users.edit', $user)
->with('success', __('crud.messages.has_been_updated', [
'model' => Str::ucfirst(__('models.classes.user'))
]));
}
return redirect()->route('bo.users.edit', $user)
->with('error', __('crud.messages.cannot_be_updated', [
'model' => Str::ucfirst(__('models.classes.user'))
]));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\User $user
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(User $user): \Illuminate\Http\RedirectResponse
{
if ($user->deleteOrFail()) {
return redirect()->route('bo.users.index')
->with('success', __('crud.messages.has_been_deleted', [
'model' => Str::ucfirst(__('models.classes.user'))
]));
}
return redirect()->back()
->with('error', __('crud.messages.cannot_be_deleted', [
'model' => Str::ucfirst(__('models.classes.user'))
]));
}
/**
* Duplicate the specified resource.
*
* @param \App\Models\User $user
* @return \Illuminate\Contracts\View\View
*/
public function duplicate(User $user): \Illuminate\Contracts\View\View
{
return $this->create($user->replicate());
}
}

View file

@ -0,0 +1,238 @@
<?php
namespace App\Http\Controllers;
use App\Enums\Pagination\ItemsPerPaginationEnum;
use App\Enums\Theme\BootstrapThemeEnum;
use App\Lib\Helpers\ToolboxHelper;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;
class Controller extends BaseController
{
use AuthorizesRequests;
use ValidatesRequests;
/**
* Build Search query on specified fields
* splitting search into words or using whole sentence
*
* @param \Illuminate\Database\Eloquent\Builder $query The eloquent query builder.
* @param string $search The query string.
* @param callable|null $searchQuery The query string.
* @param string ...$fields Either a simple array or a string
* in case of a string the two fields
* would be concatenate to make the search.
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function searchQuery(
Builder $query,
string $search,
callable|null $searchQuery = null,
string ...$fields
): \Illuminate\Database\Eloquent\Builder {
if (count($fields)) {
// Search using words.
$words = explode(' ', $search);
$query->where(function ($query) use ($searchQuery, $words, $search, $fields) {
foreach ($words as $word) {
if (!strlen($word)) {
continue;
}
$this->searchOnFields($query, $word, $fields);
} //end foreach
// Search whole using whole sentence.
$this->searchOnFields($query, $search, $fields);
if ($searchQuery) {
$searchQuery($query);
}
});
} //end if
return $query;
}
/**
* Build query search on all fields
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $search
* @param array $fields
* @return \Illuminate\Database\Eloquent\Builder
*/
private function searchOnFields(
Builder $query,
string $search,
array $fields
): \Illuminate\Database\Eloquent\Builder {
$table = $query->getModel()->getTable();
foreach ($fields as $field) {
$field = str_replace('?', '\?', $field);
if (is_array($field)) {
$query->orWhereRaw(
sprintf("UPPER(CONCAT(%s)) LIKE UPPER(?)", collect($field)->map(function ($q) use ($table) {
return "`$table`.`$q`";
})->implode(', \' \', ')),
['%' . htmlspecialchars($search) . '%']
);
return $query;
}
// Get models woth enum's label.
if (is_array($this->getSearchValue($query, $search, $field))) {
foreach ($this->getSearchValue($query, $search, $field) as $array) {
$query->orWhereRaw(
"UPPER(`$table`.`$field`) LIKE UPPER(?)",
['%' . htmlspecialchars($array->value) . '%']
);
}
return $query;
}
// Get models with relation's name/label.
if (Str::endsWith($field, '_id')) {
$query->orWhereHas(Str::remove('_id', $field), function ($queryRelation) use ($field, $search) {
if (Schema::hasColumn(Str::remove('_id', $field) . 's', 'name')) {
$queryRelation->where('name', 'like', '%' . $search . '%');
} elseif (Schema::hasColumn(Str::remove('_id', $field) . 's', 'label')) {
$queryRelation->where('label', 'like', '%' . $search . '%');
}
});
return $query;
}
$query->orWhereRaw(
"UPPER(`$table`.`$field`) LIKE UPPER(?)",
['%' . htmlspecialchars($this->getSearchValue($query, $search, $field)) . '%']
);
} //end foreach
return $query;
}
/**
* Get the search value (on string or Enum).
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $search
* @param string $field
* @return string|array
*/
protected function getSearchValue(Builder $query, string $search, string $field): string|array
{
$cast = $query->getModel()->getCasts()[$field] ?? null;
if (
count($query->getModel()->getCasts()) and // Check if the model has casts.
$cast and // Check if there is cast about specific field.
enum_exists($cast) // Check if the cast is an enum.
) {
/** @var \App\Traits\Enums $cast */
// @phpstan-ignore-next-line
$cases = collect($cast::toArray());
$enum = $cases->filter(function ($item) use ($search) {
return preg_match('/' . Str::lower($search) . '/', Str::lower($item->label));
});
return $enum->toArray();
} else {
return $search;
}
}
/**
* Sort columns with a query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param array $ignore
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function sortQuery(Builder $query, array $ignore = []): \Illuminate\Database\Eloquent\Builder
{
$rName = request()->route()->getName();
$table = $query->getModel()->getTable();
if (request()->input('sort_col')) {
Session::put("$rName.sort_col", request()->input('sort_col'));
Session::put("$rName.sorted", true);
}
if (request()->input('sort_way')) {
Session::put("$rName.sort_way", request()->input('sort_way'));
Session::put("$rName.sorted", true);
}
if (request()->rst) {
Session::remove("$rName.sorted");
Session::remove("$rName.sort_col");
Session::remove("$rName.sort_way");
}
if (
request()->input('sort_col') and
request()->input('sort_way') and
Schema::hasColumn($table, request()->input('sort_col'))
) {
if (!in_array(request()->input('sort_col'), $ignore)) {
$query = $query->orderBy(
\sprintf("$table.%s", request()->input('sort_col')),
request()->input('sort_way')
);
}
} elseif (Schema::hasColumn($table, 'order')) {
$query = $query->orderBy('order', 'ASC');
Session::put("$rName.sort_col", 'order');
Session::put("$rName.sort_way", 'asc');
} elseif (Schema::hasColumn($table, 'updated_at')) {
$query = $query->orderBy('updated_at', 'DESC');
Session::put("$rName.sort_col", 'updated_at');
Session::put("$rName.sort_way", 'desc');
} elseif (Schema::hasColumn($table, 'created_at')) {
$query = $query->orderBy('created_at', 'DESC');
Session::put("$rName.sort_col", 'created_at');
Session::put("$rName.sort_way", 'desc');
}
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|null $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;
}
/**
* Set the bootstrap theme or light (default).
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/
protected function setTheme(Request $request): \Illuminate\Http\RedirectResponse
{
$theme = ToolboxHelper::getValidatedEnum(
$request->theme ?: Cache::get('theme', BootstrapThemeEnum::light->value()),
'theme',
'\App\Http\Controllers\BootstrapThemeEnum',
);
if (Cache::get("theme") !== $theme) {
Cache::put("theme", $theme);
}
return redirect()->back()->with('success', __('crud.messages.theme_updated'));
}
}

View file

@ -0,0 +1,69 @@
<?php
namespace App\Http\Controllers\Fo;
use App\Enums\StaticPageType;
use App\Http\Controllers\Controller;
use App\Lib\Helpers\CollectionHelper;
use App\Lib\Helpers\ToolboxHelper;
use App\Models\News;
use App\Models\StaticPage;
use Illuminate\Contracts\Database\Query\Builder;
class NewsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Contracts\View\View
*/
public function index(): \Illuminate\Contracts\View\View
{
/** @var \App\Models\StaticPage $staticPageModel */
$staticPageModel = StaticPage::query()->where('type', StaticPageType::news)->firstOrFail();
/** @var \App\Models\News $newsModels */
$newsModels = News::query()->where('published', true)->orderBy('publish_at', 'desc')->paginate(12);
return view('fo.pages.news.index', \compact('staticPageModel', 'newsModels'));
}
/**
* Display a news articles
*
* @param string $slug
* @return \Illuminate\Contracts\View\View
*/
public function show(string $slug): \Illuminate\Contracts\View\View
{
/** @var \App\Models\News $newsModel */
$newsModel = News::query()
->where('published', true)
->where('slug', $slug)
->firstOrFail();
return view('fo.pages.news.show', \compact('newsModel'));
}
/**
* Get filtered news.
*
* @return \Illuminate\Http\JsonResponse
*/
public function newsFiltered(): \Illuminate\Http\JsonResponse
{
$categoryId = ToolboxHelper::getValidatedEnum(
0,
'category',
'\App\Enums\News\CategoryEnum',
);
$newsModels = News::query()
->where('published', true)
->when($categoryId != 0, function (Builder $query) use ($categoryId) {
$query->where('category', $categoryId);
})
->orderBy('publish_at', 'desc')
->get();
$newsModels = CollectionHelper::paginateManually($newsModels, 12, request()->page ?? 1);
return response()->json($newsModels);
}
}

View file

@ -0,0 +1,45 @@
<?php
namespace App\Http\Controllers\Fo;
use App\Http\Controllers\Controller;
use App\Lib\Helpers\CollectionHelper;
use App\Models\Product;
class ProductController extends Controller
{
/**
* Display the product page.
*
* @param string $slug
* @return \Illuminate\Contracts\View\View
*/
public function show(string $slug): \Illuminate\Contracts\View\View
{
$productModel = Product::query()->where('slug', $slug)->firstOrFail();
$otherProductModels = $productModel->range->products()
->where('id', '!=', $productModel->id)
->where('published', true)
->inRandomOrder()
->get();
return view('fo.pages.products.show', compact('productModel', 'otherProductModels'));
}
/**
* Get filtered products.
*
* @return \Illuminate\Http\JsonResponse
*/
public function productsFiltered(): \Illuminate\Http\JsonResponse
{
$productModels = Product::query()
->where('published', true)
->where('range_id', request()->range_id)
->orderBy('order', 'asc')
->get();
$productModels = CollectionHelper::paginateManually($productModels, 12, request()->page ?? 1);
return response()->json($productModels);
}
}

View file

@ -0,0 +1,65 @@
<?php
namespace App\Http\Controllers\Fo;
use App\Enums\StaticPageType;
use App\Http\Controllers\Controller;
use App\Lib\Helpers\CollectionHelper;
use App\Models\Product;
use App\Models\Range;
use App\Models\StaticPage;
class RangeController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Contracts\View\View
*/
public function index(): \Illuminate\Contracts\View\View
{
/** @var \App\Models\StaticPage $staticPageModel */
$staticPageModel = StaticPage::query()->where('type', StaticPageType::ranges)->firstOrFail();
/** @var \App\Models\Range $rangeModels */
$rangeModels = Range::query()->where('published', true)->orderBy('order')->paginate(12);
return view('fo.pages.ranges.index', compact('rangeModels', 'staticPageModel'));
}
/**
* Show a specific resource.
*
* @param string $slug
* @return \Illuminate\Contracts\View\View
*/
public function show(string $slug): \Illuminate\Contracts\View\View
{
/** @var \App\Models\Range $rangeModel */
$rangeModel = Range::query()->where('published', true)->where('slug', $slug)->firstOrFail();
/** @var \App\Models\Product $productModels */
$productModels = Product::query()
->where('range_id', $rangeModel->id)
->where('published', true)
->orderBy('order')
->paginate(12);
return view('fo.pages.ranges.show', compact('rangeModel', 'productModels'));
}
/**
* Get filtered ranges.
*
* @return \Illuminate\Http\JsonResponse
*/
public function rangesFiltered(): \Illuminate\Http\JsonResponse
{
$productModels = Range::query()
->where('published', true)
->orderBy('order', 'asc')
->get();
$productModels = CollectionHelper::paginateManually($productModels, 12, request()->page ?? 1);
return response()->json($productModels);
}
}

View file

@ -0,0 +1,207 @@
<?php
namespace App\Http\Controllers\Fo;
use App\Enums\Contact\ObjectEnum;
use App\Enums\StaticPageType;
use App\Http\Controllers\Controller;
use App\Http\Requests\Fo\ContactRequest;
use App\Http\Requests\Fo\JoinusRequest;
use App\Mail\SendContactMail;
use App\Mail\SendJoinusMail;
use App\Models\Convictionpage;
use App\Models\Explorerpage;
use App\Models\Homepage;
use App\Models\Joinuspage;
use App\Models\News;
use App\Models\Range;
use App\Models\SeasonalSection;
use App\Models\StaticPage;
use App\Models\Testimonial;
use Illuminate\Support\Facades\Mail;
class StaticPageController extends Controller
{
/**
* About us show
*
* @param \App\Models\StaticPage $aboutUsPage
* @return \Illuminate\Contracts\View\View
*/
public function aboutUs(StaticPage $aboutUsPage): \Illuminate\Contracts\View\View
{
$aboutUsPage = StaticPage::query()->where('type', StaticPageType::aboutus)
->get();
return view('fo.pages.about-us', ['staticPageModel' => $aboutUsPage[0]]);
}
/**
* Legal show
*
* @param \App\Models\StaticPage $legalPage
* @return \Illuminate\Contracts\View\View
*/
public function legals(StaticPage $legalPage): \Illuminate\Contracts\View\View
{
$legalPage = StaticPage::query()->where('type', StaticPageType::legals)->get();
return view('fo.pages.legals', ['staticPageModel' => $legalPage[0]]);
}
/**
* Policies show
*
* @param \App\Models\StaticPage $policiesPage
* @return \Illuminate\Contracts\View\View
*/
public function policies(StaticPage $policiesPage): \Illuminate\Contracts\View\View
{
$policiesPage = StaticPage::query()->where('type', StaticPageType::confidentiality)->get();
return view('fo.pages.legals', ['staticPageModel' => $policiesPage[0]]);
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Contracts\View\View
*/
public function homepage(): \Illuminate\Contracts\View\View
{
/** @var \App\Models\Homepage $homepageModel */
$homepageModel = Homepage::query()->firstOrFail();
/** @var \App\Models\StaticPage $staticPageModel */
$staticPageModel = StaticPage::query()->where('type', StaticPageType::home)->firstOrFail();
/** @var \App\Models\SeasonalSection $seasonalSectionsModel */
$seasonalSectionsModel = SeasonalSection::query()->where('published', true)->first();
/** @var \App\Models\News $newsModels */
$newsModels = News::query()->where('published', true)->latest('publish_at')->limit(2)->get();
/** @var \App\Models\Range $rangeModels */
$rangeModels = Range::query()->where('published', true)->orderBy('order')->get();
return view('fo.pages.home', compact(
'homepageModel',
'staticPageModel',
'seasonalSectionsModel',
'newsModels',
'rangeModels',
));
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Contracts\View\View
*/
public function contact(): \Illuminate\Contracts\View\View
{
/** @var \App\Models\StaticPage $contactModel */
$contactModel = StaticPage::query()->where('type', StaticPageType::contact)->firstOrFail();
return view('fo.pages.contact', compact('contactModel'));
}
/**
* Handle contactForm Request
*
* @param \App\Http\Requests\Fo\ContactRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function contactForm(ContactRequest $request): \Illuminate\Http\RedirectResponse
{
if ($request->object === strval(ObjectEnum::customerService->value())) {
$receivers = \config('mail.contactform.customerService');
} else {
$receivers = \config('mail.contactform.receiver');
}
foreach ($receivers as $email) {
Mail::to($email)->send(new SendContactMail((object)$request->validated()));
}
return redirect()->route('fo.contact.show')
->with(
'success',
'Bonjour, votre message a bien été transmis. nous vous en remercions. Cordialement, l’équipe Agis.'
);
}
/**
* Display the explorer and gastronome page.
*
* @return \Illuminate\Contracts\View\View
*/
public function explorer(): \Illuminate\Contracts\View\View
{
/** @var \App\Models\Explorerpage $explorerpageModel */
$explorerpageModel = Explorerpage::query()->firstOrFail();
/** @var \App\Models\StaticPage $staticPageModel */
$staticPageModel = StaticPage::query()->where('type', StaticPageType::explorer)->firstOrFail();
return view('fo.pages.explorer-and-gastronome', compact(
'explorerpageModel',
'staticPageModel',
));
}
/**
* Display the convictions page.
*
* @return \Illuminate\Contracts\View\View
*/
public function convictions(): \Illuminate\Contracts\View\View
{
/** @var \App\Models\Convictionpage $convictionpageModel */
$convictionpageModel = Convictionpage::query()->firstOrFail();
/** @var \App\Models\StaticPage $staticPageModel */
$staticPageModel = StaticPage::query()->where('type', StaticPageType::conviction)->firstOrFail();
return view('fo.pages.convictions', compact(
'convictionpageModel',
'staticPageModel',
));
}
/**
* Display the explorer and gastonome page.
*
* @return \Illuminate\Contracts\View\View
*/
public function joinus(): \Illuminate\Contracts\View\View
{
/** @var \App\Models\StaticPage $staticPageModel */
$staticPageModel = StaticPage::query()->where('type', StaticPageType::joinus)->firstOrFail();
/** @var \App\Models\Joinuspage $joinuspageModel */
$joinuspageModel = Joinuspage::query()->firstOrFail();
/** @var \App\Models\Testimonial $testimonialModels */
$testimonialModels = Testimonial::query()->get();
return view('fo.pages.join-us', compact('staticPageModel', 'joinuspageModel', 'testimonialModels'));
}
/**
* Handle joinusForm Request
*
* @param \App\Http\Requests\Fo\JoinusRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function joinusForm(JoinusRequest $request): \Illuminate\Http\RedirectResponse
{
$receivers = \config('mail.contactform.receiver');
foreach ($receivers as $email) {
Mail::to($email)->send(new SendJoinusMail((object)$request->validated()));
}
return redirect()->route('fo.joinus.show')
->with(
'success',
'Bonjour, votre candidature a bien été transmise. nous vous en remercions. Cordialement, l’équipe Agis.'
);
}
}

76
app/Http/Kernel.php Normal file
View file

@ -0,0 +1,76 @@
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array<int, class-string|string>
*/
protected $middleware = [
\App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* @var array<string, array<int, class-string|string>>
*/
protected $middlewareGroups = [
'web' => [
'htmlsanitize',
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\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,
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array<string, class-string|string>
*/
protected $middlewareAliases = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'htmlsanitize' => \App\Http\Middleware\HtmlSanitizer::class,
'local-development' => \App\Http\Middleware\LocalDevelopment::class,
];
}

View file

@ -0,0 +1,39 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @return string|null
*/
protected function redirectTo(Request $request): ?string
{
$logins = [
'backend' => route('bo.login')
];
if (!$request->expectsJson()) {
// * Notify must login
Session::flash('warning', trans('Veuillez vous connecter pour continuer'));
foreach ($request->route()->gatherMiddleware() as $middleware) {
if (\is_string($middleware) and strpos($middleware, 'auth:') !== false) {
$route = $logins[str_replace('auth:', '', $middleware)] ?? null;
if ($route) {
return $route;
}
}
}
return route('login');
}
return null;
}
}

View file

@ -0,0 +1,15 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array<int, string>
*/
protected $except = [];
}

View file

@ -0,0 +1,61 @@
<?php
namespace App\Http\Middleware;
use App\Lib\Helpers\ToolboxHelper;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class HtmlSanitizer
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|array ...$params
* @return \Symfony\Component\HttpFoundation\Response
*/
public function handle(Request $request, \Closure $next, string|array ...$params): Response
{
$inputs = $request->all();
/** @var callable|null */
$cleanInput = null;
$cleanInput = function (
null|string|array &$input,
string $name,
?string $rootName = null
) use (
$params,
&$cleanInput
): void {
// * Nested element array
if (is_array($input)) {
array_walk_recursive($input, $cleanInput, $name);
}
if (!is_string($input)) {
return;
}
if (in_array($name, $params) or in_array($rootName ?? $name, $params)) {
// ? Is a json input ?
if ($isJson = \json_decode($input, true) and is_array($isJson)) {
// ! Decode each json field recursive.
\array_walk_recursive($isJson, function (string|array &$item) {
if (\is_string($item)) {
$item = clean($item);
$item = ToolboxHelper::stripCkEditorSchemesOnMediaInputs($item);
}
});
} else {
$input = clean($input);
$input = ToolboxHelper::stripCkEditorSchemesOnMediaInputs($input);
}
} else {
$input = strip_tags($input);
}
};
\array_walk($inputs, $cleanInput);
$request->merge($inputs);
return $next($request);
}
}

View file

@ -0,0 +1,25 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class LocalDevelopment
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if (app()->environment() != 'local') {
return abort(403, 'You are not authorized to access this');
}
return $next($request);
}
}

View file

@ -0,0 +1,15 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
class PreventRequestsDuringMaintenance extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array<int, string>
*/
protected $except = [];
}

View file

@ -0,0 +1,43 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
* @param string|null ...$guards
* @return \Symfony\Component\HttpFoundation\Response
* @throws \RuntimeException If guard is unhandled.
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
*/
public function handle(Request $request, \Closure $next, ...$guards): Response
{
// phpcs:enable phpcs:disable
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (auth($guard)->check()) {
switch ($guard) {
case 'frontend':
return \redirect()->route('fo.homepage');
case 'backend':
if (!$request->routeIs('bo.*')) {
continue;
}
return \redirect()->route('bo.dashboard');
default:
throw new \RuntimeException("Unhandled guard `{$guard}` .");
}
}
}
return $next($request);
}
}

View file

@ -0,0 +1,133 @@
<?php
namespace App\Http\Middleware;
use Closure;
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
{
/**
* Enumerate headers which you do not want in your application's responses.
* Great starting point would be to go check out @Scott_Helme's:
* https://securityheaders.com/
*
* @var array
*/
private $unwantedHeaderList = [
'X-Powered-By',
'Server',
];
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
* @return \Symfony\Component\HttpFoundation\Response
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
*/
public function handle(Request $request, Closure $next): Response
{
// phpcs:enable
// * For Vite DEV
$host = \parse_url(\config('app.url'), \PHP_URL_HOST);
View::share('nonce', $nonce = Vite::useCspNonce());
// * For VueJS dev tool to execute
$jsDev = config('app.debug') ? "'unsafe-eval' 'unsafe-inline'" : "'nonce-{$nonce}' 'strict-dynamic'";
$scheme = config('app.env') === 'local' ? 'http' : 'https';
$reportUri = Route::has('cspReportUri') ?
\sprintf(' report-uri %s ;', \parse_url(route('cspReportUri'), \PHP_URL_PATH)) : '';
$this->removeUnwantedHeaders($this->unwantedHeaderList);
$response = $next($request);
$response->headers->set('Referrer-Policy', 'no-referrer-when-downgrade');
$response->headers->set('X-Content-Type-Options', 'nosniff');
$response->headers->set('X-XSS-Protection', '1; mode=block');
$response->headers->set('X-Frame-Options', 'SAMEORIGIN');
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains;');
$cspPolicies = [
"default-src 'none';",
"manifest-src 'self';",
// * CKEDITOR Specific https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/csp.html
"connect-src 'self' " . implode(' ', [
// * VITE DEV
config('app.debug') ? "wss://{$host}:4443" : '',
config('app.debug') ? "https://{$host}:4443" : '',
'https://yl.s-web.fr',
]) . ';',
"img-src 'self' data: blob: " . implode(' ', [
'https://yl.s-web.fr',
// * VITE DEV
config('app.debug') ? "https://{$host}:4443" : ''
]) . ';',
'frame-src ' . implode(' ', [
'https://www.google.com/recaptcha/',
'https://recaptcha.google.com/recaptcha/',
'https://www.google.com/maps/',
'https://www.youtube.com',
'https://player.vimeo.com',
]) . ';',
"font-src 'self' data: " . \implode(' ', [
// * VITE DEV
config('app.debug') ? "https://{$host}:4443" : '',
'https://fonts.gstatic.com;'
]) . ';',
// ! Using CKEditor will must have unsafe-inline style
// phpcs:ignore Generic.Files.LineLength.TooLong
"style-src 'self' 'unsafe-inline' " . \implode(' ', [
'https://cdnjs.cloudflare.com',
// * File Manager
'https://fonts.googleapis.com',
'https://cdn.jsdelivr.net',
'https://use.fontawesome.com',
'https://fonts.googleapis.com',
// * VITE DEV
config('app.debug') ? "https://{$host}:4443" : '',
]) . ';',
// ! If you dont use ckeditor use this
// "style-src 'self' 'nonce-$nonce';",
// phpcs:ignore Generic.Files.LineLength.TooLong
"script-src 'self' {$jsDev} " . \implode(' ', [
'https: blob:',
'https://www.googletagmanager.com',
'https://cdnjs.cloudflare.com',
"$scheme://www.google-analytics.com",
'https://www.google.com/recaptcha/',
'https://www.gstatic.com/recaptcha/',
'https://yl.s-web.fr',
// * VITE DEV
config('app.debug') ? "https://{$host}:4443" : '',
]) . ';'
];
$response->headers->set(
'Content-Security-Policy',
implode(' ', $cspPolicies) . $reportUri
);
$response->headers->set('Feature-Policy', \implode(',', [
'fullscreen',
'accelerometer',
'encrypted-media',
'gyroscope',
'picture-in-picture'
]) . ';');
return $response;
}
/**
* Remove unwanted headers
*
* @param array $headerList
* @return void
*/
private function removeUnwantedHeaders(array $headerList): void
{
foreach ($headerList as $header) {
header_remove($header);
}
}
}

View file

@ -0,0 +1,19 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
class TrimStrings extends Middleware
{
/**
* The names of the attributes that should not be trimmed.
*
* @var array<int, string>
*/
protected $except = [
'current_password',
'password',
'password_confirmation',
];
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustHosts as Middleware;
class TrustHosts extends Middleware
{
/**
* Get the host patterns that should be trusted.
*
* @return array<int, string|null>
*/
public function hosts()
{
return [
$this->allSubdomainsOfApplicationUrl(),
];
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array<int, string>|string|null
*/
protected $proxies;
/**
* The headers that should be used to detect proxies.
*
* @var integer
*/
protected $headers =
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB;
}

View file

@ -0,0 +1,15 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Routing\Middleware\ValidateSignature as Middleware;
class ValidateSignature extends Middleware
{
/**
* The names of the query string parameters that should be ignored.
*
* @var array<int, string>
*/
protected $except = [];
}

View file

@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array<int, string>
*/
protected $except = [
'/csp-report'
];
}

View file

@ -0,0 +1,68 @@
<?php
namespace App\Http\Requests\Bo\Commitments;
use App\Traits\Requests\HasPicture;
use Illuminate\Foundation\Http\FormRequest;
class StoreCommitmentRequest extends FormRequest
{
use HasPicture;
/**
* 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
*/
protected function prepareForValidation()
{
$this->merge([
'published' => $this->published ? true : false
]);
$this->mergePicture('picture');
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$rules = [
'title' => 'required|string|min:3|max:255',
'picture_alt' => 'required|string|min:3|max:255',
'picture_title' => 'required|string|min:3|max:255',
'published' => 'required|boolean',
];
return \array_merge(
$rules,
$this->pictureRules('picture', 185, 185, 185, 185, false),
);
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'title' => trans('validation.attributes.title'),
'picture_alt' => trans('validation.custom.picture_alt', ['field' => __('validation.custom.picture')]),
'picture_title' => trans('validation.custom.picture_title', ['field' => __('validation.custom.picture')]),
'published' => trans('validation.attributes.published'),
];
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace App\Http\Requests\Bo\Commitments;
class UpdateCommitmentRequest extends StoreCommitmentRequest
{
}

View file

@ -0,0 +1,59 @@
<?php
namespace App\Http\Requests\Bo\Convictionpages;
use App\Traits\Requests\HasPicture;
use Illuminate\Foundation\Http\FormRequest;
class UpdateConvictionpageRequest extends FormRequest
{
use HasPicture;
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth('backend')->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'key_feed' => 'required|numeric|max:2147483647',
'key_earth_1' => 'required|numeric|max:2147483647',
'key_earth_2' => 'required|numeric|max:2147483647',
'key_together_1' => 'required|numeric|max:2147483647',
'key_together_2' => 'required|numeric|max:2147483647',
'key_together_3' => 'required|numeric|max:2147483647',
'key_together_4' => 'required|numeric|max:2147483647',
'key_territory' => 'required|numeric|max:2147483647',
];
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'key_feed' => trans('validation.custom.key_feed'),
'key_earth_1' => trans('validation.custom.key_earth_1'),
'key_earth_2' => trans('validation.custom.key_earth_2'),
'key_together_1' => trans('validation.custom.key_together_1'),
'key_together_2' => trans('validation.custom.key_together_2'),
'key_together_3' => trans('validation.custom.key_together_3'),
'key_together_4' => trans('validation.custom.key_together_4'),
'key_territory' => trans('validation.custom.key_territory'),
];
}
}

View file

@ -0,0 +1,91 @@
<?php
namespace App\Http\Requests\Bo\Explorerpage;
use App\Traits\Requests\HasPicture;
use Illuminate\Foundation\Http\FormRequest;
class UpdateExplorerpageRequest extends FormRequest
{
use HasPicture;
/**
* 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
*/
protected function prepareForValidation()
{
$this->mergePicture('picture_1');
$this->mergePicture('picture_2');
$this->mergePicture('picture_3');
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$rules = [
'picture_1_alt' => 'required|string|between:3,255',
'picture_1_title' => 'required|string|between:3,255',
'picture_2_alt' => 'required|string|between:3,255',
'picture_2_title' => 'required|string|between:3,255',
'picture_3_alt' => 'required|string|between:3,255',
'picture_3_title' => 'required|string|between:3,255',
'commitments' => 'required|array',
'commitments.*.id' => 'required|exists:commitments,id',
];
return \array_merge(
$rules,
$this->pictureRules('picture_1', 265, 364, 265, 364, false),
$this->pictureRules('picture_2', 265, 364, 265, 364, false),
$this->pictureRules('picture_3', 265, 364, 265, 364, false),
);
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'picture_1_alt' => trans('validation.custom.picture_alt', [
'field' => __('validation.custom.picture_1')
]),
'picture_1_title' => trans('validation.custom.picture_title', [
'field' => __('validation.custom.picture_1')
]),
'picture_2_alt' => trans('validation.custom.picture_alt', [
'field' => __('validation.custom.picture_2')
]),
'picture_2_title' => trans('validation.custom.picture_title', [
'field' => __('validation.custom.picture_2')
]),
'picture_3_alt' => trans('validation.custom.picture_alt', [
'field' => __('validation.custom.picture_3')
]),
'picture_3_title' => trans('validation.custom.picture_title', [
'field' => __('validation.custom.picture_3')
]),
'commitments' => trans('validation.custom.commitments'),
'commitments.*.id' => trans('validation.custom.commitments'),
];
}
}

View file

@ -0,0 +1,91 @@
<?php
namespace App\Http\Requests\Bo\Homepage;
use App\Rules\IsValidVimeoId;
use App\Rules\IsValidYoutubeId;
use App\Traits\Requests\HasPicture;
use Illuminate\Foundation\Http\FormRequest;
class UpdateHomepageRequest extends FormRequest
{
use HasPicture;
/**
* 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
*/
protected function prepareForValidation()
{
$this->merge([
'display_video' => $this->boolean('display_video')
]);
$this->mergePicture('picture');
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$rules = [
'title_part1' => 'required|string|between:3,255',
'title_part2' => 'required|string|between:3,255',
'title_part3' => 'required|string|between:3,255',
'picture_alt' => 'required|string|between:3,255',
'picture_title' => 'required|string|between:3,255',
'presentation_title' => 'required|string|between:3,255',
'presentation_content' => 'required|string',
'display_video' => 'present|boolean',
'video_id' => [
'nullable', 'required_if:display_video,true',
function (string $attribute, mixed $value, \Closure $fail) {
if (!IsValidYoutubeId::validates($value) and !IsValidVimeoId::validates($value)) {
(new IsValidYoutubeId())->validate($attribute, $value, $fail);
(new IsValidVimeoId())->validate($attribute, $value, $fail);
}
}
],
];
return \array_merge(
$rules,
$this->pictureRules('picture', 640, 390, 640, 390, true, requiredIf: 'display_video,false'),
);
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'video_id' => trans('validation.custom.video_id'),
'title_part1' => trans('validation.custom.title_part1'),
'title_part2' => trans('validation.custom.title_part2'),
'title_part3' => trans('validation.custom.title_part3'),
'picture_alt' => trans('validation.custom.picture_alt', [
'field' => __('validation.custom.picture')
]),
'picture_title' => trans('validation.custom.picture_title', [
'field' => __('validation.custom.picture')
]),
'presentation_title' => trans('validation.custom.presentation_title'),
'presentation_content' => trans('validation.custom.presentation_content'),
];
}
}

View file

@ -0,0 +1,52 @@
<?php
namespace App\Http\Requests\Bo\Joinuspage;
use App\Rules\IsValidVimeoId;
use App\Rules\IsValidYoutubeId;
use Illuminate\Foundation\Http\FormRequest;
class UpdateJoinuspageRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth('backend')->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'video_id' => [
'required', 'string',
function (string $attribute, mixed $value, \Closure $fail) {
if (!IsValidYoutubeId::validates($value) and !IsValidVimeoId::validates($value)) {
(new IsValidYoutubeId())->validate($attribute, $value, $fail);
(new IsValidVimeoId())->validate($attribute, $value, $fail);
}
}
],
];
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'video_id' => trans('validation.custom.video_id'),
];
}
}

View file

@ -0,0 +1,91 @@
<?php
namespace App\Http\Requests\Bo\News;
use App\Enums\News\CategoryEnum;
use App\Traits\Requests\HasPicture;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Enum;
class StoreNewsRequest extends FormRequest
{
use HasPicture;
/**
* 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
*/
protected function prepareForValidation()
{
$this->merge([
'published' => $this->published ? true : false
]);
$this->mergePicture('picture');
$this->mergePicture('picture_thumbnail');
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
$rules = [
'seo_title' => 'required|between:45,70',
'seo_description' => 'required|between:50,160',
'title' => 'required|string|between:3,100',
'category' => ['required', new Enum(CategoryEnum::class)],
'picture_alt' => 'required|string|between:3,255',
'picture_title' => 'required|string|between:3,255',
'picture_thumbnail_alt' => 'required|string|between:3,255',
'picture_thumbnail_title' => 'required|string|between:3,255',
'subtitle' => 'required|string|between:3,255',
'content' => 'required|string|min:15',
'published' => 'required|boolean',
'publish_at' => 'required|date',
'unpublish_at' => 'nullable|date|after:publish_at',
];
return \array_merge(
$rules,
$this->pictureRules('picture', 1002, 565, 1002, 565, false),
$this->pictureRules('picture_thumbnail', 265, 354, 265, 354, false),
);
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'seo_title' => trans('validation.custom.seo_title'),
'seo_description' => trans('validation.custom.seo_description'),
'title' => trans('validation.attributes.title'),
'category' => trans('validation.custom.category'),
'subtitle' => trans('validation.custom.subtitle'),
'content' => trans('validation.attributes.content'),
'picture_alt' => trans('validation.custom.picture_alt'),
'picture_title' => trans('validation.custom.picture_title'),
'picture_thumbnail_alt' => trans('validation.custom.picture_thumbnail_alt'),
'picture_thumbnail_title' => trans('validation.custom.picture_thumbnail_title'),
'published' => trans('validation.custom.activated'),
'publish_at' => trans('validation.custom.publish_at'),
'unpublish_at' => trans('validation.custom.unpublish_at'),
];
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace App\Http\Requests\Bo\News;
class UpdateNewsRequest extends StoreNewsRequest
{
}

View file

@ -0,0 +1,163 @@
<?php
namespace App\Http\Requests\Bo\Products;
use App\Enums\Products\CookingModeEnum;
use App\Traits\Requests\HasPicture;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Enum;
class StoreProductRequest extends FormRequest
{
use HasPicture;
/**
* 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
*/
protected function prepareForValidation()
{
$this->merge([
'published' => $this->published ? true : false
]);
$this->mergePicture('picture_thumbnail');
$this->mergePicture('picture_ambiance');
$this->mergePicture('picture_packshot');
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
$rules = [
'seo_title' => 'required|between:45,70',
'seo_description' => 'required|between:50,160',
'title' => 'required|string|between:3,100',
'subtitle' => 'required|string|between:3,255',
'picture_thumbnail_alt' => 'required|string|between:3,255',
'picture_thumbnail_title' => 'required|string|between:3,255',
'picture_ambiance_alt' => 'required|string|between:3,255',
'picture_ambiance_title' => 'required|string|between:3,255',
'picture_packshot_alt' => 'required|string|between:3,255',
'picture_packshot_title' => 'required|string|between:3,255',
'description' => 'required|string|min:15',
'cooking_mode' => ['required', new Enum(CookingModeEnum::class)],
'cooking_advice' => 'required|string|min:15',
'ingredients' => 'required|string|min:15',
'nutritionnal_values' => 'required|array',
'nutritionnal_values.*' => 'required|numeric|min:0',
'range_id' => 'required|exists:ranges,id',
'commitments' => 'nullable|array',
'commitments.*.id' => 'required|exists:commitments,id',
'published' => 'required|boolean',
];
return \array_merge(
$rules,
$this->pictureRules('picture_thumbnail', 332, 252, 332, 252, false),
$this->pictureRules('picture_ambiance', 1115, 790, 1115, 790, false),
$this->pictureRules('picture_packshot', 560, 480, 560, 480, false),
);
}
/**
* Override validated() function from FormRequest.
*
* @param array|integer|string|null $key
* @param mixed $default
* @return array|null
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassAfterLastUsed
*/
public function validated($key = null, mixed $default = null): array|null
{
if ($key === 'commitments') {
return parent::validated($key, $default);
}
// phpcs:enable
$nutritionnal_values = json_encode([
"energyKj" => [
"label" => "ÉNERGIE (kJ)",
"value" => $this->nutritionnal_values['energy_kj'],
],
"energyKcal" => [
"label" => "ÉNERGIE (kcal)",
"value" => $this->nutritionnal_values['energy_kcal'],
],
"fat" => [
"label" => "MATIÈRES GRASSES (g)",
"value" => $this->nutritionnal_values['fat'],
],
"saturated-fat" => [
"label" => "ACIDES GRAS SATURÉS (g)",
"value" => $this->nutritionnal_values['saturated_fat'],
],
"carbohydrate" => [
"label" => "GLUCIDES (g)",
"value" => $this->nutritionnal_values['carbohydrate'],
],
"sugar" => [
"label" => "SUCRES (g)",
"value" => $this->nutritionnal_values['sugar'],
],
"proteins" => [
"label" => "PROTÉINES (g)",
"value" => $this->nutritionnal_values['proteins'],
],
"salt" => [
"label" => "SEL (g)",
"value" => $this->nutritionnal_values['salt'],
]
]);
return array_merge(
parent::validated($key, $default),
[
'nutritionnal_values' => $nutritionnal_values
]
);
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'seo_title' => trans('validation.custom.seo_title'),
'seo_description' => trans('validation.custom.seo_description'),
'title' => trans('validation.attributes.title'),
'subtitle' => trans('validation.custom.subtitle'),
'description' => trans('validation.custom.description'),
'picture_thumbnail_alt' => trans('validation.custom.picture_thumbnail_alt'),
'picture_thumbnail_title' => trans('validation.custom.picture_thumbnail_title'),
'picture_ambiance_alt' => trans('validation.custom.picture_ambiance_alt'),
'picture_ambiance_title' => trans('validation.custom.picture_ambiance_title'),
'picture_packshot_alt' => trans('validation.custom.picture_packshot_alt'),
'picture_packshot_title' => trans('validation.custom.picture_packshot_title'),
'cooking_mode' => trans('validation.custom.cooking_mode'),
'cooking_advice' => trans('validation.custom.cooking_advice'),
'ingredients' => trans('validation.custom.ingredients'),
'nutritionnal_values' => trans('validation.custom.nutritionnal_values'),
'range_id' => trans('models.classes.range'),
'commitments' => trans('Engagements associés au produit'),
'commitments.*.id' => trans('Élément parmis les engagements associés au produit'),
'published' => trans('validation.custom.activated'),
];
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace App\Http\Requests\Bo\Products;
class UpdateProductRequest extends StoreProductRequest
{
}

View file

@ -0,0 +1,90 @@
<?php
namespace App\Http\Requests\Bo\Ranges;
use App\Traits\Requests\HasPicture;
use Illuminate\Foundation\Http\FormRequest;
class StoreRangeRequest extends FormRequest
{
use HasPicture;
/**
* 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
*/
protected function prepareForValidation()
{
$this->merge([
'published' => $this->published ? true : false
]);
$this->mergePicture('picture');
$this->mergePicture('picture_productsheet');
$this->mergePicture('picture_thumbnail');
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
$rules = [
'seo_title' => 'required|between:45,70',
'seo_description' => 'required|between:50,160',
'title' => 'required|string|between:3,100',
'subtitle' => 'required|string|between:3,255',
'tagline' => 'required|string|between:3,255',
'description' => 'required|string|min:15',
'picture_alt' => 'required|string|between:3,255',
'picture_title' => 'required|string|between:3,255',
'picture_productsheet_alt' => 'required|string|between:3,255',
'picture_productsheet_title' => 'required|string|between:3,255',
'picture_thumbnail_alt' => 'required|string|between:3,255',
'picture_thumbnail_title' => 'required|string|between:3,255',
'published' => 'required|boolean',
];
return \array_merge(
$rules,
$this->pictureRules('picture', 466, 440, 466, 440, false),
$this->pictureRules('picture_productsheet', 680, 300, 680, 300, false),
$this->pictureRules('picture_thumbnail', 246, 337, 246, 337, false),
);
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'seo_title' => trans('validation.custom.seo_title'),
'seo_description' => trans('validation.custom.seo_description'),
'title' => trans('validation.attributes.title'),
'subtitle' => trans('validation.custom.subtitle'),
'tagline' => trans('validation.custom.tagline'),
'description' => trans('validation.custom.description'),
'picture_alt' => trans('validation.custom.picture_alt'),
'picture_title' => trans('validation.custom.picture_title'),
'picture_productsheet_alt' => trans('validation.custom.picture_productsheet_alt'),
'picture_productsheet_title' => trans('validation.custom.picture_productsheet_title'),
'picture_thumbnail_alt' => trans('validation.custom.picture_thumbnail_alt'),
'picture_thumbnail_title' => trans('validation.custom.picture_thumbnail_title'),
'published' => trans('validation.custom.activated'),
];
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace App\Http\Requests\Bo\Ranges;
class UpdateRangeRequest extends StoreRangeRequest
{
}

View file

@ -0,0 +1,80 @@
<?php
namespace App\Http\Requests\Bo\SeasonalSections;
use App\Enums\SeasonalSections\BackgroundEnum;
use App\Traits\Requests\HasPicture;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Enum;
class StoreSeasonalSectionRequest extends FormRequest
{
use HasPicture;
/**
* 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
*/
protected function prepareForValidation()
{
$this->merge([
'published' => $this->published ? true : false
]);
$this->mergePicture('picture');
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
$rules = [
'title' => 'required|string|between:3,100',
'text' => 'required|string|min:15',
'picture_alt' => 'required|string|between:3,255',
'picture_title' => 'required|string|between:3,255',
'background' => ['required', new Enum(BackgroundEnum::class)],
'published' => 'required|boolean',
'publish_at' => 'nullable|date',
'unpublish_at' => 'nullable|date|after:publish_at',
];
return \array_merge(
$rules,
$this->pictureRules('picture', 362, 542, 362, 542, false),
);
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'title' => trans('validation.attributes.title'),
'text' => trans('validation.attributes.content'),
'picture_alt' => trans('validation.custom.picture_alt'),
'picture_title' => trans('validation.custom.picture_title'),
'background' => trans('validation.custom.background'),
'published' => trans('validation.custom.activated'),
'publish_at' => trans('validation.custom.publish_at'),
'unpublish_at' => trans('validation.custom.unpublish_at'),
];
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace App\Http\Requests\Bo\SeasonalSections;
class UpdateSeasonalSectionRequest extends StoreSeasonalSectionRequest
{
}

View file

@ -0,0 +1,66 @@
<?php
namespace App\Http\Requests\Bo\Stamps;
use App\Traits\Requests\HasPicture;
use Illuminate\Foundation\Http\FormRequest;
class StoreStampRequest extends FormRequest
{
use HasPicture;
/**
* 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
*/
protected function prepareForValidation()
{
$this->merge([
'published' => $this->published ? true : false
]);
$this->mergePicture('picture');
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
$rules = [
'picture_alt' => 'required|string|between:3,255',
'picture_title' => 'required|string|between:3,255',
'published' => 'required|boolean',
];
return \array_merge(
$rules,
$this->pictureRules('picture', 120, 120, 120, 120, false),
);
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'picture_alt' => trans('validation.custom.picture_alt'),
'picture_title' => trans('validation.custom.picture_title'),
'published' => trans('validation.custom.activated'),
];
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace App\Http\Requests\Bo\Stamps;
class UpdateStampRequest extends StoreStampRequest
{
}

View file

@ -0,0 +1,74 @@
<?php
namespace App\Http\Requests\Bo\StaticPages;
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
{
/** @var \App\Models\StaticPage $staticPageModel */
$staticPageModel = $this->route('static_page');
if (
\in_array($staticPageModel->type, [
\App\Enums\StaticPageType::confidentiality,
\App\Enums\StaticPageType::legals
])
) {
$this->merge([
'content' => (string)Str::of($this->post('content'))
]);
} else {
$this->merge([
'content' => ''
]);
}
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'seo_title' => 'required|min:45|max:70',
'seo_description' => 'required|min:50|max:160',
'title' => 'required|min:3|max:255',
'content' => 'present',
];
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'seo_title' => trans('validation.custom.seo_title'),
'seo_description' => trans('validation.custom.seo_description'),
'title' => trans('validation.attributes.title'),
'content' => trans('validation.attributes.content'),
];
}
}

View file

@ -0,0 +1,67 @@
<?php
namespace App\Http\Requests\Bo\Testimonials;
use App\Traits\Requests\HasPicture;
use Illuminate\Foundation\Http\FormRequest;
class StoreTestimonialRequest extends FormRequest
{
use HasPicture;
/**
* 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
*/
protected function prepareForValidation()
{
$this->mergePicture('picture');
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$rules = [
'picture_alt' => 'required|string|between:3,255',
'picture_title' => 'required|string|between:3,255',
'description' => 'required|string|between:3,255',
'job' => 'required|string|between:3,255',
'statut' => 'required|string|between:3,255',
];
return \array_merge(
$rules,
$this->pictureRules('picture', 292, 417, 292, 417, false),
);
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'picture_alt' => trans('validation.custom.picture_alt', ['field' => __('validation.custom.picture')]),
'picture_title' => trans('validation.custom.picture_title', ['field' => __('validation.custom.picture')]),
'description' => trans('validation.attributes.description'),
'job' => trans('validation.custom.job'),
'statut' => trans('validation.custom.statut'),
];
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace App\Http\Requests\Bo\Testimonials;
class UpdateTestimonialRequest extends StoreTestimonialRequest
{
}

View file

@ -0,0 +1,54 @@
<?php
namespace App\Http\Requests\Bo;
use Illuminate\Foundation\Http\FormRequest;
class UpdateChangeOrderRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth()->check();
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation(): void
{
$this->merge([
'direction' => $this->direction === 'up' ? true : false
]);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
return [
'direction' => 'required|boolean',
];
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'direction' => trans('validation.custom.direction'),
];
}
}

View file

@ -0,0 +1,66 @@
<?php
namespace App\Http\Requests\Bo\Users;
use App\Enums\Users\RoleEnum;
use App\Models\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\Rules\Enum;
class StoreUserRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return Gate::check('create', User::class);
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation(): void
{
$this->merge([
'published' => $this->boolean('published')
]);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
return [
'first_name' => 'required|string|min:3|max:255',
'last_name' => 'required|string|min:3|max:255',
'email' => 'required|email:rfc,strict,dns,spoof,filter|unique:users,email',
'role' => ['required', new Enum(RoleEnum::class)],
'published' => 'required|boolean',
];
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'first_name' => trans('validation.attributes.first_name'),
'last_name' => trans('validation.attributes.last_name'),
'email' => trans('validation.attributes.email'),
'role' => trans('validation.attributes.role'),
'published' => trans('validation.custom.publication')
];
}
}

View file

@ -0,0 +1,47 @@
<?php
namespace App\Http\Requests\Bo\Users;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\Rule;
class UpdateUserRequest extends StoreUserRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return Gate::check('update', $this->route('user'));
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation(): void
{
$this->merge([
'published' => $this->boolean('published'),
]);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
return array_merge(parent::rules(), [
'email' => [
'required',
'email:rfc,strict,dns,spoof,filter',
Rule::unique('users', 'email')->ignore(\optional($this->route('user'))->getRouteKey())
],
]);
}
}

View file

@ -0,0 +1,208 @@
<?php
namespace App\Http\Requests\Fo;
use App\Enums\Contact\CivilityEnum;
use App\Enums\Contact\ObjectEnum;
use App\Lib\Helpers\ToolboxHelper;
use App\Traits\Requests\HasPicture;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Enum;
class ContactRequest extends FormRequest
{
use HasPicture;
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
{
$this->mergePicture('file');
}
/**
* Get the validation rules that apply to the request.
*
* @return array
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
*/
public function rules()
{
// phpcs:enable
ToolboxHelper::validateRecaptcha($this, \config('services.google.recaptcha.version'));
$rules = [
'civility' => ['sometimes', 'nullable', new Enum(CivilityEnum::class)],
'last_name' => 'sometimes|nullable|string|between:3,255',
'first_name' => 'sometimes|nullable|string|between:3,255',
'society' => 'sometimes|nullable|string|between:3,255',
'email' => 'required|email:rfc,strict,dns,spoof,filter|max:255',
'phone' => 'sometimes|nullable|numeric|min:0',
'address' => 'required|string|between:3,255',
'postal_code' => 'required|numeric|min:0',
'city' => 'required|string|between:3,255',
'object' => ['required', new Enum(ObjectEnum::class)],
'message' => 'required|string|between:3,500',
];
if ($this->object === strval(ObjectEnum::customerService->value())) {
$rules = \array_merge($rules, [
'product_name' => [
'string',
'between:3,255',
'required',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_name'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'product_date_limit' => [
'required',
'date',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_date_limit'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'product_barcode' => [
'numeric',
'min:0',
'required',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_barcode'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'product_lot' => [
'numeric',
'min:0',
'required',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_lot'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'product_date_consumption' => [
'required',
'date',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_date_consumption'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'product_location' => [
'string',
'between:3,255',
'required',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_location'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
]);
} //end if
if (
isset(request()->file) and
(request()->file->getClientMimeType() === "image/jpeg" ||
request()->file->getClientMimeType() === "image/png")
) {
$rules = \array_merge($rules, $this->pictureRules(
'file',
0,
0,
1920,
1080,
true,
3000,
'product_name,product_date_limit,product_barcode,product_lot,product_date_consumption,product_location'
));
} elseif (isset(request()->file) and (request()->file->getClientMimeType() === "application/pdf")) {
$rules = \array_merge($rules, [
//phpcs:ignore Generic.Files.LineLength.TooLong
'file' => 'sometimes|nullable|mimes:pdf|required_with:product_name,product_date_limit,product_barcode,product_lot,product_date_consumption,product_location'
]);
} elseif (
isset(request()->file) and
(request()->file->getClientMimeType() !== "application/pdf") and
(request()->file->getClientMimeType() !== "image/jpeg") and
(request()->file->getClientMimeType() !== "image/png")
) {
$rules = \array_merge($rules, [
'file' => [
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
$fail(\trans('Le format du fichier doit être .jpg, .png ou .pdf'));
}
],
]);
} //end if
return $rules;
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'civility' => trans('validation.custom.civility'),
'first_name' => trans('validation.attributes.first_name'),
'last_name' => trans('validation.attributes.last_name'),
'society' => trans('validation.custom.society'),
'email' => trans('validation.attributes.email'),
'phone' => trans('validation.attributes.phone'),
'address' => trans('validation.attributes.address'),
'postal_code' => trans('validation.attributes.postal_code'),
'city' => trans('validation.attributes.city'),
'object' => trans('validation.custom.object'),
'product_name' => trans('validation.custom.product_name'),
'product_date_limit' => trans('validation.custom.product_date_limit'),
'product_barcode' => trans('validation.custom.product_barcode'),
'product_lot' => trans('validation.custom.product_lot'),
'product_date_consumption' => trans('validation.custom.product_date_consumption'),
'product_location' => trans('validation.custom.product_location'),
'message' => trans('validation.attributes.message'),
'file' => trans('validation.custom.file'),
];
}
}

View file

@ -0,0 +1,49 @@
<?php
namespace App\Http\Requests\Fo;
use App\Enums\DesiredLocation;
use App\Lib\Helpers\ToolboxHelper;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Enum;
class JoinusRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
ToolboxHelper::validateRecaptcha($this, \config('services.google.recaptcha.version'));
return [
'last_name' => 'required|string|between:3,255',
'first_name' => 'required|string|between:3,255',
'email' => 'required|email:rfc,strict,dns,spoof,filter|max:255',
'phone' => 'required|numeric|min:0',
'desired_location' => ['required', new Enum(DesiredLocation::class)],
'message' => 'required|string|between:3,500',
"file" => "sometimes|nullable|mimes:pdf|max:10000"
];
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'first_name' => trans('validation.attributes.first_name'),
'last_name' => trans('validation.attributes.last_name'),
'email' => trans('validation.attributes.email'),
'phone' => trans('validation.attributes.phone'),
'desired_location' => trans('validation.custom.desired_location'),
'message' => trans('validation.attributes.message'),
'file' => trans('validation.attributes.file'),
];
}
}

View file

@ -0,0 +1,46 @@
<?php
namespace App\Jobs;
use App\Models\News;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;
/**
* Update published attribute reading its
* publish_at and unpublish_at attributes.
*/
class NewsStatusUpdate
{
/**
* Called when the job will be executed.
*
* @return void
*/
public function handle()
{
/** @var \Illuminate\Database\Eloquent\Collection<array-key, \App\Models\News> */
$newsListToPublish = News::query()
->where('publish_at', '<=', Carbon::now()->toDateTime())
->whereNotNull('publish_at')
->where('published', false)->get();
Log::debug(__CLASS__ . " news to publish " . $newsListToPublish->count());
foreach ($newsListToPublish as $news) {
$news->publish_at = null;
$news->published = true;
$news->saveOrFail();
}
/** @var \Illuminate\Database\Eloquent\Collection<array-key, \App\Models\News> */
$newsListToUnPublish = News::query()
->where('unpublish_at', '<=', Carbon::now()->toDateTime())
->whereNotNull('unpublish_at')
->where('published', true)->get();
Log::debug(__CLASS__ . " news to unpublish " . $newsListToPublish->count());
foreach ($newsListToUnPublish as $news) {
$news->publish_at = null;
$news->unpublish_at = null;
$news->published = false;
$news->saveOrFail();
}
}
}

View file

@ -0,0 +1,46 @@
<?php
namespace App\Jobs;
use App\Models\SeasonalSection;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;
/**
* Update published attribute reading its
* publish_at and unpublish_at attributes.
*/
class SeasonalSectionStatusUpdate
{
/**
* Called when the job will be executed.
*
* @return void
*/
public function handle()
{
/** @var \Illuminate\Database\Eloquent\Collection<array-key, \App\Models\SeasonalSection> */
$seasonalsectionsListToPublish = SeasonalSection::query()
->where('publish_at', '<=', Carbon::now()->toDateTime())
->whereNotNull('publish_at')
->where('published', false)->get();
Log::debug(__CLASS__ . " seasonalsections to publish " . $seasonalsectionsListToPublish->count());
foreach ($seasonalsectionsListToPublish as $seasonalsections) {
$seasonalsections->publish_at = null;
$seasonalsections->published = true;
$seasonalsections->saveOrFail();
}
/** @var \Illuminate\Database\Eloquent\Collection<array-key, \App\Models\SeasonalSection> */
$seasonalsectionsListToUnPublish = SeasonalSection::query()
->where('unpublish_at', '<=', Carbon::now()->toDateTime())
->whereNotNull('unpublish_at')
->where('published', true)->get();
Log::debug(__CLASS__ . " seasonalsections to unpublish " . $seasonalsectionsListToPublish->count());
foreach ($seasonalsectionsListToUnPublish as $seasonalsections) {
$seasonalsections->publish_at = null;
$seasonalsections->unpublish_at = null;
$seasonalsections->published = false;
$seasonalsections->saveOrFail();
}
}
}

View file

@ -0,0 +1,64 @@
<?php
namespace App\Lib\Helpers;
use Illuminate\Container\Container;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Collection;
class CollectionHelper
{
/**
* Paginate a collection
*
* @param \Illuminate\Support\Collection $results
* @param integer $pageSize
* @return \Illuminate\Pagination\LengthAwarePaginator
*/
public static function paginate(Collection $results, int $pageSize): LengthAwarePaginator
{
$page = Paginator::resolveCurrentPage('page');
return self::paginateManually($results, $pageSize, $page);
}
/**
* Paginate a collection
*
* @param \Illuminate\Support\Collection $results
* @param integer $pageSize
* @param integer $page
* @return \Illuminate\Pagination\LengthAwarePaginator
*/
public static function paginateManually(Collection $results, int $pageSize, int $page = 1): LengthAwarePaginator
{
$total = $results->count();
return self::paginator($results->forPage($page, $pageSize), $total, $pageSize, $page, [
'path' => Paginator::resolveCurrentPath(),
'pageName' => 'page',
]);
}
/**
* Create a new length-aware paginator instance.
*
* @param \Illuminate\Support\Collection $items
* @param integer $total
* @param integer $perPage
* @param integer $currentPage
* @param array $options
* @return \Illuminate\Pagination\LengthAwarePaginator
*/
protected static function paginator(Collection $items, int $total, int $perPage, int $currentPage, array $options)
{
return Container::getInstance()->makeWith(LengthAwarePaginator::class, [
'items' => $items,
'total' => $total,
'perPage' => $perPage,
'currentPage' => $currentPage,
'options' => $options
]);
}
}

View file

@ -0,0 +1,190 @@
<?php
namespace App\Lib\Helpers;
class ExceptionsHelper
{
/**
* Handle sentry event
*
* @param \Sentry\Event $event
* @return null|\Sentry\Event
*/
public static function sentryEventHandler(\Sentry\Event $event): ?\Sentry\Event
{
// Remove unwanted reports.
$event->setModules([]);
$event->setOsContext(null);
/** @var \Sentry\ExceptionDataBag[] */
$exceptionBag = [];
foreach ($event->getExceptions() as $exceptionDataBag) {
$exceptionBag[] = self::getAnonymizedSentryException($exceptionDataBag);
}
$event->setExceptions($exceptionBag);
return $event;
}
/**
* Anonimize Sentry Exception bag
*
* @param \Sentry\ExceptionDataBag $exceptionDataBag
* @return \Sentry\ExceptionDataBag
*/
private static function getAnonymizedSentryException(
\Sentry\ExceptionDataBag $exceptionDataBag
): \Sentry\ExceptionDataBag {
$exceptionDataBag->setValue(self::getAnonymizedMessage($exceptionDataBag->getValue()));
if ($stackTrace = $exceptionDataBag->getStacktrace()) {
$exceptionDataBag->setStacktrace(self::getAnonymizedSentryStackTrace($stackTrace));
}
return $exceptionDataBag;
}
/**
* Anonymise sentry stacktrace
*
* @param \Sentry\Stacktrace $stackTrace
* @return \Sentry\Stacktrace
*/
private static function getAnonymizedSentryStackTrace(\Sentry\Stacktrace $stackTrace): \Sentry\Stacktrace
{
/** @var \Sentry\Frame[] */
$frames = \array_reverse($stackTrace->getFrames(), true);
$i = \count($frames) - 1;
// * Remove all but keep first (index.php).
while ($i-- > 0) {
$stackTrace->removeFrame(count($stackTrace->getFrames()) - 1);
}
foreach ($frames as $index => $frame) {
$frame->setPostContext([]);
$frame->setPreContext([]);
$frame->setContextLine('');
$frame->setVars(self::getAnonymizedSentryParams($frame->getVars()));
$stackTrace->addFrame($frame);
if ($index === 0) {
$stackTrace->removeFrame(count($stackTrace->getFrames()) - 1);
}
}
return $stackTrace;
}
/**
* Get anonymized sentry params
*
* @param mixed[] $params
* @return string[]
*/
private static function getAnonymizedSentryParams(array $params): array
{
foreach ($params as &$param) {
$type = \strtolower(\gettype($param));
if (\is_string($param)) {
$type = \explode(' ', \trim(strtolower($param)))[0] ?? null;
}
switch (true) {
case $type === 'lambda':
case $type === 'object':
continue 2;
case $type === 'array' and \is_array($param):
$param = sprintf('Array(%d)', \count($param));
continue 2;
default:
if (\is_numeric($param)) {
$param = \ucfirst($type);
continue 2;
}
if (\is_string($param)) {
$param = sprintf('String(%d)', \strlen($param));
continue 2;
}
} //end switch
} //end foreach
return $params;
}
/**
* Anonymize at least Sql queries
*
* @param string $message
* @return string
*/
public static function getAnonymizedMessage(string $message): string
{
$message = \preg_replace('/^(.*)( \(SQL:.*\))$/', '$1', $message) ?? $message;
if ($sqlPos = \strpos($message, 'to use near')) {
$message = \mb_strcut($message, 0, $sqlPos);
}
return $message;
}
/**
* Anonymize stack trace
*
* @param \Throwable $e
* @return string
*/
public static function getAnonymizedStackTrace(\Throwable $e): string
{
$projectPath = \realpath(\sprintf('%s/../', \app_path()));
$traceStack = $e->getTrace();
$traceStr = '';
$maxStackStage = 0;
foreach ($traceStack as $stackStage => $stack) {
$maxStackStage = $stackStage;
$traceStr .= \sprintf(
'#%s %s(%d): ',
$stackStage,
str_replace($projectPath, '', $stack['file'] ?? ''),
$stack['line'] ?? ''
);
if (isset($stack['class'])) {
$traceStr .= "{$stack['class']}->{$stack['function']}(";
if (isset($stack['args'])) {
$traceStr .= self::handleArgs($stack);
}
$traceStr .= ")\n";
} else {
$traceStr .= "{$stack['function']}(";
if (isset($stack['args'])) {
$traceStr .= self::handleArgs($stack);
}
$traceStr .= ")\n";
}
} //end foreach
$maxStackStage++;
$traceStr .= "#$maxStackStage {main}";
return $traceStr;
}
/**
* Handle Args
*
* @param array $stack
* @return string
*/
public static function handleArgs(array $stack): string
{
$traceArgs = '';
$argsCount = count($stack['args']);
for ($i = 0; $i < $argsCount; $i++) {
$type = \gettype($stack['args'][$i]);
switch ($type) {
case 'object':
$traceArgs .= sprintf('Object(%s)', \get_class($stack['args'][$i]));
break;
case 'array':
$traceArgs .= sprintf('Array(%d)', \count($stack['args'][$i]));
break;
case 'string':
$traceArgs .= sprintf('String(%d)', \strlen($stack['args'][$i]));
break;
default:
$traceArgs .= \gettype($stack['args'][$i]);
}
$traceArgs .= ($i !== ($argsCount - 1) ? ',' : '');
}
return $traceArgs;
}
}

Some files were not shown because too many files have changed in this diff Show more