Compare commits

..

174 commits

Author SHA1 Message Date
Noah Lancien
5a15a5713f Merge branch 'trunk' 2025-12-01 09:12:22 +01:00
Noah Lancien
324841b778 Merge branch 'develop' into trunk 2025-12-01 09:11:52 +01:00
noah.lancien
42faaf51bb Merge branch '28-code-article' into 'develop'
fix: adding an article code to a media was broken #28

See merge request ldc-web/projets/dam!10
2025-12-01 08:09:29 +00:00
Noah Lancien
6f5a7dae69 fix: remove useless parts from previous commit 2025-11-28 17:31:54 +01:00
Noah Lancien
0f74b496ab fix: adding an article code to a media was broken #28 2025-11-28 17:20:03 +01:00
Vincent BRIDIER
286d3adc6b Merge branch 'trunk' 2025-11-19 15:07:56 +01:00
Vincent BRIDIER
748597277e Merge branch 'develop' into trunk 2025-11-19 15:07:48 +01:00
Vincent BRIDIER
20e5a325ff fix: some fixes 2025-11-19 15:07:39 +01:00
Vincent BRIDIER
ea692f98ac Merge branch 'trunk' 2025-11-19 15:03:03 +01:00
Vincent BRIDIER
931c53d76a Merge branch 'develop' into trunk 2025-11-19 15:02:55 +01:00
Vincent BRIDIER
a73bcc2b4b fix: some fixes 2025-11-19 15:02:45 +01:00
Vincent BRIDIER
05e1d60159 Merge branch 'trunk' 2025-11-19 14:28:31 +01:00
Vincent BRIDIER
9c2a3fb82e Merge branch 'develop' into trunk 2025-11-19 14:28:22 +01:00
Vincent BRIDIER
6c90845c4c fix: some fixes 2025-11-19 14:27:59 +01:00
Vincent BRIDIER
4976f1cac9 Merge branch 'block-arcadia-link-for-drafts' into 'develop'
feat: block arcadia link request when the media is in draft status

See merge request ldc-web/projets/dam!9
2025-11-19 13:20:20 +00:00
Noah Lancien
116f465849 feat: block arcadia link request when the media is in draft status 2025-11-19 11:20:01 +01:00
Vincent BRIDIER
840c3ea475
fix: Fix media link on ArcadiaLink 2025-11-17 17:31:56 +01:00
Vincent BRIDIER
7a9c8f4da3
fix: Fix xml generation on ArcadiaLink 2025-11-17 17:06:38 +01:00
Vincent BRIDIER
dbb92dd6ed
fix: Fix variante field - Close #27 2025-11-17 16:00:34 +01:00
Vincent BRIDIER
23147b209e Merge branch '24-alphabetical-order-for-user-list' into 'develop'
feat: order by alphabetical ASC the user list in delete page

See merge request ldc-web/projets/dam!7
2025-10-28 12:06:40 +00:00
Noah Lancien
763ace7667 feat: order by alphabetical ASC the user list in delete page 2025-10-28 09:49:12 +01:00
Vincent BRIDIER
241adfeb50
Merge branch 'trunk' 2025-10-27 16:08:03 +01:00
Vincent BRIDIER
9f3b536bf7
Merge branch 'develop' into trunk 2025-10-27 16:07:54 +01:00
Vincent BRIDIER
b6338d4574
fix: Fix folders regressions in controller 2025-10-27 16:07:44 +01:00
Vincent BRIDIER
485e66c137
Merge branch 'trunk' 2025-10-24 12:25:26 +02:00
Vincent BRIDIER
ac9dbc3aad
Merge branch 'develop' into trunk 2025-10-24 12:25:07 +02:00
Vincent BRIDIER
3d1e08c664
Merge branch 'develop' of lab.s-web.fr:ldc-web/projets/dam into develop 2025-10-24 12:22:53 +02:00
Vincent BRIDIER
1a64f7b0d2
feat: Remove ldc web status checker deps + composer update 2025-10-24 12:15:28 +02:00
Vincent BRIDIER
f3c97443a6
feat: Add auth bypass feature for local dev 2025-10-24 12:15:01 +02:00
Vincent BRIDIER
5a25b0ba21
fix: Fix Media model event triggering 2025-10-24 12:06:58 +02:00
Vincent BRIDIER
b7392ec487
fix: Fix arcadia:import command 2025-10-24 11:19:49 +02:00
Noah Lancien
43ae1cb818 Merge branch 'trunk' 2025-06-04 15:18:47 +02:00
Noah Lancien
3b8cb4c5ae Merge branch 'develop' into trunk 2025-05-07 14:42:28 +02:00
noah.lancien
82368e2dd3 Merge branch 're7-feedback' into 'develop'
fix: folder filter now reset when the subject is updated

See merge request ldc-web/projets/dam!6
2025-05-07 12:41:56 +00:00
Noah Lancien
925dc2a495 fix: folder filter now reset when the subject is updated 2025-05-07 12:40:45 +02:00
Noah Lancien
b1763e5db3 Merge branch 'develop' into trunk 2025-05-06 12:08:43 +02:00
noah.lancien
e0870d362e Merge branch 'multiple-fixes' into 'develop'
Issues 6,7,8,9,10,12,13

See merge request ldc-web/projets/dam!4
2025-05-06 10:07:55 +00:00
Noah Lancien
0984fa00b7 fix: many fixes from develop branch + new re7 feedbacks 2025-05-06 12:05:18 +02:00
Jérémy Munsch
ad00dd2246 Reset Media route resolv using uid (besoin métier) vu avec Vincent 2025-05-06 11:10:16 +02:00
Jérémy Munsch
3dce58d9a0 Fixes #12 Fixed MediaController::esFilters arcadia_id fetch from filters issue 2025-05-06 11:10:16 +02:00
Jérémy Munsch
0194d8e0c1 Fix Media duplicate
- put in transaction
- set arcadia_id to null
2025-05-06 11:10:13 +02:00
Jérémy Munsch
14aeec5e2a Fixes #10
- Remove explicition resolve for media in RouteServicePRovider
- Set usage of media id on media routes everywhere
2025-05-06 11:02:02 +02:00
Jérémy Munsch
eb212215a8 Fixes #9
- add FK on arcadia_links to media.id and remove orphans
- Refactored ArcadiaLinkController
- Added comments on ArcadiaLink model
- refactored arcadialinks.index
2025-05-06 11:02:02 +02:00
Jérémy Munsch
c5d8ea542f Add View service provider (prepare to bump slowly) 2025-05-06 11:02:02 +02:00
Jérémy Munsch
50832db21b Fixes #8+
Enums arent using BaseEnum trait and cannot since tool low php level, need to manually implement behaviors
2025-05-06 11:02:02 +02:00
Jérémy Munsch
c6eaf2f12b MediaController refactor getMediaOtherInfos 2025-05-06 11:02:02 +02:00
Jérémy Munsch
8651a5cc2a Fixes #7,#13 REfactor BasektController + Flush cache before querying basket media list 2025-05-06 11:02:00 +02:00
Jérémy Munsch
bc4a8f64ae Fixes #6 2025-05-06 11:01:28 +02:00
Jérémy Munsch
d62b1d513f UploadController fix Media query 2025-05-06 11:01:26 +02:00
Jérémy Munsch
f6dc577255 Add TODO in config/roles 2025-05-06 11:00:15 +02:00
Jérémy Munsch
80615fe61a Add Model User comments 2025-05-06 11:00:15 +02:00
Jérémy Munsch
92d837586e MediaController::loadMedia refactor 2025-05-06 11:00:14 +02:00
Jérémy Munsch
e18918fa61 Dossier model refactor getMediacountAttribute 2025-05-06 10:59:23 +02:00
Jérémy Munsch
156c4a6317 DossierController refactor with typehint 2025-05-06 10:59:23 +02:00
Jérémy Munsch
20c1d2da6f .gitignore update 2025-05-06 10:59:23 +02:00
Jérémy Munsch
d0778093d5 npm update 2025-05-06 10:59:23 +02:00
Jérémy Munsch
39a28c5e3f composer update 2025-05-06 10:59:23 +02:00
Jérémy Munsch
d41acba6c5 add name to package json 2025-05-06 10:59:23 +02:00
Jérémy Munsch
c9be7205be update client api + add .gitmodules 2025-05-06 10:59:23 +02:00
Noah Lancien
d34a9a4624 Merge branch 'develop' into trunk 2025-03-25 16:18:55 +01:00
noah.lancien
29f8dfd724 Merge branch 'issue-20-re7-feedback' into 'develop'
fix: many bug fixes - #20

See merge request ldc-web/projets/dam!5
2025-03-25 15:17:09 +00:00
Noah Lancien
58287ae7bc Merge branch 'develop' into trunk 2025-03-25 16:17:00 +01:00
Noah Lancien
98cbbe5b93 fix: review feedbacks 2025-03-25 15:23:44 +01:00
Noah Lancien
e39f4e8146 feat: added a link to media manager in the home page 2025-03-25 11:24:59 +01:00
Noah Lancien
caa7189cc3 fix: many bug fixes - #20 2025-03-25 11:00:14 +01:00
Vincent BRIDIER
764044384a Fix issue templates dir name 2023-11-24 11:05:14 +00:00
Vincent BRIDIER
daafb0c314 Add issue templates 2023-11-24 11:02:28 +00:00
Vincent BRIDIER
42f28abe33
Merge branch 'develop' into trunk 2023-11-24 09:42:12 +01:00
Vincent BRIDIER
6cce9a4449 Merge into 'develop'
Full rewrite DAM + API DAM + CLIENT

See merge request ldc-web/projets/dam!2
2023-11-24 08:27:41 +00:00
Vincent BRIDIER
2a898c3816
Remove sanctum 2023-11-10 16:31:11 +01:00
Vincent BRIDIER
a96fa57b85
NPM audit fix 2023-11-10 11:22:27 +01:00
Vincent BRIDIER
347a83d502
Composer update 2023-11-10 11:20:43 +01:00
Vincent BRIDIER
84e05664c5
Merge branch 'develop' into fckApi 2023-11-10 11:13:33 +01:00
Sebastien Hattry
1d8e8994bb Change dest mail 2023-06-29 07:32:26 +00:00
Jérémy Munsch
e6bcdcb8af
Merge branch 'hotfix' into develop 2022-10-26 13:00:29 +02:00
Jérémy Munsch
d343d87486
Merge branch 'hotfix' 2022-10-26 12:59:57 +02:00
Jérémy Munsch
5926c23a04
Allow contact list to be an array 2022-10-26 12:59:45 +02:00
Jérémy Munsch
9dfc4bf7e1
Merge branch 'hotfix' into develop 2022-10-26 12:47:17 +02:00
Jérémy Munsch
592bd9bdaa
Merge branch 'hotfix' 2022-10-26 12:45:49 +02:00
Jérémy Munsch
4e19c1c408
mail config MAIL_LIST_INVALID_XML 2022-10-26 12:45:23 +02:00
Jérémy Munsch
694eab00d0
add client as submodule 2022-08-01 17:46:36 +02:00
Jérémy Munsch
6bcfc66a9d
Add missing thumbs to api media list 2022-08-01 17:38:13 +02:00
Jérémy Munsch
d5edbebbdf
redis caching for used models on api 2022-08-01 16:27:22 +02:00
Jérémy Munsch
b06642b1bf
Token regen 2022-08-01 10:59:56 +02:00
Jérémy Munsch
f63220ff2a
Client generartion 2022-07-29 15:19:30 +02:00
Jérémy Munsch
5e14218ad4
Api + unit tests 2022-07-29 13:12:34 +02:00
Jérémy Munsch
aef61a6c8f
Media : Fix thumbnail generation 2022-07-28 12:21:06 +02:00
Jérémy Munsch
d2236fe041
Fixed upload system 2022-07-28 12:21:02 +02:00
Jérémy Munsch
ba2b9dcde2
Fix media sync with arcadia on update only if linked, check before link that is not already linked. 2022-07-27 16:57:05 +02:00
Jérémy Munsch
e7f5a7e6cd
Fix update media request missing articles + enum validate 2022-07-27 16:35:18 +02:00
Jérémy Munsch
14ff7b9413
Fix isLocked to be boolean 2022-07-27 16:30:03 +02:00
Jérémy Munsch
1f988cab3a
Change Media statut into Enum 2022-07-26 13:20:21 +02:00
Jérémy Munsch
f657e39a2e
Fix update media articles 2022-07-26 11:57:16 +02:00
Jérémy Munsch
7166d9a097
Token Crud on console + Mail on create and destroy 2022-07-26 10:39:55 +02:00
Jérémy Munsch
28f95934ed
Fix user marques relation 2022-07-25 13:09:46 +02:00
Jérémy Munsch
34a589307e
fir selector list freaking JS 2022-07-25 13:06:09 +02:00
Jérémy Munsch
3e4484ab71
npm bump deps 2022-07-25 12:57:53 +02:00
Jérémy Munsch
916c49012a
update composer deps 2022-07-25 12:49:18 +02:00
Jérémy Munsch
58a848524f
simplify more code 2022-07-25 12:21:18 +02:00
Jérémy Munsch
e107cfd337
simplify esFolderSearch 2022-07-25 12:11:35 +02:00
Jérémy Munsch
50a5aa5604
Changed event history to type 2022-07-25 12:08:16 +02:00
Jérémy Munsch
01cef75e0c
Remove TODO Supprimer old fichier dans le cas d'un update alrready done 2022-07-25 12:08:15 +02:00
Jérémy Munsch
ae30f926bb
Done TODO: delete all subject file type for a media on delete 2022-07-25 12:08:15 +02:00
Jérémy Munsch
914ab4c5f9
Fix: download media public 2022-07-25 12:08:15 +02:00
Jérémy Munsch
7085ec1aaa
Reorder route things + bind models for some routes 2022-07-25 12:08:11 +02:00
Jérémy Munsch
9767e62c72
Update NPM deps and webpack.mix.js
composer require ldc/web-status-checker-laravel remove Old static status checker

Fix ImportMedia

WIP commands OK

many fixes

Fix and try to optimize folder component

Fix front icons + actions based on icons

Favico

front fix alert

Fix Media upload on depot

fix folder component buttons

Full front fix with perf due tu vuejs

Download medias

Navigate within medias superfix

Move media + loader

isLocked boolean and remove media fix

Folder scroll fix

arcadia link color red

Fix panier show external

Tons of fixes back as front

REwrited all
2022-07-22 17:00:48 +02:00
Vincent BRIDIER
bb38b9e400 Merge bump into 'develop' 2022-06-20 12:07:52 +00:00
Vincent BRIDIER
412ccdd57a
Update config mail verify_peer 2022-06-20 14:04:17 +02:00
Jérémy Munsch
e0aef7537b
Install handler + require kwaadpepper/exception-handler 2022-06-20 14:04:17 +02:00
Jérémy Munsch
c76a7ff50c
PSR4 Fix LdcWebStatusChecker 2022-06-20 14:04:16 +02:00
Jérémy Munsch
0d95c8bbfd
Bump to Laravel 9 2022-06-20 14:04:16 +02:00
Jérémy Munsch
aa29234e55
PHPCS pass + some refactor 2022-06-20 14:04:15 +02:00
Jérémy Munsch
5bd0004152
Bump to Laravel 8 2022-06-20 14:00:52 +02:00
Jérémy Munsch
3a50b41bb3
Bump to Laravel 7 2022-06-20 13:59:09 +02:00
Jérémy Munsch
0970756f77
Bump to laravel 6 2022-06-20 13:59:09 +02:00
Jérémy Munsch
2607ad4493
composer bump and npm bump 2022-06-20 13:59:09 +02:00
Vincent BRIDIER
44a6f6b7ed
Merge branch 'trunk' 2022-04-20 17:34:32 +02:00
Vincent BRIDIER
f6e0e96e62
Merge branch 'develop' into trunk 2022-04-20 17:34:19 +02:00
Vincent BRIDIER
ab997c2327
Fix ES ArcadiaMedia IN 2022-04-20 17:33:40 +02:00
Vincent BRIDIER
e2b70f3e6f
Merge branch 'trunk' 2022-04-20 16:54:04 +02:00
Vincent BRIDIER
1fd1ee1317
Merge branch 'develop' into trunk 2022-04-20 16:53:46 +02:00
Vincent BRIDIER
67d7175874
Fix ES ArcadiaMedia IN 2022-04-20 16:50:22 +02:00
Vincent BRIDIER
9631a9eb2f
Merge branch 'trunk' 2022-04-20 16:06:56 +02:00
Vincent BRIDIER
b9814687c0
Merge branch 'develop' into trunk 2022-04-20 16:06:37 +02:00
Vincent BRIDIER
0eede926cd
Fix ArcadiaLink 2022-04-20 16:06:19 +02:00
Vincent BRIDIER
43fcd9e09f
Merge branch 'trunk' 2022-04-20 15:20:21 +02:00
Vincent BRIDIER
8fde9fb434
Merge branch 'develop' into trunk 2022-04-20 15:19:56 +02:00
Vincent BRIDIER
2ed9468fb5
Merge branch 'ticket552' into develop 2022-04-19 18:05:10 +02:00
Jérémy Munsch
c8eaa0cc3f
Fix component loader 2022-04-19 17:30:21 +02:00
Jérémy Munsch
dd0c611845
Reload FolderComponent + enchainement sur reload DisplayComponent + loader sur Delete fiche 2022-04-14 17:00:56 +02:00
Jérémy Munsch
7d90eab8ec
Fix check error response nullable 2022-04-13 12:51:42 +02:00
Vincent BRIDIER
d91f4f4d3c
Merge branch 'trunk' 2022-04-07 09:16:44 +02:00
Vincent BRIDIER
5aaf5c642b
merge develop 2022-04-07 09:16:14 +02:00
Jérémy Munsch
5d69546de5
Ticket 552: Delete files reactivation (except locked ones) 2022-04-04 18:28:55 +02:00
Jérémy Munsch
73813051b1
Ticket 772: versionnage des assets compilé mix 2022-04-04 15:52:06 +02:00
Jérémy Munsch
aad92ff352
Ticket 780 fix cancel on basket creation 2022-04-01 15:18:29 +02:00
Vincent BRIDIER
8b5ea3735c
Merge branch 'develop' into trunk 2022-04-01 12:16:05 +02:00
Vincent BRIDIER
22e796ec67
Merge branch 'ticket765' into develop 2022-04-01 12:14:05 +02:00
Vincent BRIDIER
710b8a4ab0
Update FolderComponent to toggle favs 2022-04-01 11:53:14 +02:00
Jérémy Munsch
a8e220a803
Ticket 765: Rewrite panier system 2022-04-01 10:18:04 +02:00
Vincent BRIDIER
2467e01e0e
Merge branch 'develop' into trunk 2022-03-31 12:43:03 +02:00
Jérémy Munsch
26d540a28c
Ticket 762 : Session Alert and redirect on ajax + add afterClose to FancyMessage 2022-03-31 12:30:59 +02:00
Jérémy Munsch
1d06a75b1e
Add project peacock color 2022-03-31 11:53:23 +02:00
Vincent BRIDIER
f3423f4c89
Merge branch 'develop' into trunk 2022-03-31 11:42:21 +02:00
Vincent BRIDIER
b120c1a039
Merge remote-tracking branch 'origin/ticket766' into develop 2022-03-31 11:39:59 +02:00
Vincent BRIDIER
25ccced946
re merge ticket559 2022-03-31 11:33:43 +02:00
Jérémy Munsch
ae64232b39
Ticket 766: users.index remove sujets var 2022-03-31 11:22:26 +02:00
Vincent BRIDIER
45e80a7840
fix folder icon fontawesome 2022-03-30 18:01:55 +02:00
Vincent BRIDIER
1ac87290fa
ticket 369 2022-03-28 17:43:52 +02:00
Vincent BRIDIER
9a35d7a5b6
Merge branch 'develop' into trunk 2022-03-28 12:38:05 +02:00
Vincent BRIDIER
4f522db2b9
Fix Ticket 86 2022-03-28 12:37:43 +02:00
Vincent BRIDIER
4f7de039e8
Merge branch 'develop' into trunk 2022-03-28 11:40:19 +02:00
Vincent BRIDIER
6975680e64
Fix folders close 2022-03-28 11:39:59 +02:00
Vincent BRIDIER
99df59ce23
Merge branch 'develop' into trunk 2022-03-28 10:54:30 +02:00
Vincent BRIDIER
353fa7108a
Merge remote-tracking branch 'origin/ticket356' into develop 2022-03-28 10:44:41 +02:00
Jérémy Munsch
67106ef209
Ticket 356: FolderComponent Close Folders by default + force rerender after click on develop folder 2022-03-28 10:39:52 +02:00
Jérémy Munsch
e78c901d21
Ticket 734: reset grabbed on component load instead of loadMedias action (prevent selection reset on inifinite load) 2022-03-28 10:18:48 +02:00
Jérémy Munsch
9af98e3225
Fix: remaining font awesome classes after upgrade 2022-03-28 10:06:12 +02:00
Jérémy Munsch
dd1291d2f1
Ticket 559: Fix display layout + sort date (reste UTF-8 elastic) 2022-03-24 12:25:00 +01:00
Vincent BRIDIER
8bcf95011a Merge branch 'develop' into trunk 2022-02-15 10:25:48 +01:00
Olivier Legat
ef798a07ae Merge branch 'develop' into trunk 2022-01-24 17:07:44 +01:00
Vincent BRIDIER
1b5f49d979 Merge branch 'trunk' 2021-11-09 16:42:33 +01:00
Vincent BRIDIER
4b3f3ea948 Merge branch 'develop' into trunk 2021-11-09 16:42:17 +01:00
Vincent BRIDIER
6039963868 Merge branch 'trunk' 2021-09-28 10:02:40 +02:00
Vincent BRIDIER
5cf9e286eb Merge branch 'develop' into trunk 2021-09-28 10:01:43 +02:00
Olivier Legat
3b20915c4f Merge branch 'trunk' 2021-09-01 11:57:24 +02:00
Olivier Legat
82267c1b9d Merge branch 'develop' into trunk 2021-09-01 11:56:41 +02:00
Olivier Legat
d7469ef5c6 Merge branch 'trunk' 2021-07-19 09:05:24 +02:00
Olivier Legat
b46841a024 Merge branch 'develop' into trunk 2021-07-19 09:05:10 +02:00
Olivier Legat
4ae3f4f70f Merge branch 'trunk' 2021-07-13 14:40:17 +02:00
Olivier Legat
8691c45231 Merge branch 'trunk' 2021-07-09 13:19:36 +02:00
Olivier Legat
f8ea161878 Merge branch 'trunk' 2021-07-09 10:35:07 +02:00
Olivier Legat
50f1da22e6 Merge branch 'trunk' 2021-06-17 16:43:58 +02:00
Olivier Legat
89973ff2a0 Merge branch 'trunk' 2021-06-17 16:35:42 +02:00
362 changed files with 33688 additions and 33107 deletions

