mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-11-04 11:18:25 +00:00 
			
		
		
		
	Compare commits
	
		
			254 Commits
		
	
	
		
			v3.0.0-RC1
			...
			295-cancel
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						fad7bdf235
	
				 | 
					
					
						|||
| 
						
						
							
						
						8521cea46c
	
				 | 
					
					
						|||
| 
						
						
							
						
						4ead7ba761
	
				 | 
					
					
						|||
| 
						
						
							
						
						9721b166eb
	
				 | 
					
					
						|||
| 
						
						
							
						
						1b21cd6c33
	
				 | 
					
					
						|||
| 
						
						
							
						
						97860a9487
	
				 | 
					
					
						|||
| 
						
						
							
						
						2fb46c65c2
	
				 | 
					
					
						|||
| 
						
						
							
						
						f4356ac249
	
				 | 
					
					
						|||
| 
						
						
							
						
						d152efe084
	
				 | 
					
					
						|||
| 
						
						
							
						
						ee9530d03f
	
				 | 
					
					
						|||
| 
						
						
							
						
						b97eabf0d2
	
				 | 
					
					
						|||
| 
						
						
							
						
						2e69d2df90
	
				 | 
					
					
						|||
| 
						
						
							
						
						cb446edd18
	
				 | 
					
					
						|||
| 
						
						
							
						
						5d84e997c1
	
				 | 
					
					
						|||
| 
						
						
							
						
						35199b6993
	
				 | 
					
					
						|||
| 
						
						
							
						
						dab68fb409
	
				 | 
					
					
						|||
| 
						
						
							
						
						6001bb6447
	
				 | 
					
					
						|||
| 
						
						
							
						
						29fec50515
	
				 | 
					
					
						|||
| 
						
						
							
						
						34edb02cd0
	
				 | 
					
					
						|||
| 
						
						
							
						
						860ae5cedf
	
				 | 
					
					
						|||
| 
						
						
							
						
						bf056046ab
	
				 | 
					
					
						|||
| 
						
						
							
						
						4d73f9b81a
	
				 | 
					
					
						|||
| dd159f4379 | |||
| 
						
						
							
						
						49ad25b4c8
	
				 | 
					
					
						|||
| 
						
						
							
						
						ad94310981
	
				 | 
					
					
						|||
| 
						
						
							
						
						e8f09b507f
	
				 | 
					
					
						|||
| 
						
						
							
						
						e29e1db6ed
	
				 | 
					
					
						|||
| 
						
						
							
						
						8c4f342ca1
	
				 | 
					
					
						|||
| 
						
						
							
						
						745a29f742
	
				 | 
					
					
						|||
| 
						
						
							
						
						41ffc470a0
	
				 | 
					
					
						|||
| 
						
						
							
						
						46b31ae1ea
	
				 | 
					
					
						|||
| 
						
						
							
						
						8c5e94e295
	
				 | 
					
					
						|||
| 
						
						
							
						
						9c8a84cdbd
	
				 | 
					
					
						|||
| 
						
						
							
						
						a82b99aecc
	
				 | 
					
					
						|||
| 
						
						
							
						
						deb4bda16e
	
				 | 
					
					
						|||
| 
						
						
							
						
						c1e5f4a57e
	
				 | 
					
					
						|||
| 
						
						
							
						
						6fc5a10dc4
	
				 | 
					
					
						|||
| 
						
						
							
						
						18abc84e68
	
				 | 
					
					
						|||
| 
						
						
							
						
						e85c31826f
	
				 | 
					
					
						|||
| 
						
						
							
						
						d119ba49f7
	
				 | 
					
					
						|||
| 
						
						
							
						
						c21de777fd
	
				 | 
					
					
						|||
| 
						
						
							
						
						15eaf648df
	
				 | 
					
					
						|||
| 
						
						
							
						
						42471269db
	
				 | 
					
					
						|||
| 
						
						
							
						
						9475a708c3
	
				 | 
					
					
						|||
| bf1af1aaad | |||
| 
						
						
							
						
						8ea87053f0
	
				 | 
					
					
						|||
| 
						
						
							
						
						3c9ee41b3b
	
				 | 
					
					
						|||
| 
						
						
							
						
						d0031e82e8
	
				 | 
					
					
						|||
| 
						
						
							
						
						20f2bc6c35
	
				 | 
					
					
						|||
| 
						
						
							
						
						71d3aa3969
	
				 | 
					
					
						|||
| 
						
						
							
						
						ce781a5b58
	
				 | 
					
					
						|||
| 2dd275a074 | |||
| 5f5d4b8f06 | |||
| 
						
						
							
						
						cc8214d52c
	
				 | 
					
					
						|||
| 
						
						
							
						
						0c797c2997
	
				 | 
					
					
						|||
| 
						
						
							
						
						ee6edba206
	
				 | 
					
					
						|||
| 
						
						
							
						
						3e6d764b9b
	
				 | 
					
					
						|||
| 
						
						
							
						
						3e5a558cdf
	
				 | 
					
					
						|||
| 
						
						
							
						
						0e6b7d76a4
	
				 | 
					
					
						|||
| b2042bd1e4 | |||
| 
						
						
							
						
						6e9f111fd9
	
				 | 
					
					
						|||
| 
						
						
							
						
						313fb9ffdf
	
				 | 
					
					
						|||
| 
						
						
							
						
						063bc2857f
	
				 | 
					
					
						|||
| 
						
						
							
						
						615629d1b4
	
				 | 
					
					
						|||
| 
						
						
							
						
						667e144681
	
				 | 
					
					
						|||
| 
						
						
							
						
						e17203ca3a
	
				 | 
					
					
						|||
| 
						
						
							
						
						c6a6d76790
	
				 | 
					
					
						|||
| 
						
						
							
						
						3d49c959e0
	
				 | 
					
					
						|||
| 
						 | 
					86896a12e6 | ||
| 
						 | 
					3a959b7044 | ||
| 
						 | 
					f8d95384ea | ||
| 
						
						
							
						
						b6edbb3eed
	
				 | 
					
					
						|||
| 
						
						
							
						
						00cc3b7806
	
				 | 
					
					
						|||
| 
						
						
							
						
						7ab52ff09e
	
				 | 
					
					
						|||
| 
						
						
							
						
						2d82c1e105
	
				 | 
					
					
						|||
| 
						
						
							
						
						e477a49c92
	
				 | 
					
					
						|||
| 
						
						
							
						
						0db2652f08
	
				 | 
					
					
						|||
| 
						
						
							
						
						c38f7c1179
	
				 | 
					
					
						|||
| 
						
						
							
						
						67d24cb951
	
				 | 
					
					
						|||
| 
						
						
							
						
						cb90261309
	
				 | 
					
					
						|||
| 
						
						
							
						
						2feea24c41
	
				 | 
					
					
						|||
| 
						
						
							
						
						1b16d4fe3b
	
				 | 
					
					
						|||
| 
						
						
							
						
						ce5659219a
	
				 | 
					
					
						|||
| 
						
						
							
						
						5fefe09a39
	
				 | 
					
					
						|||
| 
						
						
							
						
						e21db73b84
	
				 | 
					
					
						|||
| 
						
						
							
						
						3978ea9a47
	
				 | 
					
					
						|||
| 
						
						
							
						
						4fbb7811ac
	
				 | 
					
					
						|||
| 
						
						
							
						
						2b7ea4178b
	
				 | 
					
					
						|||
| 
						
						
							
						
						8a374864fa
	
				 | 
					
					
						|||
| 
						
						
							
						
						bb848746d5
	
				 | 
					
					
						|||
| 
						
						
							
						
						3738c110f8
	
				 | 
					
					
						|||
| 
						
						
							
						
						f57fdb2b4c
	
				 | 
					
					
						|||
| 
						
						
							
						
						b57824fc7e
	
				 | 
					
					
						|||
| 
						
						
							
						
						6b4e1ed2d3
	
				 | 
					
					
						|||
| 
						
						
							
						
						b0485dbcc8
	
				 | 
					
					
						|||
| 
						
						
							
						
						c16219dc6d
	
				 | 
					
					
						|||
| ad47804c91 | |||
| 85e2466611 | |||
| 94d6b5eff8 | |||
| d87f380f16 | |||
| 58bf722fae | |||
| 50fb79ebbf | |||
| 
						
						
							
						
						564813ef3d
	
				 | 
					
					
						|||
| 
						
						
							
						
						5fed42a623
	
				 | 
					
					
						|||
| b19dd4fc11 | |||
| 
						
						
							
						
						44226d6f7f
	
				 | 
					
					
						|||
| d75607a1d2 | |||
| bf66af0f25 | |||
| 15f3e474a0 | |||
| 5623cf946e | |||
| 0a6f3a99da | |||
| 50bd9f32c3 | |||
| 1396304af5 | |||
| c33e4adeec | |||
| 7351a35c42 | |||
| 72e3325626 | |||
| 0a46b5304d | |||
| 
						 | 
					e57d52d00e | ||
| 64e527672d | |||
| 
						
						
							
						
						123168a5ee
	
				 | 
					
					
						|||
| 
						
						
							
						
						3836d0dc9b
	
				 | 
					
					
						|||
| 
						
						
							
						
						51ab4bef38
	
				 | 
					
					
						|||
| 
						 | 
					567ca8a26f | ||
| 
						 | 
					111305d09c | ||
| 
						 | 
					67395f52b5 | ||
| 
						 | 
					421226c0dc | ||
| 
						 | 
					77da2c1ac6 | ||
| 
						 | 
					39d3ba2f40 | ||
| 
						 | 
					fb62e54d63 | ||
| 
						 | 
					c968d6c541 | ||
| 
						 | 
					c428e6665f | ||
| 
						 | 
					5b7e3f0336 | ||
| 
						 | 
					0c8ef37860 | ||
| 
						 | 
					794c479b9e | ||
| 
						 | 
					1bee3114ac | ||
| 
						 | 
					1344b65dd4 | ||
| 
						 | 
					68dcf4dd28 | ||
| 
						 | 
					b0a8fd54a8 | ||
| 
						 | 
					0f589ec57e | ||
| 
						 | 
					2d4fc45a0c | ||
| 
						 | 
					c80f23f0db | ||
| 
						 | 
					c950400fe2 | ||
| 
						 | 
					21c1e77d36 | ||
| 
						 | 
					bbfd0caf10 | ||
| 
						 | 
					9192883217 | ||
| 3836622d27 | |||
| cc2c4be1b0 | |||
| 873940786f | |||
| db73dcffc7 | |||
| 
						
						
							
						
						8aec69f0f9
	
				 | 
					
					
						|||
| 
						
						
							
						
						9f88eef249
	
				 | 
					
					
						|||
| 
						
						
							
						
						d689ce9aef
	
				 | 
					
					
						|||
| 
						
						
							
						
						d5e4991982
	
				 | 
					
					
						|||
| 
						
						
							
						
						ca68b58246
	
				 | 
					
					
						|||
| 
						
						
							
						
						747a1de321
	
				 | 
					
					
						|||
| 
						
						
							
						
						9e92ede16f
	
				 | 
					
					
						|||
| 
						
						
							
						
						31f842471a
	
				 | 
					
					
						|||
| 
						
						
							
						
						7d0f9175be
	
				 | 
					
					
						|||
| 
						
						
							
						
						e83307ca6d
	
				 | 
					
					
						|||
| 215eba41b7 | |||
| 52a3d1be1b | |||
| 8d543be5cc | |||
| 0474b25859 | |||
| 
						
						
							
						
						db94af0958
	
				 | 
					
					
						|||
| 3e8805bdda | |||
| 
						
						
							
						
						a887602f4f
	
				 | 
					
					
						|||
| 
						
						
							
						
						c1cf27c42d
	
				 | 
					
					
						|||
| 
						
						
							
						
						fe6b4848e6
	
				 | 
					
					
						|||
| 
						
						
							
						
						b5af9f7b63
	
				 | 
					
					
						|||
| 
						
						
							
						
						7f3de62b2c
	
				 | 
					
					
						|||