View file

@ -11,5 +11,8 @@ trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.yml]
[*.yml,yaml]
indent_size = 2
[docker-compose.yml]
indent_size = 4

View file

@ -6,6 +6,8 @@ APP_URL=http://localhost
PROJECT_UUID=
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
@ -16,13 +18,20 @@ DB_PASSWORD=secret
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
@ -39,6 +48,16 @@ LDAP_USERNAME="cn=admin,dc=example,dc=org"
LDAP_PASSWORD=adminpassword
LDAP_USE_SSL=false
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
ELASTICSEARCH_HOSTS=
MAIL_LIST_SERVICEWEB=
PROJECT_UUID=
## MAIL ADDRESSES
MAIL_LIST_SERVICEWEB=digital@ldc.fr

60
.env.testing Normal file
View file

@ -0,0 +1,60 @@
APP_NAME=Dam
APP_ENV=local
APP_KEY=base64:2fKdUeMKBwyKzJeOcIaRXC0yujSMKkQJ98XLhC2uqf0=
APP_DEBUG=true
APP_URL=https://dam.s-web.test
PROJECT_UUID=
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=dev-mariadb
DB_PORT=3306
DB_DATABASE=testing_dam
DB_USERNAME=root
DB_PASSWORD=secret
ELASTICSEARCH_HOSTS=dev-elasticsearch:9200
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=dev-mailhog
MAIL_PORT=1025
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=no-reply@dam.lesidc.com
MAIL_FROM_NAME="${APP_NAME}"
MAIL_ADMIN=digital@ldc.fr
LDAP_ACCOUNT_PREFIX="cn="
LDAP_ACCOUNT_SUFFIX=",ou=users,dc=example,dc=org"
LDAP_HOSTS=dev-openldap
LDAP_PORT=1389
LDAP_BASE_DN="dc=example,dc=org"
LDAP_USERNAME="cn=admin,dc=example,dc=org"
LDAP_PASSWORD=adminpassword
LDAP_USE_SSL=false
PROJECT_UUID=
## MAIL ADDRESSES
MAIL_LIST_SERVICEWEB=digital@ldc.fr
LDC_STATUS_CHECKER_API_KEY=CE8S52Qq7stf5k8frF4T
LDC_STATUS_CHECKER_UUID=4d8b2c20-107a-4682-b591-dc6c685126df

60
.env.testing.example Normal file
View file

@ -0,0 +1,60 @@
APP_NAME=Dam
APP_ENV=local
APP_KEY=base64:2fKdUeMKBwyKzJeOcIaRXC0yujSMKkQJ98XLhC2uqf0=
APP_DEBUG=true
APP_URL=https://dam.s-web.test
PROJECT_UUID=
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=dev-mariadb
DB_PORT=3306
DB_DATABASE=testing_dam
DB_USERNAME=root
DB_PASSWORD=
ELASTICSEARCH_HOSTS=dev-elasticsearch:9200
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=dev-mailhog
MAIL_PORT=1025
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=no-reply@dam.lesidc.com
MAIL_FROM_NAME="${APP_NAME}"
MAIL_ADMIN=digital@ldc.fr
LDAP_ACCOUNT_PREFIX=
LDAP_ACCOUNT_SUFFIX=
LDAP_HOSTS=
LDAP_PORT=
LDAP_BASE_DN=
LDAP_USERNAME=
LDAP_PASSWORD=
LDAP_USE_SSL=
PROJECT_UUID=
## MAIL ADDRESSES
MAIL_LIST_SERVICEWEB=digital@ldc.fr
LDC_STATUS_CHECKER_API_KEY=
LDC_STATUS_CHECKER_UUID=

11
.gitattributes vendored
View file

@ -1,5 +1,10 @@
* text=auto
*.css linguist-vendored
*.scss linguist-vendored
*.js linguist-vendored
*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php
/.github export-ignore
CHANGELOG.md export-ignore

7
.gitignore vendored
View file