| cfa51cd659 | |||
| facc4affed | |||
| f9122341d1 | |||
| 7dd5f542a6 | |||
| 3b80d9a93b | |||
| 790576863f | |||
| 25e89571f7 | |||
| 435836c7d1 | |||
| af4db22184 | |||
| 2adc8b3bf6 | |||
| 21b79c1981 | |||
| 428494ca1f | |||
| 5d57ec8a3b | |||
| 719fabc878 | |||
| e9a9a3430f | |||
| c648a560cc | |||
| 3d7c8596ee | |||
| 345f379650 | |||
| 3262a1dd02 | |||
| a9f4f8c973 | |||
| c19c597ba0 | |||
| 03800029c9 | |||
| 064dfc5a56 | |||
| ba95687f46 | |||
| 
						
						
							
						
						a309cc0774
	
				 | 
					
					
						|||
| 5b0babb9b0 | |||
| ac2f314395 | |||
| 8c92d11722 | |||
| 
						
						
							
						
						3db4fff80d
	
				 | 
					
					
						|||
| fb743b522d | |||
| d1653a074b | |||
| 254122d125 | |||
| c9d2e37cee | |||
| 
						
						
							
						
						c9d54a5fea
	
				 | 
					
					
						|||
| 
						
						
							
						
						86c862e69d
	
				 | 
					
					
						|||
| 
						
						
							
						
						9bc6fe6aff
	
				 | 
					
					
						|||
| 
						
						
							
						
						18a03fd740
	
				 | 
					
					
						|||
| e9d4b9e2ab | |||
| efaad1981d | |||
| 742f2540f6 | |||
| bab6528ed6 | |||
| a25f2c7539 | |||
| c06e76a0ee | |||
| 4607c36b57 | |||
| 7c03a25f1a | |||
| cce04ee490 | |||
| e54633d14d | |||
| d9892f6822 | |||
| f75c7a0232 | |||
| 062afd6695 | |||
| 830dace1ba | |||
| 2ce9810243 | |||
| 26b3d84d62 | |||
| 30078db841 | |||
| aaac80be84 | |||
| a0fead48e1 | |||
| 2d09efb2e0 | |||
| 3a87513a11 | |||
| d3956319ca | |||
| bd36735cb1 | |||
| 1310d53589 | |||
| 
						
						
							
						
						610239930b
	
				 | 
					
					
						|||
| b65e2c62c4 | |||
| 
						
						
							
						
						89f5231649
	
				 | 
					
					
						|||
| 73797b98f6 | |||
| 3d40db7493 | |||
| 760d65b972 | |||
| d26fa6bde6 | |||
| 427f232ab8 | |||
| 
						
						
							
						
						99818c211d
	
				 | 
					
					
						|||
| 
						
						
							
						
						a9f0059743
	
				 | 
					
					
						|||
| 
						
						
							
						
						5bc542a567
	
				 | 
					
					
						|||
| 482f279dc5 | |||
| e0828b1f0f | |||
| e015f71bb0 | |||
| 04a48f22ad | |||
| ad4fe80240 | |||
| 4b82e67952 | |||
| 
						
						
							
						
						c8ccce83fd
	
				 | 
					
					
						|||
| e9a9262fae | |||
| d9e37d0958 | |||
| 65c41e6fa9 | |||
| 7923b5a1ef | |||
| 4a229ebf6b | 
							
								
								
									
										8
									
								
								.changes/unreleased/Feature-20240614-153236.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.changes/unreleased/Feature-20240614-153236.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
kind: Feature
 | 
			
		||||
body: |-
 | 
			
		||||
  Electronic signature
 | 
			
		||||
 | 
			
		||||
  Implementation of the electronic signature for documents within chill.
 | 
			
		||||
time: 2024-06-14T15:32:36.875891692+02:00
 | 
			
		||||
custom:
 | 
			
		||||
  Issue: ""
 | 
			
		||||
							
								
								
									
										7
									
								
								.changes/unreleased/Feature-20240614-153537.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.changes/unreleased/Feature-20240614-153537.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
kind: Feature
 | 
			
		||||
body: The behavoir of the voters for stored objects is adjusted so as to limit edit
 | 
			
		||||
  and delete possibilities to users related to the activity, social action or workflow
 | 
			
		||||
  entity.
 | 
			
		||||
time: 2024-06-14T15:35:37.582159301+02:00
 | 
			
		||||
custom:
 | 
			
		||||
  Issue: "286"
 | 
			
		||||
							
								
								
									
										5
									
								
								.changes/unreleased/Feature-20240718-151233.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.changes/unreleased/Feature-20240718-151233.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
kind: Feature
 | 
			
		||||
body: Metadata form added for person signatures
 | 
			
		||||
time: 2024-07-18T15:12:33.8134266+02:00
 | 
			
		||||
custom:
 | 
			
		||||
  Issue: "288"
 | 
			
		||||
@@ -1,5 +0,0 @@
 | 
			
		||||
kind: Fixed
 | 
			
		||||
body: Fix delete action for accompanying periods in draft state
 | 
			
		||||
time: 2024-08-21T15:14:13.753383913+02:00
 | 
			
		||||
custom:
 | 
			
		||||
  Issue: ""
 | 
			
		||||
@@ -1,5 +0,0 @@
 | 
			
		||||
kind: Fixed
 | 
			
		||||
body: Fix connection to azure when making an calendar event in chill
 | 
			
		||||
time: 2024-08-21T16:55:37.977150909+02:00
 | 
			
		||||
custom:
 | 
			
		||||
  Issue: ""
 | 
			
		||||
@@ -1,5 +0,0 @@
 | 
			
		||||
kind: Fixed
 | 
			
		||||
body: CollectionType js fixes for remove button and adding multiple entries
 | 
			
		||||
time: 2024-08-22T14:24:27.381070019+02:00
 | 
			
		||||
custom:
 | 
			
		||||
  Issue: ""
 | 
			
		||||
							
								
								
									
										5
									
								
								.changes/v3.0.0.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.changes/v3.0.0.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
## v3.0.0 - 2024-08-26
 | 
			
		||||
### Fixed
 | 
			
		||||
* Fix delete action for accompanying periods in draft state 
 | 
			
		||||
* Fix connection to azure when making an calendar event in chill 
 | 
			
		||||
* CollectionType js fixes for remove button and adding multiple entries 
 | 
			
		||||
@@ -122,7 +122,7 @@ unit_tests:
 | 
			
		||||
        - php tests/console chill:db:sync-views --env=test
 | 
			
		||||
        - php -d memory_limit=2G tests/console cache:clear --env=test
 | 
			
		||||
        - php -d memory_limit=3G tests/console doctrine:fixtures:load -n --env=test
 | 
			
		||||
        - php -d memory_limit=4G bin/phpunit --colors=never --exclude-group dbIntensive
 | 
			
		||||
        - php -d memory_limit=4G bin/phpunit --colors=never --exclude-group dbIntensive,openstack-integration,collabora-integration
 | 
			
		||||
    artifacts:
 | 
			
		||||
        expire_in: 1 day
 | 
			
		||||
        paths:
 | 
			
		||||
@@ -138,4 +138,4 @@ release:
 | 
			
		||||
        - echo "running release_job"
 | 
			
		||||
    release:
 | 
			
		||||
        tag_name: '$CI_COMMIT_TAG'
 | 
			
		||||
        description: "./.changes/v$CI_COMMIT_TAG.md"
 | 
			
		||||
        description: "./.changes/$CI_COMMIT_TAG.md"
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,12 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
 | 
			
		||||