@ -25,10 +25,13 @@ public/uploads/*
/storage/*.key
/vendor
.env
.env*
.phpunit.result.cache
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
.idea/
/.idea
/.vscode
*.sqlite*
auth.json

View file

@ -0,0 +1,11 @@
## Comportement constaté
## Comportement attendu
## Solution envisagée
## Étapes pour la reproduction du bug
*

View file

@ -0,0 +1,7 @@
## Présentation du besoin
## Implémentation
## Maquettes, documentations...

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "clients/Api"]
path = clients/Api
url = ../dam-client.git

13
.styleci.yml Normal file
View file

@ -0,0 +1,13 @@
php:
preset: laravel
disabled:
- unused_use
- no_unused_imports
finder:
not-name:
- index.php
js:
finder:
not-name:
- webpack.mix.js
css: true

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

@ -0,0 +1,24 @@
{
"workbench.colorCustomizations": {
"activityBar.activeBackground": "#826d05",
"activityBar.activeBorder": "#07b89a",
"activityBar.background": "#826d05",
"activityBar.foreground": "#e7e7e7",
"activityBar.inactiveForeground": "#e7e7e799",
"activityBarBadge.background": "#07b89a",
"activityBarBadge.foreground": "#e7e7e7",
"sash.hoverBorder": "#826d05",
"statusBar.background": "#514403",
"statusBar.foreground": "#e7e7e7",
"statusBarItem.hoverBackground": "#826d05",
"statusBarItem.remoteBackground": "#514403",
"statusBarItem.remoteForeground": "#e7e7e7",
"titleBar.activeBackground": "#514403",
"titleBar.activeForeground": "#e7e7e7",
"titleBar.inactiveBackground": "#51440399",
"titleBar.inactiveForeground": "#e7e7e799",
"commandCenter.border": "#e7e7e799"
},
"peacock.remoteColor": "#514403",
"intelephense.environment.phpVersion": "8.1"
}

View file

@ -1,4 +1,10 @@
# DAM
# TODO:
- Remplace par VUE 3 + Runtime Only
- Typescript
- Faut-il exporter les stats Api avant de supprimer un ApiToken ?
## Installation
### - Default
```
@ -7,20 +13,24 @@ composer install
cp .env.example .env
php artisan key:generate
```
### - Stack en attendant le bump Laravel
### - Stack Laravel
```
npm install && npm run prod
composer install
```
Dans vendor/laravel/framework/src/Illuminate/Foundation/PackageManifest.php, ligne 116
```
//$packages = json_decode($this->files->get($path), true);
$installed = json_decode($this->files->get($path), true);
$packages = $installed['packages'] ?? $installed;
```
Puis
```
composer install
cp .env.example .env
php artisan key:generate
```
# BUMP LARAVEL MEP
.env => remplacer MAIL_DRIVER par MAIL_MAILER
.env => remplacer FILESYSTEM_DRIVER par FILESYSTEM_DISK
.env rajouter PROJECT_UUID=
.env rajouter MAIL_LIST_SERVICEWEB=digital@ldc.fr
# SUPERVISOR
jobs Api stats sur queue `database`
## Dans les LABs
```
MAIL_VERIFY_PEER=false
```

View file

@ -0,0 +1,225 @@
<?php
namespace App\Console\Commands\Api;
use App\Enums\Legacy\ApiError;
use App\Enums\Legacy\ApiStatus;
use App\Enums\MediaExtension;
use App\Exceptions\Api\ApiErrorException;
use App\Exceptions\Api\DamException;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Route;
use Symfony\Component\Process\Process;
/**
* @codeCoverageIgnore
*/
class GenerateApiClient extends Command
{
private const TARGET = 'clients/Api/src';
private const CLIENTNAMESPACE = 'LDC\\DAM\\Client';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'api:generate-client';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate the dam client in clients/Api folder';
/**
* Execute the console command.
*
* @return integer
*/
public function handle()
{
$this->copyEnums();
$this->copyExceptions();
$this->copyRoutesList();
$this->copyApiConfigInfo();
return 0;
}
/**
* Copy config files
*
* @return void
*/
private function copyApiConfigInfo()
{
$this->info('Copy Api Config');
$rootTarget = app_path('../' . self::TARGET);
if (File::exists("$rootTarget/../apiConfig.readonly.json")) {
File::delete("$rootTarget/../apiConfig.readonly.json");
}
File::put(
"$rootTarget/../apiConfig.readonly.json",
\json_encode(config('api'), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
);
$this->phpcbfFile("$rootTarget/../apiConfig.readonly.json");
}
/**
* Copy routes into a json file
*
* @return void
*/
private function copyRoutesList()
{
$this->info('Copy Routes');
$routes = [];
/** @var \Illuminate\Routing\Route */
foreach (Route::getRoutes() as $route) {
if (\strpos($route->getPrefix(), 'api') !== false) {
$routes[$route->getName()] = [
'uri' => $route->uri(),
'methods' => $route->methods()
];
}
}
$rootTarget = app_path('../' . self::TARGET);
if (File::exists("$rootTarget/routes.json")) {
File::delete("$rootTarget/routes.json");
}
File::put(
"$rootTarget/routes.json",
\json_encode($routes, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
);
$this->phpcbfFile("$rootTarget/routes.json");
}
/**
* Copy Exeption classes
*
* @return void
*/
private function copyExceptions(): void
{
$this->info('Copy Exceptions');
$rootTarget = app_path('../' . self::TARGET);
$this->copyToFolder([
DamException::class,
ApiErrorException::class
], 'Exceptions');
$this->replaceInPhpFile(
"$rootTarget/Exceptions/ApiErrorException.php",
ApiError::class,
self::CLIENTNAMESPACE . '\\Enums\\ApiError'
);
$this->replaceInPhpFile(
"$rootTarget/Exceptions/DamException.php",
DamException::class,
self::CLIENTNAMESPACE . '\\Exceptions\\DamException'
);
$this->replaceInPhpFile(
"$rootTarget/Exceptions/DamException.php",
ApiErrorException::class,
self::CLIENTNAMESPACE . '\\Exceptions\\ApiErrorException'
);
$this->phpcbfFile("$rootTarget/Exceptions/DamException.php");
$this->phpcbfFile("$rootTarget/Exceptions/ApiErrorException.php");
}
/**
* Copy enums classes
*
* @return void
*/
private function copyEnums(): void
{
$this->info('Copy Enums');
$classes = [
ApiError::class,
ApiStatus::class
];
$this->copyToFolder($classes, 'Enums');
$rootTarget = app_path('../' . self::TARGET);
foreach ($classes as $class) {
$classBasename = class_basename($class);
$dest = "$rootTarget/Enums/$classBasename.php";
$this->replaceInPhpFile($dest, 'BaseEnumRoutable', 'BaseEnum');
$this->replaceInPhpFile($dest, '\\Legacy', '');
$this->phpcbfFile($dest);
}
$mediaExtensionEnum = "<?php\n\nnamespace LDC\DAM\Client\Enums;\n\nuse Kwaadpepper\Enum\BaseEnum;\n\n/**\n";
foreach (MediaExtension::cases() as $strType) {
$mediaExtensionEnum .= " * @method static self {$strType->name}()\n";
}
// phpcs:ignore Generic.Files.LineLength.TooLong
$mediaExtensionEnum .= " *\n * @package DAMclient\n * @subpackage enums\n */\nclass MediaExtension extends BaseEnum\n{\n}\n";
File::put("$rootTarget/Enums/MediaExtension.php", $mediaExtensionEnum);
$this->phpcbfFile("$rootTarget/Enums/MediaExtensio.php");
}
/**
* Copy Classes to specified folder
*
* @param array $classes
* @param string $folder
* @return void
*/
private function copyToFolder(array $classes, string $folder): void
{
$rootTarget = app_path('../' . self::TARGET);
foreach ($classes as $class) {
$classFileName = \str_replace("App\\$folder\\", '', sprintf('%s.php', $class));
$classFileName = \str_replace('\\', '/', $classFileName);
$classBasename = class_basename($class);
$source = \app_path("$folder/$classFileName");
$dest = "$rootTarget/$folder/$classBasename.php";
if (File::exists($dest)) {
File::delete($dest);
}
File::copy($source, $dest);
$this->replaceInPhpFile($dest, 'namespace App', 'namespace ' . self::CLIENTNAMESPACE);
}
}
/**
* Replaces a specific string with another on a file
*
* @param string $source
* @param string $search
* @param string $replace
* @return void
*/
private function replaceInPhpFile(string $source, string $search, string $replace): void
{
$fContent = File::get($source);
// Remove trailing \Api .
$regex = '/namespace ([a-zA-Z0-9\\\\]+)\\\\Api;/m';
$fContent = preg_replace($regex, 'namespace $1;', $fContent);
// Replace namespace top level.
$pos = strpos($fContent, $search);
if ($pos !== false) {
File::put($source, \str_replace($search, $replace, $fContent));
}
}
/**
* Lint the file
*
* @param string $path
* @return void
* @throws \Symfony\Component\Process\Exception\RuntimeException If anything goes wrong.
* @throws \Symfony\Component\Process\Exception\ProcessTimedOutException If anything goes wrong.
* @throws \Symfony\Component\Process\Exception\ProcessSignaledException If anything goes wrong.
* @throws \Symfony\Component\Process\Exception\LogicException If anything goes wrong.
*/
private function phpcbfFile(string $path): void
{
$process = new Process(['./vendor/bin/phpcbf', $path]);
$process->run();
}
}

View file

@ -0,0 +1,184 @@
<?php
namespace App\Console\Commands\Api;
use App\Mail\Api\ApiTokenCreated;
use App\Mail\Api\ApiTokenRegenerated;
use App\Mail\Api\ApiTokenRemoved;
use App\Models\Api\ApiToken;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
class TokenCrud extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'api:token
{action? : Can be list, add, remove, regen, default is list}
{api_token? : Only if action is remove, pass the ID to remove}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Manage api tokens';
/**
* Execute the console command.
*
* @return inteager
*/
public function handle(): int
{
switch ($this->argument('action')) {
case null:
case 'list':
$this->table(['id', 'name', 'token_date'], ApiToken::all()->map(function (ApiToken $apiToken) {
return [
'id' => $apiToken->id,
'name' => $apiToken->name,
'token_date' => $apiToken->token_date,
];
}));
return 0;
case 'add':
return $this->createApiToken();
case 'remove':
return $this->removeApiToken();
case 'regen':
return $this->regenApiToken();
default:
$this->error(\sprintf(
'action \'%s\' is not availaible, use --help to see usage.',
$this->argument('action')
));
return -1;
} //end switch
}
/**
* Create api Token
*
* @return integer
*/
private function createApiToken(): int
{
return DB::transaction(function () {
$apiToken = new ApiToken();
do {
if (!($apiToken->name = $this->ask('Give your token a name'))) {
$this->warn('Please provide a valid name.');
}
} while (!$apiToken->name);
$publicToken = $apiToken->generatePublicToken();
$privateToken = $apiToken->generatePrivateToken();
if (
!$this->confirm(
"Are you should you want to create the following '{$apiToken->name}'"
)
) {
$this->info('Nothing was created.');
return 0;
}
$apiToken->saveOrFail();
Mail::send(new ApiTokenCreated($apiToken));
$this->alert("
Your new api Token for '{$apiToken->id}' named '{$apiToken->name}'
public: {$publicToken}
private: {$privateToken}
Please take note as it wont be available to display anymore !
");
return 0;
});
}
/**
* Remove Api token
*
* @return integer
*/
private function removeApiToken(): int
{
return DB::transaction(function () {
if (!\is_numeric($apiTokenId = $this->argument('api_token'))) {
$this->error('remove command needs an id, use `list` to see all.');
return -1;
}
/** @var \App\Models\Api\ApiToken|null */
if (!($apiToken = ApiToken::where('id', $apiTokenId)->first())) {
$this->error("api_token '{$apiTokenId}' was not found");
return -1;
}
if (
!$this->confirm(
"Are you sur you want to remove apiToken '{$apiToken->id}' '{$apiToken->name}' ?"
)
) {
$this->info('Nothing was deleted.');
return 0;
}
if (!$apiToken->deleteOrFail()) {
$this->error('removing apiToken failed');
}
Mail::send(new ApiTokenRemoved($apiToken));
$this->alert("apiToken '{$apiToken->id}' '{$apiToken->name}' has been removed !");
return 0;
});
}
/**
* Regenerate Api token
*
* @return integer
*/
private function regenApiToken(): int
{
return DB::transaction(function () {
if (!\is_numeric($apiTokenId = $this->argument('api_token'))) {
$this->error('remove command needs an id, use `list` to see all.');
return -1;
}
/** @var \App\Models\Api\ApiToken|null */
if (!($apiToken = ApiToken::where('id', $apiTokenId)->first())) {
$this->error("api_token '{$apiTokenId}' was not found");
return -1;
}
$publicToken = $apiToken->generatePublicToken();
$privateToken = $apiToken->generatePrivateToken();
if (
!$this->confirm(
"Are you sur you want to regen apiToken '{$apiToken->id}' '{$apiToken->name}' ?"
)
) {
$this->info('Nothing was done.');
return 0;
}
$apiToken->saveOrFail();
Mail::send(new ApiTokenRegenerated($apiToken));
$this->alert("
Your new api Token for '{$apiToken->id}' named '{$apiToken->name}'
public: {$publicToken}
private: {$privateToken}
Please take note as it wont be available to display anymore !
");
return 0;
});
}
}

View file

@ -19,7 +19,7 @@ class ArcadiaLinkCommand extends Command
*
* @var string
*/
protected $description = 'Lecture du flux Arcadia entrant (medias). Run the XmlArcadiaMediasIn manually';
protected $description = 'Lecture du flux Arcadia entrant (media). Run the XmlArcadiaMediasIn manually';
/**
* Execute the console command.
@ -34,7 +34,7 @@ class ArcadiaLinkCommand extends Command
$job->console = $this;
$job->handle();
$this->line("");
$this->newLine();
$this->info('Fin du traitement');
}
}

View file

@ -2,10 +2,9 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use App\Models\Sujet;
use App\Models\Media;
use App\Models\Sujet;
use Illuminate\Console\Command;
class DeleteMediaArchive extends Command
{
@ -14,25 +13,16 @@ class DeleteMediaArchive extends Command
*
* @var string
*/
protected $signature = 'medias:deletearchive';
protected $signature = 'media:deletearchive';
/**
* The console command description.
*
* @var string
* @phpcs:disable Generic.Files.LineLength.TooLong
*/
protected $description = 'Suppression définitive de tous les médias (et leurs fichiers) qui ont été supprimés (en soft delete)';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
@ -40,60 +30,62 @@ class DeleteMediaArchive extends Command
*/
public function handle()
{
$this->info('Vous allez supprimer définitivement tous les médias (et leurs fichiers) qui ont été supprimés (en soft delete).');
//phpcs:ignore Generic.Files.LineLength.TooLong
$this->info('Vous allez supprimer définitivement tous les médias (et leurs fichiers) qui ont été supprimés (en soft delete).');
$choice = $this->choice('Etes-vous sûr de vouloir lancer ce traitement ?' , ['y', 'n'], 'y');
if (!$this->confirm('Etes-vous sûr de vouloir lancer ce traitement ?')) {
return 0;
}
if($choice != "y"){
$this->error('Choix incorrect');
die();
}
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Sujet> */
$subjects = Sujet::where('sujet_dam', true)->get();
$sujets = Sujet::where('sujet_dam', 1)->get();
$this->newLine();
$this->line('Liste des sujets disponibles');
$this->line('----------------------------');
$this->line('[0] Tous les sujets');
foreach ($subjects as $subject) {
$this->line("[{$subject->codeSujet}] {$subject->libelle}");
}
$this->line("");
$this->line("Liste des sujets disponibles");
$this->line("----------------------------");
foreach ($sujets as $key => $sujet) {
$this->line("[".$sujet->codeSujet."] ". $sujet->libelle);
}
$this->line("[0] Tous les sujets");
$sujetId = $this->askWithCompletion(
'Pour quel sujet de média souhaitez vous executer le traitement ?',
$subjects->pluck('codeSujet')->toArray(),
0
);
$sujetId = $this->ask('Pour quel sujet de média souhaitez vous executer le traitement ?' );
$this->newLine();
if($sujetId == ""){
$this->error('Id de sujet incorrect');
die();
}
if ($sujetId != 0 and !$subjects->pluck('codeSujet')->contains(\intval($sujetId))) {
$this->error('Id de sujet incorrect');
return -1;
}
if($sujetId == 0){
$medias = Media::onlyTrashed()->with('Sujet.formats')->get();
}else{
$medias = Media::onlyTrashed()->where('sujet_id', $sujetId)->with('Sujet.formats')->get();
}
$sujetId = intval($sujetId);
if($medias->count() == 0){
$this->error('Aucun média a supprimer');
die();
}
$mediaCollection = Media::onlyTrashed()->with('sujet.formats');
if ($sujetId !== 0) {
$mediaCollection->where('sujet_id', $sujetId);
}
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Media> */
$mediaCollection = $mediaCollection->get();
$this->info($medias->count().' média(s) trouvé(s) - Début du traitement');
$bar = $this->output->createProgressBar(count($medias));
$bar->start();
if (!$mediaCollection->count()) {
$this->error('Aucun média a supprimer');
return -1;
}
foreach ($medias as $media) {
// supprime les fichiers médias stockés sur disque
$files = Storage::files($media->folder."/");
$filepath = preg_quote($media->folder.$media->uid, '/');
$matchingFiles = preg_grep('/^'.$filepath.'/', $files);
Storage::delete($matchingFiles);
// supprime le media en bdd
$media->forceDelete();
$bar->advance();
}
$this->info($mediaCollection->count() . ' média(s) trouvé(s) - Début du traitement');
$bar = $this->output->createProgressBar($mediaCollection->count());
$bar->start();
$bar->finish();
$this->line("");
$this->info('Fin du traitement');
foreach ($mediaCollection as $media) {
$media->prune();
$bar->advance();
}
$bar->finish();
$this->newLine();
$this->info('Fin du traitement');
}
}

View file

@ -1,233 +0,0 @@
<?php
namespace App\Console\Commands;
use App\Models\Societe;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\File;
use App\Models\Article;
use App\Models\Marque;
use App\Models\Sujet;
use App\Models\Typemedia;
use App\Models\Typevue;
use App\Models\Site;
use App\Models\Variante;
use App\Models\Media;
use App\Http\Traits\MediaTools;
class ImportArcadiaFiles extends Command
{
use MediaTools;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'arcadia:import';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Import des fichiers xml Arcadia';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->info('Démarrage du traitement');
$files = Storage::disk('arcadia')->files();
$bar = $this->output->createProgressBar(count($files)-1);
$bar->start();
// ---- Pour chaque fichier
foreach ($files as $filename) {
if($filename == ".gitignore") continue;
// ---- Récupération du contenu
$files = Storage::disk('arcadia')->get($filename);
$fileContent = simplexml_load_string($files);
// ---- traitement du fichier
if(substr($filename, 0, 11) == "DAM_ARTICLE"){
foreach ($fileContent->dam as $row) {
$record = Article::where('noArt', $row->noArt)->first();
if($record){ // Update record
$record->libCcial = $row->libCcial;
$record->codMarq = $row->codMarq;
$record->libMarq = $row->libMarq;
$record->codFamVte = $row->codFamVte;
$record->libFamVte = $row->libFamVte;
$record->codGencodAdm = $row->codGencodAdm;
$record->codGencodSymb = $row->codGencodSymb;
$record->codGencodPds = $row->codGencodPds;
$record->utilisableGroupe = $row->utilisableGroupe;
$record->save();
}else{ // Insert new record
$record = new Article();
$record->noArt = $row->noArt;
$record->libCcial = $row->libCcial;
$record->codMarq = $row->codMarq;
$record->libMarq = $row->libMarq;
$record->codFamVte = $row->codFamVte;
$record->libFamVte = $row->libFamVte;
$record->codGencodAdm = $row->codGencodAdm;
$record->codGencodSymb = $row->codGencodSymb;
$record->codGencodPds = $row->codGencodPds;
$record->utilisableGroupe = $row->utilisableGroupe;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}elseif (substr($filename, 0, 10) == "DAM_MARQUE") {
foreach ($fileContent->dam as $row) {
$record = Marque::where('codMarq', $row->codMarq)->first();
if($record){ // Update record
$record->libMarq = $row->libMarq;
$record->save();
}else{ // Insert new record
$record = new Marque();
$record->codMarq = $row->codMarq;
$record->libMarq = $row->libMarq;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}elseif (substr($filename, 0, 15) == "DAM_MEDIA_SUJET") {
foreach ($fileContent->mediaSujet as $row) {
$record = Sujet::where('codeSujet', $row->code)->first();
if($record){ // Update record
$record->libelle = $row->libelle;
$record->save();
}else{ // Insert new record
$record = new Sujet();
$record->codeSujet = $row->code;
$record->libelle = $row->libelle;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}elseif (substr($filename, 0, 20) == "DAM_MEDIA_TYPE_MEDIA") {
foreach ($fileContent->mediatypemedia as $row) {
$record = Typemedia::where('codeTypemedia', $row->code)->first();
if($record){ // Update record
$record->libelle = $row->libelle;
$record->save();
}else{ // Insert new record
$record = new Typemedia();
$record->codeTypemedia = $row->code;
$record->libelle = $row->libelle;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}elseif (substr($filename, 0, 17) == "DAM_MEDIA_TYPEVUE") {
foreach ($fileContent->mediatypesvue as $row) {
$record = Typevue::where('codeTypevue', $row->code)->first();
if($record){ // Update record
$record->libelle = $row->libelle;
$record->sujet_id = $row->sujet_id->mediasujet->code;
$record->save();
}else{ // Insert new record
$record = new Typevue();
$record->codeTypevue = $row->code;
$record->libelle = $row->libelle;
$record->sujet_id = $row->sujet_id->mediasujet->code;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}elseif (substr($filename, 0, 18) == "DAM_MEDIA_VARIANTE") {
foreach ($fileContent->mediavariante as $row) {
$record = Variante::where('codeVariante', $row->code)->first();
if($record){ // Update record
$record->libelle = $row->libelle;
$record->sujet_id = $row->sujet_id->children()[0]->code;
$record->typevue_id = $row->CodeTypeVue->mediatypesvue->code;
$record->save();
}else{ // Insert new record
$record = new Variante();
$record->codeVariante = $row->code;
$record->libelle = $row->libelle;
$record->sujet_id = $row->sujet_id->children()[0]->code;
$record->typevue_id = $row->CodeTypeVue->mediatypesvue->code;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}elseif (substr($filename, 0, 20) == "DAM_SITE_PROD_GROUPE") {
foreach ($fileContent->SITE_PROD_GRP as $row) {
$record = Site::where('id', $row->code)->first();
if($record){ // Update record
$record->libelle = $row->libelle;
$record->save();
}else{ // Insert new record
$record = new Site();
$record->id = $row->code;
$record->libelle = $row->libelle;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}elseif (substr($filename, 0, 11) == "DAM_SOCIETE") {
foreach ($fileContent->dam as $row) {
$record = Societe::where('id', $row->codSociete)->first();
if($record){ // Update record
$record->libelle = $row->nomSociete;
$record->save();
}else{ // Insert new record
$record = new Societe();
$record->id = $row->codSociete;
$record->libelle = $row->nomSociete;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}
$bar->advance();
}
$bar->finish();
$this->line("");
$this->info('Fin du traitement');
}
}

View file

@ -0,0 +1,317 @@
<?php
namespace App\Console\Commands;
use App\Traits\Http\HandlesMedia;
use App\Models\Article;
use App\Models\Marque;
use App\Models\Site;
use App\Models\Societe;
use App\Models\Sujet;
use App\Models\TypeMedia;
use App\Models\TypeVue;
use App\Models\Variante;
use Illuminate\Console\Command;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
class ImportArcadiaModelFiles extends Command
{
use HandlesMedia;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'arcadia:import';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Import des modèles xml Arcadia';
/**
* Execute the console command.
*
* @return mixed
* @throws \League\Flysystem\FileNotFoundException If a file could not be read.
* @throws \ErrorException If a xml file could not be parsed.
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
*/
public function handle()
{
/** @var \Illuminate\Support\Collection<string> */
$files = collect(Storage::disk('arcadia')->files())
->filter(function (string $fileName) {
return !\in_array($fileName, ['.gitignore']);
});
if (!$files->count()) {
$this->info('Pas de nouveau fichiers');
return 0;
}
$this->info('Démarrage du traitement');
$bar = $this->output->createProgressBar($files->count() - 1);
$bar->start();
// ---- Pour chaque fichier
foreach ($files as $filename) {
// ---- Récupération du contenu
if (!($fileContent = Storage::disk('arcadia')->get($filename))) {
throw new FileNotFoundException($filename);
}
if (!($fileContent = simplexml_load_string($fileContent))) {
throw new \ErrorException("Could not parse $filename from arcadia storage.");
}
// ---- traitement du fichier
switch (true) {
case substr($filename, 0, 11) == 'DAM_ARTICLE':
$this->insertDamArticle($fileContent);
$this->deleteFile($filename);
break;
case substr($filename, 0, 10) == 'DAM_MARQUE':
$this->insertDamMarque($fileContent);
$this->deleteFile($filename);
break;
case substr($filename, 0, 15) == 'DAM_MEDIA_SUJET':
$this->insertDamMediaSujet($fileContent);
$this->deleteFile($filename);
break;
case substr($filename, 0, 20) == 'DAM_MEDIA_TYPE_MEDIA':
$this->insertDamMediaTypeMedia($fileContent);
$this->deleteFile($filename);
break;
case substr($filename, 0, 17) == 'DAM_MEDIA_TYPEVUE':
$this->insertDamMediaTypeVue($fileContent);
$this->deleteFile($filename);
break;
case substr($filename, 0, 18) == 'DAM_MEDIA_VARIANTE':
$this->insertDamMediaVariante($fileContent);
$this->deleteFile($filename);
break;
case substr($filename, 0, 20) == 'DAM_SITE_PROD_GROUPE':
$this->insertDamSiteProdGroupe($fileContent);
$this->deleteFile($filename);
break;
case substr($filename, 0, 11) == 'DAM_SOCIETE':
$this->insertDamSociete($fileContent);
$this->deleteFile($filename);
break;
default:
throw new \ErrorException("Unhandled file $filename");
} //end switch
$bar->advance();
} //end foreach
$bar->finish();
$this->newLine();
$this->info('Fin du traitement');
}
/**
* Update or Create Dam Article
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamArticle(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->dam as $row) {
/** @var \App\Models\Article|null $record */
$record = Article::where('noArt', (int)$row->noArt)->first();
if (!$record) {
$record = new Article();
$record->noArt = (int)$row->noArt;
}
$record->libCcial = (string)$row->libCcial;
$record->codMarq = (int)$row->codMarq;
$record->libMarq = (string)$row->libMarq;
$record->codFamVte = (int)$row->codFamVte;
$record->libFamVte = (string)$row->libFamVte;
$record->codGencodAdm = (string)$row->codGencodAdm;
$record->codGencodSymb = (string)$row->codGencodSymb;
$record->codGencodPds = (string)$row->codGencodPds;
$record->utilisableGroupe = (int)$row->utilisableGroupe;
$record->saveOrFail();
} //end foreach
}
/**
* Update or Create Dam Marque
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamMarque(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->dam as $row) {
/** @var \App\Models\Marque|null $record */
$record = Marque::where('codMarq', (int)$row->codMarq)->first();
if (!$record) {
$record = new Marque();
$record->codMarq = (int)$row->codMarq;
}
$record->libMarq = (string)$row->libMarq;
$record->saveOrFail();
}
}
/**
* Update or Create Dam Media Sujet
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamMediaSujet(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->mediaSujet as $row) {
/** @var \App\Models\Sujet|null $record */
$record = Sujet::where('codeSujet', (int)$row->code)->first();
if (!$record) {
$record = new Sujet();
$record->codeSujet = (int)$row->code;
}
$record->libelle = (string)$row->libelle;
$record->saveOrFail();
}
}
/**
* Update or Create Dam Media Type Media
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamMediaTypeMedia(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->mediatypemedia as $row) {
/** @var \App\Models\TypeMedia|null $record */
$record = TypeMedia::where('codeTypemedia', (int)$row->code)->first();
if (!$record) {
$record = new TypeMedia();
$record->codeTypemedia = (int)$row->code;
}
$record->libelle = (string)$row->libelle;
$record->saveOrFail();
}
}
/**
* Update or Create Dam Media Type Vue
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamMediaTypeVue(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->mediatypesvue as $row) {
/** @var \App\Models\TypeVue|null $record */
$record = TypeVue::where('codeTypevue', (int)$row->code)->first();
if (!$record) {
$record = new TypeVue();
$record->codeTypevue = (int)$row->code;
}
$record->libelle = (string)$row->libelle;
$record->sujet_id = (int)$row->sujet_id->mediasujet->code;
$record->saveOrFail();
}
}
/**
* Update or Create Dam Media Variante
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamMediaVariante(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->mediavariante as $row) {
/** @var \App\Models\TypeVue|null $record */
$record = Variante::where('codeVariante', (int)$row->code)->first();
if (!$record) {
$record = new Variante();
$record->codeVariante = (int)$row->code;
}
$record->libelle = (string)$row->libelle;
$record->sujet_id = (int)$row->sujet_id->children()[0]->code;
$record->type_vue_id = (int)$row->CodeTypeVue->mediatypesvue->code;
$record->saveOrFail();
}
}
/**
* Update or Create Dam Site Prod Groupe
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamSiteProdGroupe(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->SITE_PROD_GRP as $row) {
/** @var \App\Models\TypeVue|null $record */
$record = Site::where('id', (int)$row->code)->first();
if (!$record) {
$record = new Site();
$record->id = (int)$row->code;
}
$record->libelle = (string)$row->libelle;
$record->saveOrFail();
}
}
/**
* Update or Create Dam Societe
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamSociete(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->dam as $row) {
/** @var \App\Models\TypeVue|null $record */
$record = Societe::where('id', (int)$row->codSociete)->first();
if (!$record) {
$record = new Societe();
$record->id = (int)$row->codSociete;
}
$record->libelle = (string)$row->nomSociete;
$record->saveOrFail();
}
}
/**
* Delete file
*
* @param string $filename
* @return void
*/
private function deleteFile(string $filename)
{
if (!Storage::disk('arcadia')->delete($filename)) {
Log::warning("Could not delete $filename from arcadia storage.");
}
}
}

View file

@ -1,299 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\File;
use App\Http\Traits\MediaTools;
use App\Models\Article;
use App\Models\Marque;
use App\Models\Media;
use App\Models\Dossier;
class ImportMedia extends Command
{
use MediaTools;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'medias:import';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Import des fichiers xml Média Visuel Arcadia';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->info('Démarrage du traitement');
$files = File::glob(storage_path('export_arcadia') . "/DAM_MEDIA_VISUEL_*.*");
$this->line("-> Import du fichier DAM_MEDIA_VISUEL");
// ---- Traitement de l'import des XML Visuel
foreach ($files as $filename) {
$path = explode("/", $filename);
$filename = $path[count($path) - 1];
// ---- Récupération du contenu
$oneFile = Storage::disk('arcadia')->get($filename);
$fileContent = simplexml_load_string($oneFile);
// ---- traitement du fichier
$bar = $this->output->createProgressBar(count($fileContent->MEDIA_VISUEL)-1);
$bar->start();
foreach ($fileContent->MEDIA_VISUEL as $row) {
$record = Media::where('arcadia_id', $row->code)->first();
if (!$record) { // Insert new record
$record = new Media();
$record->arcadia_id = $row->code;
if ($row->extension != "") {
$record->extension = $row->extension->typeFichier->libExtension;
}
$record->libelle = $row->libelle;
$record->largeur = $row->nbPxLargeur;
$record->largeur_mm = $row->largeurMm;
$record->hauteur = $row->nbPxHauteur;
$record->hauteur_mm = $row->hauteurMm;
$record->resolution = $row->pppLargeur;
if ($row->version != "") {
$record->version = $row->version;
} else {
$record->version = 1;
}
if ($row->codeTypeMedia != "") {
$record->typemedia_id = $row->codeTypeMedia;
} else {
$record->typemedia_id = 1;
}
if ($row->codeTypeVue != "") {
$record->typevue_id = $row->codeTypeVue;
}
$record->commentaire = $row->commentaire;
$record->sujet_id = $row->codeSujet;
if ($row->langue != "") {
$record->langue_id = $row->langue;
}
if ($row->copyright != "") {
$record->copyright_id = $row->copyright;
}else{
$record->copyright_id = 3;
}
if ($row->codeVariante != "") {
$record->variante_id = $row->codeVariante;
}
if ($row->dateCreation != "") {
$row->dateCreation = substr($row->dateCreation, 0, 10);
$date = explode("/", $row->dateCreation);
$record->created_at = $date[2] . '-' . $date[1] . '-' . $date[0];
}
if ($row->dateModification != "") {
$row->dateModification = substr($row->dateModification, 0, 10);
$date = explode("/", $row->dateModification);
$record->updated_at = $date[2] . '-' . $date[1] . '-' . $date[0];
}
if ($row->datePublication != "") {
$row->datePublication = substr($row->datePublication, 0, 10);
$date = explode("/", $row->datePublication);
$record->published_at = $date[2] . '-' . $date[1] . '-' . $date[0];
}
$record->statut = config('services.statut.public_etendu');
// Affectation d'un dossier et d'un uid
$destinationPath = $this->get_mediaFolder() . "/";
$record->folder = $destinationPath;
$record->uid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));
$mediaFile = "/images/" . $record->arcadia_id . "." . $record->extension;
$fileExists = Storage::disk('arcadia')->exists($mediaFile);
if ($fileExists) {
// déplacement du média et renommage du fichier
$file = Storage::disk('arcadia')->get($mediaFile);
$full_path_source = Storage::disk('arcadia')->getDriver()->getAdapter()->applyPathPrefix($mediaFile);
$full_path_dest = Storage::disk('local')->getDriver()->getAdapter()->applyPathPrefix($destinationPath . $record->uid . '.' . $record->extension);
File::move($full_path_source, $full_path_dest);
// calcul de la taille du média
$record->taille = $this->formatBytes($this->get_file_size($full_path_dest));
} else {
// on applique une image par défaut
$record->extension = "jpg";
Storage::disk('local')->copy("assets/images/default.jpg", $destinationPath . $record->uid . '.' . $record->extension);
// calcul de la taille du média
$record->taille = $this->formatBytes($this->get_file_size("public/" . $destinationPath . $record->uid . '.' . $record->extension));
}
$record->save();
// ---- Creation des vignettes de base
$this->create_sys_thumb($record);
// ---- Creation des vignettes en lien avec le sujet du média
$this->create_thumb($record);
} else {
$this->line("\nDAM_MEDIA_VISUEL : le media n°" . $row->code . " existe déjà en base");
}
$bar->advance();
}
$bar->finish();
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}
// ---- Traitement de l'association media <-> article
$files = File::glob(storage_path('export_arcadia') . "/DAM_ASSO_ARTICLE_*.*");
$this->line("-> Import du fichier DAM_ASSO_ARTICLE");
foreach ($files as $filename) {
$path = explode("/", $filename);
$filename = $path[count($path) - 1];
// ---- Récupération du contenu
$oneFile = Storage::disk('arcadia')->get($filename);
$fileContent = simplexml_load_string($oneFile);
// ---- traitement du fichier
$bar = $this->output->createProgressBar(count($fileContent->mediaassoarticle)-1);
$bar->start();
foreach ($fileContent->mediaassoarticle as $row) {
$record = Media::where('arcadia_id', $row->codeVisuel)->first();
if ($record) {
$article = Article::where('noArt', $row->noArt)->first();
if ($article) {
// attache l'article au média
$record->articles()->syncWithoutDetaching($article->id);
// recherche un dossier lié à la marque de l'article
$marque_id = $article->codMarq;
$dossier = Dossier::whereHas("marques", function ($query) use ($marque_id) {
$query->where("codMarq", $marque_id);
})->first();
if ($dossier) {
// attache le dossier marque au Média
$record->dossier_id = $dossier->id;
$record->save();
$this->line("Liason media n°" . $row->codeVisuel . " à la marque n°" . $article->libMarq);
} else {
$marque = Marque::where('codMarq', '=', $marque_id)->first();
// On cree le dossier
$dossier = new Dossier();
$dossier->libelle = $marque->libMarq;
$dossier->sujet_id = 1;
$dossier->system = 0;
$dossier->save();
$dossier->marques()->syncWithoutDetaching($marque_id);
$dossier->save();
$record->dossier_id = $dossier->id;
$record->save();
//$this->line("Liason media n°" . $row->codeVisuel . " à la marque n°" . $article->libMarq);
}
} else {
$this->line("\nDAM_ASSO_ARTICLE : le media n°" . $row->codeVisuel . " ne peut être lié à l'article n°" . $row->noArt);
}
} else {
$this->line("\nDAM_ASSO_ARTICLE : le media n°" . $row->codeVisuel . " n'existe pas");
}
$bar->advance();
}
$bar->finish();
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}
// ---- Traitement de l'association media <-> marque
$files = File::glob(storage_path('export_arcadia') . "/DAM_ASSO_MARQUE_*.*");
$this->line("-> Import du fichier DAM_ASSO_MARQUE");
foreach ($files as $filename) {
$path = explode("/", $filename);
$filename = $path[count($path) - 1];
// ---- Récupération du contenu
$oneFile = Storage::disk('arcadia')->get($filename);
$fileContent = simplexml_load_string($oneFile);
// ---- traitement du fichier
$bar = $this->output->createProgressBar(count($fileContent->mediaassomarque)-1);
$bar->start();
foreach ($fileContent->mediaassomarque as $row) {
$record = Media::where('arcadia_id', $row->codeVisuel)->first();
if ($record) {
if ($record->marques->contains($row->codMarq)){
$this->line("\nDAM_ASSO_MARQUE : le media n°" . $row->codeVisuel . " est déjà associé à cette marque.");
}else{
// attache la marque au média
$record->marques()->attach($row->codMarq);
}
} else {
$this->line("\nDAM_ASSO_MARQUE : le media n°" . $row->codeVisuel . " n'existe pas");
}
$bar->advance();
}
$bar->finish();
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}
// ---- Traitement de l'association media <-> societe
$files = File::glob(storage_path('export_arcadia') . "/DAM_ASSO_SOCIETE_*.*");
$this->line("-> Import du fichier DAM_ASSO_SOCIETE");
foreach ($files as $filename) {
$path = explode("/", $filename);
$filename = $path[count($path) - 1];
// ---- Récupération du contenu
$oneFile = Storage::disk('arcadia')->get($filename);
$fileContent = simplexml_load_string($oneFile);
// ---- traitement du fichier
$bar = $this->output->createProgressBar(count($fileContent->mediaassosociete)-1);
$bar->start();
foreach ($fileContent->mediaassosociete as $row) {
$record = Media::where('arcadia_id', $row->codeVisuel)->first();
if ($record) {
// attache la societe au média
$record->societes()->attach($row->codSociete);
} else {
$this->line("\nDAM_ASSO_SOCIETE : le media n°" . $row->codeVisuel . " n'existe pas");
}
$bar->advance();
}
$bar->finish();
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}
$this->line("");
$this->info('Fin du traitement');
}
}

View file

@ -1,85 +0,0 @@
<?php
/*
* Command Name: LDC Web Status Checker
* Description: Envoi des infos Serveur/Laravel vers LDC Web
* Version: 1.0
* Author: Vincent BRIDIER
* Author URI: vincent.bridier@ldc.fr
*/
namespace App\Console\Commands;
use Illuminate\Console\Command;
class LDCWebStatusChecker extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'ldcweb:statuschecker';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Envoi des infos Serveur/Laravel vers LDC Web';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$data = [];
$data['uuid'] = env('PROJECT_UUID');
// Sitemap.xml ?
if (file_exists(public_path() . '/sitemap.xml')) {
$data['sitemap'] = 'true';
}else{
$data['sitemap'] = 'false';
}
// Robots.txt ?
if (file_exists(public_path() . '/robots.txt')) {
$data['robots'] = 'true';
}else{
$data['robots'] = 'false';
}
//Check logs
$data['logs'] = 0;
$patherror = storage_path('/logs');
$files = glob($patherror.'/*.log');
if(count($files) > 0){
foreach ($files as $file) {
$data['logs'] = $data['logs'] + filesize($file);
}
}
$data['code']['version'] = app()->version();
// Send by cURL
$url = 'https://ldc-web.ldc.fr/api/status-checker';
$ch = curl_init($url);
$payload = ['token' => 'CE8S52Qq7stf5k8frF4T', 'datas' => json_encode($data)];
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);
}
}

View file

@ -2,24 +2,18 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use App\Models\Sujet;
use App\Models\Format;
use App\Models\Media;
use App\Http\Traits\MediaTools;
use App\Models\Sujet;
use Illuminate\Console\Command;
class RegenerateThumbnails extends Command
{
use MediaTools;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'medias:regenerate';
protected $signature = 'media:regenerate';
/**
* The console command description.
@ -28,16 +22,6 @@ class RegenerateThumbnails extends Command
*/
protected $description = 'Regénération de toutes les vignettes des médias';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
@ -45,50 +29,63 @@ class RegenerateThumbnails extends Command
*/
public function handle()
{
$this->info('Vous allez regénérer toutes les miniatures des médias.');
$this->info('Vous allez regénérer toutes les miniatures des médias.');
$sujets = Sujet::where('sujet_dam', 1)->get();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Sujet> */
$subjects = Sujet::where('sujet_dam', true)->get();
$this->line("");
$this->line("Liste des sujets disponibles");
$this->line("----------------------------");
foreach ($sujets as $key => $sujet) {
$this->line("[".$sujet->codeSujet."] ". $sujet->libelle);
}
$this->line("[0] Tous les sujets");
$this->newLine();
$this->line('Liste des sujets disponibles');
$this->line('----------------------------');
$this->line('[0] Tous les sujets');
foreach ($subjects as $subject) {
$this->line("[{$subject->codeSujet}] {$subject->libelle}");
}
$sujetId = $this->ask('Pour quel sujet de média souhaitez vous executer le traitement ?' );
$sujetId = $this->askWithCompletion(
'Pour quel sujet de média souhaitez vous executer le traitement ?',
$subjects->pluck('codeSujet')->toArray(),
0
);
if($sujetId == ""){
$this->error('Id de sujet incorrect');
die();
}
if ($sujetId != 0 and !$subjects->pluck('codeSujet')->contains(\intval($sujetId))) {
$this->error('Id de sujet incorrect');
return -1;
}
if($sujetId == 0){
$medias = Media::where('typemedia_id', 1)->with('Sujet.formats')->get();
}else{
$medias = Media::where('sujet_id', $sujetId)->where('typemedia_id', 1)->with('Sujet.formats')->get();
}
$sujetId = intval($sujetId);
if($medias->count() == 0){
$this->error('Aucun média n\'a été trouvé');
die();
}
$mediaCollection = Media::onlyTrashed()->with('sujet.formats');
if ($sujetId !== 0) {
$mediaCollection->where('sujet_id', $sujetId);
}
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Media> */
$mediaCollection = $mediaCollection->get();
$this->info($medias->count().' média(s) trouvé(s) - Début du traitement');
$bar = $this->output->createProgressBar(count($medias));
$bar->start();
if (!$mediaCollection->count()) {
$this->error('Aucun média n\'a été trouvé');
return -1;
}
foreach ($medias as $media) {
// ---- Creation des vignettes de base
$this->create_sys_thumb($media);
// ---- Creation des vignettes en lien avec le sujet du média
$this->create_thumb($media);
$bar->advance();
}
$this->info($mediaCollection->count() . ' média(s) trouvé(s) - Début du traitement');
$bar = $this->output->createProgressBar($mediaCollection->count());
$bar->start();
$bar->finish();
$this->line("");
$this->info('Fin du traitement');
/** @var \App\Models\Media $media */
foreach ($mediaCollection as $media) {
try {
// ---- Creation des vignettes de base
$media->createThumbnail();
// ---- Creation des vignettes en lien avec le sujet du média
$media->createSubjectThumbnails();
} catch (\ImagickException | \RuntimeException $e) {
report($e);
}
$bar->advance();
}
$bar->finish();
$this->newLine();
$this->info('Fin du traitement');
}
}

View file

@ -2,8 +2,8 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\Media;
use Illuminate\Console\Command;
class ReindexElasticMedia extends Command
{
@ -12,7 +12,7 @@ class ReindexElasticMedia extends Command
*
* @var string
*/
protected $signature = 'medias:reindex';
protected $signature = 'media:reindex';
/**
* The console command description.
@ -29,39 +29,48 @@ class ReindexElasticMedia extends Command
public function handle()
{
$this->info('Reindexation de la base médias dans Elasticsearch...');
$this->info('Test Présence...');
$this->info('ES: Test présence index...');
if (Media::indexExists()) {
$this->info('Suppression index...');
$this->info('ES: Suppression index...');
Media::deleteIndex();
}
$this->info('Création...');
$this->info('ES: Création index...');
Media::createIndex();
$pageNumber = 0;
$perPage = 200;
/** @var \Illuminate\Pagination\LengthAwarePaginator $medias */
$medias = Media::paginate($perPage);
$bar = $this->output->createProgressBar(count($medias));
/** @var \Illuminate\Pagination\LengthAwarePaginator $mediaCollection */
$mediaCollection = Media::paginate($perPage);
$bar->start($medias->total());
if (!$mediaCollection->total()) {
$this->info('Pas de medias');
}
$bar = $this->output->createProgressBar(count($mediaCollection));
$bar->start($mediaCollection->total());
// * LOOP
do {
if ($pageNumber > 0) {
/** @var \Illuminate\Pagination\LengthAwarePaginator $medias */
$medias = Media::paginate($perPage, ['*'], 'page', $pageNumber);
/** @var \Illuminate\Pagination\LengthAwarePaginator $mediaCollection */
$mediaCollection = Media::paginate($perPage, ['*'], 'page', $pageNumber);
}
foreach ($medias as $media) {
$media->addToIndex();
/** @var \App\Models\Media $media */
foreach ($mediaCollection->getCollection() as $media) {
/** @throws \RuntimeException */
$media->addToElasticSearch();
$bar->advance();
}
++$pageNumber;
} while ($medias->hasMorePages());
} while ($mediaCollection->hasMorePages());
$bar->finish();
$this->line('');
$this->newLine();
$this->info('Fin du traitement');
}
}

View file

@ -0,0 +1,41 @@
<?php
namespace App\Console\Commands;
use App\Models\Media;
use Illuminate\Console\Command;
class ReindexElasticOneMedia extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'media:reindexone {media_id}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$mediaID = \strval($this->argument('media_id'));
$this->info("Reindexation du media $mediaID dans Elasticsearch...");
/** @var \App\Models\Media */
if (!($media = Media::withTrashed()->find($this->argument('media_id')))) {
$this->info("Pas de media $mediaID");
}
/** @throws \RuntimeException */
$media->addToElasticSearch();
$this->info("Media ID '$mediaID' Ajouté");
}
}

View file

@ -0,0 +1,54 @@
<?php
namespace App\Console\Commands;
use App\Lib\ArcadiaLinkUtilities;
use App\Models\ArcadiaLink;
use App\Models\Media;
use Illuminate\Console\Command;
class ResendArcadiaLinkMedias extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'medias:resend-aracadia-links';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Resend files to Arcadia after Arcadia Link fix';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
// FIXME : Variabiliser la date
//$al = ArcadiaLink::where('created_at', '>=', '2025-10-23')->get();
foreach ($al as $error)
{
$media = Media::withTrashed()->find($error->media_id);
if ($error->arcadia_id === 0) {
ArcadiaLinkUtilities::create($media);
} else {
if (is_null($media->deleted_at)) {
ArcadiaLinkUtilities::update($media);
} else {
ArcadiaLinkUtilities::delete($media);
}
}
}
return Command::SUCCESS;
}
}

View file

@ -12,7 +12,7 @@ class SendMediasModificationsReport extends Command
*
* @var string
*/
protected $signature = 'medias:sendreport';
protected $signature = 'media:sendreport';
/**
* The console command description.
@ -21,16 +21,6 @@ class SendMediasModificationsReport extends Command
*/
protected $description = 'Run the SendMediasModificationsReport Manually';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
@ -39,7 +29,7 @@ class SendMediasModificationsReport extends Command
public function handle()
{
$this->info('Running the Job, this could take some time.');
$job = new JobsSendMediasModificationsReport();
$job = new JobsSendMediasModificationsReport();
$job->console = $this;
$job->handle();
$this->info('Job completed');

View file

@ -1,49 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\Media;
class reindexElasticOneMedia extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'medias:reindexone {media_id}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->info('Reindexation du media '.$this->argument('media_id').' dans Elasticsearch...');
$media = Media::withTrashed()->find($this->argument('media_id'));
$esExist = Media::searchByQuery(array('match' => array('arcadia_id' => "$media->arcadia_id")));
if ($esExist->totalHits() > 0) {
$media->removeFromIndex();
}
$media->addToIndex();
}
}

View file

@ -2,22 +2,12 @@
namespace App\Console;
use App\Console\Commands\ArcadiaLinkCommand;
use App\Jobs\Arcadia\XmlArcadiaMediasIn;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
ArcadiaLinkCommand::class
];
/**
* Define the application's command schedule.
*
@ -26,8 +16,10 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule)
{
$schedule->job(XmlArcadiaMediasIn::class)->name('arcadia_medias_in')
$schedule->job(XmlArcadiaMediasIn::class)->name('Import Arcadia Media Files')
->onOneServer()->cron('*/2 * * * *');
$schedule->command('arcadia:import')->name('Import Arcadia XML Models')
->onOneServer()->cron('*/30 * * * *');
}
/**

23
app/Enums/ContactType.php Normal file
View file

@ -0,0 +1,23 @@
<?php
namespace App\Enums;
enum ContactType: int
{
case bug = 1;
case evolution = 2;
/**
* Get num label
*
* @return string
*/
public function label(): string
{
return match ($this) {
static::bug => trans('Signaler un bug'),
static::evolution => trans('Proposer une amélioration'),
default => trans('MISSING LABEL')
};
}
}

View file

@ -0,0 +1,11 @@
<?php
namespace App\Enums;
enum EdiMouvementType: string
{
case create = 'C';
case update = 'M';
case delete = 'S';
case reactivate = 'R';
}

View file

@ -0,0 +1,29 @@
<?php
namespace App\Enums;
enum EventHistoryType: int
{
case created = 0;
case moved = 1;
case changed = 2;
case destroyed = 3;
case labelled = 4;
/**
* Get num label
*
* @return string
*/
public function label(): string
{
return match ($this) {
static::created => trans('Création'),
static::moved => trans('Déplacement'),
static::changed => trans('Modification'),
static::destroyed => trans('Suppression'),
static::labelled => trans('Etiquette'),
default => trans('MISSING LABEL')
};
}
}

View file

@ -0,0 +1,93 @@
<?php
namespace App\Enums\Legacy;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* This describes an API error.
*
* @method static self modelNotFound()
* The request model was not found (typically the customer)
*
* @method static self validationFailed()
* This means some data could not be validated,
* you may have to look into message to get the details
*
* @method static self apiAuthFailed()
* The authentification to the api failed. You may have to
* check into config or .env file for your service credentials
*
* @method static self authFailed()
* The authentification for this customer failed because of wrong credentials
*
* @method static self methodNotAllowed()
* This http method is not allowed
*
* @method static self wrongTimeStamp()
* The timestamp given is wrong. This would happen in case if
* a replay attack scenario. Timestamps are provided in headers
* and in the http body
*
* @method static self missingParameter()
* The request is missing some parameters
*
* @method static self throttleRequestsException()
* Too many requests have been attempted. The is a throttle security.
* Normally you should not trigger this.
* If this happens fill a ticket on https://supportweb.ldc.fr
* with some technical details
*
* @method static self authorizationException()
* You are maybe trying to access data that is out of your range.
* This should not happen normally, it is here to allow you to handle this case.
* If this happens fill a ticket on https://supportweb.ldc.fr
* with some technical details
*
* @package DAMclient
* @subpackage enums
*
* TODO: pass this as php8 enum, when support of 7 will be dropped.
*/
class ApiError extends BaseEnumRoutable
{
/**
* Valeurs des possibilités de cet énumération (value)
*
* @return array
*/
public static function values(): array
{
return [
'modelNotFound' => 101,
'validationFailed' => 102,
'authFailed' => 117,
'apiAuthFailed' => 119,
'methodNotAllowed' => 150,
'wrongTimeStamp' => 151,
'missingParameter' => 400,
'authorizationException' => 403,
'throttleRequestsException' => 429
];
}
/**
* Libellés des possibilités de cet énumération (label)
*
* @return array
*/
public static function labels(): array
{
return [
'modelNotFound' => '%s introuvable.',
'validationFailed' => 'Impossible de valider les données',
'authFailed' => 'Echec de l\'authentification du compte',
'apiAuthFailed' => 'Echec de l\'authentification client à l\'Api DAM',
'methodNotAllowed' => 'This method is not allowed for this request',
'wrongTimeStamp' => 'Your request is malformed, please check timestamp header and parameter',
'missingParameter' => 'The request is missing some parameters',
'authorizationException' => 'You are not autorized to access this',
'throttleRequestsException' => 'Throttle: too many request have been attempted, please retry later'
];
}
}

View file

@ -0,0 +1,18 @@
<?php
namespace App\Enums\Legacy;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* @method static self OK()
* @method static self KO()
*
* @package DAMclient
* @subpackage enums
*
* TODO: pass this as php8 enum, when support of 7 will be dropped.
*/
class ApiStatus extends BaseEnumRoutable
{
}

View file

@ -2,16 +2,12 @@
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* @method static self debug()
* @method static self log()
* @method static self warning()
* @method static self info()
* @method static self error()
* @method static self critical()
*/
final class LogType extends BaseEnumRoutable
enum LogType: int
{
case debug = 0;
case log = 1;
case warning = 2;
case info = 3;
case error = 4;
case critical = 5;
}

View file

@ -0,0 +1,17 @@
<?php
namespace App\Enums;
enum MediaExtension: string
{
case ai = 'ai';
case gif = 'gif';
case jpeg = 'jpeg';
case jpg = 'jpg';
case mp4 = 'mp4';
case mp3 = 'mp3';
case pdf = 'pdf';
case png = 'png';
case psd = 'psd';
case svg = 'svg';
}

10
app/Enums/MediaStatut.php Normal file
View file

@ -0,0 +1,10 @@
<?php
namespace App\Enums;
enum MediaStatut: int
{
case brouillon = 0;
case public = 1;
case public_etendu = 2;
}

View file