and is generated by [Changie](https://github.com/miniscruff/changie).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## v3.0.0 - 2024-08-26
 | 
			
		||||
### Fixed
 | 
			
		||||
* Fix delete action for accompanying periods in draft state 
 | 
			
		||||
* Fix connection to azure when making an calendar event in chill 
 | 
			
		||||
* CollectionType js fixes for remove button and adding multiple entries 
 | 
			
		||||
 | 
			
		||||
## v2.23.0 - 2024-07-23
 | 
			
		||||
### Feature
 | 
			
		||||
* ([#221](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/221)) [DX] move async-upload-bundle features into chill-bundles 
 | 
			
		||||
 
 | 
			
		||||
@@ -31,6 +31,7 @@
 | 
			
		||||
        "phpoffice/phpspreadsheet": "^1.16",
 | 
			
		||||
        "ramsey/uuid-doctrine": "^1.7",
 | 
			
		||||
        "sensio/framework-extra-bundle": "^5.5",
 | 
			
		||||
        "smalot/pdfparser": "^2.10",
 | 
			
		||||
        "spomky-labs/base64url": "^2.0",
 | 
			
		||||
        "symfony/asset": "^5.4",
 | 
			
		||||
        "symfony/browser-kit": "^5.4",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										125
									
								
								docs/source/installation/enable-collabora-for-dev.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								docs/source/installation/enable-collabora-for-dev.rst
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,125 @@
 | 
			
		||||
 | 
			
		||||
Enable CODE for development
 | 
			
		||||
===========================
 | 
			
		||||
 | 
			
		||||
For editing a document, there must be a way to communicate between the collabora server and the symfony server, in
 | 
			
		||||
both direction. The domain name should also be the same for collabora server and for the browser which access to the
 | 
			
		||||
online editor.
 | 
			
		||||
 | 
			
		||||
Using ngrok (or other http tunnel)
 | 
			
		||||
----------------------------------
 | 
			
		||||
 | 
			
		||||
One can configure a tunnel server to expose your local install to the web, and access to your local server using the
 | 
			
		||||
tunnel url.
 | 
			
		||||
 | 
			
		||||
Start ngrok
 | 
			
		||||
^^^^^^^^^^^
 | 
			
		||||
 | 
			
		||||
This can be achieve using `ngrok <https://ngrok.com/>`_.
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
 | 
			
		||||
   The configuration of ngrok is outside of the scope of this document. Refers to the ngrok's documentation.
 | 
			
		||||
 | 
			
		||||
.. code-block:: bash
 | 
			
		||||
 | 
			
		||||
   # ensuring that your server is running through http and port 8000
 | 
			
		||||
   ngrok http 8000
 | 
			
		||||
   # then open the link given by the ngrok utility and you should reach your app
 | 
			
		||||
 | 
			
		||||
At this step, ensure that you can reach your local app using the ngrok url.
 | 
			
		||||
 | 
			
		||||
Configure Collabora
 | 
			
		||||
^^^^^^^^^^^^^^^^^^^
 | 
			
		||||
 | 
			
		||||
The collabora server must be executed online and configure to access to your ngrok installation. Ensure that the aliasgroup
 | 
			
		||||
exists for your ngrok application (`See the CODE documentation: <https://sdk.collaboraonline.com/docs/installation/Configuration.html#multihost-configuration>`_).
 | 
			
		||||
 | 
			
		||||
Configure your app
 | 
			
		||||
^^^^^^^^^^^^^^^^^^
 | 
			
		||||
 | 
			
		||||
Set the :code:`EDITOR_SERVER` variable to point to your collabora server, this should be done in your :code:`.env.local` file.
 | 
			
		||||
 | 
			
		||||
At this point, everything must be fine. In case of errors, watch the log from your collabora server, use the `profiler <https://symfony.com/doc/current/profiler.html>`_
 | 
			
		||||
to debug the requests.
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
 | 
			
		||||
   In case of error while validating proof (you'll see those message in the collabora's logs), you can temporarily disable
 | 
			
		||||
   the proof validation adding this code snippet in `config/services.yaml`:
 | 
			
		||||
 | 
			
		||||
   .. code-block:: yaml
 | 
			
		||||
 | 
			
		||||
      when@dev:
 | 
			
		||||
          # add only in dev environment, to avoid security problems
 | 
			
		||||
          services:
 | 
			
		||||
              ChampsLibres\WopiLib\Contract\Service\ProofValidatorInterface:
 | 
			
		||||
                  # this class will always validate proof
 | 
			
		||||
                  alias: Chill\WopiBundle\Service\Wopi\NullProofValidator
 | 
			
		||||
 | 
			
		||||
With a local CODE image
 | 
			
		||||
-----------------------
 | 
			
		||||
 | 
			
		||||
.. warning::
 | 
			
		||||
 | 
			
		||||
   This configuration is not sure, and must be refined. The documentation does not seems to be entirely valid.
 | 
			
		||||
 | 
			
		||||
Use a local domain name and https for your app
 | 
			
		||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
			
		||||
 | 
			
		||||
Use the proxy feature from embedded symfony server to run your app. `See the dedicated doc <https://symfony.com/doc/current/setup/symfony_server.html#local-domain-names>`
 | 
			
		||||
 | 
			
		||||
Configure also the `https certificate <https://symfony.com/doc/current/setup/symfony_server.html#enabling-tls>`_
 | 
			
		||||
 | 
			
		||||
In this example, your local domain name will be :code:`my-domain` and the url will be :code:`https://my-domain.wip`.
 | 
			
		||||
 | 
			
		||||
Ensure that the proxy is running.
 | 
			
		||||
 | 
			
		||||
Create a certificate database for collabora
 | 
			
		||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
			
		||||
 | 
			
		||||
Collabora must validate your certificate generated by symfony console. For that, you need `to create a NSS database <https://sdk.collaboraonline.com/docs/installation/Configuration.html#validating-digital-signatures>`
 | 
			
		||||
and configure collabora to use it.
 | 
			
		||||
 | 
			
		||||
At first, export the certificate for symfony development. Use the graphical interface from your browser to get the
 | 
			
		||||
certificate as a PEM file.
 | 
			
		||||
 | 
			
		||||
.. code-block:: bash
 | 
			
		||||
 | 
			
		||||
   # create your database in a custom directory
 | 
			
		||||
   mkdir /path/to/your/directory
 | 
			
		||||
   certutil -N -d /path/to/your/directory
 | 
			
		||||
   cat /path/to/your/ca.crt | certutil -d . -A symfony -t -t C,P,C,u,w -a
 | 
			
		||||
 | 
			
		||||
Launch CODE properly configured
 | 
			
		||||
 | 
			
		||||
.. code-block:: yaml
 | 
			
		||||
 | 
			
		||||
     collabora:
 | 
			
		||||
         image: collabora/code:latest
 | 
			
		||||
         environment:
 | 
			
		||||
             - SLEEPFORDEBUGGER=0
 | 
			
		||||
             - DONT_GEN_SSL_CERT="True"
 | 
			
		||||
             # add path to the database
 | 
			
		||||
             - extra_params=--o:ssl.enable=false --o:ssl.termination=false --o:logging.level=7 -o:certificates.database_path=/etc/custom-certificates/nss-database
 | 
			
		||||
             - username=admin
 | 
			
		||||
             - password=admin
 | 
			
		||||
             - dictionaries=en_US
 | 
			
		||||
             - aliasgroup1=https://my-domain.wip
 | 
			
		||||
         ports:
 | 
			
		||||
             - "127.0.0.1:9980:9980"
 | 
			
		||||
         volumes:
 | 
			
		||||
             - "/path/to/your/directory/nss-database:/etc/custom-certificates/nss-database"
 | 
			
		||||
         extra_hosts:
 | 
			
		||||
             - "my-domain.wip:host-gateway"
 | 
			
		||||
 | 
			
		||||
Configure your app
 | 
			
		||||
^^^^^^^^^^^^^^^^^^
 | 
			
		||||
 | 
			
		||||
Into your :code:`.env.local` file:
 | 
			
		||||
 | 
			
		||||
.. code-block:: env
 | 
			
		||||
 | 
			
		||||
   EDITOR_SERVER=http://${COLLABORA_HOST}:${COLLABORA_PORT}
 | 
			
		||||
 | 
			
		||||
At this step, you should be able to edit a document through collabora.
 | 
			
		||||
@@ -53,7 +53,7 @@
 | 
			
		||||
    "marked": "^12.0.2",
 | 
			
		||||
    "masonry-layout": "^4.2.2",
 | 
			
		||||
    "mime": "^4.0.0",
 | 
			
		||||
    "swagger-ui": "^4.15.5",
 | 
			
		||||
    "pdfjs-dist": "^4.3.136",
 | 
			
		||||
    "vis-network": "^9.1.0",
 | 
			
		||||
    "vue": "^3.2.37",
 | 
			
		||||
    "vue-i18n": "^9.1.6",
 | 
			
		||||
 
 | 
			
		||||
@@ -69,9 +69,8 @@ return static function (RectorConfig $rectorConfig): void {
 | 
			
		||||
 | 
			
		||||
    // skip some path...
 | 
			
		||||
    $rectorConfig->skip([
 | 
			
		||||
        // we must adapt service definition
 | 
			
		||||
        \Rector\Symfony\Symfony28\Rector\MethodCall\GetToConstructorInjectionRector::class,
 | 
			
		||||
        \Rector\Symfony\Symfony34\Rector\Closure\ContainerGetNameToTypeInTestsRector::class,
 | 
			
		||||
        // waiting for fixing this bug: https://github.com/rectorphp/rector-doctrine/issues/342
 | 
			
		||||
        \Rector\Doctrine\CodeQuality\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector::class,
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    $rectorConfig->ruleWithConfiguration(AnnotationToAttributeRector::class, [
 | 
			
		||||
 
 | 
			
		||||
@@ -68,7 +68,7 @@ final class ActivityController extends AbstractController
 | 
			
		||||
        private readonly FilterOrderHelperFactoryInterface $filterOrderHelperFactory,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        private readonly PaginatorFactory $paginatorFactory,
 | 
			
		||||
        private readonly ChillSecurity $security
 | 
			
		||||
        private readonly ChillSecurity $security,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -80,7 +80,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
    private \DateTime $date;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var Collection<StoredObject>
 | 
			
		||||
     * @var Collection<int, StoredObject>
 | 
			
		||||
     */
 | 
			
		||||
    #[Assert\Valid(traverse: true)]
 | 
			
		||||
    #[ORM\ManyToMany(targetEntity: StoredObject::class, cascade: ['persist'])]
 | 
			
		||||
@@ -107,7 +107,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
    private ?Person $person = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var Collection<Person>
 | 
			
		||||
     * @var Collection<int, \Chill\PersonBundle\Entity\Person>
 | 
			
		||||
     */
 | 
			
		||||
    #[Groups(['read', 'docgen:read'])]
 | 
			
		||||
    #[ORM\ManyToMany(targetEntity: Person::class)]
 | 
			
		||||
@@ -117,7 +117,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
    private PrivateCommentEmbeddable $privateComment;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var Collection<ActivityReason>
 | 
			
		||||
     * @var Collection<int, ActivityReason>
 | 
			
		||||
     */
 | 
			
		||||
    #[Groups(['docgen:read'])]
 | 
			
		||||
    #[ORM\ManyToMany(targetEntity: ActivityReason::class)]
 | 
			
		||||
@@ -132,7 +132,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
    private string $sentReceived = '';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var Collection<SocialAction>
 | 
			
		||||
     * @var Collection<int, \Chill\PersonBundle\Entity\SocialWork\SocialAction>
 | 
			
		||||
     */
 | 
			
		||||
    #[Groups(['read', 'docgen:read'])]
 | 
			
		||||
    #[ORM\ManyToMany(targetEntity: SocialAction::class)]
 | 
			
		||||
@@ -140,7 +140,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
    private Collection $socialActions;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var Collection<SocialIssue>
 | 
			
		||||
     * @var Collection<int, SocialIssue>
 | 
			
		||||
     */
 | 
			
		||||
    #[Groups(['read', 'docgen:read'])]
 | 
			
		||||
    #[ORM\ManyToMany(targetEntity: SocialIssue::class)]
 | 
			
		||||
@@ -148,7 +148,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
    private Collection $socialIssues;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var Collection<ThirdParty>
 | 
			
		||||
     * @var Collection<int, ThirdParty>
 | 
			
		||||
     */
 | 
			
		||||
    #[Groups(['read', 'docgen:read'])]
 | 
			
		||||
    #[ORM\ManyToMany(targetEntity: ThirdParty::class)]
 | 
			
		||||
@@ -162,7 +162,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
    private ?User $user = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var Collection<User>
 | 
			
		||||
     * @var Collection<int, User>
 | 
			
		||||
     */
 | 
			
		||||
    #[Groups(['read', 'docgen:read'])]
 | 
			
		||||
    #[ORM\ManyToMany(targetEntity: User::class)]
 | 
			
		||||
 
 | 
			
		||||
@@ -40,9 +40,9 @@ class ActivityReasonCategory implements \Stringable
 | 
			
		||||
    /**
 | 
			
		||||
     * Array of ActivityReason.
 | 
			
		||||
     *
 | 
			
		||||
     * @var Collection<ActivityReason>
 | 
			
		||||
     * @var Collection<int, ActivityReason>
 | 
			
		||||
     */
 | 
			
		||||
    #[ORM\OneToMany(targetEntity: ActivityReason::class, mappedBy: 'category')]
 | 
			
		||||
    #[ORM\OneToMany(mappedBy: 'category', targetEntity: ActivityReason::class)]
 | 
			
		||||
    private Collection $reasons;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        protected ActivityReasonCategoryRepository $activityReasonCategoryRepository,
 | 
			
		||||
        protected ActivityReasonRepository $activityReasonRepository,
 | 
			
		||||
        protected TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
        protected TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ class ActivityUsersJobAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly UserJobRepositoryInterface $userJobRepository,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ class ActivityUsersScopeAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly ScopeRepositoryInterface $scopeRepository,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ class CreatorJobAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly UserJobRepositoryInterface $userJobRepository,
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ class CreatorScopeAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly ScopeRepository $scopeRepository,
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,7 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
        /**
 | 
			
		||||
         * The action for this report.
 | 
			
		||||
         */
 | 
			
		||||
        protected string $action = 'sum'
 | 
			
		||||
        protected string $action = 'sum',
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,7 @@ class ListActivityHelper
 | 
			
		||||
        private readonly TranslatorInterface $translator,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        private readonly TranslatableStringExportLabelHelper $translatableStringLabelHelper,
 | 
			
		||||
        private readonly UserHelper $userHelper
 | 
			
		||||
        private readonly UserHelper $userHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addSelect(QueryBuilder $qb): void
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ final readonly class ActivityPresenceFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        private TranslatorInterface $translator
 | 
			
		||||
        private TranslatorInterface $translator,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function getTitle()
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        protected TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        protected ActivityTypeRepositoryInterface $activityTypeRepository
 | 
			
		||||
        protected ActivityTypeRepositoryInterface $activityTypeRepository,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ class UsersJobFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        private readonly UserJobRepositoryInterface $userJobRepository
 | 
			
		||||
        private readonly UserJobRepositoryInterface $userJobRepository,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ class UsersScopeFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly ScopeRepositoryInterface $scopeRepository,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -59,7 +59,7 @@ class ActivityType extends AbstractType
 | 
			
		||||
        protected TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
        protected array $timeChoices,
 | 
			
		||||
        protected SocialIssueRender $socialIssueRender,
 | 
			
		||||
        protected SocialActionRender $socialActionRender
 | 
			
		||||
        protected SocialActionRender $socialActionRender,
 | 
			
		||||
    ) {
 | 
			
		||||
        if (!$tokenStorage->getToken()->getUser() instanceof User) {
 | 
			
		||||
            throw new \RuntimeException('you should have a valid user');
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@ class PickActivityReasonType extends AbstractType
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly ActivityReasonRepository $activityReasonRepository,
 | 
			
		||||
        private readonly ActivityReasonRender $reasonRender,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function configureOptions(OptionsResolver $resolver)
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ final readonly class ActivityDocumentACLAwareRepository implements ActivityDocum
 | 
			
		||||
        private EntityManagerInterface $em,
 | 
			
		||||
        private CenterResolverManagerInterface $centerResolverManager,
 | 
			
		||||
        private AuthorizationHelperForCurrentUserInterface $authorizationHelperForCurrentUser,
 | 
			
		||||
        private Security $security
 | 
			
		||||
        private Security $security,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function buildFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, ?\DateTimeImmutable $startDate = null, ?\DateTimeImmutable $endDate = null, ?string $content = null): FetchQueryInterface
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ class ActivityReasonRepository extends ServiceEntityRepository
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ManagerRegistry $registry,
 | 
			
		||||
        private readonly RequestStack $requestStack
 | 
			
		||||
        private readonly RequestStack $requestStack,
 | 
			
		||||
    ) {
 | 
			
		||||
        parent::__construct($registry, ActivityReason::class);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,8 @@ declare(strict_types=1);
 | 
			
		||||
namespace Chill\ActivityBundle\Repository;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Entity\Activity;
 | 
			
		||||
use Chill\DocStoreBundle\Entity\StoredObject;
 | 
			
		||||
use Chill\DocStoreBundle\Repository\AssociatedEntityToStoredObjectInterface;
 | 
			
		||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
 | 
			
		||||
use Chill\PersonBundle\Entity\Person;
 | 
			
		||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
 | 
			
		||||
@@ -23,7 +25,7 @@ use Doctrine\Persistence\ManagerRegistry;
 | 
			
		||||
 * @method Activity[]    findAll()
 | 
			
		||||
 * @method Activity[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 | 
			
		||||
 */
 | 
			
		||||
class ActivityRepository extends ServiceEntityRepository
 | 
			
		||||
class ActivityRepository extends ServiceEntityRepository implements AssociatedEntityToStoredObjectInterface
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(ManagerRegistry $registry)
 | 
			
		||||
    {
 | 
			
		||||
@@ -97,4 +99,16 @@ class ActivityRepository extends ServiceEntityRepository
 | 
			
		||||
 | 
			
		||||
        return $qb->getQuery()->getResult();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function findAssociatedEntityToStoredObject(StoredObject $storedObject): ?Activity
 | 
			
		||||
    {
 | 
			
		||||
        $qb = $this->createQueryBuilder('a');
 | 
			
		||||
        $query = $qb
 | 
			
		||||
            ->leftJoin('a.documents', 'ad')
 | 
			
		||||
            ->where('ad.id = :storedObjectId')
 | 
			
		||||
            ->setParameter('storedObjectId', $storedObject->getId())
 | 
			
		||||
            ->getQuery();
 | 
			
		||||
 | 
			
		||||
        return $query->getOneOrNullResult();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,54 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Chill is a software for social workers
 | 
			
		||||
 *
 | 
			
		||||
 * For the full copyright and license information, please view
 | 
			
		||||
 * the LICENSE file that was distributed with this source code.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\ActivityBundle\Security\Authorization;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Entity\Activity;
 | 
			
		||||
use Chill\ActivityBundle\Repository\ActivityRepository;
 | 
			
		||||
use Chill\DocStoreBundle\Repository\AssociatedEntityToStoredObjectInterface;
 | 
			
		||||
use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum;
 | 
			
		||||
use Chill\DocStoreBundle\Security\Authorization\StoredObjectVoter\AbstractStoredObjectVoter;
 | 
			
		||||
use Chill\DocStoreBundle\Service\WorkflowStoredObjectPermissionHelper;
 | 
			
		||||
use Symfony\Component\Security\Core\Security;
 | 
			
		||||
 | 
			
		||||
class ActivityStoredObjectVoter extends AbstractStoredObjectVoter
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly ActivityRepository $repository,
 | 
			
		||||
        Security $security,
 | 
			
		||||
        WorkflowStoredObjectPermissionHelper $workflowDocumentService,
 | 
			
		||||
    ) {
 | 
			
		||||
        parent::__construct($security, $workflowDocumentService);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function getRepository(): AssociatedEntityToStoredObjectInterface
 | 
			
		||||
    {
 | 
			
		||||
        return $this->repository;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function getClass(): string
 | 
			
		||||
    {
 | 
			
		||||
        return Activity::class;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function attributeToRole(StoredObjectRoleEnum $attribute): string
 | 
			
		||||
    {
 | 
			
		||||
        return match ($attribute) {
 | 
			
		||||
            StoredObjectRoleEnum::EDIT => ActivityVoter::UPDATE,
 | 
			
		||||
            StoredObjectRoleEnum::SEE => ActivityVoter::SEE_DETAILS,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function canBeAssociatedWithWorkflow(): bool
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -75,7 +75,7 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        protected Security $security,
 | 
			
		||||
        VoterHelperFactoryInterface $voterHelperFactory
 | 
			
		||||
        VoterHelperFactoryInterface $voterHelperFactory,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->voterHelper = $voterHelperFactory->generate(self::class)
 | 
			
		||||
            ->addCheckFor(Person::class, [self::SEE, self::CREATE])
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,7 @@ class ActivityContext implements
 | 
			
		||||
        private readonly TranslatorInterface $translator,
 | 
			
		||||
        private readonly BaseContextData $baseContextData,
 | 
			
		||||
        private readonly ThirdPartyRender $thirdPartyRender,
 | 
			
		||||
        private readonly ThirdPartyRepository $thirdPartyRepository
 | 
			
		||||
        private readonly ThirdPartyRepository $thirdPartyRepository,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function adminFormReverseTransform(array $data): array
 | 
			
		||||
 
 | 
			
		||||
@@ -56,7 +56,7 @@ class ListActivitiesByAccompanyingPeriodContext implements
 | 
			
		||||
        private readonly SocialIssueRepository $socialIssueRepository,
 | 
			
		||||
        private readonly ThirdPartyRepository $thirdPartyRepository,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        private readonly UserRepository $userRepository
 | 
			
		||||
        private readonly UserRepository $userRepository,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function adminFormReverseTransform(array $data): array
 | 
			
		||||
 
 | 
			
		||||
@@ -76,7 +76,7 @@ final class TranslatableActivityReasonTest extends TypeTestCase
 | 
			
		||||
     */
 | 
			
		||||
    protected function getTranslatableStringHelper(
 | 
			
		||||
        $locale = 'en',
 | 
			
		||||
        $fallbackLocale = 'en'
 | 
			
		||||
        $fallbackLocale = 'en',
 | 
			
		||||
    ) {
 | 
			
		||||
        $prophet = new \Prophecy\Prophet();
 | 
			
		||||
        $requestStack = $prophet->prophesize();
 | 
			
		||||
 
 | 
			
		||||
@@ -138,7 +138,7 @@ final class ActivityVoterTest extends KernelTestCase
 | 
			
		||||
        Scope $scope,
 | 
			
		||||
        Center $center,
 | 
			
		||||
        $attribute,
 | 
			
		||||
        $message
 | 
			
		||||
        $message,
 | 
			
		||||
    ) {
 | 
			
		||||
        $token = $this->prepareToken($user);
 | 
			
		||||
        $activity = $this->prepareActivity($scope, $this->preparePerson($center));
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ class TimelineActivityProvider implements TimelineProviderInterface
 | 
			
		||||
        protected EntityManagerInterface $em,
 | 
			
		||||
        protected AuthorizationHelperInterface $helper,
 | 
			
		||||
        TokenStorageInterface $storage,
 | 
			
		||||
        protected ActivityACLAwareRepository $aclAwareRepository
 | 
			
		||||
        protected ActivityACLAwareRepository $aclAwareRepository,
 | 
			
		||||
    ) {
 | 
			
		||||
        if (!$storage->getToken()->getUser() instanceof User) {
 | 
			
		||||
            throw new \RuntimeException('A user should be authenticated !');
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ final class AsideActivityController extends CRUDController
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly AsideActivityCategoryRepository $categoryRepository,
 | 
			
		||||
        private readonly Security $security
 | 
			
		||||
        private readonly Security $security,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function createEntity(string $action, Request $request): object
 | 
			
		||||
@@ -76,7 +76,7 @@ final class AsideActivityController extends CRUDController
 | 
			
		||||
        string $action,
 | 
			
		||||
        $query,
 | 
			
		||||
        Request $request,
 | 
			
		||||
        PaginatorInterface $paginator
 | 
			
		||||
        PaginatorInterface $paginator,
 | 
			
		||||
    ) {
 | 
			
		||||
        if ('index' === $action) {
 | 
			
		||||
            return $query->orderBy('e.date', 'DESC');
 | 
			
		||||
 
 | 
			
		||||
@@ -22,9 +22,9 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
 | 
			
		||||
class AsideActivityCategory
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var Collection<AsideActivityCategory>
 | 
			
		||||
     * @var Collection<int, AsideActivityCategory>
 | 
			
		||||
     */
 | 
			
		||||
    #[ORM\OneToMany(targetEntity: AsideActivityCategory::class, mappedBy: 'parent')]
 | 
			
		||||
    #[ORM\OneToMany(mappedBy: 'parent', targetEntity: AsideActivityCategory::class)]
 | 
			
		||||
    private Collection $children;
 | 
			
		||||
 | 
			
		||||
    #[ORM\Id]
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ class ByActivityTypeAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly AsideActivityCategoryRepository $asideActivityCategoryRepository,
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ class ByUserJobAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly UserJobRepositoryInterface $userJobRepository,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ class ByUserScopeAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly ScopeRepositoryInterface $scopeRepository,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ final readonly class ListAsideActivity implements ListInterface, GroupedExportIn
 | 
			
		||||
        private AsideActivityCategoryRepository $asideActivityCategoryRepository,
 | 
			
		||||
        private CategoryRender $categoryRender,
 | 
			
		||||
        private LocationRepository $locationRepository,
 | 
			
		||||
        private TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
        private TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder) {}
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@ class ByActivityTypeFilter implements FilterInterface
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly CategoryRender $categoryRender,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        private readonly AsideActivityCategoryRepository $asideActivityTypeRepository
 | 
			
		||||
        private readonly AsideActivityCategoryRepository $asideActivityTypeRepository,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ use Symfony\Component\Security\Core\Security;
 | 
			
		||||
final readonly class ByLocationFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private Security $security
 | 
			
		||||
        private Security $security,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function getTitle(): string
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ class ByUserJobFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        private readonly UserJobRepositoryInterface $userJobRepository
 | 
			
		||||
        private readonly UserJobRepositoryInterface $userJobRepository,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ class ByUserScopeFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly ScopeRepositoryInterface $scopeRepository,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,7 @@ class UserMenuBuilder implements LocalMenuBuilderInterface
 | 
			
		||||
        CountNotificationTask $counter,
 | 
			
		||||
        TokenStorageInterface $tokenStorage,
 | 
			
		||||
        TranslatorInterface $translator,
 | 
			
		||||
        AuthorizationCheckerInterface $authorizationChecker
 | 
			
		||||
        AuthorizationCheckerInterface $authorizationChecker,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->counter = $counter;
 | 
			
		||||
        $this->tokenStorage = $tokenStorage;
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ class AsideActivityVoter extends AbstractChillVoter implements ProvideRoleHierar
 | 
			
		||||
    private readonly VoterHelperInterface $voterHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        VoterHelperFactoryInterface $voterHelperFactory
 | 
			
		||||
        VoterHelperFactoryInterface $voterHelperFactory,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->voterHelper = $voterHelperFactory
 | 
			
		||||
            ->generate(self::class)
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ class SendTestShortMessageOnCalendarCommand extends Command
 | 
			
		||||
        private readonly PhoneNumberHelperInterface $phoneNumberHelper,
 | 
			
		||||
        private readonly ShortMessageForCalendarBuilderInterface $messageForCalendarBuilder,
 | 
			
		||||
        private readonly ShortMessageTransporterInterface $transporter,
 | 
			
		||||
        private readonly UserRepositoryInterface $userRepository
 | 
			
		||||
        private readonly UserRepositoryInterface $userRepository,
 | 
			
		||||
    ) {
 | 
			
		||||
        parent::__construct('chill:calendar:test-send-short-message');
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -59,7 +59,7 @@ class CalendarController extends AbstractController
 | 
			
		||||
        private readonly AccompanyingPeriodRepository $accompanyingPeriodRepository,
 | 
			
		||||
        private readonly UserRepositoryInterface $userRepository,
 | 
			
		||||
        private readonly TranslatorInterface $translator,
 | 
			
		||||
        private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry
 | 
			
		||||
        private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,7 @@ class RemoteCalendarConnectAzureController
 | 
			
		||||
            ->redirect(['https://graph.microsoft.com/.default', 'offline_access'], []);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[Route(path: '/connect/azure/check', name: 'chill_calendar_remote_connect_azure_check', schemes: ['https'])]
 | 
			
		||||
    #[Route(path: '/connect/azure/check', name: 'chill_calendar_remote_connect_azure_check')]
 | 
			
		||||
    public function connectAzureCheck(Request $request): Response
 | 
			
		||||
    {
 | 
			
		||||
        /** @var Azure $client */
 | 
			
		||||
 
 | 
			
		||||
@@ -103,7 +103,7 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface, HasCente
 | 
			
		||||
    private int $dateTimeVersion = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var Collection<CalendarDoc>
 | 
			
		||||
     * @var Collection<int, \Chill\CalendarBundle\Entity\CalendarDoc>
 | 
			
		||||
     */
 | 
			
		||||
    #[ORM\OneToMany(mappedBy: 'calendar', targetEntity: CalendarDoc::class, orphanRemoval: true)]
 | 
			
		||||
    private Collection $documents;
 | 
			
		||||
@@ -120,7 +120,7 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface, HasCente
 | 
			
		||||
    private ?int $id = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var Collection&Selectable<int, Invite>
 | 
			
		||||
     * @var \Doctrine\Common\Collections\Collection<int, \Chill\CalendarBundle\Entity\Invite>&Selectable
 | 
			
		||||
     */
 | 
			
		||||
    #[Serializer\Groups(['read', 'docgen:read'])]
 | 
			
		||||
    #[ORM\OneToMany(mappedBy: 'calendar', targetEntity: Invite::class, cascade: ['persist', 'remove', 'merge', 'detach'], orphanRemoval: true)]
 | 
			
		||||
@@ -143,7 +143,7 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface, HasCente
 | 
			
		||||
    private ?Person $person = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var Collection<Person>
 | 
			
		||||
     * @var Collection<int, Person>
 | 
			
		||||
     */
 | 
			
		||||
    #[Serializer\Groups(['calendar:read', 'read', 'calendar:light', 'docgen:read'])]
 | 
			
		||||
    #[Assert\Count(min: 1, minMessage: 'calendar.At least {{ limit }} person is required.')]
 | 
			
		||||
@@ -157,7 +157,7 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface, HasCente
 | 
			
		||||
    private PrivateCommentEmbeddable $privateComment;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var Collection<ThirdParty>
 | 
			
		||||
     * @var Collection<int, ThirdParty>
 | 
			
		||||
     */
 | 
			
		||||
    #[Serializer\Groups(['calendar:read', 'read', 'calendar:light', 'docgen:read'])]
 | 
			
		||||
    #[ORM\ManyToMany(targetEntity: ThirdParty::class)]
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ class CalendarDoc implements TrackCreationInterface, TrackUpdateInterface
 | 
			
		||||
        Calendar $calendar,
 | 
			
		||||
        #[ORM\ManyToOne(targetEntity: StoredObject::class, cascade: ['persist'])]
 | 
			
		||||
        #[ORM\JoinColumn(nullable: false)]
 | 
			
		||||
        private ?StoredObject $storedObject
 | 
			
		||||
        private ?StoredObject $storedObject,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->setCalendar($calendar);
 | 
			
		||||
        $this->datetimeVersion = $calendar->getDateTimeVersion();
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ final readonly class JobAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private UserJobRepository $jobRepository,
 | 
			
		||||
        private TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
        private TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ final readonly class ScopeAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private ScopeRepository $scopeRepository,
 | 
			
		||||
        private TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
        private TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ final readonly class JobFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
        private UserJobRepositoryInterface $userJobRepository
 | 
			
		||||
        private UserJobRepositoryInterface $userJobRepository,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ class ScopeFilter implements FilterInterface
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        protected TranslatorInterface $translator,
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
        private readonly ScopeRepositoryInterface $scopeRepository
 | 
			
		||||
        private readonly ScopeRepositoryInterface $scopeRepository,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@ class CalendarType extends AbstractType
 | 
			
		||||
        private readonly IdToUsersDataTransformer $idToUsersDataTransformer,
 | 
			
		||||
        private readonly IdToLocationDataTransformer $idToLocationDataTransformer,
 | 
			
		||||
        private readonly ThirdPartiesToIdDataTransformer $partiesToIdDataTransformer,
 | 
			
		||||
        private readonly IdToCalendarRangeDataTransformer $calendarRangeDataTransformer
 | 
			
		||||
        private readonly IdToCalendarRangeDataTransformer $calendarRangeDataTransformer,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder, array $options)
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,7 @@ class CalendarMessage
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        Calendar $calendar,
 | 
			
		||||
        private readonly string $action,
 | 
			
		||||
        User $byUser
 | 
			
		||||
        User $byUser,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->calendarId = $calendar->getId();
 | 
			
		||||
        $this->byUserId = $byUser->getId();
 | 
			
		||||
 
 | 
			
		||||
@@ -59,7 +59,7 @@ final readonly class MSUserAbsenceReader implements MSUserAbsenceReaderInterface
 | 
			
		||||
            'alwaysEnabled' => true,
 | 
			
		||||
            'scheduled' => RemoteEventConverter::convertStringDateWithoutTimezone($automaticRepliesSettings['scheduledStartDateTime']['dateTime']) < $this->clock->now()
 | 
			
		||||
                && RemoteEventConverter::convertStringDateWithoutTimezone($automaticRepliesSettings['scheduledEndDateTime']['dateTime']) > $this->clock->now(),
 | 
			
		||||
            default => throw new UserAbsenceSyncException('this status is not documented by Microsoft')
 | 
			
		||||
            default => throw new UserAbsenceSyncException('this status is not documented by Microsoft'),
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -177,7 +177,7 @@ class MapCalendarToUser
 | 
			
		||||
        User $user,
 | 
			
		||||
        int $expiration,
 | 
			
		||||
        ?string $id = null,
 | 
			
		||||
        ?string $secret = null
 | 
			
		||||
        ?string $secret = null,
 | 
			
		||||
    ): void {
 | 
			
		||||
        $user->setAttributeByDomain(self::METADATA_KEY, self::EXPIRATION_SUBSCRIPTION_EVENT, $expiration);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -57,7 +57,7 @@ class RemoteEventConverter
 | 
			
		||||
        private readonly LocationConverter $locationConverter,
 | 
			
		||||
        private readonly LoggerInterface $logger,
 | 
			
		||||
        private readonly PersonRenderInterface $personRender,
 | 
			
		||||
        private readonly TranslatorInterface $translator
 | 
			
		||||
        private readonly TranslatorInterface $translator,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->defaultDateTimeZone = (new \DateTimeImmutable())->getTimezone();
 | 
			
		||||
        $this->remoteDateTimeZone = self::getRemoteTimeZone();
 | 
			
		||||
 
 | 
			
		||||
@@ -351,7 +351,7 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface
 | 
			
		||||
        [
 | 
			
		||||
            'id' => $id,
 | 
			
		||||
            'lastModifiedDateTime' => $lastModified,
 | 
			
		||||
            'changeKey' => $changeKey
 | 
			
		||||
            'changeKey' => $changeKey,
 | 
			
		||||
        ] = $this->createOnRemote($eventData, $calendar->getMainUser(), 'calendar_'.$calendar->getId());
 | 
			
		||||
 | 
			
		||||
        if (null === $id) {
 | 
			
		||||
@@ -427,7 +427,7 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface
 | 
			
		||||
        [
 | 
			
		||||
            'id' => $id,
 | 
			
		||||
            'lastModifiedDateTime' => $lastModified,
 | 
			
		||||
            'changeKey' => $changeKey
 | 
			
		||||
            'changeKey' => $changeKey,
 | 
			
		||||
        ] = $this->createOnRemote(
 | 
			
		||||
            $eventData,
 | 
			
		||||
            $calendarRange->getUser(),
 | 
			
		||||
@@ -564,7 +564,7 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface
 | 
			
		||||
            [
 | 
			
		||||
                'id' => $id,
 | 
			
		||||
                'lastModifiedDateTime' => $lastModified,
 | 
			
		||||
                'changeKey' => $changeKey
 | 
			
		||||
                'changeKey' => $changeKey,
 | 
			
		||||
            ] = $this->patchOnRemote(
 | 
			
		||||
                $calendar->getRemoteId(),
 | 
			
		||||
                $eventData,
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,6 @@ class RemoteEvent
 | 
			
		||||
        #[Serializer\Groups(['read'])]
 | 
			
		||||
        public \DateTimeImmutable $endDate,
 | 
			
		||||
        #[Serializer\Groups(['read'])]
 | 
			
		||||
        public bool $isAllDay = false
 | 
			
		||||
        public bool $isAllDay = false,
 | 
			
		||||
    ) {}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ class CalendarRangeRepository implements ObjectRepository
 | 
			
		||||
        \DateTimeImmutable $from,
 | 
			
		||||
        \DateTimeImmutable $to,
 | 
			
		||||
        ?int $limit = null,
 | 
			
		||||
        ?int $offset = null
 | 
			
		||||
        ?int $offset = null,
 | 
			
		||||
    ): array {
 | 
			
		||||
        $qb = $this->buildQueryAvailableRangesForUser($user, $from, $to);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,7 @@ final readonly class CalendarContext implements CalendarContextInterface
 | 
			
		||||
        private PersonRepository $personRepository,
 | 
			
		||||
        private ThirdPartyRender $thirdPartyRender,
 | 
			
		||||
        private ThirdPartyRepository $thirdPartyRepository,
 | 
			
		||||
        private TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
        private TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function adminFormReverseTransform(array $data): array
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@ final readonly class AccompanyingPeriodCalendarGenericDocProvider implements Gen
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private Security $security,
 | 
			
		||||
        private EntityManagerInterface $em
 | 
			
		||||
        private EntityManagerInterface $em,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,7 @@ final readonly class PersonCalendarGenericDocProvider implements GenericDocForPe
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private Security $security,
 | 
			
		||||
        private EntityManagerInterface $em
 | 
			
		||||
        private EntityManagerInterface $em,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    private function addWhereClausesToQuery(FetchQuery $query, ?\DateTimeImmutable $startDate = null, ?\DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery
 | 
			
		||||
 
 | 
			
		||||
@@ -156,7 +156,7 @@ final class CalendarTypeTest extends TypeTestCase
 | 
			
		||||
 | 
			
		||||
    private function buildMultiToIdDataTransformer(
 | 
			
		||||
        string $classTransformer,
 | 
			
		||||
        string $objClass
 | 
			
		||||
        string $objClass,
 | 
			
		||||
    ) {
 | 
			
		||||
        $transformer = $this->prophesize($classTransformer);
 | 
			
		||||
        $transformer->transform(Argument::type('array'))
 | 
			
		||||
@@ -195,7 +195,7 @@ final class CalendarTypeTest extends TypeTestCase
 | 
			
		||||
 | 
			
		||||
    private function buildSingleToIdDataTransformer(
 | 
			
		||||
        string $classTransformer,
 | 
			
		||||
        string $class
 | 
			
		||||
        string $class,
 | 
			
		||||
    ) {
 | 
			
		||||
        $transformer = $this->prophesize($classTransformer);
 | 
			
		||||
        $transformer->transform(Argument::type('object'))
 | 
			
		||||
 
 | 
			
		||||
@@ -203,7 +203,7 @@ final class CalendarContextTest extends TestCase
 | 
			
		||||
 | 
			
		||||
    private function buildCalendarContext(
 | 
			
		||||
        ?EntityManagerInterface $entityManager = null,
 | 
			
		||||
        ?NormalizerInterface $normalizer = null
 | 
			
		||||
        ?NormalizerInterface $normalizer = null,
 | 
			
		||||
    ): CalendarContext {
 | 
			
		||||
        $baseContext = $this->prophesize(BaseContextData::class);
 | 
			
		||||
        $baseContext->getData(null)->willReturn(['base_context' => 'data']);
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,7 @@ class CreateFieldsOnGroupCommand extends Command
 | 
			
		||||
        private readonly EntityManager $entityManager,
 | 
			
		||||
        private readonly ValidatorInterface $validator,
 | 
			
		||||
        private $availableLanguages,
 | 
			
		||||
        private $customizablesEntities
 | 
			
		||||
        private $customizablesEntities,
 | 
			
		||||
    ) {
 | 
			
		||||
        parent::__construct();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,7 @@ class CustomFieldsGroupController extends AbstractController
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly CustomFieldProvider $customFieldProvider,
 | 
			
		||||
        private readonly TranslatorInterface $translator,
 | 
			
		||||
        private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry
 | 
			
		||||
        private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,7 @@ class CustomFieldChoice extends AbstractCustomField
 | 
			
		||||
        /**
 | 
			
		||||
         * @var TranslatableStringHelper Helper that find the string in current locale from an array of translation
 | 
			
		||||
         */
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function allowOtherChoice(CustomField $cf)
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,7 @@ class CustomFieldDate extends AbstractCustomField
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly Environment $templating,
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder, CustomField $customField)
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ class CustomFieldNumber extends AbstractCustomField
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly Environment $templating,
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder, CustomField $customField)
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ class CustomFieldText extends AbstractCustomField
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly Environment $templating,
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@ class CustomFieldTitle extends AbstractCustomField
 | 
			
		||||
        /**
 | 
			
		||||
         * @var TranslatableStringHelper Helper that find the string in current locale from an array of translation
 | 
			
		||||
         */
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder, CustomField $customField)
 | 
			
		||||
 
 | 
			
		||||
@@ -23,9 +23,9 @@ class Option
 | 
			
		||||
    private bool $active = true;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var Collection<Option>
 | 
			
		||||
     * @var Collection<int, Option>
 | 
			
		||||
     */
 | 
			
		||||
    #[ORM\OneToMany(targetEntity: Option::class, mappedBy: 'parent')]
 | 
			
		||||
    #[ORM\OneToMany(mappedBy: 'parent', targetEntity: Option::class)]
 | 
			
		||||
    private Collection $children;
 | 
			
		||||
 | 
			
		||||
    #[ORM\Id]
 | 
			
		||||
 
 | 
			
		||||
@@ -32,9 +32,9 @@ class CustomFieldsGroup
 | 
			
		||||
     * The custom fields of the group.
 | 
			
		||||
     * The custom fields are asc-ordered regarding to their property "ordering".
 | 
			
		||||
     *
 | 
			
		||||
     * @var Collection<CustomField>
 | 
			
		||||
     * @var Collection<int, CustomField>
 | 
			
		||||
     */
 | 
			
		||||
    #[ORM\OneToMany(targetEntity: CustomField::class, mappedBy: 'customFieldGroup')]
 | 
			
		||||
    #[ORM\OneToMany(mappedBy: 'customFieldGroup', targetEntity: CustomField::class)]
 | 
			
		||||
    #[ORM\OrderBy(['ordering' => \Doctrine\Common\Collections\Criteria::ASC])]
 | 
			
		||||
    private Collection $customFields;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ class CustomFieldsGroupType extends AbstractType
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly array $customizableEntities,
 | 
			
		||||
        // TODO : add comment about this variable
 | 
			
		||||
        private readonly TranslatorInterface $translator
 | 
			
		||||
        private readonly TranslatorInterface $translator,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    // TODO : details about the function
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,7 @@ final class DocGeneratorTemplateController extends AbstractController
 | 
			
		||||
        private readonly PaginatorFactory $paginatorFactory,
 | 
			
		||||
        private readonly EntityManagerInterface $entityManager,
 | 
			
		||||
        private readonly ClockInterface $clock,
 | 
			
		||||
        private readonly ChillSecurity $security
 | 
			
		||||
        private readonly ChillSecurity $security,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    #[Route(path: '{_locale}/admin/doc/gen/generate/test/from/{template}/for/{entityClassName}/{entityId}', name: 'chill_docgenerator_test_generate_from_template')]
 | 
			
		||||
@@ -56,7 +56,7 @@ final class DocGeneratorTemplateController extends AbstractController
 | 
			
		||||
        DocGeneratorTemplate $template,
 | 
			
		||||
        string $entityClassName,
 | 
			
		||||
        int $entityId,
 | 
			
		||||
        Request $request
 | 
			
		||||
        Request $request,
 | 
			
		||||
    ): Response {
 | 
			
		||||
        return $this->generateDocFromTemplate(
 | 
			
		||||
            $template,
 | 
			
		||||
@@ -71,7 +71,7 @@ final class DocGeneratorTemplateController extends AbstractController
 | 
			
		||||
        DocGeneratorTemplate $template,
 | 
			
		||||
        string $entityClassName,
 | 
			
		||||
        int $entityId,
 | 
			
		||||
        Request $request
 | 
			
		||||
        Request $request,
 | 
			
		||||
    ): Response {
 | 
			
		||||
        return $this->generateDocFromTemplate(
 | 
			
		||||
            $template,
 | 
			
		||||
@@ -137,7 +137,7 @@ final class DocGeneratorTemplateController extends AbstractController
 | 
			
		||||
        DocGeneratorTemplate $template,
 | 
			
		||||
        int $entityId,
 | 
			
		||||
        Request $request,
 | 
			
		||||
        bool $isTest
 | 
			
		||||
        bool $isTest,
 | 
			
		||||
    ): Response {
 | 
			
		||||
        try {
 | 
			
		||||
            $context = $this->contextManager->getContextByDocGeneratorTemplate($template);
 | 
			
		||||
 
 | 
			
		||||
@@ -54,12 +54,15 @@ class LoadDocGeneratorTemplate extends AbstractFixture
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        foreach ($templates as $template) {
 | 
			
		||||
            $newStoredObj = (new StoredObject())
 | 
			
		||||
                ->setFilename($template['file']['filename'])
 | 
			
		||||
                ->setKeyInfos(json_decode($template['file']['key'], true))
 | 
			
		||||
                ->setIv(json_decode($template['file']['iv'], true))
 | 
			
		||||
            $newStoredObj = (new StoredObject());
 | 
			
		||||
 | 
			
		||||
            $newStoredObj
 | 
			
		||||
                ->setCreatedAt(new \DateTime('today'))
 | 
			
		||||
                ->setType($template['file']['type']);
 | 
			
		||||
                ->registerVersion(
 | 
			
		||||
                    json_decode($template['file']['key'], true),
 | 
			
		||||
                    json_decode($template['file']['iv'], true),
 | 
			
		||||
                    $template['file']['type'],
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
            $manager->persist($newStoredObj);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ final readonly class RelatorioDriver implements DriverInterface
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private HttpClientInterface $client,
 | 
			
		||||
        ParameterBagInterface $parameterBag,
 | 
			
		||||
        private LoggerInterface $logger
 | 
			
		||||
        private LoggerInterface $logger,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->url = $parameterBag->get('chill_doc_generator')['driver']['relatorio']['url'];
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ class DocGenObjectNormalizer implements NormalizerAwareInterface, NormalizerInte
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly ClassMetadataFactoryInterface $classMetadataFactory,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->propertyAccess = PropertyAccess::createPropertyAccessor();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@ class Generator implements GeneratorInterface
 | 
			
		||||
        private readonly DriverInterface $driver,
 | 
			
		||||
        private readonly ManagerRegistry $objectManagerRegistry,
 | 
			
		||||
        private readonly LoggerInterface $logger,
 | 
			
		||||
        private readonly StoredObjectManagerInterface $storedObjectManager
 | 
			
		||||
        private readonly StoredObjectManagerInterface $storedObjectManager,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function generateDataDump(
 | 
			
		||||
@@ -134,13 +134,11 @@ class Generator implements GeneratorInterface
 | 
			
		||||
            $content = Yaml::dump($data, 6);
 | 
			
		||||
            /* @var StoredObject $destinationStoredObject */
 | 
			
		||||
            $destinationStoredObject
 | 
			
		||||
                ->setType('application/yaml')
 | 
			
		||||
                ->setFilename(sprintf('%s_yaml', uniqid('doc_', true)))
 | 
			
		||||
                ->setStatus(StoredObject::STATUS_READY)
 | 
			
		||||
            ;
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                $this->storedObjectManager->write($destinationStoredObject, $content);
 | 
			
		||||
                $this->storedObjectManager->write($destinationStoredObject, $content, 'application/yaml');
 | 
			
		||||
            } catch (StoredObjectManagerException $e) {
 | 
			
		||||
                $destinationStoredObject->addGenerationErrors($e->getMessage());
 | 
			
		||||
 | 
			
		||||
@@ -174,13 +172,11 @@ class Generator implements GeneratorInterface
 | 
			
		||||
 | 
			
		||||
        /* @var StoredObject $destinationStoredObject */
 | 
			
		||||
        $destinationStoredObject
 | 
			
		||||
            ->setType($template->getFile()->getType())
 | 
			
		||||
            ->setFilename(sprintf('%s_odt', uniqid('doc_', true)))
 | 
			
		||||
            ->setStatus(StoredObject::STATUS_READY)
 | 
			
		||||
        ;
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            $this->storedObjectManager->write($destinationStoredObject, $generatedResource);
 | 
			
		||||
            $this->storedObjectManager->write($destinationStoredObject, $generatedResource, $template->getFile()->getType());
 | 
			
		||||
        } catch (StoredObjectManagerException $e) {
 | 
			
		||||
            $destinationStoredObject->addGenerationErrors($e->getMessage());
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,7 @@ final readonly class OnGenerationFails implements EventSubscriberInterface
 | 
			
		||||
        private MailerInterface $mailer,
 | 
			
		||||
        private StoredObjectRepositoryInterface $storedObjectRepository,
 | 
			
		||||
        private TranslatorInterface $translator,
 | 
			
		||||
        private UserRepositoryInterface $userRepository
 | 
			
		||||
        private UserRepositoryInterface $userRepository,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public static function getSubscribedEvents()
 | 
			
		||||
 
 | 
			
		||||
@@ -56,7 +56,7 @@ final class BaseContextDataTest extends KernelTestCase
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function buildBaseContext(
 | 
			
		||||
        ?NormalizerInterface $normalizer = null
 | 
			
		||||
        ?NormalizerInterface $normalizer = null,
 | 
			
		||||
    ): BaseContextData {
 | 
			
		||||
        return new BaseContextData(
 | 
			
		||||
            $normalizer ?? self::getContainer()->get(NormalizerInterface::class)
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ use Chill\DocGeneratorBundle\Service\Generator\Generator;
 | 
			
		||||
use Chill\DocGeneratorBundle\Service\Generator\ObjectReadyException;
 | 
			
		||||
use Chill\DocGeneratorBundle\Service\Generator\RelatedEntityNotFoundException;
 | 
			
		||||
use Chill\DocStoreBundle\Entity\StoredObject;
 | 
			
		||||
use Chill\DocStoreBundle\Entity\StoredObjectVersion;
 | 
			
		||||
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
 | 
			
		||||
use Chill\MainBundle\Entity\User;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
@@ -39,11 +40,11 @@ class GeneratorTest extends TestCase
 | 
			
		||||
 | 
			
		||||
    public function testSuccessfulGeneration(): void
 | 
			
		||||
    {
 | 
			
		||||
        $template = (new DocGeneratorTemplate())->setFile($templateStoredObject = (new StoredObject())
 | 
			
		||||
            ->setType('application/test'));
 | 
			
		||||
        $templateStoredObject = new StoredObject();
 | 
			
		||||
        $templateStoredObject->registerVersion(type: 'application/test');
 | 
			
		||||
        $template = (new DocGeneratorTemplate())->setFile($templateStoredObject);
 | 
			
		||||
        $destinationStoredObject = (new StoredObject())->setStatus(StoredObject::STATUS_PENDING);
 | 
			
		||||
        $reflection = new \ReflectionClass($destinationStoredObject);
 | 
			
		||||
        $reflection->getProperty('id')->setAccessible(true);
 | 
			
		||||
        $reflection->getProperty('id')->setValue($destinationStoredObject, 1);
 | 
			
		||||
        $entity = new class () {};
 | 
			
		||||
        $data = [];
 | 
			
		||||
@@ -76,7 +77,14 @@ class GeneratorTest extends TestCase
 | 
			
		||||
 | 
			
		||||
        $storedObjectManager = $this->prophesize(StoredObjectManagerInterface::class);
 | 
			
		||||
        $storedObjectManager->read($templateStoredObject)->willReturn('template');
 | 
			
		||||
        $storedObjectManager->write($destinationStoredObject, 'generated')->shouldBeCalled();
 | 
			
		||||
        $storedObjectManager->write($destinationStoredObject, 'generated', 'application/test')
 | 
			
		||||
            ->will(function ($args): StoredObjectVersion {
 | 
			
		||||
                /** @var StoredObject $storedObject */
 | 
			
		||||
                $storedObject = $args[0];
 | 
			
		||||
 | 
			
		||||
                return $storedObject->registerVersion(type: $args[2]);
 | 
			
		||||
            })
 | 
			
		||||
            ->shouldBeCalled();
 | 
			
		||||
 | 
			
		||||
        $generator = new Generator(
 | 
			
		||||
            $contextManagerInterface->reveal(),
 | 
			
		||||
@@ -107,8 +115,9 @@ class GeneratorTest extends TestCase
 | 
			
		||||
            $this->prophesize(StoredObjectManagerInterface::class)->reveal()
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $template = (new DocGeneratorTemplate())->setFile($templateStoredObject = (new StoredObject())
 | 
			
		||||
            ->setType('application/test'));
 | 
			
		||||
        $templateStoredObject = new StoredObject();
 | 
			
		||||
        $templateStoredObject->registerVersion(type: 'application/test');
 | 
			
		||||
        $template = (new DocGeneratorTemplate())->setFile($templateStoredObject);
 | 
			
		||||
        $destinationStoredObject = (new StoredObject())->setStatus(StoredObject::STATUS_READY);
 | 
			
		||||
 | 
			
		||||
        $generator->generateDocFromTemplate(
 | 
			
		||||
@@ -124,11 +133,11 @@ class GeneratorTest extends TestCase
 | 
			
		||||
    {
 | 
			
		||||
        $this->expectException(RelatedEntityNotFoundException::class);
 | 
			
		||||
 | 
			
		||||
        $template = (new DocGeneratorTemplate())->setFile($templateStoredObject = (new StoredObject())
 | 
			
		||||
            ->setType('application/test'));
 | 
			
		||||
        $templateStoredObject = new StoredObject();
 | 
			
		||||
        $templateStoredObject->registerVersion(type: 'application/test');
 | 
			
		||||
        $template = (new DocGeneratorTemplate())->setFile($templateStoredObject);
 | 
			
		||||
        $destinationStoredObject = (new StoredObject())->setStatus(StoredObject::STATUS_PENDING);
 | 
			
		||||
        $reflection = new \ReflectionClass($destinationStoredObject);
 | 
			
		||||
        $reflection->getProperty('id')->setAccessible(true);
 | 
			
		||||
        $reflection->getProperty('id')->setValue($destinationStoredObject, 1);
 | 
			
		||||
 | 
			
		||||
        $context = $this->prophesize(DocGeneratorContextInterface::class);
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,7 @@ final readonly class TempUrlOpenstackGenerator implements TempUrlGeneratorInterf
 | 
			
		||||
        ?int $expire_delay = null,
 | 
			
		||||
        ?int $submit_delay = null,
 | 
			
		||||
        int $max_file_count = 1,
 | 
			
		||||
        ?string $object_name = null,
 | 
			
		||||
    ): SignedUrlPost {
 | 
			
		||||
        $delay = $expire_delay ?? $this->max_expire_delay;
 | 
			
		||||
        $submit_delay ??= $this->max_submit_delay;
 | 
			
		||||
@@ -84,11 +85,14 @@ final readonly class TempUrlOpenstackGenerator implements TempUrlGeneratorInterf
 | 
			
		||||
 | 
			
		||||
        $expires = $this->clock->now()->add(new \DateInterval('PT'.(string) $delay.'S'));
 | 
			
		||||
 | 
			
		||||
        $object_name = $this->generateObjectName();
 | 
			
		||||
        if (null === $object_name) {
 | 
			
		||||
            $object_name = $this->generateObjectName();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $g = new SignedUrlPost(
 | 
			
		||||
            $url = $this->generateUrl($object_name),
 | 
			
		||||
            $expires,
 | 
			
		||||
            $object_name,
 | 
			
		||||
            $this->max_post_file_size,
 | 
			
		||||
            $max_file_count,
 | 
			
		||||
            $submit_delay,
 | 
			
		||||
@@ -127,7 +131,7 @@ final readonly class TempUrlOpenstackGenerator implements TempUrlGeneratorInterf
 | 
			
		||||
        ];
 | 
			
		||||
        $url = $url.'?'.\http_build_query($args);
 | 
			
		||||
 | 
			
		||||
        $signature = new SignedUrl(strtoupper($method), $url, $expires);
 | 
			
		||||
        $signature = new SignedUrl(strtoupper($method), $url, $expires, $object_name);
 | 
			
		||||
 | 
			
		||||
        $this->event_dispatcher->dispatch(
 | 
			
		||||
            new TempUrlGenerateEvent($signature)
 | 
			
		||||
@@ -140,7 +144,7 @@ final readonly class TempUrlOpenstackGenerator implements TempUrlGeneratorInterf
 | 
			
		||||
    {
 | 
			
		||||
        return match (str_ends_with($this->base_url, '/')) {
 | 
			
		||||
            true => $this->base_url.$relative_path,
 | 
			
		||||
            false => $this->base_url.'/'.$relative_path
 | 
			
		||||
            false => $this->base_url.'/'.$relative_path,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -178,21 +182,19 @@ final readonly class TempUrlOpenstackGenerator implements TempUrlGeneratorInterf
 | 
			
		||||
        return \hash_hmac('sha512', $body, $this->key, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function generateSignature($method, $url, \DateTimeImmutable $expires)
 | 
			
		||||
    private function generateSignature(string $method, $url, \DateTimeImmutable $expires)
 | 
			
		||||
    {
 | 
			
		||||
        if ('POST' === $method) {
 | 
			
		||||
            return $this->generateSignaturePost($url, $expires);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $path = \parse_url((string) $url, PHP_URL_PATH);
 | 
			
		||||
 | 
			
		||||
        $body = sprintf(
 | 
			
		||||
            "%s\n%s\n%s",
 | 
			
		||||
            $method,
 | 
			
		||||
            strtoupper($method),
 | 
			
		||||
            $expires->format('U'),
 | 
			
		||||
            $path
 | 
			
		||||
        )
 | 
			
		||||
        ;
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $this->logger->debug(
 | 
			
		||||
            'generate signature GET',
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,8 @@ readonly class SignedUrl
 | 
			
		||||
        #[Serializer\Groups(['read'])]
 | 
			
		||||
        public string $url,
 | 
			
		||||
        public \DateTimeImmutable $expires,
 | 
			
		||||
        #[Serializer\Groups(['read'])]
 | 
			
		||||
        public string $object_name,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    #[Serializer\Groups(['read'])]
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ readonly class SignedUrlPost extends SignedUrl
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        string $url,
 | 
			
		||||
        \DateTimeImmutable $expires,
 | 
			
		||||
        string $object_name,
 | 
			
		||||
        #[Serializer\Groups(['read'])]
 | 
			
		||||
        public int $max_file_size,
 | 
			
		||||
        #[Serializer\Groups(['read'])]
 | 
			
		||||
@@ -31,6 +32,6 @@ readonly class SignedUrlPost extends SignedUrl
 | 
			
		||||
        #[Serializer\Groups(['read'])]
 | 
			
		||||
        public string $signature,
 | 
			
		||||
    ) {
 | 
			
		||||
        parent::__construct('POST', $url, $expires);
 | 
			
		||||
        parent::__construct('POST', $url, $expires, $object_name);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,8 @@ interface TempUrlGeneratorInterface
 | 
			
		||||
    public function generatePost(
 | 
			
		||||
        ?int $expire_delay = null,
 | 
			
		||||
        ?int $submit_delay = null,
 | 
			
		||||
        int $max_file_count = 1
 | 
			
		||||
        int $max_file_count = 1,
 | 
			
		||||
        ?string $object_name = null,
 | 
			
		||||
    ): SignedUrlPost;
 | 
			
		||||
 | 
			
		||||
    public function generate(string $method, string $object_name, ?int $expire_delay = null): SignedUrl;
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ class AsyncUploadExtension extends AbstractExtension
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly TempUrlGeneratorInterface $tempUrlGenerator,
 | 
			
		||||
        private readonly UrlGeneratorInterface $routingUrlGenerator
 | 
			
		||||
        private readonly UrlGeneratorInterface $routingUrlGenerator,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function getFilters()
 | 
			
		||||
 
 | 
			
		||||
@@ -11,9 +11,11 @@ declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Chill\DocStoreBundle\Controller;
 | 
			
		||||
 | 
			
		||||
use Chill\DocStoreBundle\AsyncUpload\Exception\TempUrlGeneratorException;
 | 
			
		||||
use Chill\DocStoreBundle\AsyncUpload\TempUrlGeneratorInterface;
 | 
			
		||||
use Chill\DocStoreBundle\Security\Authorization\AsyncUploadVoter;
 | 
			
		||||
use Chill\DocStoreBundle\Entity\StoredObject;
 | 
			
		||||
use Chill\DocStoreBundle\Entity\StoredObjectVersion;
 | 
			
		||||
use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum;
 | 
			
		||||
use Chill\MainBundle\Entity\User;
 | 
			
		||||
use Psr\Log\LoggerInterface;
 | 
			
		||||
use Symfony\Component\HttpFoundation\JsonResponse;
 | 
			
		||||
use Symfony\Component\HttpFoundation\Request;
 | 
			
		||||
@@ -30,62 +32,84 @@ final readonly class AsyncUploadController
 | 
			
		||||
        private TempUrlGeneratorInterface $tempUrlGenerator,
 | 
			
		||||
        private SerializerInterface $serializer,
 | 
			
		||||
        private Security $security,
 | 
			
		||||
        private LoggerInterface $logger,
 | 
			
		||||
        private LoggerInterface $chillLogger,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    #[Route(path: '/asyncupload/temp_url/generate/{method}', name: 'async_upload.generate_url')]
 | 
			
		||||
    public function getSignedUrl(string $method, Request $request): JsonResponse
 | 
			
		||||
    #[Route(path: '/api/1.0/doc-store/async-upload/temp_url/{uuid}/generate/post', name: 'chill_docstore_asyncupload_getsignedurlpost')]
 | 
			
		||||
    public function getSignedUrlPost(Request $request, StoredObject $storedObject): JsonResponse
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            switch (strtolower($method)) {
 | 
			
		||||
                case 'post':
 | 
			
		||||
                    $p = $this->tempUrlGenerator
 | 
			
		||||
                        ->generatePost(
 | 
			
		||||
                            $request->query->has('expires_delay') ? $request->query->getInt('expires_delay') : null,
 | 
			
		||||
                            $request->query->has('submit_delay') ? $request->query->getInt('submit_delay') : null
 | 
			
		||||
                        )
 | 
			
		||||
                    ;
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'get':
 | 
			
		||||
                case 'head':
 | 
			
		||||
                    $object_name = $request->query->get('object_name', null);
 | 
			
		||||
        if (!$this->security->isGranted(StoredObjectRoleEnum::EDIT->value, $storedObject)) {
 | 
			
		||||
            throw new AccessDeniedHttpException('not able to edit the given stored object');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
                    if (null === $object_name) {
 | 
			
		||||
                        return (new JsonResponse((object) [
 | 
			
		||||
                            'message' => 'the object_name is null',
 | 
			
		||||
                        ]))
 | 
			
		||||
                            ->setStatusCode(JsonResponse::HTTP_BAD_REQUEST);
 | 
			
		||||
                    }
 | 
			
		||||
                    $p = $this->tempUrlGenerator->generate(
 | 
			
		||||
                        $method,
 | 
			
		||||
                        $object_name,
 | 
			
		||||
                        $request->query->has('expires_delay') ? $request->query->getInt('expires_delay') : null
 | 
			
		||||
                    );
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    return (new JsonResponse((object) ['message' => 'the method '
 | 
			
		||||
                        ."{$method} is not valid"]))
 | 
			
		||||
                        ->setStatusCode(JsonResponse::HTTP_BAD_REQUEST);
 | 
			
		||||
        // we create a dummy version, to generate a filename
 | 
			
		||||
        $version = $storedObject->registerVersion();
 | 
			
		||||
 | 
			
		||||
        $p = $this->tempUrlGenerator
 | 
			
		||||
            ->generatePost(
 | 
			
		||||
                $request->query->has('expires_delay') ? $request->query->getInt('expires_delay') : null,
 | 
			
		||||
                $request->query->has('submit_delay') ? $request->query->getInt('submit_delay') : null,
 | 
			
		||||
                object_name: $version->getFilename()
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
        $this->chillLogger->notice('[Privacy Event] a request to upload a document has been generated', [
 | 
			
		||||
            'doc_uuid' => $storedObject->getUuid(),
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        return new JsonResponse(
 | 
			
		||||
            $this->serializer->serialize($p, 'json', [AbstractNormalizer::GROUPS => ['read']]),
 | 
			
		||||
            Response::HTTP_OK,
 | 
			
		||||
            [],
 | 
			
		||||
            true
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[Route(path: '/api/1.0/doc-store/async-upload/temp_url/{uuid}/generate/{method}', name: 'chill_docstore_asyncupload_getsignedurlget', requirements: ['method' => 'get|head'])]
 | 
			
		||||
    public function getSignedUrlGet(Request $request, StoredObject $storedObject, string $method): JsonResponse
 | 
			
		||||
    {
 | 
			
		||||
        if (!$this->security->isGranted(StoredObjectRoleEnum::SEE->value, $storedObject)) {
 | 
			
		||||
            throw new AccessDeniedHttpException('not able to read the given stored object');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // we really want to be sure that there are no other method than get or head:
 | 
			
		||||
        if (!in_array($method, ['get', 'head'], true)) {
 | 
			
		||||
            throw new AccessDeniedHttpException('Only methods get and head are allowed');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($request->query->has('version')) {
 | 
			
		||||
            $filename = $request->query->get('version');
 | 
			
		||||
 | 
			
		||||
            $storedObjectVersion = $storedObject->getVersions()->findFirst(fn (int $index, StoredObjectVersion $version): bool => $version->getFilename() === $filename);
 | 
			
		||||
 | 
			
		||||
            if (null === $storedObjectVersion) {
 | 
			
		||||
                // we are here in the case where the version is not stored into the database
 | 
			
		||||
                // as the version is prefixed by the stored object prefix, we just have to check that this prefix
 | 
			
		||||
                // is the same. It means that the user had previously the permission to "SEE_AND_EDIT" this stored
 | 
			
		||||
                // object with same prefix that we checked before
 | 
			
		||||
                if (!str_starts_with($filename, $storedObject->getPrefix())) {
 | 
			
		||||
                    throw new AccessDeniedHttpException('not able to match the version with the same filename');
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } catch (TempUrlGeneratorException $e) {
 | 
			
		||||
            $this->logger->warning('The client requested a temp url'
 | 
			
		||||
                .' which sparkle an error.', [
 | 
			
		||||
                    'message' => $e->getMessage(),
 | 
			
		||||
                    'expire_delay' => $request->query->getInt('expire_delay', 0),
 | 
			
		||||
                    'file_count' => $request->query->getInt('file_count', 1),
 | 
			
		||||
                    'method' => $method,
 | 
			
		||||
                ]);
 | 
			
		||||
 | 
			
		||||
            $p = new \stdClass();
 | 
			
		||||
            $p->message = $e->getMessage();
 | 
			
		||||
            $p->status = JsonResponse::HTTP_BAD_REQUEST;
 | 
			
		||||
 | 
			
		||||
            return new JsonResponse($p, JsonResponse::HTTP_BAD_REQUEST);
 | 
			
		||||
        } else {
 | 
			
		||||
            $filename = $storedObject->getCurrentVersion()->getFilename();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!$this->security->isGranted(AsyncUploadVoter::GENERATE_SIGNATURE, $p)) {
 | 
			
		||||
            throw new AccessDeniedHttpException('not allowed to generate this signature');
 | 
			
		||||
        }
 | 
			
		||||
        $p = $this->tempUrlGenerator->generate(
 | 
			
		||||
            $method,
 | 
			
		||||
            $filename,
 | 
			
		||||
            $request->query->has('expires_delay') ? $request->query->getInt('expires_delay') : null
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $user = $this->security->getUser();
 | 
			
		||||
        $userId = match ($user instanceof User) {
 | 
			
		||||
            true => $user->getId(),
 | 
			
		||||
            false => $user->getUserIdentifier(),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        $this->chillLogger->notice('[Privacy Event] a request to see a document has been granted', [
 | 
			
		||||
            'doc_uuid' => $storedObject->getUuid()->toString(),
 | 
			
		||||
            'user_id' => $userId,
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        return new JsonResponse(
 | 
			
		||||
            $this->serializer->serialize($p, 'json', [AbstractNormalizer::GROUPS => ['read']]),
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ class DocumentAccompanyingCourseController extends AbstractController
 | 
			
		||||
        protected TranslatorInterface $translator,
 | 
			
		||||
        protected EventDispatcherInterface $eventDispatcher,
 | 
			
		||||
        protected AuthorizationHelper $authorizationHelper,
 | 
			
		||||
        private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry
 | 
			
		||||
        private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    #[Route(path: '/{id}/delete', name: 'chill_docstore_accompanying_course_document_delete')]
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,8 @@ use Symfony\Component\HttpFoundation\Request;
 | 
			
		||||
use Symfony\Component\HttpFoundation\Response;
 | 
			
		||||
use Symfony\Component\Routing\Annotation\Route;
 | 
			
		||||
use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZoneParser;
 | 
			
		||||
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class DocumentPersonController.
 | 
			
		||||
@@ -40,7 +42,9 @@ class DocumentPersonController extends AbstractController
 | 
			
		||||
        protected TranslatorInterface $translator,
 | 
			
		||||
        protected EventDispatcherInterface $eventDispatcher,
 | 
			
		||||
        protected AuthorizationHelper $authorizationHelper,
 | 
			
		||||
        private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry
 | 
			
		||||
        protected PDFSignatureZoneParser $PDFSignatureZoneParser,
 | 
			
		||||
        protected StoredObjectManagerInterface $storedObjectManagerInterface,
 | 
			
		||||
        private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    #[Route(path: '/{id}/delete', name: 'chill_docstore_person_document_delete')]
 | 
			
		||||
@@ -197,4 +201,36 @@ class DocumentPersonController extends AbstractController
 | 
			
		||||
            ['document' => $document, 'person' => $person]
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[Route(path: '/{id}/signature', name: 'person_document_signature', methods: 'GET')]
 | 
			
		||||
    public function signature(Person $person, PersonDocument $document): Response
 | 
			
		||||
    {
 | 
			
		||||
        $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
 | 
			
		||||
        $this->denyAccessUnlessGranted('CHILL_PERSON_DOCUMENT_SEE', $document);
 | 
			
		||||
 | 
			
		||||
        $event = new PrivacyEvent($person, [
 | 
			
		||||
            'element_class' => PersonDocument::class,
 | 
			
		||||
            'element_id' => $document->getId(),
 | 
			
		||||
            'action' => 'show',
 | 
			
		||||
        ]);
 | 
			
		||||
        $this->eventDispatcher->dispatch($event, PrivacyEvent::PERSON_PRIVACY_EVENT);
 | 
			
		||||
 | 
			
		||||
        $storedObject = $document->getObject();
 | 
			
		||||
        $content = $this->storedObjectManagerInterface->read($storedObject);
 | 
			
		||||
        $zones = $this->PDFSignatureZoneParser->findSignatureZones($content);
 | 
			
		||||
 | 
			
		||||
        $signature = [];
 | 
			
		||||
        $signature['id'] = 1;
 | 
			
		||||
        $signature['storedObject'] = [ // TEMP
 | 
			
		||||
            'filename' => $storedObject->getFilename(),
 | 
			
		||||
            'iv' => $storedObject->getIv(),
 | 
			
		||||
            'keyInfos' => $storedObject->getKeyInfos(),
 | 
			
		||||
        ];
 | 
			
		||||
        $signature['zones'] = $zones;
 | 
			
		||||
 | 
			
		||||
        return $this->render(
 | 
			
		||||
            '@ChillDocStore/PersonDocument/signature.html.twig',
 | 
			
		||||
            ['document' => $document, 'person' => $person, 'signature' => $signature]
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,67 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Chill is a software for social workers
 | 
			
		||||
 *
 | 
			
		||||
 * For the full copyright and license information, please view
 | 
			
		||||
 * the LICENSE file that was distributed with this source code.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\DocStoreBundle\Controller;
 | 
			
		||||
 | 
			
		||||
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\RequestPdfSignMessage;
 | 
			
		||||
use Chill\DocStoreBundle\Service\Signature\PDFPage;
 | 
			
		||||
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone;
 | 
			
		||||
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
 | 
			
		||||
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStepSignature;
 | 
			
		||||
use Chill\MainBundle\Workflow\EntityWorkflowManager;
 | 
			
		||||
use Symfony\Component\HttpFoundation\JsonResponse;
 | 
			
		||||
use Symfony\Component\HttpFoundation\Request;
 | 
			
		||||
use Symfony\Component\Messenger\MessageBusInterface;
 | 
			
		||||
use Symfony\Component\Routing\Annotation\Route;
 | 
			
		||||
 | 
			
		||||
class SignatureRequestController
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly MessageBusInterface $messageBus,
 | 
			
		||||
        private readonly StoredObjectManagerInterface $storedObjectManager,
 | 
			
		||||
        private readonly EntityWorkflowManager $entityWorkflowManager,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    #[Route('/api/1.0/document/workflow/{id}/signature-request', name: 'chill_docstore_signature_request')]
 | 
			
		||||
    public function processSignature(EntityWorkflowStepSignature $signature, Request $request): JsonResponse
 | 
			
		||||
    {
 | 
			
		||||
        $entityWorkflow = $signature->getStep()->getEntityWorkflow();
 | 
			
		||||
        $storedObject = $this->entityWorkflowManager->getAssociatedStoredObject($entityWorkflow);
 | 
			
		||||
        $content = $this->storedObjectManager->read($storedObject);
 | 
			
		||||
 | 
			
		||||
        $data = \json_decode((string) $request->getContent(), true, 512, JSON_THROW_ON_ERROR); // TODO parse payload: json_decode ou, mieux, dataTransfertObject
 | 
			
		||||
        $zone = new PDFSignatureZone(
 | 
			
		||||
            $data['zone']['index'],
 | 
			
		||||
            $data['zone']['x'],
 | 
			
		||||
            $data['zone']['y'],
 | 
			
		||||
            $data['zone']['height'],
 | 
			
		||||
            $data['zone']['width'],
 | 
			
		||||
            new PDFPage($data['zone']['PDFPage']['index'], $data['zone']['PDFPage']['width'], $data['zone']['PDFPage']['height'])
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $this->messageBus->dispatch(new RequestPdfSignMessage(
 | 
			
		||||
            $signature->getId(),
 | 
			
		||||
            $zone,
 | 
			
		||||
            $data['zone']['index'],
 | 
			
		||||
            'test signature', // reason (string)
 | 
			
		||||
            'Mme Caroline Diallo', // signerText (string)
 | 
			
		||||
            $content
 | 
			
		||||
        ));
 | 
			
		||||
 | 
			
		||||
        return new JsonResponse(null, JsonResponse::HTTP_OK, []);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[Route('/api/1.0/document/workflow/{id}/check-signature', name: 'chill_docstore_check_signature')]
 | 
			
		||||
    public function checkSignature(EntityWorkflowStepSignature $signature): JsonResponse
 | 
			
		||||
    {
 | 
			
		||||
        return new JsonResponse($signature->getState(), JsonResponse::HTTP_OK, []);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user