@ -0,0 +1,103 @@
<?php
namespace App\Events;
use App\Models\Etiquette;
use App\Models\Media;
use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class MediaChangedLabel extends MediaCreated
{
use Dispatchable;
use SerializesModels;
/**
* The user who created the media
*
* @var \App\Models\User
*/
private $user;
/**
* The media
*
* @var \App\Models\Media
*/
private $media;
/**
* The oldLabel
*
* @var \App\Models\Etiquette|null
*/
private $oldLabel;
/**
* The newLabel
*
* @var \App\Models\Etiquette|null
*/
private $newLabel;
/**
* Create a new event instance.
*
* @param \App\Models\User $user
* @param \App\Models\Media $media
* @param \App\Models\Etiquette|null $oldLabel
* @param \App\Models\Etiquette|null $newLabel
*/
public function __construct(
User $user,
Media $media,
Etiquette $oldLabel,
Etiquette $newLabel,
) {
$this->user = $user;
$this->media = $media;
$this->oldLabel = $oldLabel;
$this->newLabel = $newLabel;
}
/**
* Get User who triggered the event
*
* @return \App\Models\User
*/
public function getUser(): User
{
return $this->user;
}
/**
* Get the media
*
* @return \App\Models\Media
*/
public function getMedia(): Media
{
return $this->media;
}
/**
* Get the oldLabel
*
* @return \App\Models\Etiquette|null
*/
public function getOldLabel(): Etiquette|null
{
return $this->oldLabel;
}
/**
* Get the newLabel
*
* @return \App\Models\Etiquette|null
*/
public function getNewLabel(): Etiquette|null
{
return $this->newLabel;
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace App\Events;
use App\Models\Media;
use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class MediaCreated
{
use Dispatchable;
use SerializesModels;
/**
* The user who created the media
*
* @var \App\Models\User
*/
private $user;
/**
* The media
*
* @var \App\Models\Media
*/
private $media;
/**
* Create a new event instance.
*
* @param \App\Models\User $user
* @param \App\Models\Media $media
*/
public function __construct(User $user, Media $media)
{
$this->user = $user;
$this->media = $media;
}
/**
* Get User who triggered the event
*
* @return \App\Models\User
*/
public function getUser(): User
{
return $this->user;
}
/**
* Get the media
*
* @return \App\Models\Media
*/
public function getMedia(): Media
{
return $this->media;
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace App\Events;
class MediaDestroyed extends MediaCreated
{
}

View file

@ -0,0 +1,60 @@
<?php
namespace App\Events;
use App\Models\Media;
use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class MediaLinkWithArcadia
{
use Dispatchable;
use SerializesModels;
/**
* The user who created the media
*
* @var \App\Models\User
*/
private $user;
/**
* The media
*
* @var \App\Models\Media
*/
private $media;
/**
* Create a new event instance.
*
* @param \App\Models\User $user
* @param \App\Models\Media $media
*/
public function __construct(User $user, Media $media)
{
$this->user = $user;
$this->media = $media;
}
/**
* Get User who triggered the event
*
* @return \App\Models\User
*/
public function getUser(): User
{
return $this->user;
}
/**
* Get the media
*
* @return \App\Models\Media
*/
public function getMedia(): Media
{
return $this->media;
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace App\Events;
class MediaMoved extends MediaCreated
{
}

View file

@ -0,0 +1,122 @@
<?php
namespace App\Events;
use App\Models\Sujet;
use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class MediaSearched
{
use Dispatchable;
use SerializesModels;
/**
* The user who created the media
*
* @var \App\Models\User
*/
private $user;
/**
* The sujet
*
* @var \App\Models\Sujet
*/
private $sujet;
/**
* The searchString
*
* @var string
*/
private $searchString;
/**
* The filters
*
* @var object
*/
private $filters;
/**
* The dossier_id
*
* @var integer
*/
private $dossier_id;
/**
* Create a new event instance.
*
* @param \App\Models\User $user
* @param \App\Models\Sujet $sujet
* @param string $searchString
* @param object $filters
* @param integer $dossier_id
*/
public function __construct(
User $user,
Sujet $sujet,
string $searchString,
object $filters,
int $dossier_id
) {
$this->user = $user;
$this->sujet = $sujet;
$this->searchString = $searchString;
$this->filters = $filters;
$this->dossier_id = $dossier_id;
}
/**
* Get User who triggered the event
*
* @return \App\Models\User
*/
public function getUser(): User
{
return $this->user;
}
/**
* Get the sujet
*
* @return \App\Models\Sujet
*/
public function getSujet(): Sujet
{
return $this->sujet;
}
/**
* Get the searchString
*
* @return string
*/
public function getSearchString(): string
{
return $this->searchString;
}
/**
* Get the filters
*
* @return string
*/
public function getFilters(): object
{
return $this->filters;
}
/**
* Get the dossier_id
*
* @return integer
*/
public function getDossierId(): int
{
return $this->dossier_id;
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace App\Events;
class MediaUpdated extends MediaCreated
{
}

View file

@ -2,8 +2,6 @@
namespace App\Exceptions;
use ErrorException;
class AbortXmlImportException extends ErrorException
class AbortXmlImportException extends \RuntimeException
{
}

View file

@ -0,0 +1,102 @@
<?php
namespace App\Exceptions\Api;
use App\Enums\Legacy\ApiError;
use Illuminate\Support\Facades\Log;
/**
* This would be thrown if any of the case
* referenced in \App\Enums\ApiError would
* occur within the dam
*
* On the client an ApiErrorException would
* also be throw with the ApiError corresponding to
* the situation
*
* @package DAMclient
* @subpackage exceptions
*/
class ApiErrorException extends \RuntimeException
{
/**
* Api Error
* This value makes the error more explicit.
* Handling these errors are normal as inputs or
* request may be undesired or refused by the dam.
*
* @var \App\Enums\Legacy\ApiError
*/
protected $error;
/**
* This is an explicit error message,
* ou may print this to the front or not depending
* on $error value
*
* @var string
*/
protected $message;
/**
* This is the http code returned by the dam.
* This value could be used to handle errors.
* But please take in consideration $error first
*
* @var integer
*/
protected $httpCode;
/**
* Create a new exception base on ApiError enum.
*
* @param \App\Enums\Legacy\ApiError $error
* @param integer $httpCode
* @param string $message
* @param \Throwable|null $previous
*/
public function __construct(ApiError $error, int $httpCode = 400, string $message = '', \Throwable $previous = null)
{
$this->error = $error;
$this->message = $message;
$this->httpCode = $httpCode;
parent::__construct(
strlen($this->message) ? $this->message : $error->label,
$error->value,
$previous
);
}
/**
* Get the Api Error
*
* @return \App\Enums\Legacy\ApiError
*/
public function getApiError(): ApiError
{
return $this->error;
}
/**
* Get the http code
*
* @return integer
*/
public function getStatusCode(): int
{
return $this->httpCode;
}
/**
* This is used by laravel only.
* It uses Log class to print the error.
*
* @return void
*/
public function report()
{
// @codeCoverageIgnoreStart
Log::debug(sprintf('DAM API: %s', $this->getMessage()));
// @codeCoverageIgnoreEnd
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace App\Exceptions\Api;
/**
* Unhandled error that occus within DAM.
*/
class DamException extends \RuntimeException
{
}

View file

@ -2,8 +2,6 @@
namespace App\Exceptions;
use ErrorException;
class ElasticSearchException extends ErrorException
class ElasticSearchException extends \RuntimeException
{
}

View file

@ -2,50 +2,183 @@
namespace App\Exceptions;
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use App\Enums\Legacy\ApiError;
use App\Enums\Legacy\ApiStatus;
use App\Exceptions\Api\ApiErrorException;
use App\Http\Resources\Api\ApiResponse as ApiResponseResource;
use App\Lib\Helper;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Exceptions\ThrottleRequestsException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Kwaadpepper\ExceptionHandler\Exceptions\ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
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 = [
ApiErrorException::class => \Psr\Log\LogLevel::WARNING
];
/**
* A list of the exception types that are not reported.
*
* @var array
* @var array<int, class-string<\Throwable>>
*/
protected $dontReport = [
//
ApiErrorException::class,
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Report or log an exception.
* Register the exception handling callbacks for the application.
*
* @param \Exception $exception
* @return void
*/
public function report(Exception $exception)
public function register()
{
parent::report($exception);
$this->reportable(function (Throwable $e) {
});
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Illuminate\Http\Response
* @param mixed $request
* @param \Throwable $e
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \Throwable If needed.
*/
public function render($request, Exception $exception)
public function render(mixed $request, Throwable $e)
{
return parent::render($request, $exception);
if (Helper::isRequestForApi($request) and $request->isJson()) {
return $this->handleApiException($request, $e);
} //end if
// @codeCoverageIgnoreStart
return parent::render($request, $e);
// @codeCoverageIgnoreEnd
}
/**
* Generate a json response for any api error case
*
* @param \Illuminate\Http\Request $request
* @param \Throwable $e
* @return \Illuminate\Http\JsonResponse
*/
private function handleApiException(Request $request, \Throwable $e): JsonResponse
{
switch (get_class($e)) {
case AuthenticationException::class:
/** @var AuthenticationException $e */
return $this->getReponse(
$request,
401,
ApiError::apiAuthFailed()->value,
sprintf('%s, %s', ApiError::apiAuthFailed()->label, $e->getMessage())
);
case MethodNotAllowedHttpException::class:
/** @var MethodNotAllowedHttpException $e */
return $this->getReponse(
$request,
$e->getStatusCode(),
ApiError::methodNotAllowed()->value,
sprintf('%s, %s', ApiError::methodNotAllowed()->label, $e->getMessage())
);
case ValidationException::class:
/** @var ValidationException $e */
return $this->getReponse(
$request,
$e->status,
ApiError::validationFailed()->value,
sprintf(ApiError::validationFailed()->label, $e->getMessage()),
['errors' => $e->errors()]
);
case ModelNotFoundException::class:
/** @var ModelNotFoundException $e */
return $this->getReponse(
$request,
404,
ApiError::modelNotFound()->value,
sprintf(
ApiError::modelNotFound()->label,
\array_slice(explode('\\', (string)$e->getModel()), -1)[0]
)
);
case ApiErrorException::class:
/** @var ApiErrorException $e */
return $this->getReponse(
$request,
$e->getStatusCode(),
$e->getCode(),
$e->getMessage()
);
case ThrottleRequestsException::class:
/** @var ThrottleRequestsException $e */
return $this->getReponse(
$request,
429,
ApiError::throttleRequestsException()->value,
ApiError::throttleRequestsException()->label
);
case AuthorizationException::class:
/** @var AuthorizationException $e */
return $this->getReponse(
$request,
403,
ApiError::authorizationException()->value,
ApiError::authorizationException()->label
);
} //end switch
// @codeCoverageIgnoreStart
if (config('app.env') === 'testing') {
// phpcs:ignore Squiz.PHP.DiscouragedFunctions.Found
print_r((string)$e);
}
return $this->getReponse($request, 500, intval($e->getCode()), $e->getMessage());
// @codeCoverageIgnoreEnd
}
/**
* Generate an Api json response
*
* @param \Illuminate\Http\Request $request
* @param integer $httpCode
* @param integer $apiCode
* @param string $message
* @param array $data
* @return \Illuminate\Http\JsonResponse
*/
private static function getReponse(
Request $request,
int $httpCode,
int $apiCode,
string $message,
array $data = []
): JsonResponse {
return (new ApiResponseResource(
(object)array_merge($data, ['message' => $message, 'code' => $apiCode]),
ApiStatus::KO()
))->toResponse($request)->setStatusCode($httpCode);
}
}

View file

@ -2,8 +2,6 @@
namespace App\Exceptions;
use ErrorException;
class InvalidXmlException extends ErrorException
class InvalidXmlException extends \ErrorException
{
}

View file

@ -0,0 +1,19 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
class ApiController extends Controller
{
/**
* Just returns HTTP 200 response
*
* @return JsonResponse
*/
public function ping(): JsonResponse
{
return response()->json();
}
}

View file

@ -0,0 +1,86 @@
<?php
namespace App\Http\Controllers\Api;
use App\Enums\MediaStatut;
use App\Http\Controllers\Controller;
use App\Http\Resources\Api\MediaListResource;
use App\Http\Resources\Api\MediaPictureResource;
use App\Http\Resources\Api\MediaResource;
use App\Models\Article;
use App\Models\Media;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\ResourceCollection as JsonResourceCollection;
use Illuminate\Support\Facades\DB;
class MediaController extends Controller
{
/**
* Show specific media
*
* @param \App\Models\Media $media
* @return \Illuminate\Http\Resources\Json\JsonResource
*/
public function show(Media $media): JsonResource
{
return new MediaResource($media);
}
/**
* Get Media list of the latest version for each vue type and variant
* of media that is linked with an article.
*
* Working example
* SELECT `mediaList`.`id`,`mediaList`.`arcadia_id`,`mediaList`.`libelle`,`mediaList`.`uid`,
* `mediaList`.`version`,`mediaList`.`type_vue_id`,`mediaList`.`variante_id`,`mediaList`.`created_at`,`mediaList`.`updated_at`
* FROM (
* SELECT `media`.*
* from `media`
* JOIN `media_article` ON `media_article`.`media_id` =`media`.`id`
* JOIN `articles` ON `articles`.`id` =`media_article`.`article_id` AND `articles`.`noArt` = 2842
* WHERE
* `media`.type_media_id IN (1,5) AND
* `media`.isLocked = 0 AND
* `media`.statut != 0
* ORDER BY `version` DESC
* LIMIT 18446744073709551615
* ) AS mediaList
* GROUP BY `type_vue_id`,`variante_id`
*
* @param \App\Models\Article $article
* @return \Illuminate\Http\Resources\Json\ResourceCollection
*/
public function getMediaListByArticle(Article $article): JsonResourceCollection
{
// ! Hack to allow group by (may have side effects)
DB::statement("SET SQL_MODE=''");
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Media> */
$mediaList = Media::cacheForever()->withTrashed()->fromSub(
Media::query()->whereHas('articles', function ($q) use ($article) {
$q->where('noArt', $article->noArt);
})->whereHas('typeMedia', function ($q) {
$q->whereIn('libelle', ['Photo', 'jpeg']);
})->where('isLocked', false)
->where('statut', '!=', MediaStatut::brouillon)
->orderBy('version', 'DESC')
// ! Maria Hack: use limit to preserve order.
->limit(\PHP_INT_MAX),
'mediaList'
)->groupBy(['mediaList.type_vue_id', 'mediaList.variante_id'])
->paginate();
return new MediaListResource($mediaList, true);
}
/**
* Get Media picture resource
*
* @param \App\Models\Media $media
* @return \Illuminate\Http\Resources\Json\JsonResource
*/
public function getMediaPicture(Media $media): JsonResource
{
return new MediaPictureResource($media);
}
}

View file

@ -3,25 +3,46 @@
namespace App\Http\Controllers;
use App\Models\ArcadiaLink;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Contracts\Database\Eloquent\Builder;
class ArcadiaLinkController extends Controller
{
public function index(Request $request)
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
$dt = Carbon::now('Europe/Paris')->subMinutes(15)->toDateTimeString();
$ano = ArcadiaLink::where('created_at', '<', $dt)->orderBy('id', 'DESC')->get();
return view('arcadialink.index', ['ano' => $ano]);
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
// * ArcadiaLink->Media is nullable
$arcadiaLinkList = ArcadiaLink::query()
->with('media', fn (Builder $q) => $q->withTrashed())
->where('created_at', '<', now()->subMinutes(15))
->orderBy('id', 'DESC')->get();
return view('arcadialinks.index', compact('arcadiaLinkList'));
}
public function delete(Request $request)
/**
* Remove the specified resource from storage.
*
* @param \App\Models\ArcadiaLink $arcadia_link
* @return \Illuminate\Http\Response
*/
public function delete(ArcadiaLink $arcadia_link)
{
$id = $request->id;
$a = ArcadiaLink::find($id);
$a->delete();
return redirect()->route('arcadialink.index');
if ($arcadia_link->deleteOrFail()) {
return redirect()
->route('arcadialinks.index')
->with('warning', trans(
':model a bien été supprimé',
['model' => trans('ArcadiaLink')]
));
}
return back();
}
}

View file

@ -0,0 +1,22 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\Bo\Ajax\GetArticleRequest;
use App\Models\Article;
use Illuminate\Http\JsonResponse;
class ArticleController
{
/**
* Renvoie un article par ID Arcadia
* @param \App\Http\Requests\Bo\Ajax\GetArticleRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function getArticle(GetArticleRequest $request): JsonResponse
{
return \response()->json([
'article' => Article::where('noArt', $request->arcadia_id)->firstOrFail()
]);
}
}

View file

@ -1,32 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
class ForgotPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset emails and
| includes a trait which assists in sending these notifications from
| your application to your users. Feel free to explore this trait.
|
*/
use SendsPasswordResetEmails;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
}

View file

@ -3,21 +3,11 @@
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
@ -25,7 +15,7 @@ class LoginController extends Controller
*
* @var string
*/
protected $redirectTo = '/';
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
@ -37,8 +27,13 @@ class LoginController extends Controller
$this->middleware('guest')->except('logout');
}
public function username()
{
return 'matricule';
}
/**
* Get the login username to be used by the controller.
*
* @return string
*/
public function username()
{
return 'matricule';
}
}

View file

@ -1,72 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* @var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* @param array $data
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}

View file

@ -1,39 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
class ResetPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset requests
| and uses a simple trait to include this behavior. You're free to
| explore this trait and override any methods you wish to tweak.
|
*/
use ResetsPasswords;
/**
* Where to redirect users after resetting their password.
*
* @var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
}

View file

@ -1,41 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\VerifiesEmails;
class VerificationController extends Controller
{
/*
|--------------------------------------------------------------------------
| Email Verification Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling email verification for any
| user that recently registered with the application. Emails may also
| be re-sent if the user didn't receive the original email message.
|
*/
use VerifiesEmails;
/**
* Where to redirect users after verification.
*
* @var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('signed')->only('verify');
$this->middleware('throttle:6,1')->only('verify', 'resend');
}
}

View file

@ -0,0 +1,85 @@
<?php
namespace App\Http\Controllers;
use App\Enums\ContactType;
use App\Http\Requests\Bo\Ajax\SendContactMessageRequest;
use App\Mail\ContactMail;
use App\Models\Dossier;
use App\Models\Format;
use App\Models\Recherche;
use App\Models\Sujet;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Mail;
class CommonController extends Controller
{
/**
* Show main interface
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function showInterface()
{
/** @var \App\Models\User */
$user = auth()->user();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Sujet> */
$sujets = $user->sujets;
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Recherche> */
$recherches = Recherche::query()->whereHas('user', function (Builder $q) use ($user) {
$q->where('id', $user->id);
})->with('sujet')
->limit(10)
->orderBy('created_at', 'desc')
->get();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Dossier> */
$dossiers = Dossier::whereHas('users', function ($q) use ($user) {
$q->where('user_id', $user->id);
})->with('sujet')->get();
return view('home')->with([
'sujets' => $sujets,
'recherches' => $recherches,
'dossiers' => $dossiers
]);
}
/**
* Envoi d'un message
*
* @param \App\Http\Requests\Bo\Ajax\SendContactMessageRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function sendMessage(SendContactMessageRequest $request): JsonResponse
{
/** @var \App\Models\User $user */
$user = auth()->user();
foreach (config('mail.contactsList.admin') as $mail) {
Mail::to($mail)
->send(new ContactMail(ContactType::from($request->type), $request->url, $request->message, $user));
}
return response()->json(['status' => 'OK']);
}
/**
* Get data by sujet
*
* @param \App\Models\Sujet $sujet
* @return \Illuminate\Http\JsonResponse
*/
public function getDatasBySujet(Sujet $sujet): JsonResponse
{
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Format> */
$formats = Format::withoutGlobalScope('App\Scopes\SystemScope')
->where('system', 1)->get();
$formats = $formats->merge($sujet->formats);
return response()->json([
'typesvue' => $sujet->typeVues,
'typesvariantes' => $sujet->variantes,
'formats' => $formats
]);
}
}

View file

@ -1,71 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\Format;
use App\Models\Typevue;
use App\Models\Variante;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
use App\Models\Sujet;
use App\Models\Recherche;
use App\User;
use App\Models\Dossier;
use App\Mail\contact;
use Illuminate\Http\Request;
class CommunController extends Controller
{
/**
* page d'accueil
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
$user = Auth::user();
$sujets = $user->sujets;
$paniers = Auth::user()->paniersFavoris;
$recherches = Recherche::where('user_id', $user->id)
->with("sujet")
->limit(10)
->orderBy("created_at", "desc")
->get();
$dossiers = Dossier::whereHas("users", function($query) use ($user){
$query->where('user_id', $user->id);
})
->with("sujet")
->get();
return view('home')->with(['sujets'=> $sujets, 'recherches'=> $recherches, 'dossiers'=> $dossiers, 'paniers'=> $paniers]);
}
/**
* Envoi d'un message
*
*/
public function sendMessage(Request $request)
{
$type = $request->input('type');
$url = $request->input('url');
$message = $request->input('message');
if (Auth::check()) {
$user = auth()->user();
Mail::to(env('MAIL_ADMIN_ADDRESS', "informatique.internet@ldc.fr"))->send(new contact($type, $url, $message, $user));
}
return json_encode(array('status' => "OK"));
}
public function getDatasBySujet(Request $request) {
$sujet_id = $request->sujet_id;
$sujet = Sujet::findOrFail($sujet_id);
$response['typesvue'] = $sujet->typeVues;
$response['typesvariantes'] = $sujet->variantes;
$response['formats'] = array_merge(Format::withoutGlobalScope('App\Scopes\SystemScope')->where('system', 1)->get()->toArray(), $sujet->formats->toArray());
return response()->json($response);
}
}

View file

@ -2,12 +2,14 @@
namespace App\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
use AuthorizesRequests;
use DispatchesJobs;
use ValidatesRequests;
}

View file

@ -2,18 +2,141 @@
namespace App\Http\Controllers;
use App\Enums\MediaStatut;
use App\Http\Requests\Bo\Ajax\FetchFoldersRequest;
use App\Http\Requests\Bo\Ajax\LoadFoldersRequest;
use App\Http\Requests\Bo\Folders\StoreDepotFolderRequest;
use App\Http\Requests\Bo\Folders\StoreFolderRequest;
use App\Http\Requests\Bo\Folders\UpdateFolderRequest;
use App\Http\Resources\NestedDossiersListResource;
use App\Models\Dossier;
use App\Models\Sujet;
use App\Models\Marque;
use App\Models\Media;
use App\Models\Typevue;
use App\Models\Variante;
use App\Models\Format;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class DossierController extends Controller
{
/**
* Ajax Load folders
*
* @param \App\Http\Requests\Bo\Ajax\LoadFoldersRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function loadFolders(LoadFoldersRequest $request): JsonResponse
{
/** @var \App\Models\User */
$user = Auth::user();
$folders = [];
$select = ['id', 'libelle', 'system'];
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Dossier> Dossiers publiques */
$publicFolders = Dossier::query()
->whereHas('sujet', fn (Builder $q) => $q->where('codeSujet', $request->input('sujet_id')))
->where('is_private', false)
->whereNull('parent_id')
->select($select)->get();
// * On récupère les dossiers privés.
/** @var \Illuminate\Database\Eloquent\Builder */
$privateQuery = Dossier::query()
->whereHas('sujet', fn (Builder $q) => $q->where('codeSujet', $request->input('sujet_id')))
->where('is_private', true)
->select($select);
// ? Is admin ?
if (!$user->hasRole(config('roles.const.ADMIN'))) {
// * If not admin, get using brands.
/** @var \Illuminate\Database\Eloquent\Collection<integer> Codes marques */
$marques = $user->marques()->pluck('codMarq');
$privateQuery->whereHas('marques', fn (Builder $q) => $q->whereIn('codMarq', $marques));
}
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Dossier> Dossiers privés */
$privateFolders = $privateQuery->get();
$foldersCollection = $publicFolders->merge($privateFolders);
$foldersCollection = $foldersCollection
->sortBy('libelle', SORT_NATURAL | SORT_FLAG_CASE)
->sortBy('favoris')->values();
// ? Is admin ?
if ($user->hasRole(config('roles.const.ADMIN'))) {
// * Ajout du dépôt de fichier pour les admin.
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Dossier> Dossiers depots */
$depotQuery = Dossier::query()
->whereNull('parent_id')
->where('system', true)
->orderBy('libelle', 'ASC')
->get();
$foldersCollection = $foldersCollection->merge($depotQuery);
}
Arr::set($folders, 'data', new NestedDossiersListResource($foldersCollection));
// * Racine Count
$racineCountQuery = Media::query()
->whereHas('sujet', fn (Builder $q) => $q->where('codeSujet', $request->input('sujet_id')))
->whereDoesntHave('dossier');
// ? Is not admin ?
if (!$user->hasRole(config('roles.const.ADMIN'))) {
$racineCountQuery->where(
fn (Builder $q) =>
$q->where('statut', MediaStatut::public_etendu)
->orWhere('statut', MediaStatut::public)
->orWhere('created_by', $user->id)
);
}
Arr::set($folders, 'racineCount', $racineCountQuery->count());
return response()->json($folders);
}
/**
* Chargement des dossiers
*
* @param \App\Http\Requests\Bo\Ajax\FetchFoldersRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function loadFolder(FetchFoldersRequest $request): JsonResponse
{
/** @var \App\Models\User */
$user = auth()->user();
$response = [];
$response['variantes'] = Variante::query()
->whereHas('sujet', fn (Builder $q) => $q->where('codeSujet', $request->input('sujetId')))
->get();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Format> */
$FormatsSujet = Format::query()
->whereHas('sujets', fn (Builder $q) => $q->where('sujet_id', $request->input('sujetId')))
->get();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Format> */
$FormatsSystem = Format::query()
->withoutGlobalScope('App\Scopes\SystemScope')
->where('system', true)->get();
$response['formats'] = $FormatsSujet->merge($FormatsSystem);
$response['draggable'] = $user->hasRole([config('roles.const.ADMIN'), config('roles.const.REDACTEUR')]);
// Envoi du role .
$response['role'] = $user->role;
return \response()->json($response);
}
// * CRUD
/**
* Display a listing of the resource.
*
@ -21,11 +144,20 @@ class DossierController extends Controller
*/
public function index()
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
$dossiers = Dossier::whereNull('parent_id')->where('system', 0)->orderBy('libelle', 'asc')->get();
$sujets = Sujet::where('sujet_dam', 1)->get();
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
return view('dossiers.index')->with([
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Dossier> */
$dossiers = Dossier::query()
->whereNull('parent_id')
->where('system', false)
->orderBy('libelle', 'asc')
->get();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Sujet> */
$sujets = Sujet::query()->where('sujet_dam', true)->get();
return view('dossiers.index', [
'dossiers' => $dossiers,
'sujets' => $sujets,
]);
@ -34,463 +166,164 @@ class DossierController extends Controller
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function create()
public function create(Request $request)
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
$marques = Marque::all();
$sujets = Sujet::where('sujet_dam', 1)->get();
return view('dossiers.create')->with(['marques' => $marques, 'sujets' => $sujets]);
}
if ($request->sub) {
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Dossier> */
$dossiers = Dossier::query()
->whereNull('parent_id')
->where('system', false)
->orderBy('libelle', 'asc')->get();
return view('dossiers.create-sub', [
'dossiers' => $dossiers
]);
}
public function createSub()
{
$dossiers = Dossier::whereNull('parent_id')->where('system', 0)->orderBy('libelle', 'asc')->get();
return view('dossiers.create-sub')->with(['dossiers' => $dossiers]);
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
$marques = Marque::all();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Sujet> */
$sujets = Sujet::query()->where('sujet_dam', true)->get();
return view('dossiers.create')->with([
'marques' => $marques,
'sujets' => $sujets
]);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Http\Requests\Bo\Folders\StoreFolderRequest $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
public function store(StoreFolderRequest $request)
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
$validatedData = $request->validate([
'libelle' => 'required',
'sujet' => 'required',
'status' => 'required'
]);
DB::transaction(function () use ($request) {
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
$dossierExist = Dossier::where('libelle', $request->libelle)->where('sujet_id', $request->sujet)->first();
if ($dossierExist) {
session()->flash('error', "Ce nom de dossier est déjà présent dans l'application pour ce sujet. Ajout impossible.");
return redirect()->route('dossier.create');
} else {
// ---- Le dossier
$dossier = new Dossier();
$dossier->libelle = $request->libelle;
$dossier->description = $request->description;
$dossier->is_private = $request->status;
$dossier->sujet()->associate($request->sujet);
$dossier->fill($request->validated());
if ($dossier->save()) {
if ($request->sub) {
/** @var \App\Models\Dossier */
$parent_dossier = Dossier::query()->findOrFail($request->input('parent_id'));
$dossier->sujet()->associate($parent_dossier->sujet);
} else {
$dossier->sujet()->associate($request->input('sujet'));
}
if ($dossier->saveOrFail()) {
// ---- Les marques
$sMarques = $request->marques;
if ($sMarques != "") {
$marques = explode(",", $sMarques);
foreach ($marques as $marqueId) {
$dossier->marques()->attach($marqueId);
}
if ($request->input('marques')) {
$dossier->marques()->sync($request->input('marques'));
}
session()->flash('message', "Le dossier a été enregistré");
return redirect()->route('dossier.edit', ['dossier' => $dossier]);
} else {
session()->flash('error', "Une erreur s'est produite, ajout impossible");
return redirect()->route('dossier.create');
return redirect()->route('dossier.edit', ['dossier' => $dossier])
->with('success', 'Le dossier a été enregistré');
}
}
}
public function storeSub(Request $request)
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
$validatedData = $request->validate([
'libelle' => 'required',
'parent_id' => 'required',
]);
$dossierExist = Dossier::where('libelle', $request->libelle)->first();
$parent_dossier = Dossier::findOrFail($request->parent_id);
if ($dossierExist) {
session()->flash('error', "Ce nom de dossier est déjà présent dans l'application pour ce sujet. Ajout impossible.");
return redirect()->route('dossier.create');
} else {
// ---- Le dossier
$dossier = new Dossier();
$dossier->libelle = $request->libelle;
$dossier->description = $request->description;
$dossier->is_private = 0;
$dossier->parent_id = $request->parent_id;
$dossier->sujet_id = $parent_dossier->sujet_id;
if ($dossier->save()) {
session()->flash('message', "Le dossier a été enregistré");
return redirect()->route('dossier.edit', ['dossier' => $dossier]);
} else {
session()->flash('error', "Une erreur s'est produite, ajout impossible");
return redirect()->route('dossier.create');
}
}
}
/**
* Display the specified resource.
*
* @param \App\Models\Dossier $dossier
* @return \Illuminate\Http\Response
*/
public function show(Dossier $dossier)
{
//
});
return back();
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Dossier $dossier
* @return \Illuminate\Http\Response
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function edit(Dossier $dossier)
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
$dossierMarques = $dossier->marques;
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
$marques = Marque::all();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Marque> */
$dossierMarques = $dossier->marques;
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Sujet> */
$dossierSujets = $dossier->sujets;
$sujets = Sujet::where('sujet_dam', 1)->get();
return view('dossiers.edit')->with(['dossier' => $dossier, 'dossierMarques' => $dossierMarques, 'marques' => $marques, 'sujets' => $sujets]);
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Sujet> */
$sujets = Sujet::query()->where('sujet_dam', true)->get();
return view('dossiers.edit', [
'dossier' => $dossier,
'dossierMarques' => $dossierMarques,
'marques' => $marques,
'sujets' => $sujets
]);
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Models\Dossier $dossier
* @return \Illuminate\Http\Response
* @param \App\Http\Requests\Bo\Folders\UpdateFolderRequest $request
* @param \App\Models\Dossier $dossier
* @return \Illuminate\Http\RedirectResponse
*/
public function update(Request $request, Dossier $dossier)
public function update(UpdateFolderRequest $request, Dossier $dossier): RedirectResponse
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
DB::transaction(function () use ($request, $dossier) {
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
if ($dossier->parent_id === null) {
// ---- Le dossier
$dossier->fill($request->validated());
$validatedData = $request->validate([
'libelle' => 'required',
'sujet' => 'required',
'status' => 'required'
]);
$dossierExist = Dossier::where('libelle', $request->libelle)->where('sujet_id', $request->sujet)->where('id', '<>', $dossier->id)->first();
if ($dossierExist) {
session()->flash('error', "Ce nom de dossier est déjà présent dans l'application pour ce sujet. Ajout impossible.");
return redirect()->route('dossier.edit', ['dossier' => $dossier]);
} else {
// ---- Le dossier
$dossier->libelle = $request->libelle;
$dossier->description = $request->description;
$dossier->is_private = $request->status;
$dossier->sujet()->dissociate();
$dossier->sujet()->associate($request->sujet);
if ($dossier->save()) {
// ---- Les marques
$dossier->marques()->detach();
$sMarques = $request->marques;
if ($sMarques != "") {
$marques = explode(",", $sMarques);
foreach ($marques as $marqueId) {
$dossier->marques()->attach($marqueId);
}
}
session()->flash('message', "Le dossier a été mis à jour");
return redirect()->route('dossier.edit', ['dossier' => $dossier]);
} else {
session()->flash('error', "Une erreur s'est produite, enregistrement impossible");
return redirect()->route('dossier.edit');
if ($dossier->saveOrFail()) {
// ---- Les marques
if ($request->marques) {
$dossier->marques()->sync($request->marques);
}
return redirect()->route('dossier.edit', ['dossier' => $dossier])
->with('success', trans('Le dossier a été mis à jour'));
}
}else{
$validatedData = $request->validate([
'libelle' => 'required',
]);
$dossierExist = Dossier::where('libelle', $request->libelle)->where('sujet_id', $request->sujet)->where('id', '<>', $dossier->id)->first();
if ($dossierExist) {
session()->flash('error', "Ce nom de dossier est déjà présent dans l'application pour ce sujet. Ajout impossible.");
return redirect()->route('dossier.edit', ['dossier' => $dossier]);
} else {
// ---- Le dossier
$dossier->libelle = $request->libelle;
$dossier->description = $request->description;
if ($dossier->save()) {
session()->flash('message', "Le dossier a été mis à jour");
return redirect()->route('dossier.edit', ['dossier' => $dossier]);
} else {
session()->flash('error', "Une erreur s'est produite, enregistrement impossible");
return redirect()->route('dossier.edit');
}
}
}
});
return back();
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Dossier $dossier
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Dossier $dossier)
public function destroy(Dossier $dossier): RedirectResponse
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
if ($dossier->delete()) {
return redirect(route('dossier.index'));
} else {
session()->flash('error', 'Erreur lors de la suppression');
return redirect()->route('dossier.edit', ['user' => $dossier]);
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
if ($dossier->deleteOrFail()) {
return \response()->redirectToRoute('dossier.index')
->with('warning', trans('Le dossier à été supprimé'));
}
}
/**
* Chargement des dossiers
*
*/
public function loadFolder(Request $request)
{
$response = array();
$sujetId = $request->input('sujetId');
$response['variantes'] = Variante::where('sujet_id', $sujetId)->get();
$FormatsSujet = Format::whereHas('sujets', function ($query) use ($sujetId) {
$query->where('sujet_id', $sujetId);
})->get();
$FormatsSystem = Format::withoutGlobalScope('App\Scopes\SystemScope')->where('system', 1)->get();
$response['formats'] = $FormatsSujet->merge($FormatsSystem);
if (Auth::user()->hasRole([config('roles.const.ADMIN'), config('roles.const.REDACTEUR')])) {
$response['draggable'] = true;
} else {
$response['draggable'] = false;
}
// Envoi du role
$response['role'] = Auth::user()->role;
return json_encode($response);
}
/**
* Ajouter un dossier
*
*/
public function addFolder(Request $request)
{
$response = array();
Auth::user()->authorizeRoles([config('roles.const.ADMIN'), config('roles.const.REDACTEUR')]);
$parent_id = $request->input('parent_id');
$libelle = $request->input('libelle');
$description = $request->input('description');
// ---- Le dossier
$dossier = new Dossier();
$dossier->libelle = htmlspecialchars($libelle);
$dossier->description = $description;
$dossier->parent_id = $parent_id;
$dossierParent = Dossier::where('id', $parent_id)->first();
if ($parent_id == 1 || $dossierParent->system == 1) { // dossier de dépôt
$dossier->system = 1;
} else {
$dossier->system = 0;
}
$dossier->sujet_id = $dossierParent->sujet_id;
$dossier->save();
$response['folder_id'] = $dossier->id;
$response['system'] = $dossier->system;
return json_encode($response);
return back();
}
/**
* Ajouter un dossier de dépôt
*
* @param \App\Http\Requests\Bo\Folders\StoreDepotFolderRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function addDepotFolder(Request $request)
public function addDepotFolder(StoreDepotFolderRequest $request): JsonResponse
{
$response = array();
$parent_id = $request->input('parent_id');
$libelle = $request->input('libelle');
$description = $request->input('description');
// ---- Le dossier
$dossier = new Dossier();
$dossier->libelle = htmlspecialchars($libelle);
$dossier->description = $description;
$dossier = new Dossier($request->validated());
$dossier->parent_id = 1;
$dossier->system = 1;
$dossier->save();
$response['folder_id'] = $dossier->id;
return json_encode($response);
$dossier->system = true;
$dossier->saveOrFail();
return \response()->json([
'folder_id' => $dossier->id
]);
}
/**
* supprimer un dossier
*
*/
public function removeFolder(Request $request)
{
Auth::user()->authorizeRoles([config('roles.const.ADMIN'), config('roles.const.REDACTEUR')]);
$dossier_id = $request->input('dossier_id');
// ---- Le dossier
$dossier = Dossier::where('id', $dossier_id)->first();
if ($dossier && !is_null($dossier->parent_id)) {
if ($dossier->delete()) {
return json_encode($dossier->parent_id);
}
}
return json_encode(false);
}
/**
* déplacer un dossier
*
*/
public function moveFolder(Request $request)
{
Auth::user()->authorizeRoles([config('roles.const.ADMIN'), config('roles.const.REDACTEUR')]);
$dossier_id = $request->input('dossier_id');
$parent_id = $request->input('parent_id');
$sujet_id = $request->input('sujet_id');
// ---- Le dossier
$dossier = Dossier::where('id', $dossier_id)->first();
if ($dossier && !is_null($dossier->parent_id)) {
$dossier->parent_id = $parent_id;
if ($dossier->save()) {
Media::where('dossier_id', $dossier_id)->update(['sujet_id' => $sujet_id]);
return json_encode(true);
}
}
return json_encode(false);
}
/**
* renommer un dossier
*
*/
public function renameFolder(Request $request)
{
Auth::user()->authorizeRoles([config('roles.const.ADMIN'), config('roles.const.REDACTEUR')]);
$dossier_id = $request->input('dossier_id');
$libelle = $request->input('libelle');
// ---- Le dossier
$dossier = Dossier::where('id', $dossier_id)->first();
if ($dossier && !is_null($dossier->parent_id)) {
$dossier->libelle = $libelle;
if ($dossier->save()) {
return json_encode(true);
}
}
return json_encode(false);
}
/**
* get propriétés d'un dossier
*
*/
public function getFolderProperty(Request $request)
{
$response = array();
$dossier_id = $request->input('dossier_id');
// ---- Le dossier
$dossier = Dossier::where('id', $dossier_id)->first();
if ($dossier) {
$response["data"] = $dossier;
}
return json_encode($response);
}
/**
* enregistre les propriétés d'un dossier
*
*/
public function saveFolderProperty(Request $request)
{
$dossier_id = $request->input('dossier_id');
$libelle = $request->input('libelle');
$description = $request->input('description');
// ---- Le dossier
$dossier = Dossier::where('id', $dossier_id)->first();
if ($dossier && !is_null($dossier->parent_id) && strlen($libelle) > 3) {
$dossier->libelle = $libelle;
$dossier->description = $description;
$dossier->save();
}
return json_encode(true);
}
public function loadFolders(Request $request)
{
$folders = array();
$user = Auth::user();
$sujet_id = $request->sujet_id;
$dossierQuery = Dossier::where([
['sujet_id', $sujet_id],
['is_private', 0]
])
->whereNull('parent_id');
$dossierQuery = $dossierQuery->get();
// On récupère les dossiers privés
if ($user->hasRole(config('roles.const.ADMIN'))) {
$privateQuery = Dossier::where([
['is_private', '=', 1],
['sujet_id', '=', $sujet_id],
])->get();
} else {
$marques = $user->marques()->pluck("marque_id");
$privateQuery = Dossier::where([
['is_private', '=', 1],
['sujet_id', '=', $sujet_id],
])->whereHas("marques", function ($query) use ($marques) {
$query->whereIn("marque_id", $marques);
})->get();
}
$dossierQuery = $dossierQuery->merge($privateQuery);
$dossierQuery = $dossierQuery->sortBy('libelle', SORT_NATURAL | SORT_FLAG_CASE)->values();
// Ajout du dépôt de fichier pour les admin
if ($user->hasRole(config('roles.const.ADMIN'))) {
$depotQuery = Dossier::whereNull('parent_id')
->where('system', 1)
->orderBy('libelle', 'ASC')
->get();
$folders['data'] = $dossierQuery->merge($depotQuery);
} else {
$folders['data'] = $dossierQuery;
}
$folders['racineCount'] = Media::where('sujet_id', $sujet_id)
->whereNull('dossier_id')
->where(function ($query) use ($user) {
$query->where('statut', config('services.statut.public_etendu'))
->orWhere('statut', config('services.statut.public'))
->orWhere('created_by', $user->id);
})
->count();
return response()->json($folders);
}
}

File diff suppressed because it is too large Load diff

View file

@ -2,156 +2,192 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Requests\Bo\Ajax\AddMediasBasketRequest;
use App\Http\Requests\Bo\Ajax\CreateBasketRequest;
use App\Http\Requests\Bo\Ajax\DestroyBasketRequest;
use App\Http\Requests\Bo\Ajax\RemoveMediasBasketRequest;
use App\Http\Requests\Bo\Ajax\SaveBasketPropsRequest;
use Illuminate\Support\Str;
use App\Models\Panier;
use App\Models\Media;
use App\Models\Format;
use App\Models\Media;
use Illuminate\Contracts\View\View;
use Illuminate\Http\JsonResponse;
class PanierController extends Controller
{
/**
// * BO
/**
* Page principale des paniers
*
* @return \Illuminate\Http\Response
* @return \Illuminate\Contracts\View\View
*/
public function index(Request $request)
public function index(): View
{
$paniers = Auth::user()->paniersOwner;
return view('panier.index')->with([
'paniers'=> $paniers,
]);
/** @var \App\Models\User $user */
$user = \auth()->user();
// ! Has to flush Media cache before querying basket with media list
Media::flushQueryCache();
$paniers = $user->paniersOwner;
return view('panier.index')->with([
'paniers' => $paniers,
]);
}
public function getBaskets(Request $request)
// * AJAX
/**
* Get user baskets
*
* @return \Illuminate\Http\JsonResponse
*/
public function getBaskets(): JsonResponse
{
return Auth::user()->paniersOwner;
/** @var \App\Models\User $user */
$user = \auth()->user();
// ! Has to flush Media cache before querying basket with media list
Media::flushQueryCache();
$paniers = $user->paniersOwner;
return response()->json($paniers);
}
/**
/**
* Ajout de média à un panier
*
* @param \App\Http\Requests\Bo\Ajax\AddMediasBasketRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function addMediasBasket(AddMediasBasketRequest $request): JsonResponse
{
/** @var \App\Models\Panier $panier */
$panier = Panier::query()
->where('id', $request->input('panier_id'))
->with('mediaList')
->firstOrFail();
// * Sync every media to basket
$panier->mediaList()->sync(array_merge(
$panier->mediaList()->pluck('id')->all(),
$request->input('mediaList')
));
Media::flushQueryCache();
return response()->json();
}
/**
* Suppression de média à un panier
*
* @param \App\Http\Requests\Bo\Ajax\RemoveMediasBasketRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function removeMediasBasket(RemoveMediasBasketRequest $request): JsonResponse
{
/** @var \App\Models\Panier $panier */
$panier = Panier::query()
->where('id', $request->input('panier_id'))
->with('mediaList')
->firstOrFail();
/** @var \App\Models\Media $media */
$media = Media::query()
->where('id', $request->input('media_id'))
->firstOrFail();
$panier->mediaList()->detach($media);
return response()->json(true);
}
/**
* Ajoute un panier
*
* @param \App\Http\Requests\Bo\Ajax\CreateBasketRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function createBasket(CreateBasketRequest $request): JsonResponse
{
/** @var \App\Models\User $user */
$user = auth()->user();
$panier = new Panier();
$panier->libelle = $request->input('title');
$panier->uid = Str::uuid();
$panier->owner()->associate($user);
$panier->saveOrFail();
return response()->json($panier);
}
/**
* Supprimer un panier
*
* @param \App\Http\Requests\Bo\Ajax\DestroyBasketRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function destroyBasket(DestroyBasketRequest $request): JsonResponse
{
/** @var \App\Models\Panier $basket */
$basket = Panier::query()
->where('id', $request->input('basket_id'))
->firstOrFail();
$basket->deleteOrFail();
return response()->json();
}
// * FO
/**
* Page publique d'un panier
*
* @return \Illuminate\Http\Response
* @param \App\Models\Panier $panier
* @return \Illuminate\Contracts\View\View
*/
public function showBasket(Request $request)
public function showBasket(Panier $panier): View
{
$panier_uid = $request->basket_uid;
$formats = Format::withoutGlobalScope('App\Scopes\SystemScope')->where('system', 1)->get();
$panier = Panier::where('uid', $panier_uid)->first();
if($panier && $panier->statut == 1){
return view('panier.show')->with([
'panier'=> $panier,
'formats' => $formats,
]);
}else{
abort(404, 'Page introuvable');
}
}
/** @var \App\Models\User|null $user */
$user = auth()->user();
/**
* Ajout de média à un panier
*/
public function addMediasBasket(Request $request)
{
$response = false;
$mediasToAdd = $request->input('medias');
$panierId = $request->input('panier_id');
$panier = Panier::where('id', $panierId)->with('medias')->first();
if($panier){
foreach ($mediasToAdd as $media) {
$panier->medias()->attach($media['id']);
// * Ne pas afficher le panier si il n'est pas pas publié et
// * que l'utilisateur n'est pas le propiétaire
if (!$panier->statut) {
if (!$user or \optional($panier->owner)->id !== $user->id) {
abort(404);
}
$response = true;
}
}
return json_encode($response);
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Format> $formats */
$formats = Format::query()
->withoutGlobalScope('App\Scopes\SystemScope')
->where('system', true)
->get();
return view('panier.show', [
'panier' => $panier,
'formats' => $formats,
]);
}
/**
* Suppression de média à un panier
*/
public function removeMediasBasket(Request $request)
{
$response = false;
/**
* Enregistre les propriétés d'un panier
*
* @param \App\Http\Requests\Bo\Ajax\SaveBasketPropsRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function saveBasketProperty(SaveBasketPropsRequest $request): JsonResponse
{
/** @var \App\Models\Panier $panier */
$panier = Panier::query()
->where('id', $request->input('basket_id'))
->firstOrFail();
$mediaToRemove = $request->input('media_id');
$panierId = $request->input('panier_id');
$panier = Panier::where('id', $panierId)->with('medias')->first();
if($panier && $mediaToRemove != ""){
$panier->medias()->detach($mediaToRemove);
$response = true;
}
return json_encode($response);
}
/**
* Ajoute un panier
*/
public function addBasket(Request $request)
{
$response = false;
$uid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));
$title = $request->input('title');
if($title == ""){
$title = "Panier du ".date("d/m/Y");
}
$panier = new Panier();
$panier->owner = Auth::user()->id;
$panier->libelle = $title;
$panier->uid = $uid;
if($panier->save()){
$response = $panier;
}
return json_encode($response);
}
/**
* Supprimer un panier
*
*/
public function removeBasket(Request $request)
{
$response = false;
$basket_id = $request->input('basket_id');
$panier = Panier::where('id', $basket_id);
if($panier){
$panier->delete();
$response = true;
}
return json_encode($response);
}
/**
* enregistre les propriétés d'un panier
*
*/
public function saveBasketProperty(Request $request)
{
$response = false;
$basket_id = $request->input('basket_id');
$libelle = $request->input('libelle');
$description = $request->input('description');
$statut = $request->input('statut');
$panier = Panier::where('id', $basket_id)->first();
if($panier){
$panier->libelle = $libelle;
$panier->description = $description;
$panier->statut = $statut;
$panier->save();
$response = $panier;
}
return json_encode($response);
}
$panier->fill($request->validated());
$panier->saveOrFail();
return response()->json($panier);
}
}

View file

@ -4,24 +4,33 @@ namespace App\Http\Controllers;
use App\Models\Media;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class RecoveryController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
return view('recovery.index');
}
/**
* Check if ArcadiaId exists.
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function checkArcadiaId(Request $request)
{
$response = false;
$arcadia_id = $request->id;
$media = Media::onlyTrashed()->where('arcadia_id', '=', $arcadia_id)->first();
if ($media)
$response = true;
return json_encode($response);
return \response()->json(
Media::onlyTrashed()->where('arcadia_id', '=', \intval($request->id))->exists()
);
}
}

View file

@ -1,516 +1,350 @@
<?php
namespace App\Http\Controllers;
use App\Http\Traits\ArcadiaLink;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\Request;
use App\Enums\MediaExtension;
use App\Http\Requests\Bo\Ajax\UploadMediaFileRequest;
use App\Lib\ToolboxHelper;
use App\Models\Copyright;
use App\Models\Dossier;
use App\Models\Etiquette;
use App\Models\Langue;
use App\Models\Media;
use App\Models\Site;
use App\Models\Historique;
use App\Http\Traits\MediaTools;
use App\Models\Sujet;
use App\Models\TypeMedia;
use App\Models\User;
use App\Traits\Http\HandlesMedia;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Pion\Laravel\ChunkUpload\Exceptions\UploadMissingFileException;
use Pion\Laravel\ChunkUpload\Receiver\FileReceiver;
use Symfony\Component\Mime\MimeTypes;
class UploadController extends Controller
{
use HandlesMedia;
use MediaTools;
public function index(Request $request)
/**
* Show upload form
*
* @param Request $request
* @return \Illuminate\Contracts\Validation\Validator|\Illuminate\Contracts\Validation\Factory
*/
public function showUploadForm(Request $request)
{
// ---- Vérification du token de sécurité
// TODO: Quand le DAM sera ouvert au public, Enforce security with dynamic tokens.
// ---- Vérification du token de sécurité .
$token = $request->get('token');
if($token != env('TOKEN_DEPOT', "c8c4613a-236c-4b06-95f6-a9c9c6c18861")) { return abort(404);
if ($token != env('TOKEN_DEPOT', "c8c4613a-236c-4b06-95f6-a9c9c6c18861")) {
return abort(404);
}
$sites = Site::orderBy('libelle')->get();
return view('upload.show')->with(
[
'sites'=> $sites,
]
);
return view('upload.show')->with([
'sites' => $sites,
]);
}
public function storeMedia(Request $request)
{
$uid = $request->input('uid');
$sujet_id = $request->input('sujet_id');
$dossier_id = $request->input('dossier_id');
$replaceMediaId = $request->input('replaceMediaId');
if($dossier_id == 0) { $dossier_id = null;
/**
* Asynchronous chunked upload file.
*
* @param \App\Http\Requests\Bo\Ajax\UploadMediaFileRequest $request
* @param \Pion\Laravel\ChunkUpload\Receiver\FileReceiver $receiver
* @return \Illuminate\Http\JsonResponse
* @throws \Pion\Laravel\ChunkUpload\Exceptions\UploadMissingFileException If failed upload.
*/
public function uploadMediaFileIntoDepot(
UploadMediaFileRequest $request,
FileReceiver $receiver,
): JsonResponse {
/** @var \App\Models\Dossier */
$dossier = Dossier::where('id', intval($request->dossier_id))->firstOrFail();
// Check if the upload is success, throw exception or return response you need.
if ($receiver->isUploaded() === false) {
throw new UploadMissingFileException();
}
// Receive the file.
$save = $receiver->receive();
$headers = $request->headers->all();
$acceptFileTypes = array('gif','jpeg', 'jpg','png','mp4','mp3','psd','ai','svg','pdf');
// Check if the upload has finished (in chunk mode it will send smaller files).
if ($save->isFinished()) {
/** @var \App\Models\User */
$user = auth()->user();
if ($request->hasFile('files')) {
$filesa = [];
$file = $request->file('files');
$uplodedFile = $save->getFile();
foreach($file as $files){
$is_last_chunk = false;
$is_chunked_upload = !empty($headers['content-range']);
if ($is_chunked_upload) {
if (preg_match('|(\d+)/(\d+)|', $headers['content-range'][0], $range)) {
if ($range[1] == $range[2] - 1) {
$is_last_chunk = true;
}
}
}
try {
/** @throws \Illuminate\Validation\ValidationException */
$this->validateUploadedFile($uplodedFile);
$extension = strtolower($files->getClientOriginalExtension());
$originalName = str_replace(".".$extension, "", $files->getClientOriginalName());
if (!in_array($extension, $acceptFileTypes)) { return array("false");
}
/** @var \App\Models\Media */
$media = Media::whereId($request->media_id)
->whereHas('dossier', function ($q) use ($dossier) {
$q->whereId($dossier->id);
})->firstOrNew();
if($is_chunked_upload) {
$filename = $uid."_".$range[1].".".$extension;
}else{
$filename = $uid.'.'.$extension;
}
$uploadPath = public_path() . '/uploads/';
$files->move($uploadPath, $filename);
// si c'est le dernier morceux d'un fichier
if($is_last_chunk) {
if($dossier = opendir($uploadPath)) {
$dirFiles = array();
// on compile tous les chunk du fichier
while(false !== ($fichier = readdir($dossier))){
if($fichier != '.' && $fichier != '..' ) {
if(strpos($fichier, $uid) !== false) {
$dirFiles[$fichier] = str_replace(".".$extension, "", str_replace($uid."_", "", $fichier));
}
}
}
closedir($dossier);
// on les trie pour les assembler dans le bon ordre
asort($dirFiles, SORT_NUMERIC);
// on les assemble dans un fichier final
$filename = $uid . '.' . $extension;
foreach($dirFiles as $key => $fichier) {
$file = fopen($uploadPath.$key, 'rb');
$buff = fread($file, filesize($uploadPath.$key));
fclose($file);
$final = fopen($uploadPath.$filename, 'a');
$write = fwrite($final, $buff);
fclose($final);
unlink($uploadPath.$key);
}
}
}
// si c'est le dernier morceau d'un fichier ou que c'est un envoi simple
if($is_last_chunk || !$is_chunked_upload ) {
$destinationPath = $this->get_mediaFolder()."/";
// si on upload un média pour remplacer un fichier par un autre
if($replaceMediaId != 0) {
// on récupère le média à modifier
$media= Media::where('id', $replaceMediaId)->first();
// On déplace le fichier dans le répertoire des médias
Storage::move("uploads/".$filename, $destinationPath.$filename);
// supprime les fichiers médias stockés sur disque
$filesfF= Storage::files($media->folder."/");
$filepath = preg_quote($media->folder.$media->uid, '/');
$matchingFiles = preg_grep('/^'.$filepath.'/', $filesfF);
Storage::delete($matchingFiles);
$media->isDefault = 0;
$media->save();
}else{
// On déplace le fichier dans le répertoire des médias
Storage::move("uploads/".$filename, $destinationPath.$filename);
// on créé un média en bdd
$media = new Media();
$media->dossier_id = $dossier_id;
$media->sujet_id = $sujet_id;
// Par défaut FR
$media->langue_id = 1;
// Par défaut propriété de la marque
$media->copyright_id = 3;
}
$media->extension = $extension;
$media->folder = $destinationPath;
if($replaceMediaId == 0) {
$media->libelle = mb_substr($originalName, 0, 50, "UTF-8");
$media->created_by= Auth::user()->id;
}
$media->uid = $uid;
$media->taille = $this->formatBytes($this->get_file_size($destinationPath.$filename));
switch ($extension) {
// Photo (1)
case 'gif':
case 'jpeg':
case 'jpg':
case 'png':
case 'ai':
case 'pdf':
case 'psd':
$media->typemedia_id = 1;
$im = new \imagick($destinationPath.$filename);
if(in_array($extension, array("pdf", "ai", "psd", "gif")) ) {
$im->setIteratorIndex(0);
}
$resolutions = $im->getImageResolution();
$media->resolution = round($resolutions['x'] * 2.54);
$imageprops = $im->getImageGeometry();
$media->largeur = $imageprops['width'];
$media->hauteur = $imageprops['height'];
if($media->resolution != 0) {
$media->largeur_mm = ceil(($media->largeur * 2.54 / $media->resolution)*10);
$media->hauteur_mm = ceil(($media->hauteur * 2.54 / $media->resolution)*10);
}else{
$media->largeur_mm = "";
$media->hauteur_mm = "";
}
$media->save();
$im->destroy();
// ---- Creation des vignettes de base
$this->create_sys_thumb($media);
// ---- Creation des vignettes en lien avec le sujet du média
if(isset($sujet_id) ) {
$this->create_thumb($media);
}
break;
// Illustration/Vectorielle (2)
case 'svg':
$media->typemedia_id = 2;
$media->save();
break;
// Vidéo (3)
case 'mp4':
$media->typemedia_id =3 ;
$getID3 = new \getID3;
if($fileInfo = $getID3->analyze($destinationPath.$filename)) {
$media->largeur = $fileInfo['video']['resolution_x'];
$media->hauteur = $fileInfo['video']['resolution_y'];
$media->duree = $fileInfo['playtime_string'];
}
$media->save();
break;
// Audio (4)
case 'mp3':
$media->typemedia_id = 4;
$getID3 = new \getID3;
if($fileInfo = $getID3->analyze($destinationPath.$filename)) {
$media->duree= $fileInfo['playtime_string'];
}
$media->save();
break;
}
$id = $media->id;
$media = Media::find($id);
// ---- Index dans Elasticsearch
$media = Media::where('id', $media->id)->first();
$media->addToIndex();
// ---- Historique des actions
$historique = new historique();
if($user = Auth::user()) {
$historique->user_id = $user->id;
}
$historique->media_id = $media->id;
if($replaceMediaId == 0) {
$historique->type = "Création";
$historique->description = "Média ajouté";
}else{
$historique->type = "Modification";
$historique->description = "Le média a été remplacé";
}
$historique->save();
$filest = array();
$filest['name'] = $filename;
$filest['uid'] = $uid;
$filest['libelle'] = $media->libelle;
$filest['id'] = $media->id;
$filest['folder'] = $media->folder;
$filest['extension'] = $media->extension;
$filest['typemedia_id'] = $media->typemedia_id;
$filesa['files'][]=$filest;
}
// Save the file and return any response you need.
return $this->createOrUpdateMedia($user, $uplodedFile, $media, $dossier);
} catch (ValidationException $e) {
// 400 instead of 422 is for resumablejs to handle properly.
return \response()->json($e->errors(), 400);
}
return $filesa;
}
} //end if
// We are in chunk mode, lets send the current progress.
/** @var AbstractHandler $handler */
$handler = $save->handler();
return response()->json([
'done' => $handler->getPercentageDone()
]);
}
public function storeMediaV2(Request $request)
/**
* Asynchronous chunked upload file.
*
* @param \App\Http\Requests\Bo\Ajax\UploadMediaFileRequest $request
* @param \Pion\Laravel\ChunkUpload\Receiver\FileReceiver $receiver
* @param \App\Models\Sujet $sujet
* @param \App\Models\Dossier $dossier
* @return \Illuminate\Http\JsonResponse
* @throws \Pion\Laravel\ChunkUpload\Exceptions\UploadMissingFileException If failed upload.
*/
public function uploadMediaFile(
UploadMediaFileRequest $request,
FileReceiver $receiver,
Sujet $sujet,
Dossier $dossier
): JsonResponse {
// Check if the upload is success, throw exception or return response you need.
if ($receiver->isUploaded() === false) {
throw new UploadMissingFileException();
}
// Receive the file.
$save = $receiver->receive();
// Check if the upload has finished (in chunk mode it will send smaller files).
if ($save->isFinished()) {
/** @var \App\Models\User */
$user = auth()->user();
$uplodedFile = $save->getFile();
try {
/** @throws \Illuminate\Validation\ValidationException */
$this->validateUploadedFile($uplodedFile);
/** @var \App\Models\Media */
$media = Media::query()
->where('id', $request->input('media_id'))
->whereHas('sujet', fn(Builder $q) => $q->where('codeSujet', $sujet->codeSujet))
->whereHas('dossier', fn(Builder $q) => $q->where('id', $dossier->id))
->firstOrNew();
// Save the file and return any response you need.
return $this->createOrUpdateMedia($user, $uplodedFile, $media, $dossier, $sujet);
} catch (ValidationException $e) {
// 400 instead of 422 is for resumablejs to handle properly.
return \response()->json($e->errors(), 400);
}
} //end if
// We are in chunk mode, lets send the current progress.
/** @var AbstractHandler $handler */
$handler = $save->handler();
return response()->json([
'done' => $handler->getPercentageDone()
]);
}
/**
* Validate uploaded file
*
* @param \Illuminate\Http\UploadedFile $file
* @return void
* @throws \Illuminate\Validation\ValidationException If uploaded file is not valid.
*/
private function validateUploadedFile(UploadedFile $file)
{
$uid = $request->input('uid');
$sujet_id = $request->input('sujet_id');
$dossier_id = $request->input('dossier_id');
$replaceMediaId = $request->input('replaceMediaId');
if($dossier_id == 0) { $dossier_id = null;
Validator::make([
'file' => $file
], [
'file' => 'required|file|mimes:gif,jpeg,jpg,png,mp4,mp3,psd,ai,svg,pdf'
], [
'files.mimes' => trans('Ce type de fichier n\'est pas accepté.')
])->validate();
$this->validateExtension($file);
}
/**
* Validate file extension matches allowed extensions enum
*
* @param \Illuminate\Http\UploadedFile $file
* @return void
* @throws \Illuminate\Validation\ValidationException If file extension could not be confirmed.
*/
private function validateExtension(UploadedFile $file)
{
if (\is_null(MediaExtension::tryFrom($file->getClientOriginalExtension()))) {
throw ValidationException::withMessages([
'file' => trans('Ce type de fichier n\'est pas accepté.')
]);
}
$filesa = [];
$acceptFileTypes = array('gif','jpeg', 'jpg','png','mp4','mp3','psd','ai','svg','pdf');
/** @throws \ValueError If value is not defined in enum */
$mediaExtension = MediaExtension::from($file->getClientOriginalExtension());
if (!$uid) {
$uid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));
}
if ($file->guessExtension()) {
$mt = new MimeTypes();
$guessedExts = $mt->getExtensions($mt->guessMimeType($file->path()));
$file = $request->file('files');
if (!empty($file)) {
$extension = strtolower($file->getClientOriginalExtension());
$originalName = str_replace(".".$extension, "", $file->getClientOriginalName());
if (!in_array($extension, $acceptFileTypes)) { return array("false");
}
if (!in_array($extension, $acceptFileTypes)) { return array("error" => "Ce type de fichier n'est pas accepté.");
}
// check the error status
if ($file->getError() != 0) {
Log::error('error ' . $file->getError() . ' in file ' . $request->resumableFilename);
}
// init the destination file (format <filename.ext>.part<#chunk>
// the file is stored in a temporary directory
if(isset($request->resumableIdentifier) && trim($request->resumableIdentifier)!='') {
$temp_dir = 'uploads/' . $request->resumableIdentifier;
}
$dest_file = $temp_dir . '/' . $request->resumableFilename . '.part' . $request->resumableChunkNumber;
// create the temporary directory
if (!is_dir($temp_dir)) {
mkdir($temp_dir, 0777, true);
}
// move the temporary file
if (!move_uploaded_file($file->getPathname(), $dest_file)) {
Log::error('Error saving (move_uploaded_file) chunk ' . $request->resumableChunkNumber.' for file ' . $request->resumableFilename);
} else {
$filename = $uid . '.' . $extension;
// check if all the parts present, and create the final destination file
$isLast = $this->createFileFromChunks($temp_dir, $request->resumableFilename, $request->resumableChunkSize, $request->resumableTotalSize, $request->resumableTotalChunks, $filename);
if ($isLast) {
$destinationPath = $this->get_mediaFolder()."/";
// si on upload un média pour remplacer un fichier par un autre
if($replaceMediaId != 0) {
// on récupère le média à modifier
$media= Media::where('id', $replaceMediaId)->first();
// On déplace le fichier dans le répertoire des médias
Storage::move("uploads/".$filename, $destinationPath.$filename);
// supprime les fichiers médias stockés sur disque
$filesfF= Storage::files($media->folder."/");
$filepath = preg_quote($media->folder.$media->uid, '/');
$matchingFiles = preg_grep('/^'.$filepath.'/', $filesfF);
Storage::delete($matchingFiles);
$media->isDefault = 0;
$media->save();
}else{
// On déplace le fichier dans le répertoire des médias
Storage::move("uploads/".$filename, $destinationPath.$filename);
// on créé un média en bdd
$media = new Media();
$media->dossier_id = $dossier_id;
$media->sujet_id = $sujet_id;
// Par défaut FR
$media->langue_id = 1;
// Par défaut propriété de la marque
$media->copyright_id = 3;
}
$media->extension = $extension;
$media->folder = $destinationPath;
if($replaceMediaId == 0) {
$media->libelle = mb_substr($originalName, 0, 50, "UTF-8");
$media->created_by= Auth::user()->id;
}
$media->uid = $uid;
$media->taille = $this->formatBytes($this->get_file_size($destinationPath.$filename));
switch ($extension) {
// Photo (1)
case 'gif':
case 'jpeg':
case 'jpg':
case 'png':
case 'ai':
case 'pdf':
case 'psd':
$media->typemedia_id = 1;
$im = new \imagick($destinationPath . $filename);
//$im = new \imagick(realpath($destinationPath.$filename));
if(in_array($extension, array("pdf", "ai", "psd", "gif")) ) {
$im->setIteratorIndex(0);
}
$resolutions = $im->getImageResolution();
$media->resolution = round($resolutions['x'] * 2.54);
$imageprops = $im->getImageGeometry();
$media->largeur = $imageprops['width'];
$media->hauteur = $imageprops['height'];
if($media->resolution != 0) {
$media->largeur_mm = ceil(($media->largeur * 2.54 / $media->resolution)*10);
$media->hauteur_mm = ceil(($media->hauteur * 2.54 / $media->resolution)*10);
}else{
$media->largeur_mm = "";
$media->hauteur_mm = "";
}
$media->save();
$im->destroy();
// ---- Creation des vignettes de base
$this->create_sys_thumb($media);
// ---- Creation des vignettes en lien avec le sujet du média
if(isset($sujet_id) ) {
$this->create_thumb($media);
}
break;
// Illustration/Vectorielle (2)
case 'svg':
$media->typemedia_id = 2;
$media->save();
break;
// Vidéo (3)
case 'mp4':
$media->typemedia_id =3 ;
$getID3 = new \getID3;
if($fileInfo = $getID3->analyze($destinationPath.$filename)) {
$media->largeur = $fileInfo['video']['resolution_x'];
$media->hauteur = $fileInfo['video']['resolution_y'];
$media->duree = $fileInfo['playtime_string'];
}
$media->save();
break;
// Audio (4)
case 'mp3':
$media->typemedia_id = 4;
$getID3 = new \getID3;
if($fileInfo = $getID3->analyze($destinationPath.$filename)) {
$media->duree= $fileInfo['playtime_string'];
}
$media->save();
break;
}
$id = $media->id;
$media = Media::find($id);
// ---- Index dans Elasticsearch
$media = Media::where('id', $media->id)->first();
$media->addToIndex();
// ---- Historique des actions
$historique = new historique();
if($user = Auth::user()) {
$historique->user_id = $user->id;
}
$historique->media_id = $media->id;
if($replaceMediaId == 0) {
$historique->type = "Création";
$historique->description = "Média ajouté";
}else{
$historique->type = "Modification";
$historique->description = "Le média a été remplacé";
}
$historique->save();
return response()->json($media);
}
if (!\in_array($mediaExtension->value, $guessedExts)) {
$guessedExts = \implode(',', $guessedExts);
throw ValidationException::withMessages([
'file' => trans(
'File guessed extensions :guessedExts does not match file name extension :extension',
[
'guessedExt' => $guessedExts,
'extension' => $mediaExtension->value,
]
)
]);
}
}
}
/**
* Check if all the parts exist, and
* gather all the parts of the file together
* Create or update media
*
* @param string $temp_dir - the temporary directory holding all the parts of the file
* @param string $fileName - the original file name
* @param string $chunkSize - each chunk size (in bytes)
* @param string $totalSize - original file size (in bytes)
* @return bool
* @param \App\Models\User $user
* @param \Illuminate\Http\UploadedFile $file
* @param \App\Models\Media $media
* @param \App\Models\Dossier $dossier
* @param \App\Models\Sujet|null $sujet
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Validation\ValidationException If $subject is missing and folder
* is not a system folder (Dossier dépot).
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
* (switch) .
*/
private function createFileFromChunks($temp_dir, $fileName, $chunkSize, $totalSize, $total_files, $finalName)
{
// count all the parts of this file
$total_files_on_server_size = 0;
$temp_total = 0;
foreach(scandir($temp_dir) as $file) {
$temp_total = $total_files_on_server_size;
$tempfilesize = filesize($temp_dir.'/'.$file);
$total_files_on_server_size = $temp_total + $tempfilesize;
}
// check that all the parts are present
// If the Size of all the chunks on the server is equal to the size of the file uploaded.
if ($total_files_on_server_size >= $totalSize) {
// create the final destination file
if (($fp = fopen('uploads/'.$finalName, 'w')) !== false) {
for ($i=1; $i<=$total_files; $i++) {
fwrite($fp, file_get_contents($temp_dir.'/'.$fileName.'.part'.$i));
//Log::info('writing chunk '.$i);
}
fclose($fp);
} else {
Log::error('cannot create the destination file');
return false;
private function createOrUpdateMedia(
User $user,
UploadedFile $file,
Media $media,
Dossier $dossier,
Sujet|null $sujet = null
): JsonResponse {
// phpcs:enable
return DB::transaction(function () use ($user, $file, $media, $dossier, $sujet) {
if (!$dossier->system and !$sujet) {
throw ValidationException::withMessages([
'file' => 'Cannot put media inside a non system folder (depot) without a subject'
]);
}
// rename the temporary directory (to avoid access from other
// concurrent chunks uploads) and than delete it
if (rename($temp_dir, $temp_dir.'_UNUSED')) {
$this->rrmdir($temp_dir.'_UNUSED');
} else {
$this->rrmdir($temp_dir);
}
return true;
}
return false;
}
/** @var \Illuminate\Filesystem\FilesystemAdapter */
$storage = Storage::disk('media');
/**
* Delete a directory RECURSIVELY
*
* @param string $dir - directory path
* @link http://php.net/manual/en/function.rmdir.php
*/
private function rrmdir($dir)
{
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (filetype($dir . "/" . $object) == "dir") {
$this->rrmdir($dir . "/" . $object);
} else {
unlink($dir . "/" . $object);
$isNewMedia = !$media->exists;
$mediaFolderName = $this->getCurentMediaFolderName();
// * File size
$fileSize = $file->getSize();
$sanitizedFileName = ToolboxHelper::sanitizeFileName($file->getClientOriginalName());
/** @var string */
$sanitizedFileBasename = \pathinfo($sanitizedFileName, \PATHINFO_BASENAME);
/** @var string */
$sanitizedFileExtension = \pathinfo($sanitizedFileName, \PATHINFO_EXTENSION);
/** @throws \ValueError If value is not defined in enum */
$mediaExtension = MediaExtension::from($sanitizedFileExtension);
if (!$isNewMedia) {
// Supprimer les vielles images.
$media->deleteFilesOnAllPath();
}
// * New folder attribution
$media->folder = $mediaFolderName;
// * New Image, New uuid.
$media->uid = Str::uuid();
// * New Image extension
$media->extension = $mediaExtension;
// * New Image size
$media->taille = $fileSize ? $fileSize : 0;
// * Le media n'est pas une image par défaut.
$media->isDefault = false;
// * On déplace le fichier dans le répertoire des médias.
/** @throws \FileException */
$file->move($storage->path($media->folder), $media->basename);
// * Si on upload un média pour remplacer un fichier par un autre
if ($isNewMedia) {
$media->libelle = Str::limit($sanitizedFileBasename, 50, '');
$media->owner()->associate($user);
$media->dossier()->associate($dossier);
$media->sujet()->associate($sujet);
// * Par défaut FR
$media->langue()->associate(Langue::getDefaultLang());
// * Par défaut propriété de la marque
$media->copyright()->associate(Copyright::getBrandCopyright());
$media->etiquette()->associate(Etiquette::getDefaultEtiquette());
}
switch ($media->extension) {
case MediaExtension::gif:
case MediaExtension::jpeg:
case MediaExtension::jpg:
case MediaExtension::png:
case MediaExtension::ai:
case MediaExtension::pdf:
case MediaExtension::psd:
$dimensions = ToolboxHelper::getImageDimensions($media->full_path);
if ($dimensions) {
$media->resolution = $dimensions['resolutionX'];
$media->largeur = $dimensions['width'];
$media->hauteur = $dimensions['height'];
$media->largeur_mm = !empty($media->resolution) ? ceil($media->largeur * 10) : 0;
$media->hauteur_mm = !empty($media->resolution) ? ceil($media->hauteur * 10) : 0;
}
}
}
reset($objects);
rmdir($dir);
}
// ---- Creation des vignettes de base
$media->createThumbnail();
// ---- Creation des vignettes en lien avec le sujet du média
$media->createSubjectThumbnails();
break;
case MediaExtension::mp4:
if ($dimensions = ToolboxHelper::getId3VideoDimensions($media->full_path)) {
$media->largeur = $dimensions['width'];
$media->hauteur = $dimensions['height'];
}
// Fall-through .
case MediaExtension::mp3:
$media->duree = ToolboxHelper::getId3Playtime($media->full_path);
break;
} //end switch
$media->typeMedia()->associate(TypeMedia::getMediaType($media->extension));
$media->saveOrFail();
Media::flushQueryCache();
// * Get props inserted by DB.
return response()->json($media->refresh());
});
}
}

View file

@ -2,12 +2,13 @@
namespace App\Http\Controllers;
use App\User;
use App\Models\User;
use App\Models\Marque;
use App\Models\Sujet;
use Illuminate\Http\Request;
use Adldap\Laravel\Facades\Adldap;
use App\Http\Requests\DestroyUserRequest;
use App\Models\Dossier;
use App\Models\Media;
use Illuminate\Support\Facades\DB;
@ -20,14 +21,12 @@ class UserController extends Controller
*/
public function index()
{
/** @var \App\User $localUser */
/** @var \App\Models\User $localUser */
$localUser = auth()->user();
$localUser->authorizeRoles(config('roles.const.ADMIN'));
$users = User::all();
$sujets = Sujet::where('sujet_dam', 1)->get();
$users = User::all();
return view('users.index')->with([
'users' => $users,
'sujets' => $sujets
'users' => $users
]);
}
@ -38,12 +37,12 @@ class UserController extends Controller
*/
public function create()
{
/** @var \App\User $localUser */
/** @var \App\Models\User $localUser */
$localUser = auth()->user();
$localUser->authorizeRoles(config('roles.const.ADMIN'));
$roles = config('roles.label');
$marques = Marque::orderBy('libMarq', 'asc')->get();
$sujets = Sujet::where('sujet_dam', 1)->orderBy('libelle', 'asc')->get();
$sujets = Sujet::where('sujet_dam', true)->orderBy('libelle', 'asc')->get();
return view('users.create')->with([
'roles' => $roles, 'marques' => $marques,
'sujets' => $sujets
@ -58,7 +57,7 @@ class UserController extends Controller
*/
public function store(Request $request)
{
/** @var \App\User $localUser */
/** @var \App\Models\User $localUser */
$localUser = auth()->user();
$localUser->authorizeRoles(config('roles.const.ADMIN'));
$validatedData = $request->validate([
@ -124,7 +123,7 @@ class UserController extends Controller
*/
public function checkMatricule(Request $request)
{
/** @var \App\User $localUser */
/** @var \App\Models\User $localUser */
$localUser = auth()->user();
$localUser->authorizeRoles(config('roles.const.ADMIN'));
$response = [];
@ -159,7 +158,7 @@ class UserController extends Controller
/**
* Display the specified resource.
*
* @param \App\User $user
* @param \App\Models\User $user
* @return \Illuminate\Http\Response
*/
public function show(User $user)
@ -177,12 +176,12 @@ class UserController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param \App\User $user
* @param \App\Models\User $user
* @return \Illuminate\Http\Response
*/
public function edit(User $user)
{
/** @var \App\User $localUser */
/** @var \App\Models\User $localUser */
$localUser = auth()->user();
$localUser->authorizeRoles(config('roles.const.ADMIN'));
@ -190,11 +189,15 @@ class UserController extends Controller
$userMarques = $user->marques;
$marques = Marque::orderBy('libMarq', 'asc')->get();
$userSujets = $user->sujets;
$sujets = Sujet::where('sujet_dam', 1)->orderBy('libelle', 'asc')->get();
$users = User::select(['id', 'email'])->whereIn('role', [
config('roles.const.ADMIN'), config('roles.const.CONTRIBUTEUR'),
config('roles.const.REDACTEUR')
])->where('id', '!=', $user->id)->get();
$sujets = Sujet::where('sujet_dam', true)->orderBy('libelle', 'asc')->get();
$users = User::select(['id', 'email'])
->whereIn('role', [
config('roles.const.ADMIN'), config('roles.const.CONTRIBUTEUR'),
config('roles.const.REDACTEUR')
])
->where('id', '!=', $user->id)
->orderBy('email')
->get();
return view('users.edit')->with([
'user' => $user, 'roles' => $roles, 'users' => $users,
'userMarques' => $userMarques, 'marques' => $marques,
@ -206,12 +209,12 @@ class UserController extends Controller
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\User $user
* @param \App\Models\User $user
* @return \Illuminate\Http\Response
*/
public function update(Request $request, User $user)
{
/** @var \App\User $localUser */
/** @var \App\Models\User $localUser */
$localUser = auth()->user();
$localUser->authorizeRoles(config('roles.const.ADMIN'));
$validatedData = $request->validate([
@ -259,7 +262,7 @@ class UserController extends Controller
* Remove the specified resource from storage.
*
* @param \App\Http\Requests\DestroyUserRequest $request
* @param \App\User $user
* @param \App\Models\User $user
* @return \Illuminate\Http\Response
*/
public function destroy(DestroyUserRequest $request, User $user)
@ -268,7 +271,7 @@ class UserController extends Controller
$localUser = auth()->user();
$localUser->authorizeRoles(config('roles.const.ADMIN'));
/** @var \App\User */
/** @var \App\Models\User */
$userPourRemplacer = User::whereId($request->created_by)->firstOrFail();
try {
@ -278,8 +281,7 @@ class UserController extends Controller
$media->owner()->associate($userPourRemplacer);
$media->saveOrFail();
});
// TODO: use deleteOrFail after upgrate to laravel 8.
if ($user->delete()) {
if ($user->deleteOrFail()) {
session()->flash('success', trans('L\'utilisateur à été supprimé'));
return redirect(route('user.index'));
}
@ -296,23 +298,22 @@ class UserController extends Controller
/**
* Ajouter un dossier en favoris
*
* @param Request $request
* @param \Illuminate\Http\Request $request
* @param \App\Models\Dossier $dossier
* @return \Illuminate\Http\JsonResponse
*/
public function favorisFolder(Request $request)
public function favorisFolder(Request $request, Dossier $dossier)
{
/** @var \App\Models\User $localUser */
$localUser = auth()->user();
$dossier_id = $request->input('dossier_id');
$favoris = $request->input('favoris');
$dossierFavExists = $localUser->dossiers()
->where('id', $dossier->id)->exists();
$dossierFav = $localUser->dossiers()->where('id', $dossier_id)->first();
if ($favoris === false && $dossierFav) {
$localUser->dossiers()->detach($dossier_id);
} elseif ($favoris === true && !$dossierFav) {
$localUser->dossiers()->attach($dossier_id);
if (!$request->boolean('favoris') and $dossierFavExists) {
$localUser->dossiers()->detach($dossier->id);
} elseif ($request->boolean('favoris') and !$dossierFavExists) {
$localUser->dossiers()->attach($dossier->id);
}
return response()->json();
}

View file

@ -11,10 +11,13 @@ class Kernel extends HttpKernel
*
* These middleware are run during every request to your application.
*
* @var array
* @var array<int, class-string|string>
*/
protected $middleware = [
\App\Http\Middleware\CheckForMaintenanceMode::class,
\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,
@ -24,22 +27,25 @@ class Kernel extends HttpKernel
/**
* The application's route middleware groups.
*
* @var array
* @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\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
'throttle:api',
\App\Http\Middleware\JsonOnly::class,
\App\Http\Middleware\ApiResponse::class,
\App\Http\Middleware\ApiCheckTimeStamps::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class
],
];
@ -48,33 +54,19 @@ class Kernel extends HttpKernel
*
* These middleware may be assigned to groups or used individually.
*
* @var array
* @var array<string, class-string|string>
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::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' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
/**
* The priority-sorted list of middleware.
*
* This forces non-global middleware to always be in the given order.
*
* @var array
*/
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
'htmlsanitize' => \App\Http\Middleware\HtmlSanitizer::class,
];
}

View file

@ -0,0 +1,41 @@
<?php
namespace App\Http\Middleware;
use App\Enums\Legacy\ApiError;
use App\Exceptions\Api\ApiErrorException;
use App\Lib\Helper;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
/**
* Check Http Header Timestamp with request timestamp
* to prevent replay attacks
* https://restfulapi.net/security-essentials/
*/
class ApiCheckTimeStamps
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
* @throws ApiErrorException With ApiError::wrongTimeStamp if timestamp has an incorrect format or is timed out.
*/
public function handle(Request $request, \Closure $next)
{
if (Helper::isRequestForApi($request)) {
if (!\is_string($request->timestamp) or !Carbon::hasFormat($request->timestamp, 'Y-m-d H:i:s')) {
throw new ApiErrorException(ApiError::wrongTimeStamp());
}
if (
Carbon::parse($request->timestamp, 'utc')
->isBefore(Carbon::now('UTC')->subSeconds(config('api.timestampTimeout', 10)))
) {
throw new ApiErrorException(ApiError::wrongTimeStamp());
}
}
return $next($request);
}
}

View file

@ -0,0 +1,59 @@
<?php
namespace App\Http\Middleware;
use App\Enums\Legacy\ApiStatus;
use App\Http\Resources\Api\ApiResponse as ApiResponseResource;
use App\Models\Api\ApiToken;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
/**
* Make sur the response is an ApiResource resource.
*/
class ApiResponse
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
* @throws \ErrorException If the received response is not a JsonResponse.
*/
public function handle(Request $request, \Closure $next)
{
/** @var \Illuminate\Http\JsonResponse $response */
$response = $next($request);
if (\get_class($response) !== JsonResponse::class) {
// @codeCoverageIgnoreStart
throw new \ErrorException('All api responses should be json.');
// @codeCoverageIgnoreEnd
}
// Set no cache header.
$response->header('Cache-Control', 'No-Store');
/** @var \App\Models\Api\ApiToken|null */
if (\optional($apiToken = app(ApiToken::class))->id) {
$apiToken->incrementStat();
}
/** @var object $data */
$data = (object)$response->getData();
// If reponse is already a ApiResponse then just return it. This happens if error handler comes into action.
if (
isset($data->status) and
isset($data->version) and
in_array($data->status, [ApiStatus::OK()->value, ApiStatus::KO()->value])
) {
return $response;
}
/** @var \App\Enums\Legacy\ApiStatus $status */
$status = intval($response->getStatusCode() / 100) == 2 ? ApiStatus::OK() : ApiStatus::KO();
return $response->setData(new ApiResponseResource((object)\optional($data)->data ?? $data, $status));
}
}

View file

@ -9,11 +9,13 @@ 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
* @param \Illuminate\Http\Request $request
* @return string|null
* @phpcs:disable Squiz.Commenting.FunctionComment.TypeHintMissing
*/
protected function redirectTo($request)
{
// phpcs:enable
if (! $request->expectsJson()) {
return route('login');
}

View file

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

View file

@ -9,9 +9,7 @@ class EncryptCookies extends Middleware
/**
* The names of the cookies that should not be encrypted.
*
* @var array
* @var array<int, string>
*/
protected $except = [
//
];
protected $except = [];
}

View file

@ -0,0 +1,43 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
class HtmlSanitizer
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param mixed ...$params
* @return mixed
*/
public function handle(Request $request, \Closure $next, mixed ...$params)
{
$inputs = $request->all();
array_walk_recursive($inputs, function (&$input, $name) use ($params) {
if (!is_string($input)) {
return;
}
if (in_array($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 (&$item) {
if (\is_string($item)) {
$item = clean($item);
}
});
} else {
$input = clean($input);
}
} else {
$input = strip_tags($input);
}
});
$request->merge($inputs);
return $next($request);
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
/**
* Allow ony json requests
*/
class JsonOnly
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, \Closure $next)
{
if (
!$request->isJson() or
!$request->expectsJson() or
is_null(json_decode($request->getContent()))
) {
abort(400, 'Invalid JSON');
}
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

@ -2,7 +2,8 @@
namespace App\Http\Middleware;
use Closure;
use App\Providers\RouteServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
@ -10,15 +11,20 @@ class RedirectIfAuthenticated
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @return mixed
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null ...$guards
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle($request, Closure $next, $guard = null)
public function handle(Request $request, \Closure $next, ...$guards)
{
if (Auth::guard($guard)->check()) {
return redirect('/');
/** @var array<string|null> */
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
}
return $next($request);

View file

@ -9,9 +9,10 @@ class TrimStrings extends Middleware
/**
* The names of the attributes that should not be trimmed.
*
* @var array
* @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

@ -2,22 +2,26 @@
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
use Fideloper\Proxy\TrustProxies as Middleware;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array
* @var array<int, string>|string|null
*/
protected $proxies = '*';
/**
* The headers that should be used to detect proxies.
*
* @var int
* @var integer
*/
protected $headers = Request::HEADER_X_FORWARDED_ALL;
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

@ -6,19 +6,10 @@ use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* Indicates whether the XSRF-TOKEN cookie should be set on the response.
*
* @var bool
*/
protected $addHttpCookie = true;
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array
* @var array<int, string>
*/
protected $except = [
//
];
protected $except = [];
}

View file

@ -0,0 +1,32 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class AddMediasBasketRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'panier_id' => 'required|exists:paniers,id,deleted_at,NULL',
'mediaList' => 'required|array',
'mediaList.*' => 'required|exists:media,id,deleted_at,NULL'
];
}
}

View file

@ -0,0 +1,33 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class ApplyStickerRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules(): array
{
return [
'etiquette_id' => 'required|exists:etiquettes,etiquette_id',
'mediaList' => 'required|array',
'mediaList.*' => 'array|min:0',
'mediaList.*.id' => 'required|exists:media,id',
];
}
}

View file

@ -0,0 +1,43 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use App\Models\Media;
use Illuminate\Foundation\Http\FormRequest;
class CheckRefKeyRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return \auth()->check() and $this->ajax();
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
{
$this->merge([
'media' => Media::where('id', $this->media_id)->first()
]);
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'media_id' => 'required|exists:media,id,deleted_at,NULL'
];
}
}

View file

@ -0,0 +1,35 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Carbon;
class CreateBasketRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
$this->merge([
'title' => $this->title ??
sprintf('Panier du %s', Carbon::now()->format('d/m/Y'))
]);
return auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'title' => 'required|min:1|max:255'
];
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class DeleteMediaRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'mediaList' => 'required|array',
'mediaList.*' => 'required|exists:media,id,deleted_at,NULL'
];
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class DestroyBasketRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'basket_id' => 'required|exists:paniers,id,deleted_at,NULL'
];
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class FetchFoldersRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'sujetId' => 'required|exists:sujets,codeSujet'
];
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class GetArticleRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return \auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'arcadia_id' => 'required|exists:articles,noArt'
];
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class LoadFoldersRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return \auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'sujet_id' => 'required|exists:sujets,codeSujet'
];
}
}

View file

@ -0,0 +1,33 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class MoveMediaRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'dossier_id' => 'required|numeric',
'mediaList' => 'required|array',
'mediaList.*' => 'required|array',
'mediaList.*.id' => 'required|exists:media,id',
];
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class RemoveMediasBasketRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'panier_id' => 'required|exists:paniers,id,deleted_at,NULL',
'media_id' => 'required|exists:media,id,deleted_at,NULL'
];
}
}

View file

@ -0,0 +1,36 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class SaveBasketPropsRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
$this->merge([
'statut' => $this->statut ? true : false
]);
return auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'basket_id' => 'required|exists:paniers,id,deleted_at,NULL',
'libelle' => 'required|string|min:2|max:255',
'description' => 'nullable|string',
'statut' => 'required|boolean'
];
}
}

View file

@ -0,0 +1,47 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use App\Enums\ContactType;
use App\Rules\EnumIsValidRule;
use Illuminate\Foundation\Http\FormRequest;
class SendContactMessageRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return auth()->check() and $this->ajax();
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
{
$this->merge([
'url' => strval($this->url),
'type' => intval($this->type)
]);
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'type' => ['required', new EnumIsValidRule(ContactType::class)],
'url' => 'nullable|url',
'message' => 'required|string|min:20'
];
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class StoreMediaFileRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'media_id' => 'nullable|exists:media,id'
];
}
}

View file

@ -0,0 +1,118 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use App\Enums\MediaStatut;
use Illuminate\Foundation\Http\FormRequest;
class UpdateMediaRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth()->check() and $this->ajax();
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
{
$this->merge([
'tags' => $this->tags ?? [],
'articles' => $this->articles ?? [],
'marques' => $this->marques ?? [],
'societes' => $this->societes ?? []
]);
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
$rules = [
'statut' => 'required|numeric|in:' . \implode(',', collect(MediaStatut::cases())->pluck('value')->all()),
'version' => 'required|numeric|min:1',
'type_vue_id' => 'required|exists:type_vues,codeTypevue',
'variante_id' => 'required|exists:variantes,codeVariante',
'langue_id' => 'required|exists:langues,langue_id',
];
// ? Est lié à arcadia ?
if ($this->media->arcadia_id) {
// Ne pas autoriser brouillon .
$rules['statut'] = 'required|numeric|in:' . \implode(',', [
MediaStatut::public->value, MediaStatut::public_etendu->value
]);
unset($rules['version']);
unset($rules['type_vue_id']);
unset($rules['variante_id']);
unset($rules['langue_id']);
}
// Article.
if ($this->sujet_id == 1) {
$rules['articles'] = 'present|array|min:0';
$rules['articles.*'] = 'array';
$rules['articles.*.id'] = 'exists:articles,id';
}
// Marque.
if ($this->sujet_id == 2) {
$rules['marques'] = 'present|array|min:0';
$rules['marques.*'] = 'array';
$rules['marques.*.codMarq'] = 'exists:marques,codMarq';
}
// Sociétés.
if ($this->sujet_id == 4) {
$rules['societes'] = 'present|array|min:0';
$rules['societes.*'] = 'array';
$rules['societes.*.id'] = 'exists:societes,id';
}
return \array_merge($rules, [
'libelle' => 'required|string|min:2|max:50',
'commentaire' => 'nullable|string|min:2',
'copyright_id' => 'required|exists:copyrights,copyright_id',
// Tags.
'tags' => 'present|array|min:0',
'tags.*.libelle' => 'min:2|max:50',
'etiquette_id' => 'required|exists:etiquettes,etiquette_id',
]);
}
/**
* Get custom attributes for validator errors.
*
* @return array<string,string>
*/
public function attributes(): array
{
return [
'libelle' => trans('libelle'),
'commentaire' => trans('commentaire'),
'societes' => trans('societes'),
'societes.*' => trans('societes'),
'societes.*.id' => trans('societes'),
'marques' => trans('marques'),
'marques.*' => trans('marques'),
'marques.*.codMarq' => trans('marques'),
'copyright_id' => trans('copyright'),
'etiquette_id' => trans('etiquette'),
'type_vue_id' => trans('type de vue'),
'variante_id' => trans('type de variante'),
'tags' => trans('nuage de tags'),
'tags.*.libelle' => trans('libellé dans le nuage de tags'),
];
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class UploadMediaFileRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'media_id' => 'nullable|exists:media,id',
'dossier_id' => 'sometimes|exists:dossiers,id'
];
}
}

View file

@ -0,0 +1,16 @@
<?php
namespace App\Http\Requests\Bo;
class DownloadMediaPublicRequest extends DownloadMediaRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return true;
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace App\Http\Requests\Bo;
use Illuminate\Foundation\Http\FormRequest;
class DownloadMediaRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'mediaList' => 'required|array',
'mediaList.*' => 'required|exists:media,id',
];
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace App\Http\Requests\Bo\Folders;
use Illuminate\Foundation\Http\FormRequest;
class StoreDepotFolderRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'libelle' => 'required|string|min:4|max:255|unique:dossiers,libelle',
'description' => 'nullable|string|min:4'
];
}
}

View file

@ -0,0 +1,56 @@
<?php
namespace App\Http\Requests\Bo\Folders;
use Illuminate\Foundation\Http\FormRequest;
class StoreFolderRequest 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()
{
$this->merge([
'sub' => $this->sub ? true : false,
'is_private' => $this->status ? true : false,
'marques' => !$this->marques ? null : \explode(',', \strval($this->marques))
]);
if ($this->sub) {
$this->merge([
'is_private' => false
]);
}
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'parent_id' => 'sometimes|exists:dossiers,id',
'libelle' => 'required|string|min:4|max:255|unique:dossiers,libelle',
'description' => 'nullable|string|min:4',
'sujet' => 'required_unless:sub,true|exists:sujets,codeSujet',
'is_private' => 'required|boolean',
'marques' => 'nullable|array',
'marques.*' => 'required|exists:marques,codMarq',
'sub' => 'required|boolean'
];
}
}

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