mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-11-04 11:18:25 +00:00 
			
		
		
		
	Compare commits
	
		
			289 Commits
		
	
	
		
			2.8.0
			...
			68-feature
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2fc6e18d0f | |||
| 2a151d13ed | |||
| 
						
						
							
						
						c7bd60a106
	
				 | 
					
					
						|||
| 
						
						
							
						
						9ec5a633ad
	
				 | 
					
					
						|||
| 
						
						
							
						
						d54d34be7c
	
				 | 
					
					
						|||
| 
						
						
							
						
						01292ba9ae
	
				 | 
					
					
						|||
| 
						
						
							
						
						794daa5c3e
	
				 | 
					
					
						|||
| 
						
						
							
						
						37265c09f7
	
				 | 
					
					
						|||
| 98cd0f3c00 | |||
| 
						
						
							
						
						bc2041cbdd
	
				 | 
					
					
						|||
| 
						
						
							
						
						0b0cbed9db
	
				 | 
					
					
						|||
| 
						
						
							
						
						c9cfe4c7e9
	
				 | 
					
					
						|||
| 
						
						
							
						
						75e15c1389
	
				 | 
					
					
						|||
| 
						
						
							
						
						48e0a0af7d
	
				 | 
					
					
						|||
| 
						
						
							
						
						adf1110340
	
				 | 
					
					
						|||
| 
						
						
							
						
						a6fcdb5256
	
				 | 
					
					
						|||
| 
						
						
							
						
						6b8d6b76ba
	
				 | 
					
					
						|||
| bbf9c58fbf | |||
| 0c8ecfe493 | |||
| 
						
						
							
						
						8523f14214
	
				 | 
					
					
						|||
| 
						
						
							
						
						b32fa42afa
	
				 | 
					
					
						|||
| 
						
						
							
						
						be8975ee04
	
				 | 
					
					
						|||
| 05865521b5 | |||
| 
						
						
							
						
						dd47ddc268
	
				 | 
					
					
						|||
| 
						
						
							
						
						0df93fb703
	
				 | 
					
					
						|||
| 
						
						
							
						
						c62495a280
	
				 | 
					
					
						|||
| 
						
						
							
						
						93b189b091
	
				 | 
					
					
						|||
| 
						
						
							
						
						304bf4258b
	
				 | 
					
					
						|||
| 
						
						
							
						
						efcb903d10
	
				 | 
					
					
						|||
| 
						
						
							
						
						b65f76262a
	
				 | 
					
					
						|||
| 
						
						
							
						
						51a4ffca2e
	
				 | 
					
					
						|||
| 
						
						
							
						
						68d28f3e28
	
				 | 
					
					
						|||
| 
						
						
							
						
						63e9d1a96f
	
				 | 
					
					
						|||
| 
						
						
							
						
						21524f052e
	
				 | 
					
					
						|||
| 
						
						
							
						
						978db5a5c5
	
				 | 
					
					
						|||
| 
						
						
							
						
						363785b779
	
				 | 
					
					
						|||
| 
						
						
							
						
						4e13b2ae3a
	
				 | 
					
					
						|||
| 
						
						
							
						
						239372270e
	
				 | 
					
					
						|||
| ada28265ee | |||
| 0b6b25fd95 | |||
| c526973475 | |||
| 9bbddd8405 | |||
| 935210aa1d | |||
| 
						
						
							
						
						58e189ee07
	
				 | 
					
					
						|||
| 9f476dddaf | |||
| dac48ea4e0 | |||
| af4bee4d50 | |||
| b4e5618e00 | |||
| 15e23087ed | |||
| 
						
						
							
						
						e3559774fd
	
				 | 
					
					
						|||
| d6a1044585 | |||
| c6a06ebaf9 | |||
| c00c26c3e5 | |||
| fa3fc2c781 | |||
| 6e48d036d7 | |||
| 31fc7fffe9 | |||
| 84ba626fb5 | |||
| eddcfc3921 | |||
| f025b0d184 | |||
| 8c44e92079 | |||
| 1973a4b849 | |||
| bea21d45fc | |||
| 3aa10927d7 | |||
| 4460db1dc4 | |||
| e4cf07c7b3 | |||
| 2100d45671 | |||
| aeb0d5eab8 | |||
| bc69f83c37 | |||
| 9b272e9b9e | |||
| f225a83a3e | |||
| e738bf0f5e | |||
| 0953faedc4 | |||
| 7c25ca8dd4 | |||
| 8b7600e09f | |||
| 9db0011b2e | |||
| 3f4a42adb2 | |||
| f18ee2383c | |||
| 28583f4193 | |||
| c5b153e6ed | |||
| 2d4d1eda50 | |||
| baeccf0970 | |||
| 6665a443b9 | |||
| fc919e9547 | |||
| 949c5424f0 | |||
| e6e42777d7 | |||
| c590d60a7f | |||
| 6228cc5ede | |||
| 024790128a | |||
| d2feb0f0b4 | |||
| 8a6f29ef79 | |||
| 124abf563e | |||
| 096fb6219f | |||
| bebc746d57 | |||
| d47e6c5ba1 | |||
| 
						
						
							
						
						ef8ac6041a
	
				 | 
					
					
						|||
| 
						
						
							
						
						41f4bbfdce
	
				 | 
					
					
						|||
| 
						
						
							
						
						6a37079ee5
	
				 | 
					
					
						|||
| 
						
						
							
						
						2d7bc06539
	
				 | 
					
					
						|||
| 
						
						
							
						
						bad302f512
	
				 | 
					
					
						|||
| 
						
						
							
						
						294aaf5bed
	
				 | 
					
					
						|||
| 
						
						
							
						
						d2864605b9
	
				 | 
					
					
						|||
| 
						
						
							
						
						2efd5ebc9a
	
				 | 
					
					
						|||
| b0a7612329 | |||
| 0c5b35926b | |||
| b38f5800d9 | |||
| 
						
						
							
						
						8dce0473ff
	
				 | 
					
					
						|||
| 
						
						
							
						
						5f8b86b839
	
				 | 
					
					
						|||
| 
						
						
							
						
						65aa0a1588
	
				 | 
					
					
						|||
| 
						
						
							
						
						d8b0e0671a
	
				 | 
					
					
						|||
| 29983cc2ad | |||
| 260a173a61 | |||
| 500b37601a | |||
| 5d41b37620 | |||
| 05e86a3360 | |||
| 9b061eeaae | |||
| 3816d68e18 | |||
| 7db7f34f62 | |||
| 6b958d193d | |||
| 
						
						
							
						
						1070d33670
	
				 | 
					
					
						|||
| 
						
						
							
						
						b93a822299
	
				 | 
					
					
						|||
| 
						
						
							
						
						fc7cfb1760
	
				 | 
					
					
						|||
| 
						
						
							
						
						76f1814848
	
				 | 
					
					
						|||
| 
						
						
							
						
						cd9611a669
	
				 | 
					
					
						|||
| 
						
						
							
						
						d3b68f8f8f
	
				 | 
					
					
						|||
| 
						
						
							
						
						2ce29f36ff
	
				 | 
					
					
						|||
| 
						
						
							
						
						d2323e91ca
	
				 | 
					
					
						|||
| 
						
						
							
						
						b9231a91a3
	
				 | 
					
					
						|||
| 
						
						
							
						
						b36e37d9c5
	
				 | 
					
					
						|||
| 
						
						
							
						
						899ed5d0a4
	
				 | 
					
					
						|||
| 
						
						
							
						
						9375d50112
	
				 | 
					
					
						|||
| 
						
						
							
						
						e53540ec74
	
				 | 
					
					
						|||
| 
						
						
							
						
						582b27fbd6
	
				 | 
					
					
						|||
| 
						
						
							
						
						19c6e3e6ba
	
				 | 
					
					
						|||
| 
						
						
							
						
						0711b7f84a
	
				 | 
					
					
						|||
| 
						
						
							
						
						608663d25c
	
				 | 
					
					
						|||
| 
						
						
							
						
						40b7c8ad8f
	
				 | 
					
					
						|||
| 
						
						
							
						
						412c55a1a5
	
				 | 
					
					
						|||
| 
						
						
							
						
						afa4b7ad2c
	
				 | 
					
					
						|||
| 
						
						
							
						
						0db1e3e0d7
	
				 | 
					
					
						|||
| 
						
						
							
						
						a2a660c954
	
				 | 
					
					
						|||
| 
						
						
							
						
						2c52a5bffa
	
				 | 
					
					
						|||
| 
						
						
							
						
						10a75f44e9
	
				 | 
					
					
						|||
| 
						
						
							
						
						1361e2bbf9
	
				 | 
					
					
						|||
| 
						
						
							
						
						37c1dfb0ba
	
				 | 
					
					
						|||
| 
						
						
							
						
						a197a6b418
	
				 | 
					
					
						|||
| 
						
						
							
						
						f8f04c69d0
	
				 | 
					
					
						|||
| 
						
						
							
						
						355ed03500
	
				 | 
					
					
						|||
| 
						
						
							
						
						d8062be131
	
				 | 
					
					
						|||
| 
						
						
							
						
						e72df84442
	
				 | 
					
					
						|||
| 
						
						
							
						
						d44f5d7af8
	
				 | 
					
					
						|||
| 
						
						
							
						
						d595c17cd4
	
				 | 
					
					
						|||
| 
						
						
							
						
						cbb89ecf35
	
				 | 
					
					
						|||
| 
						
						
							
						
						6f11dffcbd
	
				 | 
					
					
						|||
| 
						
						
							
						
						7c58880139
	
				 | 
					
					
						|||
| 
						
						
							
						
						76142c1264
	
				 | 
					
					
						|||
| 
						
						
							
						
						650e3a84c8
	
				 | 
					
					
						|||
| 
						
						
							
						
						6001e15907
	
				 | 
					
					
						|||
| 
						
						
							
						
						2a9e461d6f
	
				 | 
					
					
						|||
| 
						
						
							
						
						b85cd1b994
	
				 | 
					
					
						|||
| 
						
						
							
						
						e4e52234ad
	
				 | 
					
					
						|||
| 
						
						
							
						
						bc9b7b1776
	
				 | 
					
					
						|||
| 
						
						
							
						
						1f2ecb923e
	
				 | 
					
					
						|||
| 
						
						
							
						
						37419e06fc
	
				 | 
					
					
						|||
| 
						
						
							
						
						bad3cdca09
	
				 | 
					
					
						|||
| 
						
						
							
						
						711cdc3481
	
				 | 
					
					
						|||
| 
						
						
							
						
						149ed2bd75
	
				 | 
					
					
						|||
| 
						
						
							
						
						2f1f724860
	
				 | 
					
					
						|||
| 
						
						
							
						
						68e1384416
	
				 | 
					
					
						|||
| 
						
						
							
						
						0907d5b76a
	
				 | 
					
					
						|||
| 
						
						
							
						
						1c0fd57913
	
				 | 
					
					
						|||
| 
						
						
							
						
						d01172274d
	
				 | 
					
					
						|||
| 
						
						
							
						
						876ebca210
	
				 | 
					
					
						|||
| 
						
						
							
						
						364a67b83a
	
				 | 
					
					
						|||
| 
						
						
							
						
						6bedd673cd
	
				 | 
					
					
						|||
| 
						
						
							
						
						df9f30265f
	
				 | 
					
					
						|||
| 
						
						
							
						
						1b8acfab24
	
				 | 
					
					
						|||
| 
						
						
							
						
						690697cb35
	
				 | 
					
					
						|||
| 
						
						
							
						
						5314e7b501
	
				 | 
					
					
						|||
| 
						
						
							
						
						939a6753bd
	
				 | 
					
					
						|||
| 
						
						
							
						
						52d791f6d0
	
				 | 
					
					
						|||
| 
						
						
							
						
						80684f65fe
	
				 | 
					
					
						|||
| 
						
						
							
						
						b1a9749dc0
	
				 | 
					
					
						|||
| 
						
						
							
						
						2dfc228917
	
				 | 
					
					
						|||
| 
						
						
							
						
						3f2339bc60
	
				 | 
					
					
						|||
| 
						
						
							
						
						e2a739eeff
	
				 | 
					
					
						|||
| 
						
						
							
						
						847fd71364
	
				 | 
					
					
						|||
| 
						
						
							
						
						667104a595
	
				 | 
					
					
						|||
| 
						
						
							
						
						2c83b4c912
	
				 | 
					
					
						|||
| 
						
						
							
						
						e2d62d5792
	
				 | 
					
					
						|||
| 
						
						
							
						
						d1e09d7047
	
				 | 
					
					
						|||
| 
						
						
							
						
						5481d029e8
	
				 | 
					
					
						|||
| 
						
						
							
						
						ebe1c11ca6
	
				 | 
					
					
						|||
| 
						
						
							
						
						398bbd12d5
	
				 | 
					
					
						|||
| 
						
						
							
						
						c33330969c
	
				 | 
					
					
						|||
| 
						
						
							
						
						ea9c21e021
	
				 | 
					
					
						|||
| 
						
						
							
						
						410aa7098a
	
				 | 
					
					
						|||
| 
						
						
							
						
						ad1e5ecc95
	
				 | 
					
					
						|||
| 
						
						
							
						
						1e353ed74b
	
				 | 
					
					
						|||
| 
						
						
							
						
						5136907d62
	
				 | 
					
					
						|||
| 
						
						
							
						
						84dbfabd66
	
				 | 
					
					
						|||
| 
						
						
							
						
						43ac6726aa
	
				 | 
					
					
						|||
| 
						
						
							
						
						0e0b0b8874
	
				 | 
					
					
						|||
| 
						
						
							
						
						24cc6a816b
	
				 | 
					
					
						|||
| 
						
						
							
						
						f2d391ea2e
	
				 | 
					
					
						|||
| 
						
						
							
						
						e2b500ea5f
	
				 | 
					
					
						|||
| 
						
						
							
						
						dbccf7ff80
	
				 | 
					
					
						|||
| 
						
						
							
						
						65e6ad0fc4
	
				 | 
					
					
						|||
| 
						
						
							
						
						f68a163a30
	
				 | 
					
					
						|||
| 
						
						
							
						
						009a0326d9
	
				 | 
					
					
						|||
| 
						
						
							
						
						4b20db7a9c
	
				 | 
					
					
						|||
| 
						
						
							
						
						458a59fe1b
	
				 | 
					
					
						|||
| 
						
						
							
						
						378e417d5c
	
				 | 
					
					
						|||
| 
						
						
							
						
						cd7b91dd98
	
				 | 
					
					
						|||
| 
						
						
							
						
						4b989fe25c
	
				 | 
					
					
						|||
| 
						
						
							
						
						984c35f8bc
	
				 | 
					
					
						|||
| 
						
						
							
						
						770d64a2f8
	
				 | 
					
					
						|||
| 
						
						
							
						
						34c46f23e3
	
				 | 
					
					
						|||
| 
						
						
							
						
						333579de06
	
				 | 
					
					
						|||
| 
						
						
							
						
						836cc7199e
	
				 | 
					
					
						|||
| 
						
						
							
						
						7f96a895e1
	
				 | 
					
					
						|||
| 
						
						
							
						
						a0d4a995d3
	
				 | 
					
					
						|||
| 
						
						
							
						
						e839b03cc9
	
				 | 
					
					
						|||
| 
						
						
							
						
						55b8502896
	
				 | 
					
					
						|||
| 
						
						
							
						
						a9c8f464bb
	
				 | 
					
					
						|||
| 
						
						
							
						
						f570fe92a5
	
				 | 
					
					
						|||
| 
						
						
							
						
						157cdf6dfc
	
				 | 
					
					
						|||
| 
						
						
							
						
						c20f65eebb
	
				 | 
					
					
						|||
| 
						
						
							
						
						b6a094aeee
	
				 | 
					
					
						|||
| 
						
						
							
						
						0ed5544ad3
	
				 | 
					
					
						|||
| 
						
						
							
						
						6f2b538e27
	
				 | 
					
					
						|||
| 
						
						
							
						
						0e94e769cb
	
				 | 
					
					
						|||
| 
						
						
							
						
						abc067adae
	
				 | 
					
					
						|||
| 
						
						
							
						
						ae04172929
	
				 | 
					
					
						|||
| 
						
						
							
						
						dd21694544
	
				 | 
					
					
						|||
| 
						
						
							
						
						5f6e506300
	
				 | 
					
					
						|||
| 
						
						
							
						
						dba1d0548e
	
				 | 
					
					
						|||
| 
						
						
							
						
						507bd5c6b5
	
				 | 
					
					
						|||
| 
						
						
							
						
						9f63d9ed0f
	
				 | 
					
					
						|||
| 
						
						
							
						
						97dad842ea
	
				 | 
					
					
						|||
| 
						
						
							
						
						d08980c8d1
	
				 | 
					
					
						|||
| 
						
						
							
						
						da6f8511a8
	
				 | 
					
					
						|||
| 
						
						
							
						
						9690359dfa
	
				 | 
					
					
						|||
| 
						
						
							
						
						2ad82e8cc1
	
				 | 
					
					
						|||
| 
						
						
							
						
						169bf3c140
	
				 | 
					
					
						|||
| 
						
						
							
						
						9cdef5f951
	
				 | 
					
					
						|||
| 
						
						
							
						
						df529be2ce
	
				 | 
					
					
						|||
| 
						
						
							
						
						d87cd0c685
	
				 | 
					
					
						|||
| 
						
						
							
						
						7a5db59ac2
	
				 | 
					
					
						|||
| 
						
						
							
						
						4028cc8a8b
	
				 | 
					
					
						|||
| 
						
						
							
						
						48cd8aaa9f
	
				 | 
					
					
						|||
| 
						
						
							
						
						d048ee3b44
	
				 | 
					
					
						|||
| 
						
						
							
						
						aa553db659
	
				 | 
					
					
						|||
| 
						
						
							
						
						e45430f0c9
	
				 | 
					
					
						|||
| 
						
						
							
						
						13abc36529
	
				 | 
					
					
						|||
| 
						
						
							
						
						023a29cb78
	
				 | 
					
					
						|||
| 
						
						
							
						
						7b637d1287
	
				 | 
					
					
						|||
| 
						
						
							
						
						74ed34ba97
	
				 | 
					
					
						|||
| 
						
						
							
						
						6e6f19c499
	
				 | 
					
					
						|||
| 
						
						
							
						
						075aca493b
	
				 | 
					
					
						|||
| 
						
						
							
						
						224c2c74e8
	
				 | 
					
					
						|||
| 
						 | 
					80ea4bbdd2 | ||
| 
						 | 
					801c693ef9 | ||
| 
						 | 
					c1c9562e67 | ||
| 
						 | 
					b9e580af9a | ||
| 
						 | 
					790c7f6724 | ||
| 
						 | 
					1be91bb392 | ||
| 
						 | 
					93f39ebe5b | ||
| 
						
						
							
						
						efaa01f4f6
	
				 | 
					
					
						|||
| 
						
						
							
						
						f04ef9c931
	
				 | 
					
					
						|||
| 
						 | 
					176c3c0e27 | ||
| 
						 | 
					59cd8466be | ||
| 
						 | 
					ef9e872394 | ||
| 
						 | 
					51a46ab5d7 | ||
| 
						 | 
					191b416c6c | ||
| 
						
						
							
						
						9252e92da0
	
				 | 
					
					
						|||
| 
						
						
							
						
						4ab4554e63
	
				 | 
					
					
						|||
| 
						
						
							
						
						6d63177ff4
	
				 | 
					
					
						|||
| 
						
						
							
						
						81e8928344
	
				 | 
					
					
						|||
| 
						
						
							
						
						737f5f9275
	
				 | 
					
					
						|||
| 
						
						
							
						
						07c681fcec
	
				 | 
					
					
						|||
| 
						
						
							
						
						1c7d90a6ef
	
				 | 
					
					
						|||
| 
						
						
							
						
						24c33b306b
	
				 | 
					
					
						|||
| 
						
						
							
						
						7e19419861
	
				 | 
					
					
						|||
| 
						
						
							
						
						c35994203d
	
				 | 
					
					
						|||
| 
						
						
							
						
						9027cbd196
	
				 | 
					
					
						|||
| 
						
						
							
						
						dde3002100
	
				 | 
					
					
						|||
| 
						
						
							
						
						d8870e906f
	
				 | 
					
					
						|||
| 6028efdc7c | |||
| 
						 | 
					60c9e037a6 | 
							
								
								
									
										23
									
								
								.changes/v2.9.0.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								.changes/v2.9.0.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
## v2.9.0 - 2023-10-17
 | 
			
		||||
### Feature
 | 
			
		||||
* ([#147](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/147)) Add history to scopes and to jobs in administrator section. When user job or main scope of user is changed, automaticaly add a new row in history.
 | 
			
		||||
* ([#146](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/146)) Allow closing motives to be identified as 'canceling the accompanying period' + don't take canceled accompanying periods into account
 | 
			
		||||
* [export] add an aggregator for activities: group by job scope's creator aggregator
 | 
			
		||||
* DX: prepare the code for the upgrade to symfony 5.4
 | 
			
		||||
 | 
			
		||||
### Traductions francophones des principaux changements
 | 
			
		||||
 | 
			
		||||
- ajout de l'historique des services et métiers pour les utilisateurs. Les exports, filtres et regroupements sont adaptés pour tenir compte du métier et du service
 | 
			
		||||
  de l'utilisateur au moment de l'échange, de sa désignation comme agent traitant de l'échange ou du moment du rendez-vous ([#147](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/147)))
 | 
			
		||||
- modification des motifs de cloture des parcours: ajout d'un chanmp "annule le parcours", qui permet d'indiquer que le motif "annule" le parcours. Les parcours annulés n'apparaissent
 | 
			
		||||
  pas dans les statistiques
 | 
			
		||||
- ajouter d'un regroupement pour les échanges: grouper par métier et service du créateur de l'échange
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Possible BC break in configuration
 | 
			
		||||
 | 
			
		||||
This release remove the use of deprecated package [symfony/templating](https://symfony.com/components/Templating).
 | 
			
		||||
 | 
			
		||||
If you use this package in your own bundle (usually `src/` directory, or other dependencies), you should add this dependencies in your local composer.json (`composer require symfony/templating`).
 | 
			
		||||
 | 
			
		||||
But if you do not need this any more, you must ensure that the configuration key `framework.templating` is removed. This is usually located into `config/packages/framework.yaml`. [See here an example](https://gitea.champs-libres.be/Chill-project/chill-skeleton-basic/commit/cc716beaecc239e6a189f3db62ea95f169a37505#diff-df607fe73ff82c569824a7392edf5e760e998efe)
 | 
			
		||||
							
								
								
									
										3
									
								
								.changes/v2.9.1.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.changes/v2.9.1.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
## v2.9.1 - 2023-10-17
 | 
			
		||||
### Fixed
 | 
			
		||||
* Fix the handling of activity form when editing or creating an activity in an accompanying period with multiple centers 
 | 
			
		||||
							
								
								
									
										3
									
								
								.changes/v2.9.2.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.changes/v2.9.2.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
## v2.9.2 - 2023-10-17
 | 
			
		||||
### Fixed
 | 
			
		||||
* Fix possible null values in string's entities 
 | 
			
		||||
							
								
								
									
										36
									
								
								.env.test
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								.env.test
									
									
									
									
									
								
							@@ -3,3 +3,39 @@
 | 
			
		||||
# Run tests from root to adapt your own environment
 | 
			
		||||
KERNEL_CLASS='App\Kernel'
 | 
			
		||||
APP_SECRET='$ecretf0rt3st'
 | 
			
		||||
 | 
			
		||||
ADMIN_PASSWORD=password
 | 
			
		||||
 | 
			
		||||
LOCALE=fr
 | 
			
		||||
REDIS_URL=redis
 | 
			
		||||
REDIS_PORT=6379
 | 
			
		||||
REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT}
 | 
			
		||||
 | 
			
		||||
JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
 | 
			
		||||
JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
 | 
			
		||||
JWT_PASSPHRASE=2a30f6ba26521a2613821da35f28386e
 | 
			
		||||
 | 
			
		||||
TWILIO_SID=~
 | 
			
		||||
TWILIO_SECRET=~
 | 
			
		||||
DEFAULT_CARRIER_CODE=BE
 | 
			
		||||
 | 
			
		||||
ADD_ADDRESS_DEFAULT_COUNTRY=BE
 | 
			
		||||
 | 
			
		||||
ADD_ADDRESS_MAP_CENTER_X=50.8443
 | 
			
		||||
ADD_ADDRESS_MAP_CENTER_Y=4.3523
 | 
			
		||||
ADD_ADDRESS_MAP_CENTER_Z=15
 | 
			
		||||
 | 
			
		||||
SHORT_MESSAGE_DSN=null://null
 | 
			
		||||
MESSENGER_TRANSPORT_DSN=sync://
 | 
			
		||||
###< symfony/messenger ###
 | 
			
		||||
 | 
			
		||||
###> doctrine/doctrine-bundle ###
 | 
			
		||||
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
 | 
			
		||||
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
 | 
			
		||||
#
 | 
			
		||||
DATABASE_URL="postgresql://postgres:postgres@db:5432/test?serverVersion=14&charset=utf8"
 | 
			
		||||
###< doctrine/doctrine-bundle ###
 | 
			
		||||
 | 
			
		||||
ASYNC_UPLOAD_TEMP_URL_KEY=
 | 
			
		||||
ASYNC_UPLOAD_TEMP_URL_BASE_PATH=
 | 
			
		||||
ASYNC_UPLOAD_TEMP_URL_CONTAINER=
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
# Select what we should cache between builds
 | 
			
		||||
cache:
 | 
			
		||||
    paths:
 | 
			
		||||
        - tests/app/vendor/
 | 
			
		||||
        - /vendor/
 | 
			
		||||
        - .cache
 | 
			
		||||
 | 
			
		||||
# Bring in any services we need http://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-a-service
 | 
			
		||||
@@ -23,12 +23,10 @@ variables:
 | 
			
		||||
    # configure database access
 | 
			
		||||
    DATABASE_URL: postgresql://postgres:postgres@db:5432/postgres?serverVersion=14&charset=utf8
 | 
			
		||||
    # fetch the chill-app using git submodules
 | 
			
		||||
    GIT_SUBMODULE_STRATEGY: recursive
 | 
			
		||||
    # GIT_SUBMODULE_STRATEGY: recursive
 | 
			
		||||
    REDIS_HOST: redis
 | 
			
		||||
    REDIS_PORT: 6379
 | 
			
		||||
    REDIS_URL: redis://redis:6379
 | 
			
		||||
    # change vendor dir to make the app install into tests/apps
 | 
			
		||||
    COMPOSER_VENDOR_DIR: tests/app/vendor
 | 
			
		||||
    DEFAULT_CARRIER_CODE: BE
 | 
			
		||||
 | 
			
		||||
stages:
 | 
			
		||||
@@ -50,7 +48,7 @@ build:
 | 
			
		||||
        expire_in: 30 min
 | 
			
		||||
        paths:
 | 
			
		||||
            - bin
 | 
			
		||||
            - tests/app/vendor/
 | 
			
		||||
            - vendor/
 | 
			
		||||
 | 
			
		||||
code_style:
 | 
			
		||||
    stage: Tests
 | 
			
		||||
@@ -64,7 +62,7 @@ code_style:
 | 
			
		||||
        expire_in: 30 min
 | 
			
		||||
        paths:
 | 
			
		||||
            - bin
 | 
			
		||||
            - tests/app/vendor/
 | 
			
		||||
            - vendor/
 | 
			
		||||
 | 
			
		||||
phpstan_tests:
 | 
			
		||||
    stage: Tests
 | 
			
		||||
@@ -78,13 +76,14 @@ phpstan_tests:
 | 
			
		||||
        expire_in: 30 min
 | 
			
		||||
        paths:
 | 
			
		||||
            - bin
 | 
			
		||||
            - tests/app/vendor/
 | 
			
		||||
            - vendor/
 | 
			
		||||
 | 
			
		||||
rector_tests:
 | 
			
		||||
    stage: Tests
 | 
			
		||||
    image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82
 | 
			
		||||
    script:
 | 
			
		||||
        - bin/rector --dry-run
 | 
			
		||||
        - tests/console cache:clear
 | 
			
		||||
        - bin/rector process --dry-run
 | 
			
		||||
    cache:
 | 
			
		||||
        paths:
 | 
			
		||||
            - .cache/
 | 
			
		||||
@@ -92,7 +91,7 @@ rector_tests:
 | 
			
		||||
        expire_in: 30 min
 | 
			
		||||
        paths:
 | 
			
		||||
            - bin
 | 
			
		||||
            - tests/app/vendor/
 | 
			
		||||
            - vendor/
 | 
			
		||||
 | 
			
		||||
# psalm_tests:
 | 
			
		||||
#     stage: Tests
 | 
			
		||||
@@ -109,19 +108,17 @@ rector_tests:
 | 
			
		||||
unit_tests:
 | 
			
		||||
    stage: Tests
 | 
			
		||||
    image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82
 | 
			
		||||
    # until we fix testes
 | 
			
		||||
    allow_failure: true
 | 
			
		||||
    script:
 | 
			
		||||
        - php tests/app/bin/console doctrine:migrations:migrate -n
 | 
			
		||||
        - php -d memory_limit=2G tests/app/bin/console cache:clear --env=dev
 | 
			
		||||
        - php -d memory_limit=3G tests/app/bin/console doctrine:fixtures:load -n
 | 
			
		||||
        - php -d memory_limit=2G tests/app/bin/console cache:clear --env=test
 | 
			
		||||
        - php -d memory_limit=4G bin/phpunit --colors=never
 | 
			
		||||
        - php tests/console doctrine:migrations:migrate -n --env=test
 | 
			
		||||
        - 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
 | 
			
		||||
        - php -d memory_limit=4G bin/phpunit --colors=never --exclude-group dbIntensive
 | 
			
		||||
    artifacts:
 | 
			
		||||
        expire_in: 30 min
 | 
			
		||||
        paths:
 | 
			
		||||
            - bin
 | 
			
		||||
            - tests/app/vendor/
 | 
			
		||||
            - vendor/
 | 
			
		||||
 | 
			
		||||
release:
 | 
			
		||||
    stage: Deploy
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -1,6 +1,3 @@
 | 
			
		||||
[submodule "_exts/sphinx-php"]
 | 
			
		||||
	path = _exts/sphinx-php
 | 
			
		||||
	url = https://github.com/fabpot/sphinx-php.git
 | 
			
		||||
[submodule "tests/app"]
 | 
			
		||||
	path = tests/app
 | 
			
		||||
	url = https://gitlab.com/Chill-projet/chill-app.git
 | 
			
		||||
 
 | 
			
		||||
@@ -91,7 +91,7 @@ $rules = array_merge(
 | 
			
		||||
    [
 | 
			
		||||
        '@PhpCsFixer' => true,
 | 
			
		||||
        '@PhpCsFixer:risky' => false,
 | 
			
		||||
        '@Symfony' => false,
 | 
			
		||||
        '@Symfony' => true,
 | 
			
		||||
        '@Symfony:risky' => false,
 | 
			
		||||
        'ordered_class_elements' => [
 | 
			
		||||
            'order' => [
 | 
			
		||||
@@ -111,13 +111,13 @@ $rules = array_merge(
 | 
			
		||||
                'method_private',
 | 
			
		||||
            ],
 | 
			
		||||
            'sort_algorithm' => 'alpha',
 | 
			
		||||
        ]
 | 
			
		||||
        ],
 | 
			
		||||
    ],
 | 
			
		||||
    $rules,
 | 
			
		||||
    $riskyRules,
 | 
			
		||||
    $untilFullSwitchToPhp8,
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
$rules['header_comment']['header'] = trim(file_get_contents(__DIR__ . '/resource/header.txt'));
 | 
			
		||||
$rules['header_comment']['header'] = trim(file_get_contents(__DIR__.'/resource/header.txt'));
 | 
			
		||||
 | 
			
		||||
return $config->setRules($rules);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -6,6 +6,38 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
 | 
			
		||||
and is generated by [Changie](https://github.com/miniscruff/changie).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## v2.9.2 - 2023-10-17
 | 
			
		||||
### Fixed
 | 
			
		||||
* Fix possible null values in string's entities 
 | 
			
		||||
 | 
			
		||||
## v2.9.1 - 2023-10-17
 | 
			
		||||
### Fixed
 | 
			
		||||
* Fix the handling of activity form when editing or creating an activity in an accompanying period with multiple centers 
 | 
			
		||||
 | 
			
		||||
## v2.9.0 - 2023-10-17
 | 
			
		||||
### Feature
 | 
			
		||||
* ([#147](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/147)) Add history to scopes and to jobs in administrator section. When user job or main scope of user is changed, automaticaly add a new row in history.
 | 
			
		||||
* ([#146](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/146)) Allow closing motives to be identified as 'canceling the accompanying period' + don't take canceled accompanying periods into account
 | 
			
		||||
* [export] add an aggregator for activities: group by job scope's creator aggregator
 | 
			
		||||
* DX: prepare the code for the upgrade to symfony 5.4
 | 
			
		||||
 | 
			
		||||
### Traductions francophones des principaux changements
 | 
			
		||||
 | 
			
		||||
- ajout de l'historique des services et métiers pour les utilisateurs. Les exports, filtres et regroupements sont adaptés pour tenir compte du métier et du service
 | 
			
		||||
  de l'utilisateur au moment de l'échange, de sa désignation comme agent traitant de l'échange ou du moment du rendez-vous ([#147](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/147)))
 | 
			
		||||
- modification des motifs de cloture des parcours: ajout d'un chanmp "annule le parcours", qui permet d'indiquer que le motif "annule" le parcours. Les parcours annulés n'apparaissent
 | 
			
		||||
  pas dans les statistiques
 | 
			
		||||
- ajouter d'un regroupement pour les échanges: grouper par métier et service du créateur de l'échange
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Possible BC break in configuration
 | 
			
		||||
 | 
			
		||||
This release remove the use of deprecated package [symfony/templating](https://symfony.com/components/Templating).
 | 
			
		||||
 | 
			
		||||
If you use this package in your own bundle (usually `src/` directory, or other dependencies), you should add this dependencies in your local composer.json (`composer require symfony/templating`).
 | 
			
		||||
 | 
			
		||||
But if you do not need this any more, you must ensure that the configuration key `framework.templating` is removed. This is usually located into `config/packages/framework.yaml`. [See here an example](https://gitea.champs-libres.be/Chill-project/chill-skeleton-basic/commit/cc716beaecc239e6a189f3db62ea95f169a37505#diff-df607fe73ff82c569824a7392edf5e760e998efe)
 | 
			
		||||
 | 
			
		||||
## v2.8.0 - 2023-10-05
 | 
			
		||||
 | 
			
		||||
### Feature
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
        "social worker"
 | 
			
		||||
    ],
 | 
			
		||||
    "require": {
 | 
			
		||||
        "php": "^7.4|^8.2",
 | 
			
		||||
        "php": "^8.2",
 | 
			
		||||
        "ext-json": "*",
 | 
			
		||||
        "ext-openssl": "*",
 | 
			
		||||
        "ext-redis": "*",
 | 
			
		||||
@@ -48,7 +48,6 @@
 | 
			
		||||
        "symfony/monolog-bundle": "^3.5",
 | 
			
		||||
        "symfony/security-bundle": "^4.4",
 | 
			
		||||
        "symfony/serializer": "^5.3",
 | 
			
		||||
        "symfony/templating": "^4.4",
 | 
			
		||||
        "symfony/translation": "^4.4",
 | 
			
		||||
        "symfony/twig-bundle": "^4.4",
 | 
			
		||||
        "symfony/validator": "^4.4",
 | 
			
		||||
@@ -76,7 +75,7 @@
 | 
			
		||||
        "phpunit/phpunit": ">= 7.5",
 | 
			
		||||
        "psalm/plugin-phpunit": "^0.18.4",
 | 
			
		||||
        "psalm/plugin-symfony": "^4.0.2",
 | 
			
		||||
        "rector/rector": "^0.15.23",
 | 
			
		||||
        "rector/rector": "^0.17.7",
 | 
			
		||||
        "symfony/debug-bundle": "^5.1",
 | 
			
		||||
        "symfony/dotenv": "^4.4",
 | 
			
		||||
        "symfony/maker-bundle": "^1.20",
 | 
			
		||||
@@ -98,7 +97,6 @@
 | 
			
		||||
            "Chill\\DocGeneratorBundle\\": "src/Bundle/ChillDocGeneratorBundle",
 | 
			
		||||
            "Chill\\DocStoreBundle\\": "src/Bundle/ChillDocStoreBundle",
 | 
			
		||||
            "Chill\\EventBundle\\": "src/Bundle/ChillEventBundle",
 | 
			
		||||
            "Chill\\FamilyMemberBundle\\": "src/Bundle/ChillFamilyMemberBundle",
 | 
			
		||||
            "Chill\\MainBundle\\": "src/Bundle/ChillMainBundle",
 | 
			
		||||
            "Chill\\PersonBundle\\": "src/Bundle/ChillPersonBundle",
 | 
			
		||||
            "Chill\\ReportBundle\\": "src/Bundle/ChillReportBundle",
 | 
			
		||||
@@ -110,7 +108,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "autoload-dev": {
 | 
			
		||||
        "psr-4": {
 | 
			
		||||
            "App\\": "tests/app/src/",
 | 
			
		||||
            "App\\": "tests/",
 | 
			
		||||
            "Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests",
 | 
			
		||||
            "Chill\\WopiBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests",
 | 
			
		||||
            "Chill\\Utils\\Rector\\Tests\\": "utils/rector/tests"
 | 
			
		||||
@@ -128,12 +126,10 @@
 | 
			
		||||
        },
 | 
			
		||||
        "bin-dir": "bin",
 | 
			
		||||
        "optimize-autoloader": true,
 | 
			
		||||
        "sort-packages": true,
 | 
			
		||||
        "vendor-dir": "tests/app/vendor"
 | 
			
		||||
        "sort-packages": true
 | 
			
		||||
    },
 | 
			
		||||
    "scripts": {
 | 
			
		||||
        "auto-scripts": {
 | 
			
		||||
            "assets:install %PUBLIC_DIR%": "symfony-cmd",
 | 
			
		||||
            "cache:clear": "symfony-cmd"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -54,18 +54,9 @@ class CountPerson implements ExportInterface
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        // the Closure which will be executed by the formatter.
 | 
			
		||||
        return function ($value) {
 | 
			
		||||
            switch ($value) {
 | 
			
		||||
                case '_header':
 | 
			
		||||
                    // we have to process specifically the '_header' string,
 | 
			
		||||
                    // which will be used by the formatter to show a column title
 | 
			
		||||
                    return $this->getTitle();
 | 
			
		||||
 | 
			
		||||
                default:
 | 
			
		||||
                    // for all value, we do not process them and return them
 | 
			
		||||
                    // immediatly
 | 
			
		||||
                    return $value;
 | 
			
		||||
            }
 | 
			
		||||
        return fn($value) => match ($value) {
 | 
			
		||||
            '_header' => $this->getTitle(),
 | 
			
		||||
            default => $value,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ namespace Chill\MyBundle\Controller;
 | 
			
		||||
 | 
			
		||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
 | 
			
		||||
 | 
			
		||||
class example extends Controller
 | 
			
		||||
class example extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController
 | 
			
		||||
{
 | 
			
		||||
    public function yourAction()
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ use Chill\PersonBundle\Security\Authorization\PersonVoter;
 | 
			
		||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
 | 
			
		||||
use Symfony\Component\Security\Core\Role\Role;
 | 
			
		||||
 | 
			
		||||
class ConsultationController extends Controller
 | 
			
		||||
class ConsultationController extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @param int $id personId
 | 
			
		||||
@@ -43,7 +43,7 @@ class ConsultationController extends Controller
 | 
			
		||||
 | 
			
		||||
        $circles = $authorizationHelper->getReachableCircles(
 | 
			
		||||
            $this->getUser(),
 | 
			
		||||
            new Role(ConsultationVoter::SEE),
 | 
			
		||||
            ConsultationVoter::SEE,
 | 
			
		||||
            $person->getCenter()
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,25 +23,18 @@ class ChillMainConfiguration implements ConfigurationInterface
 | 
			
		||||
{
 | 
			
		||||
    use AddWidgetConfigurationTrait;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var ContainerBuilder
 | 
			
		||||
     */
 | 
			
		||||
    private $containerBuilder;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        array $widgetFactories,
 | 
			
		||||
        ContainerBuilder $containerBuilder
 | 
			
		||||
        private readonly ContainerBuilder $containerBuilder
 | 
			
		||||
    ) {
 | 
			
		||||
        // we register here widget factories (see below)
 | 
			
		||||
        $this->setWidgetFactories($widgetFactories);
 | 
			
		||||
        // we will need the container builder later...
 | 
			
		||||
        $this->containerBuilder = $containerBuilder;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getConfigTreeBuilder()
 | 
			
		||||
    {
 | 
			
		||||
        $treeBuilder = new TreeBuilder();
 | 
			
		||||
        $rootNode = $treeBuilder->root('chill_main');
 | 
			
		||||
        $treeBuilder = new TreeBuilder('chill_main');
 | 
			
		||||
        $rootNode = $treeBuilder->getRootNode();
 | 
			
		||||
 | 
			
		||||
        $rootNode
 | 
			
		||||
            ->children()
 | 
			
		||||
 
 | 
			
		||||
@@ -87,7 +87,7 @@ class ChillPersonAddAPersonWidget implements WidgetInterface
 | 
			
		||||
        // show only the person from the authorized centers
 | 
			
		||||
        $and = $qb->expr()->andX();
 | 
			
		||||
        $centers = $this->authorizationHelper
 | 
			
		||||
            ->getReachableCenters($this->getUser(), new Role(PersonVoter::SEE));
 | 
			
		||||
            ->getReachableCenters($this->getUser(), PersonVoter::SEE);
 | 
			
		||||
        $and->add($qb->expr()->in('person.center', ':centers'));
 | 
			
		||||
        $qb->setParameter('centers', $centers);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,63 +0,0 @@
 | 
			
		||||
Entity,Join,Attribute,Alias
 | 
			
		||||
AccompanyingPeriod::class,,,acp
 | 
			
		||||
,AccompanyingPeriodWork::class,acp.works,acpw
 | 
			
		||||
,AccompanyingPeriodParticipation::class,acp.participations,acppart
 | 
			
		||||
,Location::class,acp.administrativeLocation,acploc
 | 
			
		||||
,ClosingMotive::class,acp.closingMotive,acpmotive
 | 
			
		||||
,UserJob::class,acp.job,acpjob
 | 
			
		||||
,Origin::class,acp.origin,acporigin
 | 
			
		||||
,Scope::class,acp.scopes,acpscope
 | 
			
		||||
,SocialIssue::class,acp.socialIssues,acpsocialissue
 | 
			
		||||
,User::class,acp.user,acpuser
 | 
			
		||||
AccompanyingPeriodWork::class,,,acpw
 | 
			
		||||
,AccompanyingPeriodWorkEvaluation::class,acpw.accompanyingPeriodWorkEvaluations,workeval
 | 
			
		||||
,User::class,acpw.referrers,acpwuser
 | 
			
		||||
,SocialAction::class,acpw.socialAction,acpwsocialaction
 | 
			
		||||
,Goal::class,acpw.goals,goal
 | 
			
		||||
,Result::class,acpw.results,result
 | 
			
		||||
AccompanyingPeriodParticipation::class,,,acppart
 | 
			
		||||
,Person::class,acppart.person,partperson
 | 
			
		||||
AccompanyingPeriodWorkEvaluation::class,,,workeval
 | 
			
		||||
,Evaluation::class,workeval.evaluation,eval
 | 
			
		||||
Goal::class,,,goal
 | 
			
		||||
,Result::class,goal.results,goalresult
 | 
			
		||||
Person::class,,,person
 | 
			
		||||
,Center::class,person.center,center
 | 
			
		||||
,HouseholdMember::class,partperson.householdParticipations,householdmember
 | 
			
		||||
,MaritalStatus::class,person.maritalStatus,personmarital
 | 
			
		||||
,VendeePerson::class,,vp
 | 
			
		||||
,VendeePersonMineur::class,,vpm
 | 
			
		||||
ResidentialAddress::class,,,resaddr
 | 
			
		||||
,ThirdParty::class,resaddr.hostThirdParty,tparty
 | 
			
		||||
ThirdParty::class,,,tparty
 | 
			
		||||
,ThirdPartyCategory::class,tparty.categories,tpartycat
 | 
			
		||||
HouseholdMember::class,,,householdmember
 | 
			
		||||
,Household::class,householdmember.household,household
 | 
			
		||||
,Person::class,householdmember.person,memberperson
 | 
			
		||||
,,memberperson.center,membercenter
 | 
			
		||||
Household::class,,,household
 | 
			
		||||
,HouseholdComposition::class,household.compositions,composition
 | 
			
		||||
Activity::class,,,activity
 | 
			
		||||
,Person::class,activity.person,actperson
 | 
			
		||||
,AccompanyingPeriod::class,activity.accompanyingPeriod,acp
 | 
			
		||||
,Person::class,activity_person_having_activity.person,person_person_having_activity
 | 
			
		||||
,ActivityReason::class,activity_person_having_activity.reasons,reasons_person_having_activity
 | 
			
		||||
,ActivityType::class,activity.activityType,acttype
 | 
			
		||||
,Location::class,activity.location,actloc
 | 
			
		||||
,SocialAction::class,activity.socialActions,actsocialaction
 | 
			
		||||
,SocialIssue::class,activity.socialIssues,actsocialssue
 | 
			
		||||
,ThirdParty::class,activity.thirdParties,acttparty
 | 
			
		||||
,User::class,activity.user,actuser
 | 
			
		||||
,User::class,activity.users,actusers
 | 
			
		||||
,ActivityReason::class,activity.reasons,actreasons
 | 
			
		||||
,Center::class,actperson.center,actcenter
 | 
			
		||||
ActivityReason::class,,,actreasons
 | 
			
		||||
,ActivityReasonCategory::class,actreason.category,actreasoncat
 | 
			
		||||
Calendar::class,,,cal
 | 
			
		||||
,CancelReason::class,cal.cancelReason,calcancel
 | 
			
		||||
,Location::class,cal.location,calloc
 | 
			
		||||
,User::class,cal.user,caluser
 | 
			
		||||
VendeePerson::class,,,vp
 | 
			
		||||
,SituationProfessionelle::class,vp.situationProfessionelle,vpprof
 | 
			
		||||
,StatutLogement::class,vp.statutLogement,vplog
 | 
			
		||||
,TempsDeTravail::class,vp.tempsDeTravail,vptt
 | 
			
		||||
		
		
			
  | 
@@ -21,7 +21,6 @@ These are alias conventions :
 | 
			
		||||
|                                         | AccompanyingPeriodInfo::class           | not existing (using custom WITH clause)    | acpinfo                                |
 | 
			
		||||
| AccompanyingPeriodWork::class           |                                         |                                            | acpw                                   |
 | 
			
		||||
|                                         | AccompanyingPeriodWorkEvaluation::class | acpw.accompanyingPeriodWorkEvaluations     | workeval                               |
 | 
			
		||||
|                                         | User::class                             | acpw.referrers                             | acpwuser                               |
 | 
			
		||||
|                                         | SocialAction::class                     | acpw.socialAction                          | acpwsocialaction                       |
 | 
			
		||||
|                                         | Goal::class                             | acpw.goals                                 | goal                                   |
 | 
			
		||||
|                                         | Result::class                           | acpw.results                               | result                                 |
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,9 @@
 | 
			
		||||
    "typescript": "^4.7.2",
 | 
			
		||||
    "vue-loader": "^17.0.0",
 | 
			
		||||
    "webpack": "^5.75.0",
 | 
			
		||||
    "webpack-cli": "^5.0.1"
 | 
			
		||||
    "webpack-cli": "^5.0.1",
 | 
			
		||||
      "chart.js": "^4.2.1",
 | 
			
		||||
      "vue-chartjs": "^5.2.0"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@fullcalendar/core": "^6.1.4",
 | 
			
		||||
 
 | 
			
		||||
@@ -2,26 +2,51 @@
 | 
			
		||||
 | 
			
		||||
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
 | 
			
		||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 | 
			
		||||
         xsi:noNamespaceSchemaLocation="tests/app/vendor/phpunit/phpunit/phpunit.xsd"
 | 
			
		||||
         xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
 | 
			
		||||
         backupGlobals="false"
 | 
			
		||||
         colors="true"
 | 
			
		||||
         bootstrap="tests/app/tests/bootstrap.php"
 | 
			
		||||
         bootstrap="tests/bootstrap.php"
 | 
			
		||||
>
 | 
			
		||||
    <php>
 | 
			
		||||
        <ini name="error_reporting" value="-1" />
 | 
			
		||||
        <server name="APP_ENV" value="test" force="true" />
 | 
			
		||||
        <env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
 | 
			
		||||
        <env name="SYMFONY_DEPRECATIONS_HELPER" value="max[direct]=0&max[indirect]=999999" />
 | 
			
		||||
        <server name="SHELL_VERBOSITY" value="-1" />
 | 
			
		||||
        <env name="KERNEL_CLASS" value="\App\Kernel" />
 | 
			
		||||
    </php>
 | 
			
		||||
 | 
			
		||||
    <testsuites>
 | 
			
		||||
        <!--
 | 
			
		||||
        <testsuite name="ActivityBundle">
 | 
			
		||||
            <directory suffix="Test.php">src/Bundle/ChillActivityBundle/Tests/</directory>
 | 
			
		||||
        </testsuite>
 | 
			
		||||
        -->
 | 
			
		||||
        <testsuite name="AsideActivityBundle">
 | 
			
		||||
            <directory suffix="Test.php">src/Bundle/ChillAsideActivityBundle/src/Tests/</directory>
 | 
			
		||||
        </testsuite>
 | 
			
		||||
        <testsuite name="BudgetBundle">
 | 
			
		||||
            <directory suffix="Test.php">src/Bundle/ChillBudgetBundle/Tests/</directory>
 | 
			
		||||
        </testsuite>
 | 
			
		||||
        <testsuite name="CalendarBundle">
 | 
			
		||||
            <directory suffix="Test.php">src/Bundle/ChillCalendarBundle/Tests/</directory>
 | 
			
		||||
        </testsuite>
 | 
			
		||||
        <!-- Missing CustomFieldBundle -->
 | 
			
		||||
        <testsuite name="DocGeneratorBundle">
 | 
			
		||||
            <directory suffix="Test.php">src/Bundle/ChillDocGeneratorBundle/tests/</directory>
 | 
			
		||||
        </testsuite>
 | 
			
		||||
        <testsuite name="DocStoreBundle">
 | 
			
		||||
            <directory suffix="Test.php">src/Bundle/ChillDocStoreBundle/Tests/</directory>
 | 
			
		||||
        </testsuite>
 | 
			
		||||
        <!--
 | 
			
		||||
        <testsuite name="EventBundle">
 | 
			
		||||
            <directory suffix="Test.php">src/Bundle/ChillEventBundle/tests/</directory>
 | 
			
		||||
        </testsuite>
 | 
			
		||||
        -->
 | 
			
		||||
       <testsuite name="MainBundle">
 | 
			
		||||
         <directory suffix="Test.php">src/Bundle/ChillMainBundle/Tests/</directory>
 | 
			
		||||
       </testsuite>
 | 
			
		||||
       <testsuite name="PersonBundle">
 | 
			
		||||
         <directory suffix="Test.php">src/Bundle/ChillPersonBundle/Tests/</directory>
 | 
			
		||||
         <!-- test for export will be runned later -->
 | 
			
		||||
         <exclude>src/Bundle/ChillPersonBundle/Tests/Export/*</exclude>
 | 
			
		||||
         <!-- we are rewriting accompanying periods... Work in progress -->
 | 
			
		||||
         <exclude>src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingPeriodControllerTest.php</exclude>
 | 
			
		||||
         <!-- we are rewriting address, Work in progress -->
 | 
			
		||||
@@ -31,14 +56,18 @@
 | 
			
		||||
         <!-- temporarily removed, the time to find a fix -->
 | 
			
		||||
         <exclude>src/Bundle/ChillPersonBundle/Tests/Controller/PersonDuplicateControllerViewTest.php</exclude>
 | 
			
		||||
        </testsuite>
 | 
			
		||||
        <testsuite name="AsideActivityBundle">
 | 
			
		||||
          <directory suffix="Test.php">src/Bundle/ChillAsideActivityBundle/src/Tests/</directory>
 | 
			
		||||
        <!--
 | 
			
		||||
        <testsuite name="ReportBundle">
 | 
			
		||||
            <directory suffix="Test.php">src/Bundle/ChillReportBundle/Tests/</directory>
 | 
			
		||||
        </testsuite>
 | 
			
		||||
        <testsuite name="CalendarBundle">
 | 
			
		||||
            <directory suffix="Test.php">src/Bundle/ChillCalendarBundle/Tests/</directory>
 | 
			
		||||
        -->
 | 
			
		||||
        <!--
 | 
			
		||||
        <testsuite name="TaskBundle">
 | 
			
		||||
            <directory suffix="Test.php">src/Bundle/ChillTaskBundle/Tests</directory>
 | 
			
		||||
        </testsuite>
 | 
			
		||||
        <testsuite name="DocGeneratorBundle">
 | 
			
		||||
            <directory suffix="Test.php">src/Bundle/ChillDocGeneratorBundle/tests/</directory>
 | 
			
		||||
        -->
 | 
			
		||||
        <testsuite name="ThirdPartyBundle">
 | 
			
		||||
            <directory suffix="Test.php">src/Bundle/ChillThirdPartyBundle/Tests</directory>
 | 
			
		||||
        </testsuite>
 | 
			
		||||
        <testsuite name="WopiBundle">
 | 
			
		||||
            <directory suffix="Test.php">src/Bundle/ChillWopiBundle/tests/</directory>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										43
									
								
								rector.php
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								rector.php
									
									
									
									
									
								
							@@ -19,6 +19,9 @@ return static function (RectorConfig $rectorConfig): void {
 | 
			
		||||
        __DIR__ . '/src',
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    $rectorConfig->symfonyContainerXml(__DIR__ . '/var/cache/dev/testsApp_KernelDevDebugContainer.xml');
 | 
			
		||||
    $rectorConfig->symfonyContainerPhp(__DIR__ . '/tests/symfony-container.php');
 | 
			
		||||
 | 
			
		||||
    //$rectorConfig->cacheClass(\Rector\Caching\ValueObject\Storage\FileCacheStorage::class);
 | 
			
		||||
    //$rectorConfig->cacheDirectory(__DIR__ . '/.cache/rector');
 | 
			
		||||
 | 
			
		||||
@@ -28,43 +31,25 @@ return static function (RectorConfig $rectorConfig): void {
 | 
			
		||||
 | 
			
		||||
    //define sets of rules
 | 
			
		||||
    $rectorConfig->sets([
 | 
			
		||||
        LevelSetList::UP_TO_PHP_74
 | 
			
		||||
        LevelSetList::UP_TO_PHP_82,
 | 
			
		||||
        \Rector\Symfony\Set\SymfonyLevelSetList::UP_TO_SYMFONY_44,
 | 
			
		||||
        \Rector\Doctrine\Set\DoctrineSetList::DOCTRINE_CODE_QUALITY,
 | 
			
		||||
        \Rector\PHPUnit\Set\PHPUnitLevelSetList::UP_TO_PHPUNIT_90,
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    // some routes are added twice if it remains activated
 | 
			
		||||
    // $rectorConfig->rule(\Rector\Symfony\Configs\Rector\ClassMethod\AddRouteAnnotationRector::class);
 | 
			
		||||
 | 
			
		||||
    // chill rules
 | 
			
		||||
    $rectorConfig->rule(\Chill\Utils\Rector\Rector\ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector::class);
 | 
			
		||||
    //$rectorConfig->rule(\Chill\Utils\Rector\Rector\ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector::class);
 | 
			
		||||
 | 
			
		||||
    // skip some path...
 | 
			
		||||
    $rectorConfig->skip([
 | 
			
		||||
        // make rector stuck for some files
 | 
			
		||||
        \Rector\Php56\Rector\FunctionLike\AddDefaultValueForUndefinedVariableRector::class,
 | 
			
		||||
 | 
			
		||||
        // we need to discuss this: are we going to have FALSE in tests instead of an error ?
 | 
			
		||||
        \Rector\Php71\Rector\FuncCall\CountOnNullRector::class,
 | 
			
		||||
 | 
			
		||||
        // must merge MR500 and review a typing of "ArrayCollection" in entities
 | 
			
		||||
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
 | 
			
		||||
 | 
			
		||||
        // remove all PHP80 rules, in order to activate them one by one
 | 
			
		||||
        \Rector\Php80\Rector\ClassMethod\AddParamBasedOnParentClassMethodRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\Class_\AnnotationToAttributeRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\Class_\DoctrineAnnotationClassToAttributeRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\ClassMethod\FinalPrivateToPrivateVisibilityRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\Ternary\GetDebugTypeRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\Property\NestedAnnotationToAttributeRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\FuncCall\Php8ResourceReturnToObjectRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\ClassMethod\SetStateToStaticRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
 | 
			
		||||
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class
 | 
			
		||||
        // we must adapt service definition
 | 
			
		||||
        \Rector\Symfony\Symfony28\Rector\MethodCall\GetToConstructorInjectionRector::class,
 | 
			
		||||
        \Rector\Symfony\Symfony34\Rector\Closure\ContainerGetNameToTypeInTestsRector::class,
 | 
			
		||||
    ]);
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,6 @@ use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface;
 | 
			
		||||
use Chill\ActivityBundle\Repository\ActivityRepository;
 | 
			
		||||
use Chill\ActivityBundle\Repository\ActivityTypeCategoryRepository;
 | 
			
		||||
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
 | 
			
		||||
use Chill\ActivityBundle\Repository\ActivityUserJobRepository;
 | 
			
		||||
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
 | 
			
		||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
 | 
			
		||||
use Chill\MainBundle\Entity\UserJob;
 | 
			
		||||
@@ -35,11 +34,8 @@ use Chill\PersonBundle\Privacy\PrivacyEvent;
 | 
			
		||||
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
 | 
			
		||||
use Chill\PersonBundle\Repository\PersonRepository;
 | 
			
		||||
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
 | 
			
		||||
use DateTime;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
use InvalidArgumentException;
 | 
			
		||||
use Psr\Log\LoggerInterface;
 | 
			
		||||
use RuntimeException;
 | 
			
		||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 | 
			
		||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
 | 
			
		||||
@@ -49,7 +45,6 @@ use Symfony\Component\HttpFoundation\Request;
 | 
			
		||||
use Symfony\Component\HttpFoundation\Response;
 | 
			
		||||
use Symfony\Component\Serializer\SerializerInterface;
 | 
			
		||||
use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
use function array_key_exists;
 | 
			
		||||
 | 
			
		||||
final class ActivityController extends AbstractController
 | 
			
		||||
{
 | 
			
		||||
@@ -77,9 +72,9 @@ final class ActivityController extends AbstractController
 | 
			
		||||
    /**
 | 
			
		||||
     * Deletes a Activity entity.
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $id
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/{id}/delete", name="chill_activity_activity_delete", methods={"GET", "POST", "DELETE"})
 | 
			
		||||
     */
 | 
			
		||||
    public function deleteAction(Request $request, $id)
 | 
			
		||||
    public function deleteAction(Request $request, mixed $id)
 | 
			
		||||
    {
 | 
			
		||||
        $view = null;
 | 
			
		||||
 | 
			
		||||
@@ -92,10 +87,10 @@ final class ActivityController extends AbstractController
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($activity->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
 | 
			
		||||
            $view = 'ChillActivityBundle:Activity:confirm_deleteAccompanyingCourse.html.twig';
 | 
			
		||||
            $view = '@ChillActivity/Activity/confirm_deleteAccompanyingCourse.html.twig';
 | 
			
		||||
            $accompanyingPeriod = $activity->getAccompanyingPeriod();
 | 
			
		||||
        } else {
 | 
			
		||||
            $view = 'ChillActivityBundle:Activity:confirm_deletePerson.html.twig';
 | 
			
		||||
            $view = '@ChillActivity/Activity/confirm_deletePerson.html.twig';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO
 | 
			
		||||
@@ -103,7 +98,7 @@ final class ActivityController extends AbstractController
 | 
			
		||||
 | 
			
		||||
        $form = $this->createDeleteForm($activity->getId(), $person, $accompanyingPeriod);
 | 
			
		||||
 | 
			
		||||
        if ($request->getMethod() === Request::METHOD_DELETE) {
 | 
			
		||||
        if (Request::METHOD_DELETE === $request->getMethod()) {
 | 
			
		||||
            $form->handleRequest($request);
 | 
			
		||||
 | 
			
		||||
            if ($form->isValid()) {
 | 
			
		||||
@@ -136,10 +131,6 @@ final class ActivityController extends AbstractController
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (null === $view) {
 | 
			
		||||
            throw $this->createNotFoundException('Template not found');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->render($view, [
 | 
			
		||||
            'activity' => $activity,
 | 
			
		||||
            'delete_form' => $form->createView(),
 | 
			
		||||
@@ -150,6 +141,8 @@ final class ActivityController extends AbstractController
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Displays a form to edit an existing Activity entity.
 | 
			
		||||
     *
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/{id}/edit", name="chill_activity_activity_edit", methods={"GET", "POST", "PUT"})
 | 
			
		||||
     */
 | 
			
		||||
    public function editAction(int $id, Request $request): Response
 | 
			
		||||
    {
 | 
			
		||||
@@ -165,10 +158,10 @@ final class ActivityController extends AbstractController
 | 
			
		||||
        $person = $entity->getPerson();
 | 
			
		||||
 | 
			
		||||
        if ($entity->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
 | 
			
		||||
            $view = 'ChillActivityBundle:Activity:editAccompanyingCourse.html.twig';
 | 
			
		||||
            $view = '@ChillActivity/Activity/editAccompanyingCourse.html.twig';
 | 
			
		||||
            $accompanyingPeriod = $entity->getAccompanyingPeriod();
 | 
			
		||||
        } else {
 | 
			
		||||
            $view = 'ChillActivityBundle:Activity:editPerson.html.twig';
 | 
			
		||||
            $view = '@ChillActivity/Activity/editPerson.html.twig';
 | 
			
		||||
        }
 | 
			
		||||
        // TODO
 | 
			
		||||
        // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity);
 | 
			
		||||
@@ -229,10 +222,6 @@ final class ActivityController extends AbstractController
 | 
			
		||||
        $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        if (null === $view) {
 | 
			
		||||
            throw $this->createNotFoundException('Template not found');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
 | 
			
		||||
 | 
			
		||||
        return $this->render($view, [
 | 
			
		||||
@@ -247,6 +236,8 @@ final class ActivityController extends AbstractController
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Lists all Activity entities.
 | 
			
		||||
     *
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/", name="chill_activity_activity_list")
 | 
			
		||||
     */
 | 
			
		||||
    public function listAction(Request $request): Response
 | 
			
		||||
    {
 | 
			
		||||
@@ -282,9 +273,9 @@ final class ActivityController extends AbstractController
 | 
			
		||||
                'element_class' => Activity::class,
 | 
			
		||||
                'action' => 'list',
 | 
			
		||||
            ]);
 | 
			
		||||
            $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
 | 
			
		||||
            $this->eventDispatcher->dispatch($event, PrivacyEvent::PERSON_PRIVACY_EVENT);
 | 
			
		||||
 | 
			
		||||
            $view = 'ChillActivityBundle:Activity:listPerson.html.twig';
 | 
			
		||||
            $view = '@ChillActivity/Activity/listPerson.html.twig';
 | 
			
		||||
        } elseif ($accompanyingPeriod instanceof AccompanyingPeriod) {
 | 
			
		||||
            $this->denyAccessUnlessGranted(ActivityVoter::SEE, $accompanyingPeriod);
 | 
			
		||||
 | 
			
		||||
@@ -300,9 +291,9 @@ final class ActivityController extends AbstractController
 | 
			
		||||
                    $filterArgs
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
            $view = 'ChillActivityBundle:Activity:listAccompanyingCourse.html.twig';
 | 
			
		||||
            $view = '@ChillActivity/Activity/listAccompanyingCourse.html.twig';
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \LogicException("Unsupported");
 | 
			
		||||
            throw new \LogicException('Unsupported');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->render(
 | 
			
		||||
@@ -332,25 +323,28 @@ final class ActivityController extends AbstractController
 | 
			
		||||
                ->addEntityChoice('activity_types', 'activity_filter.Types', \Chill\ActivityBundle\Entity\ActivityType::class, $types, [
 | 
			
		||||
                    'choice_label' => function (\Chill\ActivityBundle\Entity\ActivityType $activityType) {
 | 
			
		||||
                        $text = match ($activityType->hasCategory()) {
 | 
			
		||||
                            true => $this->translatableStringHelper->localize($activityType->getCategory()->getName()) . ' > ',
 | 
			
		||||
                            true => $this->translatableStringHelper->localize($activityType->getCategory()->getName()).' > ',
 | 
			
		||||
                            false => '',
 | 
			
		||||
                        };
 | 
			
		||||
 | 
			
		||||
                        return $text . $this->translatableStringHelper->localize($activityType->getName());
 | 
			
		||||
                    }
 | 
			
		||||
                        return $text.$this->translatableStringHelper->localize($activityType->getName());
 | 
			
		||||
                    },
 | 
			
		||||
                ]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (1 < count($jobs)) {
 | 
			
		||||
            $filterBuilder
 | 
			
		||||
                ->addEntityChoice('jobs', 'activity_filter.Jobs', UserJob::class, $jobs, [
 | 
			
		||||
                    'choice_label' => fn (UserJob $u) => $this->translatableStringHelper->localize($u->getLabel())
 | 
			
		||||
                    'choice_label' => fn (UserJob $u) => $this->translatableStringHelper->localize($u->getLabel()),
 | 
			
		||||
                ]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $filterBuilder->build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/new", name="chill_activity_activity_new", methods={"POST", "GET"})
 | 
			
		||||
     */
 | 
			
		||||
    public function newAction(Request $request): Response
 | 
			
		||||
    {
 | 
			
		||||
        $view = null;
 | 
			
		||||
@@ -358,16 +352,16 @@ final class ActivityController extends AbstractController
 | 
			
		||||
        [$person, $accompanyingPeriod] = $this->getEntity($request);
 | 
			
		||||
 | 
			
		||||
        if ($accompanyingPeriod instanceof AccompanyingPeriod) {
 | 
			
		||||
            $view = 'ChillActivityBundle:Activity:newAccompanyingCourse.html.twig';
 | 
			
		||||
            $view = '@ChillActivity/Activity/newAccompanyingCourse.html.twig';
 | 
			
		||||
        } elseif ($person instanceof Person) {
 | 
			
		||||
            $view = 'ChillActivityBundle:Activity:newPerson.html.twig';
 | 
			
		||||
            $view = '@ChillActivity/Activity/newPerson.html.twig';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $activityType_id = $request->get('activityType_id', 0);
 | 
			
		||||
        $activityType = $this->activityTypeRepository->find($activityType_id);
 | 
			
		||||
 | 
			
		||||
        if (isset($activityType) && !$activityType->isActive()) {
 | 
			
		||||
            throw new InvalidArgumentException('Activity type must be active');
 | 
			
		||||
            throw new \InvalidArgumentException('Activity type must be active');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $activityData = null;
 | 
			
		||||
@@ -402,45 +396,45 @@ final class ActivityController extends AbstractController
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $entity->setActivityType($activityType);
 | 
			
		||||
        $entity->setDate(new DateTime('now'));
 | 
			
		||||
        $entity->setDate(new \DateTime('now'));
 | 
			
		||||
 | 
			
		||||
        if ($request->query->has('activityData')) {
 | 
			
		||||
            $activityData = $request->query->get('activityData');
 | 
			
		||||
 | 
			
		||||
            if (array_key_exists('durationTime', $activityData) && $activityType->getDurationTimeVisible() > 0) {
 | 
			
		||||
            if (\array_key_exists('durationTime', $activityData) && $activityType->getDurationTimeVisible() > 0) {
 | 
			
		||||
                $durationTimeInMinutes = $activityData['durationTime'];
 | 
			
		||||
                $hours = floor($durationTimeInMinutes / 60);
 | 
			
		||||
                $minutes = $durationTimeInMinutes % 60;
 | 
			
		||||
                $duration = DateTime::createFromFormat('H:i', $hours . ':' . $minutes);
 | 
			
		||||
                $duration = \DateTime::createFromFormat('H:i', $hours.':'.$minutes);
 | 
			
		||||
 | 
			
		||||
                if ($duration) {
 | 
			
		||||
                    $entity->setDurationTime($duration);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (array_key_exists('date', $activityData)) {
 | 
			
		||||
                $date = DateTime::createFromFormat('Y-m-d', $activityData['date']);
 | 
			
		||||
            if (\array_key_exists('date', $activityData)) {
 | 
			
		||||
                $date = \DateTime::createFromFormat('Y-m-d', $activityData['date']);
 | 
			
		||||
 | 
			
		||||
                if ($date) {
 | 
			
		||||
                    $entity->setDate($date);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (array_key_exists('personsId', $activityData) && $activityType->getPersonsVisible() > 0) {
 | 
			
		||||
            if (\array_key_exists('personsId', $activityData) && $activityType->getPersonsVisible() > 0) {
 | 
			
		||||
                foreach ($activityData['personsId'] as $personId) {
 | 
			
		||||
                    $concernedPerson = $this->personRepository->find($personId);
 | 
			
		||||
                    $entity->addPerson($concernedPerson);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (array_key_exists('professionalsId', $activityData) && $activityType->getThirdPartiesVisible() > 0) {
 | 
			
		||||
            if (\array_key_exists('professionalsId', $activityData) && $activityType->getThirdPartiesVisible() > 0) {
 | 
			
		||||
                foreach ($activityData['professionalsId'] as $professionalsId) {
 | 
			
		||||
                    $professional = $this->thirdPartyRepository->find($professionalsId);
 | 
			
		||||
                    $entity->addThirdParty($professional);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (array_key_exists('usersId', $activityData) && $activityType->getUsersVisible() > 0) {
 | 
			
		||||
            if (\array_key_exists('usersId', $activityData) && $activityType->getUsersVisible() > 0) {
 | 
			
		||||
                foreach ($activityData['usersId'] as $userId) {
 | 
			
		||||
                    $user = $this->userRepository->find($userId);
 | 
			
		||||
 | 
			
		||||
@@ -450,16 +444,16 @@ final class ActivityController extends AbstractController
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (array_key_exists('location', $activityData) && $activityType->getLocationVisible() > 0) {
 | 
			
		||||
            if (\array_key_exists('location', $activityData) && $activityType->getLocationVisible() > 0) {
 | 
			
		||||
                $location = $this->locationRepository->find($activityData['location']);
 | 
			
		||||
                $entity->setLocation($location);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (array_key_exists('comment', $activityData) && $activityType->getCommentVisible() > 0) {
 | 
			
		||||
            if (\array_key_exists('comment', $activityData) && $activityType->getCommentVisible() > 0) {
 | 
			
		||||
                $comment = new CommentEmbeddable();
 | 
			
		||||
                $comment->setComment($activityData['comment']);
 | 
			
		||||
                $comment->setUserId($this->getUser()->getid());
 | 
			
		||||
                $comment->setDate(new DateTime('now'));
 | 
			
		||||
                $comment->setDate(new \DateTime('now'));
 | 
			
		||||
                $entity->setComment($comment);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -531,6 +525,9 @@ final class ActivityController extends AbstractController
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/select-type", name="chill_activity_activity_select_type")
 | 
			
		||||
     */
 | 
			
		||||
    public function selectTypeAction(Request $request): Response
 | 
			
		||||
    {
 | 
			
		||||
        $view = null;
 | 
			
		||||
@@ -538,9 +535,9 @@ final class ActivityController extends AbstractController
 | 
			
		||||
        [$person, $accompanyingPeriod] = $this->getEntity($request);
 | 
			
		||||
 | 
			
		||||
        if ($accompanyingPeriod instanceof AccompanyingPeriod) {
 | 
			
		||||
            $view = 'ChillActivityBundle:Activity:selectTypeAccompanyingCourse.html.twig';
 | 
			
		||||
            $view = '@ChillActivity/Activity/selectTypeAccompanyingCourse.html.twig';
 | 
			
		||||
        } elseif ($person instanceof Person) {
 | 
			
		||||
            $view = 'ChillActivityBundle:Activity:selectTypePerson.html.twig';
 | 
			
		||||
            $view = '@ChillActivity/Activity/selectTypePerson.html.twig';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $data = [];
 | 
			
		||||
@@ -575,6 +572,9 @@ final class ActivityController extends AbstractController
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/{id}/show", name="chill_activity_activity_show")
 | 
			
		||||
     */
 | 
			
		||||
    public function showAction(Request $request, int $id): Response
 | 
			
		||||
    {
 | 
			
		||||
        $entity = $this->activityRepository->find($id);
 | 
			
		||||
@@ -587,11 +587,11 @@ final class ActivityController extends AbstractController
 | 
			
		||||
        $person = $entity->getPerson();
 | 
			
		||||
 | 
			
		||||
        if ($accompanyingPeriod instanceof AccompanyingPeriod) {
 | 
			
		||||
            $view = 'ChillActivityBundle:Activity:showAccompanyingCourse.html.twig';
 | 
			
		||||
            $view = '@ChillActivity/Activity/showAccompanyingCourse.html.twig';
 | 
			
		||||
        } elseif ($person instanceof Person) {
 | 
			
		||||
            $view = 'ChillActivityBundle:Activity:showPerson.html.twig';
 | 
			
		||||
            $view = '@ChillActivity/Activity/showPerson.html.twig';
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new RuntimeException('the activity should be linked with a period or person');
 | 
			
		||||
            throw new \RuntimeException('the activity should be linked with a period or person');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (null !== $accompanyingPeriod) {
 | 
			
		||||
@@ -614,10 +614,6 @@ final class ActivityController extends AbstractController
 | 
			
		||||
        $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        if (null === $view) {
 | 
			
		||||
            throw $this->createNotFoundException('Template not found');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->render($view, [
 | 
			
		||||
            'person' => $person,
 | 
			
		||||
            'accompanyingCourse' => $accompanyingPeriod,
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,8 @@ class ActivityReasonCategoryController extends AbstractController
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a new ActivityReasonCategory entity.
 | 
			
		||||
     *
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/create", name="chill_activity_activityreasoncategory_create", methods={"POST"})
 | 
			
		||||
     */
 | 
			
		||||
    public function createAction(Request $request)
 | 
			
		||||
    {
 | 
			
		||||
@@ -31,15 +33,15 @@ class ActivityReasonCategoryController extends AbstractController
 | 
			
		||||
        $form = $this->createCreateForm($entity);
 | 
			
		||||
        $form->handleRequest($request);
 | 
			
		||||
 | 
			
		||||
        if ($form->isValid()) {
 | 
			
		||||
        if ($form->isSubmitted() && $form->isValid()) {
 | 
			
		||||
            $em = $this->getDoctrine()->getManager();
 | 
			
		||||
            $em->persist($entity);
 | 
			
		||||
            $em->flush();
 | 
			
		||||
 | 
			
		||||
            return $this->redirect($this->generateUrl('chill_activity_activityreasoncategory_show', ['id' => $entity->getId()]));
 | 
			
		||||
            return $this->redirectToRoute('chill_activity_activityreasoncategory_show', ['id' => $entity->getId()]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->render('ChillActivityBundle:ActivityReasonCategory:new.html.twig', [
 | 
			
		||||
        return $this->render('@ChillActivity/ActivityReasonCategory/new.html.twig', [
 | 
			
		||||
            'entity' => $entity,
 | 
			
		||||
            'form' => $form->createView(),
 | 
			
		||||
        ]);
 | 
			
		||||
@@ -48,9 +50,9 @@ class ActivityReasonCategoryController extends AbstractController
 | 
			
		||||
    /**
 | 
			
		||||
     * Displays a form to edit an existing ActivityReasonCategory entity.
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $id
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/{id}/edit", name="chill_activity_activityreasoncategory_edit")
 | 
			
		||||
     */
 | 
			
		||||
    public function editAction($id)
 | 
			
		||||
    public function editAction(mixed $id)
 | 
			
		||||
    {
 | 
			
		||||
        $em = $this->getDoctrine()->getManager();
 | 
			
		||||
 | 
			
		||||
@@ -62,7 +64,7 @@ class ActivityReasonCategoryController extends AbstractController
 | 
			
		||||
 | 
			
		||||
        $editForm = $this->createEditForm($entity);
 | 
			
		||||
 | 
			
		||||
        return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', [
 | 
			
		||||
        return $this->render('@ChillActivity/ActivityReasonCategory/edit.html.twig', [
 | 
			
		||||
            'entity' => $entity,
 | 
			
		||||
            'edit_form' => $editForm->createView(),
 | 
			
		||||
        ]);
 | 
			
		||||
@@ -70,6 +72,8 @@ class ActivityReasonCategoryController extends AbstractController
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Lists all ActivityReasonCategory entities.
 | 
			
		||||
     *
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/", name="chill_activity_activityreasoncategory")
 | 
			
		||||
     */
 | 
			
		||||
    public function indexAction()
 | 
			
		||||
    {
 | 
			
		||||
@@ -77,20 +81,22 @@ class ActivityReasonCategoryController extends AbstractController
 | 
			
		||||
 | 
			
		||||
        $entities = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReasonCategory::class)->findAll();
 | 
			
		||||
 | 
			
		||||
        return $this->render('ChillActivityBundle:ActivityReasonCategory:index.html.twig', [
 | 
			
		||||
        return $this->render('@ChillActivity/ActivityReasonCategory/index.html.twig', [
 | 
			
		||||
            'entities' => $entities,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Displays a form to create a new ActivityReasonCategory entity.
 | 
			
		||||
     *
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/new", name="chill_activity_activityreasoncategory_new")
 | 
			
		||||
     */
 | 
			
		||||
    public function newAction()
 | 
			
		||||
    {
 | 
			
		||||
        $entity = new ActivityReasonCategory();
 | 
			
		||||
        $form = $this->createCreateForm($entity);
 | 
			
		||||
 | 
			
		||||
        return $this->render('ChillActivityBundle:ActivityReasonCategory:new.html.twig', [
 | 
			
		||||
        return $this->render('@ChillActivity/ActivityReasonCategory/new.html.twig', [
 | 
			
		||||
            'entity' => $entity,
 | 
			
		||||
            'form' => $form->createView(),
 | 
			
		||||
        ]);
 | 
			
		||||
@@ -99,9 +105,9 @@ class ActivityReasonCategoryController extends AbstractController
 | 
			
		||||
    /**
 | 
			
		||||
     * Finds and displays a ActivityReasonCategory entity.
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $id
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/{id}/show", name="chill_activity_activityreasoncategory_show")
 | 
			
		||||
     */
 | 
			
		||||
    public function showAction($id)
 | 
			
		||||
    public function showAction(mixed $id)
 | 
			
		||||
    {
 | 
			
		||||
        $em = $this->getDoctrine()->getManager();
 | 
			
		||||
 | 
			
		||||
@@ -111,7 +117,7 @@ class ActivityReasonCategoryController extends AbstractController
 | 
			
		||||
            throw $this->createNotFoundException('Unable to find ActivityReasonCategory entity.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->render('ChillActivityBundle:ActivityReasonCategory:show.html.twig', [
 | 
			
		||||
        return $this->render('@ChillActivity/ActivityReasonCategory/show.html.twig', [
 | 
			
		||||
            'entity' => $entity,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
@@ -119,9 +125,9 @@ class ActivityReasonCategoryController extends AbstractController
 | 
			
		||||
    /**
 | 
			
		||||
     * Edits an existing ActivityReasonCategory entity.
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $id
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/{id}/update", name="chill_activity_activityreasoncategory_update", methods={"POST", "PUT"})
 | 
			
		||||
     */
 | 
			
		||||
    public function updateAction(Request $request, $id)
 | 
			
		||||
    public function updateAction(Request $request, mixed $id)
 | 
			
		||||
    {
 | 
			
		||||
        $em = $this->getDoctrine()->getManager();
 | 
			
		||||
 | 
			
		||||
@@ -134,13 +140,13 @@ class ActivityReasonCategoryController extends AbstractController
 | 
			
		||||
        $editForm = $this->createEditForm($entity);
 | 
			
		||||
        $editForm->handleRequest($request);
 | 
			
		||||
 | 
			
		||||
        if ($editForm->isValid()) {
 | 
			
		||||
        if ($editForm->isSubmitted() && $editForm->isValid()) {
 | 
			
		||||
            $em->flush();
 | 
			
		||||
 | 
			
		||||
            return $this->redirect($this->generateUrl('chill_activity_activityreasoncategory_edit', ['id' => $id]));
 | 
			
		||||
            return $this->redirectToRoute('chill_activity_activityreasoncategory_edit', ['id' => $id]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', [
 | 
			
		||||
        return $this->render('@ChillActivity/ActivityReasonCategory/edit.html.twig', [
 | 
			
		||||
            'entity' => $entity,
 | 
			
		||||
            'edit_form' => $editForm->createView(),
 | 
			
		||||
        ]);
 | 
			
		||||
 
 | 
			
		||||
@@ -24,15 +24,12 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 | 
			
		||||
 */
 | 
			
		||||
class ActivityReasonController extends AbstractController
 | 
			
		||||
{
 | 
			
		||||
    private ActivityReasonRepository $activityReasonRepository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(ActivityReasonRepository $activityReasonRepository)
 | 
			
		||||
    {
 | 
			
		||||
        $this->activityReasonRepository = $activityReasonRepository;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly ActivityReasonRepository $activityReasonRepository) {}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a new ActivityReason entity.
 | 
			
		||||
     *
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/create", name="chill_activity_activityreason_create", methods={"POST"})
 | 
			
		||||
     */
 | 
			
		||||
    public function createAction(Request $request)
 | 
			
		||||
    {
 | 
			
		||||
@@ -40,15 +37,15 @@ class ActivityReasonController extends AbstractController
 | 
			
		||||
        $form = $this->createCreateForm($entity);
 | 
			
		||||
        $form->handleRequest($request);
 | 
			
		||||
 | 
			
		||||
        if ($form->isValid()) {
 | 
			
		||||
        if ($form->isSubmitted() && $form->isValid()) {
 | 
			
		||||
            $em = $this->getDoctrine()->getManager();
 | 
			
		||||
            $em->persist($entity);
 | 
			
		||||
            $em->flush();
 | 
			
		||||
 | 
			
		||||
            return $this->redirect($this->generateUrl('chill_activity_activityreason', ['id' => $entity->getId()]));
 | 
			
		||||
            return $this->redirectToRoute('chill_activity_activityreason', ['id' => $entity->getId()]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->render('ChillActivityBundle:ActivityReason:new.html.twig', [
 | 
			
		||||
        return $this->render('@ChillActivity/ActivityReason/new.html.twig', [
 | 
			
		||||
            'entity' => $entity,
 | 
			
		||||
            'form' => $form->createView(),
 | 
			
		||||
        ]);
 | 
			
		||||
@@ -57,9 +54,9 @@ class ActivityReasonController extends AbstractController
 | 
			
		||||
    /**
 | 
			
		||||
     * Displays a form to edit an existing ActivityReason entity.
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $id
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/{id}/edit", name="chill_activity_activityreason_edit")
 | 
			
		||||
     */
 | 
			
		||||
    public function editAction($id)
 | 
			
		||||
    public function editAction(mixed $id)
 | 
			
		||||
    {
 | 
			
		||||
        $em = $this->getDoctrine()->getManager();
 | 
			
		||||
 | 
			
		||||
@@ -71,7 +68,7 @@ class ActivityReasonController extends AbstractController
 | 
			
		||||
 | 
			
		||||
        $editForm = $this->createEditForm($entity);
 | 
			
		||||
 | 
			
		||||
        return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', [
 | 
			
		||||
        return $this->render('@ChillActivity/ActivityReason/edit.html.twig', [
 | 
			
		||||
            'entity' => $entity,
 | 
			
		||||
            'edit_form' => $editForm->createView(),
 | 
			
		||||
        ]);
 | 
			
		||||
@@ -79,6 +76,8 @@ class ActivityReasonController extends AbstractController
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Lists all ActivityReason entities.
 | 
			
		||||
     *
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/", name="chill_activity_activityreason")
 | 
			
		||||
     */
 | 
			
		||||
    public function indexAction()
 | 
			
		||||
    {
 | 
			
		||||
@@ -86,20 +85,22 @@ class ActivityReasonController extends AbstractController
 | 
			
		||||
 | 
			
		||||
        $entities = $this->activityReasonRepository->findAll();
 | 
			
		||||
 | 
			
		||||
        return $this->render('ChillActivityBundle:ActivityReason:index.html.twig', [
 | 
			
		||||
        return $this->render('@ChillActivity/ActivityReason/index.html.twig', [
 | 
			
		||||
            'entities' => $entities,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Displays a form to create a new ActivityReason entity.
 | 
			
		||||
     *
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/new", name="chill_activity_activityreason_new")
 | 
			
		||||
     */
 | 
			
		||||
    public function newAction()
 | 
			
		||||
    {
 | 
			
		||||
        $entity = new ActivityReason();
 | 
			
		||||
        $form = $this->createCreateForm($entity);
 | 
			
		||||
 | 
			
		||||
        return $this->render('ChillActivityBundle:ActivityReason:new.html.twig', [
 | 
			
		||||
        return $this->render('@ChillActivity/ActivityReason/new.html.twig', [
 | 
			
		||||
            'entity' => $entity,
 | 
			
		||||
            'form' => $form->createView(),
 | 
			
		||||
        ]);
 | 
			
		||||
@@ -108,9 +109,9 @@ class ActivityReasonController extends AbstractController
 | 
			
		||||
    /**
 | 
			
		||||
     * Finds and displays a ActivityReason entity.
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $id
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/{id}/show", name="chill_activity_activityreason_show")
 | 
			
		||||
     */
 | 
			
		||||
    public function showAction($id)
 | 
			
		||||
    public function showAction(mixed $id)
 | 
			
		||||
    {
 | 
			
		||||
        $em = $this->getDoctrine()->getManager();
 | 
			
		||||
 | 
			
		||||
@@ -120,7 +121,7 @@ class ActivityReasonController extends AbstractController
 | 
			
		||||
            throw $this->createNotFoundException('Unable to find ActivityReason entity.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->render('ChillActivityBundle:ActivityReason:show.html.twig', [
 | 
			
		||||
        return $this->render('@ChillActivity/ActivityReason/show.html.twig', [
 | 
			
		||||
            'entity' => $entity,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
@@ -128,9 +129,9 @@ class ActivityReasonController extends AbstractController
 | 
			
		||||
    /**
 | 
			
		||||
     * Edits an existing ActivityReason entity.
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $id
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/{id}/update", name="chill_activity_activityreason_update", methods={"POST", "PUT"})
 | 
			
		||||
     */
 | 
			
		||||
    public function updateAction(Request $request, $id)
 | 
			
		||||
    public function updateAction(Request $request, mixed $id)
 | 
			
		||||
    {
 | 
			
		||||
        $em = $this->getDoctrine()->getManager();
 | 
			
		||||
 | 
			
		||||
@@ -143,13 +144,13 @@ class ActivityReasonController extends AbstractController
 | 
			
		||||
        $editForm = $this->createEditForm($entity);
 | 
			
		||||
        $editForm->handleRequest($request);
 | 
			
		||||
 | 
			
		||||
        if ($editForm->isValid()) {
 | 
			
		||||
        if ($editForm->isSubmitted() && $editForm->isValid()) {
 | 
			
		||||
            $em->flush();
 | 
			
		||||
 | 
			
		||||
            return $this->redirect($this->generateUrl('chill_activity_activityreason', ['id' => $id]));
 | 
			
		||||
            return $this->redirectToRoute('chill_activity_activityreason', ['id' => $id]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', [
 | 
			
		||||
        return $this->render('@ChillActivity/ActivityReason/edit.html.twig', [
 | 
			
		||||
            'entity' => $entity,
 | 
			
		||||
            'edit_form' => $editForm->createView(),
 | 
			
		||||
        ]);
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ class AdminActivityPresenceController extends CRUDController
 | 
			
		||||
     */
 | 
			
		||||
    protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
 | 
			
		||||
    {
 | 
			
		||||
        /** @var \Doctrine\ORM\QueryBuilder $query */
 | 
			
		||||
        /* @var \Doctrine\ORM\QueryBuilder $query */
 | 
			
		||||
        return $query->orderBy('e.id', 'ASC');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ class AdminActivityTypeCategoryController extends CRUDController
 | 
			
		||||
     */
 | 
			
		||||
    protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
 | 
			
		||||
    {
 | 
			
		||||
        /** @var \Doctrine\ORM\QueryBuilder $query */
 | 
			
		||||
        /* @var \Doctrine\ORM\QueryBuilder $query */
 | 
			
		||||
        return $query->orderBy('e.ordering', 'ASC');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ class AdminActivityTypeController extends CRUDController
 | 
			
		||||
     */
 | 
			
		||||
    protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
 | 
			
		||||
    {
 | 
			
		||||
        /** @var \Doctrine\ORM\QueryBuilder $query */
 | 
			
		||||
        /* @var \Doctrine\ORM\QueryBuilder $query */
 | 
			
		||||
        return $query->orderBy('e.ordering', 'ASC')
 | 
			
		||||
            ->addOrderBy('e.id', 'ASC');
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -18,11 +18,18 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 | 
			
		||||
 */
 | 
			
		||||
class AdminController extends AbstractController
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activity", name="chill_activity_admin_index")
 | 
			
		||||
     */
 | 
			
		||||
    public function indexActivityAction()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->render('ChillActivityBundle:Admin:layout_activity.html.twig');
 | 
			
		||||
        return $this->render('@ChillActivity/Admin/layout_activity.html.twig');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activity_redirect_to_main", name="chill_admin_aside_activity_redirect_to_admin_index", options={null})
 | 
			
		||||
     * @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activity_redirect_to_main", name="chill_admin_activity_redirect_to_admin_index")
 | 
			
		||||
     */
 | 
			
		||||
    public function redirectToAdminIndexAction()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->redirectToRoute('chill_main_admin_central');
 | 
			
		||||
 
 | 
			
		||||
@@ -25,17 +25,11 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface
 | 
			
		||||
{
 | 
			
		||||
    use \Symfony\Component\DependencyInjection\ContainerAwareTrait;
 | 
			
		||||
 | 
			
		||||
    private EntityManagerInterface $em;
 | 
			
		||||
    private readonly \Faker\Generator $faker;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var \Faker\Generator
 | 
			
		||||
     */
 | 
			
		||||
    private $faker;
 | 
			
		||||
 | 
			
		||||
    public function __construct(EntityManagerInterface $em)
 | 
			
		||||
    public function __construct(private readonly EntityManagerInterface $em)
 | 
			
		||||
    {
 | 
			
		||||
        $this->faker = FakerFactory::create('fr_FR');
 | 
			
		||||
        $this->em = $em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getOrder()
 | 
			
		||||
 
 | 
			
		||||
@@ -52,13 +52,13 @@ class LoadActivityReason extends AbstractFixture implements OrderedFixtureInterf
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        foreach ($reasons as $r) {
 | 
			
		||||
            echo 'Creating activity reason : ' . $r['name']['en'] . "\n";
 | 
			
		||||
            echo 'Creating activity reason : '.$r['name']['en']."\n";
 | 
			
		||||
            $activityReason = (new ActivityReason())
 | 
			
		||||
                ->setName(($r['name']))
 | 
			
		||||
                ->setName($r['name'])
 | 
			
		||||
                ->setActive(true)
 | 
			
		||||
                ->setCategory($this->getReference($r['category']));
 | 
			
		||||
            $manager->persist($activityReason);
 | 
			
		||||
            $reference = 'activity_reason_' . $r['name']['en'];
 | 
			
		||||
            $reference = 'activity_reason_'.$r['name']['en'];
 | 
			
		||||
            $this->addReference($reference, $activityReason);
 | 
			
		||||
            static::$references[] = $reference;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -34,13 +34,13 @@ class LoadActivityReasonCategory extends AbstractFixture implements OrderedFixtu
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        foreach ($categs as $c) {
 | 
			
		||||
            echo 'Creating activity reason category : ' . $c['name']['en'] . "\n";
 | 
			
		||||
            echo 'Creating activity reason category : '.$c['name']['en']."\n";
 | 
			
		||||
            $activityReasonCategory = (new ActivityReasonCategory())
 | 
			
		||||
                ->setName(($c['name']))
 | 
			
		||||
                ->setName($c['name'])
 | 
			
		||||
                ->setActive(true);
 | 
			
		||||
            $manager->persist($activityReasonCategory);
 | 
			
		||||
            $this->addReference(
 | 
			
		||||
                'cat_' . $c['name']['en'],
 | 
			
		||||
                'cat_'.$c['name']['en'],
 | 
			
		||||
                $activityReasonCategory
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -54,14 +54,14 @@ class LoadActivityType extends Fixture implements OrderedFixtureInterface
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        foreach ($types as $t) {
 | 
			
		||||
            echo 'Creating activity type : ' . $t['name']['fr'] . ' (cat:' . $t['category'] . " \n";
 | 
			
		||||
            echo 'Creating activity type : '.$t['name']['fr'].' (cat:'.$t['category']." \n";
 | 
			
		||||
            $activityType = (new ActivityType())
 | 
			
		||||
                ->setName(($t['name']))
 | 
			
		||||
                ->setCategory($this->getReference('activity_type_cat_' . $t['category']))
 | 
			
		||||
                ->setName($t['name'])
 | 
			
		||||
                ->setCategory($this->getReference('activity_type_cat_'.$t['category']))
 | 
			
		||||
                ->setSocialIssuesVisible(1)
 | 
			
		||||
                ->setSocialActionsVisible(1);
 | 
			
		||||
            $manager->persist($activityType);
 | 
			
		||||
            $reference = 'activity_type_' . $t['name']['fr'];
 | 
			
		||||
            $reference = 'activity_type_'.$t['name']['fr'];
 | 
			
		||||
            $this->addReference($reference, $activityType);
 | 
			
		||||
            static::$references[] = $reference;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -42,13 +42,13 @@ class LoadActivityTypeCategory extends Fixture implements OrderedFixtureInterfac
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        foreach ($categories as $cat) {
 | 
			
		||||
            echo 'Creating activity type category : ' . $cat['ref'] . "\n";
 | 
			
		||||
            echo 'Creating activity type category : '.$cat['ref']."\n";
 | 
			
		||||
 | 
			
		||||
            $newCat = (new ActivityTypeCategory())
 | 
			
		||||
                ->setName(($cat['name']));
 | 
			
		||||
                ->setName($cat['name']);
 | 
			
		||||
 | 
			
		||||
            $manager->persist($newCat);
 | 
			
		||||
            $reference = 'activity_type_cat_' . $cat['ref'];
 | 
			
		||||
            $reference = 'activity_type_cat_'.$cat['ref'];
 | 
			
		||||
 | 
			
		||||
            $this->addReference($reference, $newCat);
 | 
			
		||||
            static::$references[] = $reference;
 | 
			
		||||
 
 | 
			
		||||
@@ -20,8 +20,6 @@ use Doctrine\Common\DataFixtures\AbstractFixture;
 | 
			
		||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
 | 
			
		||||
use Doctrine\Persistence\ObjectManager;
 | 
			
		||||
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add a role CHILL_ACTIVITY_UPDATE & CHILL_ACTIVITY_CREATE for all groups except administrative,
 | 
			
		||||
 * and a role CHILL_ACTIVITY_SEE for administrative.
 | 
			
		||||
@@ -40,10 +38,10 @@ class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterfac
 | 
			
		||||
 | 
			
		||||
            foreach (LoadScopes::$references as $scopeRef) {
 | 
			
		||||
                $scope = $this->getReference($scopeRef);
 | 
			
		||||
                //create permission group
 | 
			
		||||
                // create permission group
 | 
			
		||||
                switch ($permissionsGroup->getName()) {
 | 
			
		||||
                    case 'social':
 | 
			
		||||
                        if ($scope->getName()['en'] === 'administrative') {
 | 
			
		||||
                        if ('administrative' === $scope->getName()['en']) {
 | 
			
		||||
                            break 2; // we do not want any power on administrative
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
@@ -51,7 +49,7 @@ class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterfac
 | 
			
		||||
 | 
			
		||||
                    case 'administrative':
 | 
			
		||||
                    case 'direction':
 | 
			
		||||
                        if (in_array($scope->getName()['en'], ['administrative', 'social'], true)) {
 | 
			
		||||
                        if (\in_array($scope->getName()['en'], ['administrative', 'social'], true)) {
 | 
			
		||||
                            break 2; // we do not want any power on social or administrative
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
@@ -60,7 +58,7 @@ class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterfac
 | 
			
		||||
 | 
			
		||||
                printf(
 | 
			
		||||
                    'Adding CHILL_ACTIVITY_UPDATE & CHILL_ACTIVITY_CREATE & CHILL_ACTIVITY_DELETE, and stats and list permissions to %s '
 | 
			
		||||
                        . "permission group, scope '%s' \n",
 | 
			
		||||
                        ."permission group, scope '%s' \n",
 | 
			
		||||
                    $permissionsGroup->getName(),
 | 
			
		||||
                    $scope->getName()['en']
 | 
			
		||||
                );
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
 | 
			
		||||
 | 
			
		||||
        $container->setParameter('chill_activity.form.time_duration', $config['form']['time_duration']);
 | 
			
		||||
 | 
			
		||||
        $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../config'));
 | 
			
		||||
        $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config'));
 | 
			
		||||
        $loader->load('services.yaml');
 | 
			
		||||
        $loader->load('services/export.yaml');
 | 
			
		||||
        $loader->load('services/repositories.yaml');
 | 
			
		||||
@@ -73,7 +73,7 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
 | 
			
		||||
     */
 | 
			
		||||
    public function prependRoutes(ContainerBuilder $container)
 | 
			
		||||
    {
 | 
			
		||||
        //add routes for custom bundle
 | 
			
		||||
        // add routes for custom bundle
 | 
			
		||||
        $container->prependExtensionConfig('chill_main', [
 | 
			
		||||
            'routing' => [
 | 
			
		||||
                'resources' => [
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,6 @@ namespace Chill\ActivityBundle\DependencyInjection;
 | 
			
		||||
 | 
			
		||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
 | 
			
		||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
 | 
			
		||||
 | 
			
		||||
use function is_int;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -59,7 +58,7 @@ class Configuration implements ConfigurationInterface
 | 
			
		||||
            ->info('The number of seconds of this duration. Must be an integer.')
 | 
			
		||||
            ->cannotBeEmpty()
 | 
			
		||||
            ->validate()
 | 
			
		||||
            ->ifTrue(static fn ($data) => !is_int($data))->thenInvalid('The value %s is not a valid integer')
 | 
			
		||||
            ->ifTrue(static fn ($data) => !\is_int($data))->thenInvalid('The value %s is not a valid integer')
 | 
			
		||||
            ->end()
 | 
			
		||||
            ->end()
 | 
			
		||||
            ->scalarNode('label')
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,6 @@ use DateTime;
 | 
			
		||||
use Doctrine\Common\Collections\ArrayCollection;
 | 
			
		||||
use Doctrine\Common\Collections\Collection;
 | 
			
		||||
use Doctrine\ORM\Mapping as ORM;
 | 
			
		||||
use Symfony\Component\Security\Core\User\UserInterface;
 | 
			
		||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
 | 
			
		||||
use Symfony\Component\Serializer\Annotation\Groups;
 | 
			
		||||
use Symfony\Component\Serializer\Annotation\SerializedName;
 | 
			
		||||
@@ -46,11 +45,15 @@ use Symfony\Component\Validator\Constraints as Assert;
 | 
			
		||||
 * Class Activity.
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\Entity(repositoryClass="Chill\ActivityBundle\Repository\ActivityRepository")
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\Table(name="activity")
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\HasLifecycleCallbacks
 | 
			
		||||
 *
 | 
			
		||||
 * @DiscriminatorMap(typeProperty="type", mapping={
 | 
			
		||||
 *     "activity": Activity::class
 | 
			
		||||
 * })
 | 
			
		||||
 *
 | 
			
		||||
 * @ActivityValidator\ActivityValidity
 | 
			
		||||
 *
 | 
			
		||||
 * TODO see if necessary
 | 
			
		||||
@@ -65,69 +68,84 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
 | 
			
		||||
    use TrackUpdateTrait;
 | 
			
		||||
 | 
			
		||||
    public const SENTRECEIVED_RECEIVED = 'received';
 | 
			
		||||
    final public const SENTRECEIVED_RECEIVED = 'received';
 | 
			
		||||
 | 
			
		||||
    public const SENTRECEIVED_SENT = 'sent';
 | 
			
		||||
    final public const SENTRECEIVED_SENT = 'sent';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"read"})
 | 
			
		||||
     */
 | 
			
		||||
    private ?AccompanyingPeriod $accompanyingPeriod = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityType")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"read", "docgen:read"})
 | 
			
		||||
     *
 | 
			
		||||
     * @SerializedName("activityType")
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\JoinColumn(name="type_id")
 | 
			
		||||
     */
 | 
			
		||||
    private ActivityType $activityType;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityPresence")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"docgen:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private ?ActivityPresence $attendee = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\CommentEmbeddable", columnPrefix="comment_")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"docgen:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private CommentEmbeddable $comment;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="datetime")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"docgen:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private DateTime $date;
 | 
			
		||||
    private \DateTime $date;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToMany(targetEntity="Chill\DocStoreBundle\Entity\StoredObject", cascade={"persist"})
 | 
			
		||||
     *
 | 
			
		||||
     * @Assert\Valid(traverse=true)
 | 
			
		||||
     *
 | 
			
		||||
     * @var Collection<StoredObject>
 | 
			
		||||
     */
 | 
			
		||||
    private Collection $documents;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="time", nullable=true)
 | 
			
		||||
     */
 | 
			
		||||
    private ?DateTime $durationTime = null;
 | 
			
		||||
    private ?\DateTime $durationTime = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="boolean", options={"default": false})
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"docgen:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private bool $emergency = false;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Id
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\Column(name="id", type="integer")
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\GeneratedValue(strategy="AUTO")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"read", "docgen:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private ?int $id = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Location")
 | 
			
		||||
     *
 | 
			
		||||
     * @groups({"read", "docgen:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private ?Location $location = null;
 | 
			
		||||
@@ -139,9 +157,12 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\Person")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"read", "docgen:read"})
 | 
			
		||||
     *
 | 
			
		||||
     * @var Collection<Person>
 | 
			
		||||
     */
 | 
			
		||||
    private ?Collection $persons = null;
 | 
			
		||||
    private Collection $persons;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\PrivateCommentEmbeddable", columnPrefix="privateComment_")
 | 
			
		||||
@@ -150,58 +171,78 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToMany(targetEntity="Chill\ActivityBundle\Entity\ActivityReason")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"docgen:read"})
 | 
			
		||||
     *
 | 
			
		||||
     * @var Collection<ActivityReason>
 | 
			
		||||
     */
 | 
			
		||||
    private Collection $reasons;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Scope")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"docgen:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private ?Scope $scope = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="string", options={"default": ""})
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"docgen:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private string $sentReceived = '';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialAction")
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\JoinTable(name="chill_activity_activity_chill_person_socialaction")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"read", "docgen:read"})
 | 
			
		||||
     *
 | 
			
		||||
     * @var Collection<SocialAction>
 | 
			
		||||
     */
 | 
			
		||||
    private Collection $socialActions;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialIssue")
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\JoinTable(name="chill_activity_activity_chill_person_socialissue")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"read", "docgen:read"})
 | 
			
		||||
     *
 | 
			
		||||
     * @var Collection<SocialIssue>
 | 
			
		||||
     */
 | 
			
		||||
    private Collection $socialIssues;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToMany(targetEntity="Chill\ThirdPartyBundle\Entity\ThirdParty")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"read", "docgen:read"})
 | 
			
		||||
     *
 | 
			
		||||
     * @var Collection<ThirdParty>
 | 
			
		||||
     */
 | 
			
		||||
    private ?Collection $thirdParties = null;
 | 
			
		||||
    private Collection $thirdParties;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="time", nullable=true)
 | 
			
		||||
     */
 | 
			
		||||
    private ?DateTime $travelTime = null;
 | 
			
		||||
    private ?\DateTime $travelTime = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"docgen:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private ?User $user = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToMany(targetEntity="Chill\MainBundle\Entity\User")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"read", "docgen:read"})
 | 
			
		||||
     *
 | 
			
		||||
     * @var Collection<User>
 | 
			
		||||
     */
 | 
			
		||||
    private ?Collection $users = null;
 | 
			
		||||
    private Collection $users;
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
@@ -268,7 +309,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
            $this->socialIssues[] = $socialIssue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($this->getAccompanyingPeriod() !== null) {
 | 
			
		||||
        if (null !== $this->getAccompanyingPeriod()) {
 | 
			
		||||
            $this->getAccompanyingPeriod()->addSocialIssue($socialIssue);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -334,7 +375,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
        return $this->comment;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getDate(): DateTime
 | 
			
		||||
    public function getDate(): \DateTime
 | 
			
		||||
    {
 | 
			
		||||
        return $this->date;
 | 
			
		||||
    }
 | 
			
		||||
@@ -356,7 +397,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
        return (int) round(($this->durationTime->getTimestamp() + $this->durationTime->getOffset()) / 60.0, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getDurationTime(): ?DateTime
 | 
			
		||||
    public function getDurationTime(): ?\DateTime
 | 
			
		||||
    {
 | 
			
		||||
        return $this->durationTime;
 | 
			
		||||
    }
 | 
			
		||||
@@ -410,7 +451,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
 | 
			
		||||
            // TODO better semantic with:  return $this->persons->filter(...);
 | 
			
		||||
            foreach ($this->persons as $person) {
 | 
			
		||||
                if ($this->accompanyingPeriod->getOpenParticipationContainsPerson($person) === null) {
 | 
			
		||||
                if (null === $this->accompanyingPeriod->getOpenParticipationContainsPerson($person)) {
 | 
			
		||||
                    $personsNotAssociated[] = $person;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -469,7 +510,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
        return $this->thirdParties;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTravelTime(): ?DateTime
 | 
			
		||||
    public function getTravelTime(): ?\DateTime
 | 
			
		||||
    {
 | 
			
		||||
        return $this->travelTime;
 | 
			
		||||
    }
 | 
			
		||||
@@ -580,7 +621,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setDate(DateTime $date): self
 | 
			
		||||
    public function setDate(\DateTime $date): self
 | 
			
		||||
    {
 | 
			
		||||
        $this->date = $date;
 | 
			
		||||
 | 
			
		||||
@@ -594,7 +635,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setDurationTime(?DateTime $durationTime): self
 | 
			
		||||
    public function setDurationTime(?\DateTime $durationTime): self
 | 
			
		||||
    {
 | 
			
		||||
        $this->durationTime = $durationTime;
 | 
			
		||||
 | 
			
		||||
@@ -664,7 +705,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setTravelTime(DateTime $travelTime): self
 | 
			
		||||
    public function setTravelTime(\DateTime $travelTime): self
 | 
			
		||||
    {
 | 
			
		||||
        $this->travelTime = $travelTime;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,9 @@ use Symfony\Component\Serializer\Annotation as Serializer;
 | 
			
		||||
 * Class ActivityPresence.
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\Entity
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\Table(name="activitytpresence")
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\HasLifecycleCallbacks
 | 
			
		||||
 */
 | 
			
		||||
class ActivityPresence
 | 
			
		||||
@@ -30,15 +32,20 @@ class ActivityPresence
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Id
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\Column(name="id", type="integer")
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\GeneratedValue(strategy="AUTO")
 | 
			
		||||
     *
 | 
			
		||||
     * @Serializer\Groups({"docgen:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private ?int $id = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="json")
 | 
			
		||||
     *
 | 
			
		||||
     * @Serializer\Groups({"docgen:read"})
 | 
			
		||||
     *
 | 
			
		||||
     * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private array $name = [];
 | 
			
		||||
 
 | 
			
		||||
@@ -17,39 +17,38 @@ use Doctrine\ORM\Mapping as ORM;
 | 
			
		||||
 * Class ActivityReason.
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\Entity
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\Table(name="activityreason")
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\HasLifecycleCallbacks
 | 
			
		||||
 */
 | 
			
		||||
class ActivityReason
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var bool
 | 
			
		||||
     * @ORM\Column(type="boolean")
 | 
			
		||||
     */
 | 
			
		||||
    private $active = true;
 | 
			
		||||
    private bool $active = true;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var ActivityReasonCategory
 | 
			
		||||
     * @ORM\ManyToOne(
 | 
			
		||||
     *     targetEntity="Chill\ActivityBundle\Entity\ActivityReasonCategory",
 | 
			
		||||
     * inversedBy="reasons")
 | 
			
		||||
     */
 | 
			
		||||
    private $category;
 | 
			
		||||
    private ?ActivityReasonCategory $category = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var int
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\Id
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\Column(name="id", type="integer")
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\GeneratedValue(strategy="AUTO")
 | 
			
		||||
     */
 | 
			
		||||
    private $id;
 | 
			
		||||
    private ?int $id = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var array
 | 
			
		||||
     * @ORM\Column(type="json")
 | 
			
		||||
     */
 | 
			
		||||
    private $name;
 | 
			
		||||
    private array $name;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get active.
 | 
			
		||||
@@ -81,27 +80,9 @@ class ActivityReason
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get name.
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed|null $locale
 | 
			
		||||
     *
 | 
			
		||||
     * @return array | string
 | 
			
		||||
     */
 | 
			
		||||
    public function getName($locale = null)
 | 
			
		||||
    public function getName(): array
 | 
			
		||||
    {
 | 
			
		||||
        if ($locale) {
 | 
			
		||||
            if (isset($this->name[$locale])) {
 | 
			
		||||
                return $this->name[$locale];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach ($this->name as $name) {
 | 
			
		||||
                if (!empty($name)) {
 | 
			
		||||
                    return $name;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return '';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,34 +12,37 @@ declare(strict_types=1);
 | 
			
		||||
namespace Chill\ActivityBundle\Entity;
 | 
			
		||||
 | 
			
		||||
use Doctrine\Common\Collections\ArrayCollection;
 | 
			
		||||
use Doctrine\Common\Collections\Collection;
 | 
			
		||||
use Doctrine\ORM\Mapping as ORM;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class ActivityReasonCategory.
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\Entity
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\Table(name="activityreasoncategory")
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\HasLifecycleCallbacks
 | 
			
		||||
 */
 | 
			
		||||
class ActivityReasonCategory
 | 
			
		||||
class ActivityReasonCategory implements \Stringable
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var bool
 | 
			
		||||
     * @ORM\Column(type="boolean")
 | 
			
		||||
     */
 | 
			
		||||
    private $active = true;
 | 
			
		||||
    private bool $active = true;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var int
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\Id
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\Column(name="id", type="integer")
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\GeneratedValue(strategy="AUTO")
 | 
			
		||||
     */
 | 
			
		||||
    private $id;
 | 
			
		||||
    private ?int $id = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var string
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\Column(type="json")
 | 
			
		||||
     */
 | 
			
		||||
    private $name;
 | 
			
		||||
@@ -47,12 +50,13 @@ class ActivityReasonCategory
 | 
			
		||||
    /**
 | 
			
		||||
     * Array of ActivityReason.
 | 
			
		||||
     *
 | 
			
		||||
     * @var ArrayCollection
 | 
			
		||||
     * @var Collection<ActivityReason>
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\OneToMany(
 | 
			
		||||
     *     targetEntity="Chill\ActivityBundle\Entity\ActivityReason",
 | 
			
		||||
     * mappedBy="category")
 | 
			
		||||
     */
 | 
			
		||||
    private $reasons;
 | 
			
		||||
    private Collection $reasons;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * ActivityReasonCategory constructor.
 | 
			
		||||
@@ -62,12 +66,9 @@ class ActivityReasonCategory
 | 
			
		||||
        $this->reasons = new ArrayCollection();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return string
 | 
			
		||||
     */
 | 
			
		||||
    public function __toString()
 | 
			
		||||
    public function __toString(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'ActivityReasonCategory(' . $this->getName('x') . ')';
 | 
			
		||||
        return 'ActivityReasonCategory('.$this->getName('x').')';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -121,11 +122,9 @@ class ActivityReasonCategory
 | 
			
		||||
     * as unactive, all the reason have this entity as category is also
 | 
			
		||||
     * set as unactive.
 | 
			
		||||
     *
 | 
			
		||||
     * @param bool $active
 | 
			
		||||
     *
 | 
			
		||||
     * @return ActivityReasonCategory
 | 
			
		||||
     */
 | 
			
		||||
    public function setActive($active)
 | 
			
		||||
    public function setActive(bool $active)
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->active !== $active && !$active) {
 | 
			
		||||
            foreach ($this->reasons as $reason) {
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,6 @@ declare(strict_types=1);
 | 
			
		||||
namespace Chill\ActivityBundle\Entity;
 | 
			
		||||
 | 
			
		||||
use Doctrine\ORM\Mapping as ORM;
 | 
			
		||||
use InvalidArgumentException;
 | 
			
		||||
use Symfony\Component\Serializer\Annotation as Serializer;
 | 
			
		||||
use Symfony\Component\Serializer\Annotation\Groups;
 | 
			
		||||
use Symfony\Component\Validator\Constraints as Assert;
 | 
			
		||||
@@ -22,31 +21,36 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
 | 
			
		||||
 * Class ActivityType.
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\Entity
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\Table(name="activitytype")
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\HasLifecycleCallbacks
 | 
			
		||||
 */
 | 
			
		||||
class ActivityType
 | 
			
		||||
{
 | 
			
		||||
    public const FIELD_INVISIBLE = 0;
 | 
			
		||||
    final public const FIELD_INVISIBLE = 0;
 | 
			
		||||
 | 
			
		||||
    public const FIELD_OPTIONAL = 1;
 | 
			
		||||
    final public const FIELD_OPTIONAL = 1;
 | 
			
		||||
 | 
			
		||||
    public const FIELD_REQUIRED = 2;
 | 
			
		||||
    final public const FIELD_REQUIRED = 2;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @deprecated not in use
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\Column(type="string", nullable=false, options={"default": ""})
 | 
			
		||||
     */
 | 
			
		||||
    private string $accompanyingPeriodLabel = '';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @deprecated not in use
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\Column(type="smallint", nullable=false, options={"default": 1})
 | 
			
		||||
     */
 | 
			
		||||
    private int $accompanyingPeriodVisible = self::FIELD_INVISIBLE;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="boolean")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"read"})
 | 
			
		||||
     */
 | 
			
		||||
    private bool $active = true;
 | 
			
		||||
@@ -118,8 +122,11 @@ class ActivityType
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Id
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\Column(name="id", type="integer")
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\GeneratedValue(strategy="AUTO")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"docgen:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private ?int $id = null;
 | 
			
		||||
@@ -136,7 +143,9 @@ class ActivityType
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="json")
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"read", "docgen:read"})
 | 
			
		||||
     *
 | 
			
		||||
     * @Serializer\Context({"is-translatable": true}, groups={"docgen:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private array $name = [];
 | 
			
		||||
@@ -158,6 +167,7 @@ class ActivityType
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="smallint", nullable=false, options={"default": 1})
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"read"})
 | 
			
		||||
     */
 | 
			
		||||
    private int $personsVisible = self::FIELD_OPTIONAL;
 | 
			
		||||
@@ -238,6 +248,7 @@ class ActivityType
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="smallint", nullable=false, options={"default": 1})
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"read"})
 | 
			
		||||
     */
 | 
			
		||||
    private int $thirdPartiesVisible = self::FIELD_INVISIBLE;
 | 
			
		||||
@@ -264,6 +275,7 @@ class ActivityType
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="smallint", nullable=false, options={"default": 1})
 | 
			
		||||
     *
 | 
			
		||||
     * @Groups({"read"})
 | 
			
		||||
     */
 | 
			
		||||
    private int $usersVisible = self::FIELD_OPTIONAL;
 | 
			
		||||
@@ -275,10 +287,8 @@ class ActivityType
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @Assert\Callback
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $payload
 | 
			
		||||
     */
 | 
			
		||||
    public function checkSocialActionsVisibility(ExecutionContextInterface $context, $payload)
 | 
			
		||||
    public function checkSocialActionsVisibility(ExecutionContextInterface $context, mixed $payload)
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->socialIssuesVisible !== $this->socialActionsVisible) {
 | 
			
		||||
            if (!(2 === $this->socialIssuesVisible && 1 === $this->socialActionsVisible)) {
 | 
			
		||||
@@ -374,13 +384,13 @@ class ActivityType
 | 
			
		||||
 | 
			
		||||
    public function getLabel(string $field): ?string
 | 
			
		||||
    {
 | 
			
		||||
        $property = $field . 'Label';
 | 
			
		||||
        $property = $field.'Label';
 | 
			
		||||
 | 
			
		||||
        if (!property_exists($this, $property)) {
 | 
			
		||||
            throw new InvalidArgumentException('Field "' . $field . '" not found');
 | 
			
		||||
            throw new \InvalidArgumentException('Field "'.$field.'" not found');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /** @phpstan-ignore-next-line  */
 | 
			
		||||
        /* @phpstan-ignore-next-line */
 | 
			
		||||
        return $this->{$property};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -533,25 +543,25 @@ class ActivityType
 | 
			
		||||
 | 
			
		||||
    public function isRequired(string $field): bool
 | 
			
		||||
    {
 | 
			
		||||
        $property = $field . 'Visible';
 | 
			
		||||
        $property = $field.'Visible';
 | 
			
		||||
 | 
			
		||||
        if (!property_exists($this, $property)) {
 | 
			
		||||
            throw new InvalidArgumentException('Field "' . $field . '" not found');
 | 
			
		||||
            throw new \InvalidArgumentException('Field "'.$field.'" not found');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /** @phpstan-ignore-next-line  */
 | 
			
		||||
        /* @phpstan-ignore-next-line */
 | 
			
		||||
        return self::FIELD_REQUIRED === $this->{$property};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function isVisible(string $field): bool
 | 
			
		||||
    {
 | 
			
		||||
        $property = $field . 'Visible';
 | 
			
		||||
        $property = $field.'Visible';
 | 
			
		||||
 | 
			
		||||
        if (!property_exists($this, $property)) {
 | 
			
		||||
            throw new InvalidArgumentException('Field "' . $field . '" not found');
 | 
			
		||||
            throw new \InvalidArgumentException('Field "'.$field.'" not found');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /** @phpstan-ignore-next-line  */
 | 
			
		||||
        /* @phpstan-ignore-next-line */
 | 
			
		||||
        return self::FIELD_INVISIBLE !== $this->{$property};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,9 @@ use Doctrine\ORM\Mapping as ORM;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ORM\Entity
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\Table(name="activitytypecategory")
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\HasLifecycleCallbacks
 | 
			
		||||
 */
 | 
			
		||||
class ActivityTypeCategory
 | 
			
		||||
@@ -27,7 +29,9 @@ class ActivityTypeCategory
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Id
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\Column(name="id", type="integer")
 | 
			
		||||
     *
 | 
			
		||||
     * @ORM\GeneratedValue(strategy="AUTO")
 | 
			
		||||
     */
 | 
			
		||||
    private ?int $id = null;
 | 
			
		||||
 
 | 
			
		||||
@@ -15,22 +15,11 @@ use Chill\ActivityBundle\Entity\Activity;
 | 
			
		||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
 | 
			
		||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
 | 
			
		||||
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
 | 
			
		||||
use DateTimeImmutable;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class ActivityEntityListener
 | 
			
		||||
{
 | 
			
		||||
    private EntityManagerInterface $em;
 | 
			
		||||
 | 
			
		||||
    private AccompanyingPeriodWorkRepository $workRepository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(EntityManagerInterface $em, AccompanyingPeriodWorkRepository $workRepository)
 | 
			
		||||
    {
 | 
			
		||||
        $this->em = $em;
 | 
			
		||||
        $this->workRepository = $workRepository;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly EntityManagerInterface $em, private readonly AccompanyingPeriodWorkRepository $workRepository) {}
 | 
			
		||||
 | 
			
		||||
    public function persistActionToCourse(Activity $activity)
 | 
			
		||||
    {
 | 
			
		||||
@@ -39,11 +28,11 @@ class ActivityEntityListener
 | 
			
		||||
 | 
			
		||||
            $accompanyingCourseWorks = $this->workRepository->findByAccompanyingPeriod($period);
 | 
			
		||||
            $periodActions = [];
 | 
			
		||||
            $now = new DateTimeImmutable();
 | 
			
		||||
            $now = new \DateTimeImmutable();
 | 
			
		||||
 | 
			
		||||
            foreach ($accompanyingCourseWorks as $key => $work) {
 | 
			
		||||
                // take only the actions which are still opened
 | 
			
		||||
                if ($work->getEndDate() === null || $work->getEndDate() > ($activity->getDate() ?? $now)) {
 | 
			
		||||
                if (null === $work->getEndDate() || $work->getEndDate() > ($activity->getDate() ?? $now)) {
 | 
			
		||||
                    $periodActions[$key] = spl_object_hash($work->getSocialAction());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -52,14 +41,14 @@ class ActivityEntityListener
 | 
			
		||||
            $associatedThirdparties = $activity->getThirdParties();
 | 
			
		||||
 | 
			
		||||
            foreach ($activity->getSocialActions() as $action) {
 | 
			
		||||
                if (in_array(spl_object_hash($action), $periodActions, true)) {
 | 
			
		||||
                if (\in_array(spl_object_hash($action), $periodActions, true)) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                $newAction = new AccompanyingPeriodWork();
 | 
			
		||||
                $newAction->setSocialAction($action);
 | 
			
		||||
                $period->addWork($newAction);
 | 
			
		||||
 | 
			
		||||
                $date = DateTimeImmutable::createFromMutable($activity->getDate());
 | 
			
		||||
                $date = \DateTimeImmutable::createFromMutable($activity->getDate());
 | 
			
		||||
                $newAction->setStartDate($date);
 | 
			
		||||
 | 
			
		||||
                foreach ($associatedPersons as $person) {
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@ class ByActivityNumberAggregator implements AggregatorInterface
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data): void
 | 
			
		||||
    {
 | 
			
		||||
        $qb
 | 
			
		||||
            ->addSelect('(SELECT COUNT(activity.id) FROM ' . Activity::class . ' activity WHERE activity.accompanyingPeriod = acp) AS activity_by_number_aggregator')
 | 
			
		||||
            ->addSelect('(SELECT COUNT(activity.id) FROM '.Activity::class.' activity WHERE activity.accompanyingPeriod = acp) AS activity_by_number_aggregator')
 | 
			
		||||
            ->addGroupBy('activity_by_number_aggregator');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -40,6 +40,7 @@ class ByActivityNumberAggregator implements AggregatorInterface
 | 
			
		||||
    {
 | 
			
		||||
        // No form needed
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -17,21 +17,10 @@ use Chill\PersonBundle\Repository\SocialWork\SocialActionRepository;
 | 
			
		||||
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class BySocialActionAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    private SocialActionRender $actionRender;
 | 
			
		||||
 | 
			
		||||
    private SocialActionRepository $actionRepository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        SocialActionRender $actionRender,
 | 
			
		||||
        SocialActionRepository $actionRepository
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->actionRender = $actionRender;
 | 
			
		||||
        $this->actionRepository = $actionRepository;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly SocialActionRender $actionRender, private readonly SocialActionRepository $actionRepository) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -40,7 +29,7 @@ class BySocialActionAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('actsocialaction', $qb->getAllAliases(), true)) {
 | 
			
		||||
        if (!\in_array('actsocialaction', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->leftJoin('activity.socialActions', 'actsocialaction');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -57,6 +46,7 @@ class BySocialActionAggregator implements AggregatorInterface
 | 
			
		||||
    {
 | 
			
		||||
        // no form
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -17,21 +17,10 @@ use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
 | 
			
		||||
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class BySocialIssueAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    private SocialIssueRender $issueRender;
 | 
			
		||||
 | 
			
		||||
    private SocialIssueRepository $issueRepository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        SocialIssueRepository $issueRepository,
 | 
			
		||||
        SocialIssueRender $issueRender
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->issueRepository = $issueRepository;
 | 
			
		||||
        $this->issueRender = $issueRender;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly SocialIssueRepository $issueRepository, private readonly SocialIssueRender $issueRender) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -40,7 +29,7 @@ class BySocialIssueAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('actsocialissue', $qb->getAllAliases(), true)) {
 | 
			
		||||
        if (!\in_array('actsocialissue', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->leftJoin('activity.socialIssues', 'actsocialissue');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -57,6 +46,7 @@ class BySocialIssueAggregator implements AggregatorInterface
 | 
			
		||||
    {
 | 
			
		||||
        // no form
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -12,14 +12,9 @@ declare(strict_types=1);
 | 
			
		||||
namespace Chill\ActivityBundle\Export\Aggregator;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
 | 
			
		||||
use Chill\MainBundle\Export\AggregatorInterface;
 | 
			
		||||
use Chill\MainBundle\Repository\LocationRepository;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Closure;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
final readonly class ActivityLocationAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
@@ -32,7 +27,7 @@ final readonly class ActivityLocationAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('actloc', $qb->getAllAliases(), true)) {
 | 
			
		||||
        if (!\in_array('actloc', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->leftJoin('activity.location', 'actloc');
 | 
			
		||||
        }
 | 
			
		||||
        $qb->addSelect(sprintf('actloc.name AS %s', self::KEY));
 | 
			
		||||
@@ -48,12 +43,13 @@ final readonly class ActivityLocationAggregator implements AggregatorInterface
 | 
			
		||||
    {
 | 
			
		||||
        // no form required for this aggregator
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getLabels($key, array $values, $data): Closure
 | 
			
		||||
    public function getLabels($key, array $values, $data): \Closure
 | 
			
		||||
    {
 | 
			
		||||
        return function ($value): string {
 | 
			
		||||
            if ('_header' === $value) {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,26 +15,14 @@ use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
 | 
			
		||||
use Chill\MainBundle\Export\AggregatorInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Closure;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class ActivityTypeAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    public const KEY = 'activity_type_aggregator';
 | 
			
		||||
    final public const KEY = 'activity_type_aggregator';
 | 
			
		||||
 | 
			
		||||
    protected ActivityTypeRepositoryInterface $activityTypeRepository;
 | 
			
		||||
 | 
			
		||||
    protected TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ActivityTypeRepositoryInterface $activityTypeRepository,
 | 
			
		||||
        TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->activityTypeRepository = $activityTypeRepository;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(protected ActivityTypeRepositoryInterface $activityTypeRepository, protected TranslatableStringHelperInterface $translatableStringHelper) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -43,7 +31,7 @@ class ActivityTypeAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('acttype', $qb->getAllAliases(), true)) {
 | 
			
		||||
        if (!\in_array('acttype', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->leftJoin('activity.activityType', 'acttype');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -60,12 +48,13 @@ class ActivityTypeAggregator implements AggregatorInterface
 | 
			
		||||
    {
 | 
			
		||||
        // no form required for this aggregator
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getLabels($key, array $values, $data): Closure
 | 
			
		||||
    public function getLabels($key, array $values, $data): \Closure
 | 
			
		||||
    {
 | 
			
		||||
        // for performance reason, we load data from db only once
 | 
			
		||||
        $this->activityTypeRepository->findBy(['id' => $values]);
 | 
			
		||||
 
 | 
			
		||||
@@ -15,25 +15,14 @@ use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Export\AggregatorInterface;
 | 
			
		||||
use Chill\MainBundle\Repository\UserRepository;
 | 
			
		||||
use Chill\MainBundle\Templating\Entity\UserRender;
 | 
			
		||||
use Closure;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class ActivityUserAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    public const KEY = 'activity_user_id';
 | 
			
		||||
    final public const KEY = 'activity_user_id';
 | 
			
		||||
 | 
			
		||||
    private UserRender $userRender;
 | 
			
		||||
 | 
			
		||||
    private UserRepository $userRepository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        UserRepository $userRepository,
 | 
			
		||||
        UserRender $userRender
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->userRepository = $userRepository;
 | 
			
		||||
        $this->userRender = $userRender;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly UserRepository $userRepository, private readonly UserRender $userRender) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -58,12 +47,13 @@ class ActivityUserAggregator implements AggregatorInterface
 | 
			
		||||
    {
 | 
			
		||||
        // nothing to add
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getLabels($key, $values, $data): Closure
 | 
			
		||||
    public function getLabels($key, $values, $data): \Closure
 | 
			
		||||
    {
 | 
			
		||||
        return function ($value) {
 | 
			
		||||
            if ('_header' === $value) {
 | 
			
		||||
 
 | 
			
		||||
@@ -17,19 +17,10 @@ use Chill\MainBundle\Repository\UserRepositoryInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\Entity\UserRender;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class ActivityUsersAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    private UserRender $userRender;
 | 
			
		||||
 | 
			
		||||
    private UserRepositoryInterface $userRepository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(UserRepositoryInterface $userRepository, UserRender $userRender)
 | 
			
		||||
    {
 | 
			
		||||
        $this->userRepository = $userRepository;
 | 
			
		||||
        $this->userRender = $userRender;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly UserRepositoryInterface $userRepository, private readonly UserRender $userRender) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -38,7 +29,7 @@ class ActivityUsersAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('actusers', $qb->getAllAliases(), true)) {
 | 
			
		||||
        if (!\in_array('actusers', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->leftJoin('activity.users', 'actusers');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -56,6 +47,7 @@ class ActivityUsersAggregator implements AggregatorInterface
 | 
			
		||||
    {
 | 
			
		||||
        // nothing to add on the form
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -12,23 +12,22 @@ declare(strict_types=1);
 | 
			
		||||
namespace Chill\ActivityBundle\Export\Aggregator;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Entity\User\UserJobHistory;
 | 
			
		||||
use Chill\MainBundle\Export\AggregatorInterface;
 | 
			
		||||
use Chill\MainBundle\Repository\UserJobRepositoryInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Doctrine\ORM\Query\Expr;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorInterface
 | 
			
		||||
class ActivityUsersJobAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
    private const PREFIX = 'act_agg_user_job';
 | 
			
		||||
 | 
			
		||||
    private UserJobRepositoryInterface $userJobRepository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(UserJobRepositoryInterface $userJobRepository, TranslatableStringHelperInterface $translatableStringHelper)
 | 
			
		||||
    {
 | 
			
		||||
        $this->userJobRepository = $userJobRepository;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly UserJobRepositoryInterface $userJobRepository,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -37,24 +36,37 @@ class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorI
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('actusers', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->leftJoin('activity.users', 'actusers');
 | 
			
		||||
        }
 | 
			
		||||
        $p = self::PREFIX;
 | 
			
		||||
 | 
			
		||||
        $qb
 | 
			
		||||
            ->addSelect('IDENTITY(actusers.userJob) AS activity_users_job_aggregator')
 | 
			
		||||
            ->addGroupBy('activity_users_job_aggregator');
 | 
			
		||||
            ->leftJoin('activity.users', "{$p}_user")
 | 
			
		||||
            ->leftJoin(
 | 
			
		||||
                UserJobHistory::class,
 | 
			
		||||
                "{$p}_history",
 | 
			
		||||
                Expr\Join::WITH,
 | 
			
		||||
                $qb->expr()->eq("{$p}_history.user", "{$p}_user")
 | 
			
		||||
            )
 | 
			
		||||
            // job_at based on activity.date
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->andX(
 | 
			
		||||
                    $qb->expr()->lte("{$p}_history.startDate", 'activity.date'),
 | 
			
		||||
                    $qb->expr()->orX(
 | 
			
		||||
                        $qb->expr()->isNull("{$p}_history.endDate"),
 | 
			
		||||
                        $qb->expr()->gt("{$p}_history.endDate", 'activity.date')
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select")
 | 
			
		||||
            ->addGroupBy("{$p}_select");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function applyOn()
 | 
			
		||||
    public function applyOn(): string
 | 
			
		||||
    {
 | 
			
		||||
        return Declarations::ACTIVITY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
        // nothing to add in the form
 | 
			
		||||
    }
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder) {}
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -81,11 +93,11 @@ class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorI
 | 
			
		||||
 | 
			
		||||
    public function getQueryKeys($data): array
 | 
			
		||||
    {
 | 
			
		||||
        return ['activity_users_job_aggregator'];
 | 
			
		||||
        return [self::PREFIX.'_select'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle()
 | 
			
		||||
    public function getTitle(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'Aggregate by users job';
 | 
			
		||||
        return 'export.aggregator.activity.by_user_job.Aggregate by users job';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,23 +12,22 @@ declare(strict_types=1);
 | 
			
		||||
namespace Chill\ActivityBundle\Export\Aggregator;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Entity\User\UserScopeHistory;
 | 
			
		||||
use Chill\MainBundle\Export\AggregatorInterface;
 | 
			
		||||
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Doctrine\ORM\Query\Expr;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\AggregatorInterface
 | 
			
		||||
class ActivityUsersScopeAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    private ScopeRepositoryInterface $scopeRepository;
 | 
			
		||||
    private const PREFIX = 'act_agg_user_scope';
 | 
			
		||||
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(ScopeRepositoryInterface $scopeRepository, TranslatableStringHelperInterface $translatableStringHelper)
 | 
			
		||||
    {
 | 
			
		||||
        $this->scopeRepository = $scopeRepository;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly ScopeRepositoryInterface $scopeRepository,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -37,24 +36,37 @@ class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\Aggregato
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('actusers', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->leftJoin('activity.users', 'actusers');
 | 
			
		||||
        }
 | 
			
		||||
        $p = self::PREFIX;
 | 
			
		||||
 | 
			
		||||
        $qb
 | 
			
		||||
            ->addSelect('IDENTITY(actusers.mainScope) AS activity_users_main_scope_aggregator')
 | 
			
		||||
            ->addGroupBy('activity_users_main_scope_aggregator');
 | 
			
		||||
            ->leftJoin('activity.users', "{$p}_user")
 | 
			
		||||
            ->leftJoin(
 | 
			
		||||
                UserScopeHistory::class,
 | 
			
		||||
                "{$p}_history",
 | 
			
		||||
                Expr\Join::WITH,
 | 
			
		||||
                $qb->expr()->eq("{$p}_history.user", "{$p}_user")
 | 
			
		||||
            )
 | 
			
		||||
            // scope_at based on activity.date
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->andX(
 | 
			
		||||
                    $qb->expr()->lte("{$p}_history.startDate", 'activity.date'),
 | 
			
		||||
                    $qb->expr()->orX(
 | 
			
		||||
                        $qb->expr()->isNull("{$p}_history.endDate"),
 | 
			
		||||
                        $qb->expr()->gt("{$p}_history.endDate", 'activity.date')
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select")
 | 
			
		||||
            ->addGroupBy("{$p}_select");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function applyOn()
 | 
			
		||||
    public function applyOn(): string
 | 
			
		||||
    {
 | 
			
		||||
        return Declarations::ACTIVITY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
        // nothing to add in the form
 | 
			
		||||
    }
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder) {}
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -81,11 +93,11 @@ class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\Aggregato
 | 
			
		||||
 | 
			
		||||
    public function getQueryKeys($data): array
 | 
			
		||||
    {
 | 
			
		||||
        return ['activity_users_main_scope_aggregator'];
 | 
			
		||||
        return [self::PREFIX.'_select'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle()
 | 
			
		||||
    public function getTitle(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'Aggregate by users scope';
 | 
			
		||||
        return 'export.aggregator.activity.by_user_scope.Aggregate by users scope';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,17 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class ByCreatorAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    private UserRender $userRender;
 | 
			
		||||
 | 
			
		||||
    private UserRepositoryInterface $userRepository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        UserRepositoryInterface $userRepository,
 | 
			
		||||
        UserRender $userRender
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->userRepository = $userRepository;
 | 
			
		||||
        $this->userRender = $userRender;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly UserRepositoryInterface $userRepository, private readonly UserRender $userRender) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -52,6 +42,7 @@ class ByCreatorAggregator implements AggregatorInterface
 | 
			
		||||
    {
 | 
			
		||||
        // no form
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -17,21 +17,10 @@ use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
 | 
			
		||||
use Chill\ThirdPartyBundle\Templating\Entity\ThirdPartyRender;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class ByThirdpartyAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    private ThirdPartyRender $thirdPartyRender;
 | 
			
		||||
 | 
			
		||||
    private ThirdPartyRepository $thirdPartyRepository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ThirdPartyRepository $thirdPartyRepository,
 | 
			
		||||
        ThirdPartyRender $thirdPartyRender
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->thirdPartyRepository = $thirdPartyRepository;
 | 
			
		||||
        $this->thirdPartyRender = $thirdPartyRender;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly ThirdPartyRepository $thirdPartyRepository, private readonly ThirdPartyRender $thirdPartyRender) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -40,7 +29,7 @@ class ByThirdpartyAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('acttparty', $qb->getAllAliases(), true)) {
 | 
			
		||||
        if (!\in_array('acttparty', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->leftJoin('activity.thirdParties', 'acttparty');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -57,6 +46,7 @@ class ByThirdpartyAggregator implements AggregatorInterface
 | 
			
		||||
    {
 | 
			
		||||
        // no form
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -12,26 +12,22 @@ declare(strict_types=1);
 | 
			
		||||
namespace Chill\ActivityBundle\Export\Aggregator;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Entity\User\UserScopeHistory;
 | 
			
		||||
use Chill\MainBundle\Export\AggregatorInterface;
 | 
			
		||||
use Chill\MainBundle\Repository\ScopeRepository;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
 | 
			
		||||
use Doctrine\ORM\Query\Expr\Join;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class CreatorScopeAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    private ScopeRepository $scopeRepository;
 | 
			
		||||
 | 
			
		||||
    private TranslatableStringHelper $translatableStringHelper;
 | 
			
		||||
    private const PREFIX = 'acp_agg_creator_scope';
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ScopeRepository $scopeRepository,
 | 
			
		||||
        TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->scopeRepository = $scopeRepository;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
        private readonly ScopeRepository $scopeRepository,
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -40,12 +36,28 @@ class CreatorScopeAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('actcreator', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->leftJoin('activity.createdBy', 'actcreator');
 | 
			
		||||
        }
 | 
			
		||||
        $p = self::PREFIX;
 | 
			
		||||
 | 
			
		||||
        $qb->addSelect('IDENTITY(actcreator.mainScope) AS creatorscope_aggregator');
 | 
			
		||||
        $qb->addGroupBy('creatorscope_aggregator');
 | 
			
		||||
        $qb
 | 
			
		||||
            ->leftJoin('activity.createdBy', "{$p}_user")
 | 
			
		||||
            ->leftJoin(
 | 
			
		||||
                UserScopeHistory::class,
 | 
			
		||||
                "{$p}_history",
 | 
			
		||||
                Join::WITH,
 | 
			
		||||
                $qb->expr()->eq("{$p}_history.user", "{$p}_user")
 | 
			
		||||
            )
 | 
			
		||||
            // scope_at based on activity.date
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->andX(
 | 
			
		||||
                    $qb->expr()->lte("{$p}_history.startDate", 'activity.date'),
 | 
			
		||||
                    $qb->expr()->orX(
 | 
			
		||||
                        $qb->expr()->isNull("{$p}_history.endDate"),
 | 
			
		||||
                        $qb->expr()->gt("{$p}_history.endDate", 'activity.date')
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select")
 | 
			
		||||
            ->addGroupBy("{$p}_select");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function applyOn(): string
 | 
			
		||||
@@ -53,10 +65,8 @@ class CreatorScopeAggregator implements AggregatorInterface
 | 
			
		||||
        return Declarations::ACTIVITY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
        // no form
 | 
			
		||||
    }
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder) {}
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -83,11 +93,11 @@ class CreatorScopeAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function getQueryKeys($data): array
 | 
			
		||||
    {
 | 
			
		||||
        return ['creatorscope_aggregator'];
 | 
			
		||||
        return [self::PREFIX.'_select'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'Group activity by creator scope';
 | 
			
		||||
        return 'export.aggregator.activity.by_creator_scope.Group activity by creator scope';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,10 +14,8 @@ namespace Chill\ActivityBundle\Export\Aggregator;
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Export\AggregatorInterface;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use RuntimeException;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
 | 
			
		||||
class DateAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
@@ -56,7 +54,7 @@ class DateAggregator implements AggregatorInterface
 | 
			
		||||
                break; // order DESC does not works !
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
                throw new RuntimeException(sprintf("The frequency data '%s' is invalid.", $data['frequency']));
 | 
			
		||||
                throw new \RuntimeException(sprintf("The frequency data '%s' is invalid.", $data['frequency']));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $qb->addSelect(sprintf("TO_CHAR(activity.date, '%s') AS date_aggregator", $fmt));
 | 
			
		||||
@@ -78,6 +76,7 @@ class DateAggregator implements AggregatorInterface
 | 
			
		||||
            'empty_data' => self::DEFAULT_CHOICE,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return ['frequency' => self::DEFAULT_CHOICE];
 | 
			
		||||
@@ -87,24 +86,16 @@ class DateAggregator implements AggregatorInterface
 | 
			
		||||
    {
 | 
			
		||||
        return static function ($value) use ($data): string {
 | 
			
		||||
            if ('_header' === $value) {
 | 
			
		||||
                return 'by ' . $data['frequency'];
 | 
			
		||||
                return 'by '.$data['frequency'];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            switch ($data['frequency']) {
 | 
			
		||||
                case 'month':
 | 
			
		||||
                case 'week':
 | 
			
		||||
                    //return $this->translator->trans('for week') .' '. $value ;
 | 
			
		||||
 | 
			
		||||
                case 'year':
 | 
			
		||||
                    //return $this->translator->trans('in year') .' '. $value ;
 | 
			
		||||
 | 
			
		||||
                default:
 | 
			
		||||
                    return $value;
 | 
			
		||||
            }
 | 
			
		||||
            return match ($data['frequency']) {
 | 
			
		||||
                default => $value,
 | 
			
		||||
            };
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,103 @@
 | 
			
		||||
<?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\Export\Aggregator;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Entity\User\UserJobHistory;
 | 
			
		||||
use Chill\MainBundle\Export\AggregatorInterface;
 | 
			
		||||
use Chill\MainBundle\Repository\ScopeRepository;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
 | 
			
		||||
use Doctrine\ORM\Query\Expr\Join;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class JobScopeAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    private const PREFIX = 'acp_agg_creator_job';
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly ScopeRepository $scopeRepository,
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        $p = self::PREFIX;
 | 
			
		||||
 | 
			
		||||
        $qb
 | 
			
		||||
            ->leftJoin('activity.createdBy', "{$p}_user")
 | 
			
		||||
            ->leftJoin(
 | 
			
		||||
                UserJobHistory::class,
 | 
			
		||||
                "{$p}_history",
 | 
			
		||||
                Join::WITH,
 | 
			
		||||
                $qb->expr()->eq("{$p}_history.user", "{$p}_user")
 | 
			
		||||
            )
 | 
			
		||||
            // job_at based on activity.date
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->andX(
 | 
			
		||||
                    $qb->expr()->lte("{$p}_history.startDate", 'activity.date'),
 | 
			
		||||
                    $qb->expr()->orX(
 | 
			
		||||
                        $qb->expr()->isNull("{$p}_history.endDate"),
 | 
			
		||||
                        $qb->expr()->gt("{$p}_history.endDate", 'activity.date')
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select")
 | 
			
		||||
            ->addGroupBy("{$p}_select");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function applyOn(): string
 | 
			
		||||
    {
 | 
			
		||||
        return Declarations::ACTIVITY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder) {}
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        return function ($value): string {
 | 
			
		||||
            if ('_header' === $value) {
 | 
			
		||||
                return 'Scope';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value || '' === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $s = $this->scopeRepository->find($value);
 | 
			
		||||
 | 
			
		||||
            return $this->translatableStringHelper->localize(
 | 
			
		||||
                $s->getName()
 | 
			
		||||
            );
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getQueryKeys($data): array
 | 
			
		||||
    {
 | 
			
		||||
        return [self::PREFIX.'_select'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.aggregator.activity.by_creator_job.Group activity by creator job';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -17,21 +17,10 @@ use Chill\MainBundle\Repository\LocationTypeRepository;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class LocationTypeAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    private LocationTypeRepository $locationTypeRepository;
 | 
			
		||||
 | 
			
		||||
    private TranslatableStringHelper $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        LocationTypeRepository $locationTypeRepository,
 | 
			
		||||
        TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->locationTypeRepository = $locationTypeRepository;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly LocationTypeRepository $locationTypeRepository, private readonly TranslatableStringHelper $translatableStringHelper) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -40,7 +29,7 @@ class LocationTypeAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('actloc', $qb->getAllAliases(), true)) {
 | 
			
		||||
        if (!\in_array('actloc', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->leftJoin('activity.location', 'actloc');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -57,6 +46,7 @@ class LocationTypeAggregator implements AggregatorInterface
 | 
			
		||||
    {
 | 
			
		||||
        // no form
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -17,34 +17,15 @@ use Chill\ActivityBundle\Repository\ActivityReasonRepository;
 | 
			
		||||
use Chill\MainBundle\Export\AggregatorInterface;
 | 
			
		||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Doctrine\ORM\Query\Expr\Join;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use RuntimeException;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
 | 
			
		||||
 | 
			
		||||
use function count;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class ActivityReasonAggregator implements AggregatorInterface, ExportElementValidatedInterface
 | 
			
		||||
{
 | 
			
		||||
    protected ActivityReasonCategoryRepository $activityReasonCategoryRepository;
 | 
			
		||||
 | 
			
		||||
    protected ActivityReasonRepository $activityReasonRepository;
 | 
			
		||||
 | 
			
		||||
    protected TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ActivityReasonCategoryRepository $activityReasonCategoryRepository,
 | 
			
		||||
        ActivityReasonRepository $activityReasonRepository,
 | 
			
		||||
        TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->activityReasonCategoryRepository = $activityReasonCategoryRepository;
 | 
			
		||||
        $this->activityReasonRepository = $activityReasonRepository;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(protected ActivityReasonCategoryRepository $activityReasonCategoryRepository, protected ActivityReasonRepository $activityReasonRepository, protected TranslatableStringHelper $translatableStringHelper) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -61,20 +42,20 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
 | 
			
		||||
            $elem = 'actreasoncat.id';
 | 
			
		||||
            $alias = 'activity_categories_id';
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new RuntimeException('The data provided are not recognized.');
 | 
			
		||||
            throw new \RuntimeException('The data provided are not recognized.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $qb->addSelect($elem . ' as ' . $alias);
 | 
			
		||||
        $qb->addSelect($elem.' as '.$alias);
 | 
			
		||||
 | 
			
		||||
        // make a jointure only if needed
 | 
			
		||||
        if (!in_array('actreasons', $qb->getAllAliases(), true)) {
 | 
			
		||||
        if (!\in_array('actreasons', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->innerJoin('activity.reasons', 'actreasons');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // join category if necessary
 | 
			
		||||
        if ('activity_categories_id' === $alias) {
 | 
			
		||||
            // add join only if needed
 | 
			
		||||
            if (!in_array('actreasoncat', $qb->getAllAliases(), true)) {
 | 
			
		||||
            if (!\in_array('actreasoncat', $qb->getAllAliases(), true)) {
 | 
			
		||||
                $qb->join('actreasons.category', 'actreasoncat');
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -82,7 +63,7 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
 | 
			
		||||
        // add the "group by" part
 | 
			
		||||
        $groupBy = $qb->getDQLPart('groupBy');
 | 
			
		||||
 | 
			
		||||
        if (count($groupBy) > 0) {
 | 
			
		||||
        if (\count($groupBy) > 0) {
 | 
			
		||||
            $qb->addGroupBy($alias);
 | 
			
		||||
        } else {
 | 
			
		||||
            $qb->groupBy($alias);
 | 
			
		||||
@@ -110,6 +91,7 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
 | 
			
		||||
            ]
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -117,21 +99,11 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
 | 
			
		||||
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        // for performance reason, we load data from db only once
 | 
			
		||||
        switch ($data['level']) {
 | 
			
		||||
            case 'reasons':
 | 
			
		||||
                $this->activityReasonRepository->findBy(['id' => $values]);
 | 
			
		||||
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case 'categories':
 | 
			
		||||
                $this->activityReasonCategoryRepository->findBy(['id' => $values]);
 | 
			
		||||
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
                throw new RuntimeException(sprintf("The level data '%s' is invalid.", $data['level']));
 | 
			
		||||
        }
 | 
			
		||||
        match ($data['level']) {
 | 
			
		||||
            'reasons' => $this->activityReasonRepository->findBy(['id' => $values]),
 | 
			
		||||
            'categories' => $this->activityReasonCategoryRepository->findBy(['id' => $values]),
 | 
			
		||||
            default => throw new \RuntimeException(sprintf("The level data '%s' is invalid.", $data['level'])),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return function ($value) use ($data) {
 | 
			
		||||
            if ('_header' === $value) {
 | 
			
		||||
@@ -171,7 +143,7 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
 | 
			
		||||
            return ['activity_categories_id'];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        throw new RuntimeException('The data provided are not recognised.');
 | 
			
		||||
        throw new \RuntimeException('The data provided are not recognised.');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle()
 | 
			
		||||
 
 | 
			
		||||
@@ -14,18 +14,12 @@ namespace Chill\ActivityBundle\Export\Aggregator;
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Export\AggregatorInterface;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use LogicException;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
 | 
			
		||||
class SentReceivedAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    private TranslatorInterface $translator;
 | 
			
		||||
 | 
			
		||||
    public function __construct(TranslatorInterface $translator)
 | 
			
		||||
    {
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly TranslatorInterface $translator) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -47,6 +41,7 @@ class SentReceivedAggregator implements AggregatorInterface
 | 
			
		||||
    {
 | 
			
		||||
        // No form needed
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -71,7 +66,7 @@ class SentReceivedAggregator implements AggregatorInterface
 | 
			
		||||
                    return $this->translator->trans('export.aggregator.activity.by_sent_received.is received');
 | 
			
		||||
 | 
			
		||||
                default:
 | 
			
		||||
                    throw new LogicException(sprintf('The value %s is not valid', $value));
 | 
			
		||||
                    throw new \LogicException(sprintf('The value %s is not valid', $value));
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -16,9 +16,9 @@ namespace Chill\ActivityBundle\Export;
 | 
			
		||||
 */
 | 
			
		||||
abstract class Declarations
 | 
			
		||||
{
 | 
			
		||||
    public const ACTIVITY = 'activity';
 | 
			
		||||
    final public const ACTIVITY = 'activity';
 | 
			
		||||
 | 
			
		||||
    public const ACTIVITY_ACP = 'activity_linked_to_acp';
 | 
			
		||||
    final public const ACTIVITY_ACP = 'activity_linked_to_acp';
 | 
			
		||||
 | 
			
		||||
    public const ACTIVITY_PERSON = 'activity_linked_to_person';
 | 
			
		||||
    final public const ACTIVITY_PERSON = 'activity_linked_to_person';
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
 | 
			
		||||
use Chill\ActivityBundle\Entity\Activity;
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
 | 
			
		||||
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
 | 
			
		||||
use Chill\MainBundle\Export\ExportInterface;
 | 
			
		||||
use Chill\MainBundle\Export\FormatterInterface;
 | 
			
		||||
use Chill\MainBundle\Export\GroupedExportInterface;
 | 
			
		||||
@@ -23,7 +24,6 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
use Doctrine\ORM\EntityRepository;
 | 
			
		||||
use Doctrine\ORM\Query;
 | 
			
		||||
use LogicException;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class AvgActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
@@ -31,12 +31,13 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
    protected EntityRepository $repository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        EntityManagerInterface $em
 | 
			
		||||
        EntityManagerInterface $em,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->repository = $em->getRepository(Activity::class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder) {}
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -60,7 +61,7 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if ('export_avg_activity_duration' !== $key) {
 | 
			
		||||
            throw new LogicException("the key {$key} is not used by this export");
 | 
			
		||||
            throw new \LogicException("the key {$key} is not used by this export");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return static fn ($value) => '_header' === $value ? 'Average activities linked to an accompanying period duration' : $value;
 | 
			
		||||
@@ -100,14 +101,16 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
        $qb
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->exists(
 | 
			
		||||
                    'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
 | 
			
		||||
                    JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
 | 
			
		||||
                    'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
 | 
			
		||||
                    JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
 | 
			
		||||
                    WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
 | 
			
		||||
                    '
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            ->setParameter('authorized_centers', $centers);
 | 
			
		||||
 | 
			
		||||
        AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
 | 
			
		||||
 | 
			
		||||
        return $qb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
 | 
			
		||||
use Chill\ActivityBundle\Entity\Activity;
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
 | 
			
		||||
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
 | 
			
		||||
use Chill\MainBundle\Export\ExportInterface;
 | 
			
		||||
use Chill\MainBundle\Export\FormatterInterface;
 | 
			
		||||
use Chill\MainBundle\Export\GroupedExportInterface;
 | 
			
		||||
@@ -23,7 +24,6 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
use Doctrine\ORM\EntityRepository;
 | 
			
		||||
use Doctrine\ORM\Query;
 | 
			
		||||
use LogicException;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
@@ -31,7 +31,7 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
 | 
			
		||||
    protected EntityRepository $repository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        EntityManagerInterface $em
 | 
			
		||||
        EntityManagerInterface $em,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->repository = $em->getRepository(Activity::class);
 | 
			
		||||
    }
 | 
			
		||||
@@ -40,6 +40,7 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
 | 
			
		||||
    {
 | 
			
		||||
        // TODO: Implement buildForm() method.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -63,7 +64,7 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if ('export_avg_activity_visit_duration' !== $key) {
 | 
			
		||||
            throw new LogicException("the key {$key} is not used by this export");
 | 
			
		||||
            throw new \LogicException("the key {$key} is not used by this export");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return static fn ($value) => '_header' === $value ? 'Average activities linked to an accompanying period visit duration' : $value;
 | 
			
		||||
@@ -103,14 +104,16 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
 | 
			
		||||
        $qb
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->exists(
 | 
			
		||||
                    'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
 | 
			
		||||
                    JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
 | 
			
		||||
                    'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
 | 
			
		||||
                    JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
 | 
			
		||||
                    WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
 | 
			
		||||
                    '
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            ->setParameter('authorized_centers', $centers);
 | 
			
		||||
 | 
			
		||||
        AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
 | 
			
		||||
 | 
			
		||||
        return $qb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
 | 
			
		||||
use Chill\ActivityBundle\Entity\Activity;
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
 | 
			
		||||
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
 | 
			
		||||
use Chill\MainBundle\Export\ExportInterface;
 | 
			
		||||
use Chill\MainBundle\Export\FormatterInterface;
 | 
			
		||||
use Chill\MainBundle\Export\GroupedExportInterface;
 | 
			
		||||
@@ -23,7 +24,6 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
use Doctrine\ORM\EntityRepository;
 | 
			
		||||
use Doctrine\ORM\Query;
 | 
			
		||||
use LogicException;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class CountActivity implements ExportInterface, GroupedExportInterface
 | 
			
		||||
@@ -31,12 +31,13 @@ class CountActivity implements ExportInterface, GroupedExportInterface
 | 
			
		||||
    protected EntityRepository $repository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        EntityManagerInterface $em
 | 
			
		||||
        EntityManagerInterface $em,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->repository = $em->getRepository(Activity::class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder) {}
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -60,7 +61,7 @@ class CountActivity implements ExportInterface, GroupedExportInterface
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if ('export_count_activity' !== $key) {
 | 
			
		||||
            throw new LogicException("the key {$key} is not used by this export");
 | 
			
		||||
            throw new \LogicException("the key {$key} is not used by this export");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return static fn ($value) => '_header' === $value ? 'Number of activities linked to an accompanying period' : $value;
 | 
			
		||||
@@ -97,14 +98,16 @@ class CountActivity implements ExportInterface, GroupedExportInterface
 | 
			
		||||
        $qb
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->exists(
 | 
			
		||||
                    'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
 | 
			
		||||
                    JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
 | 
			
		||||
                    'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
 | 
			
		||||
                    JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
 | 
			
		||||
                    WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
 | 
			
		||||
                    '
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            ->setParameter('authorized_centers', $centers);
 | 
			
		||||
 | 
			
		||||
        AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
 | 
			
		||||
 | 
			
		||||
        $qb->select('COUNT(DISTINCT activity.id) as export_count_activity');
 | 
			
		||||
 | 
			
		||||
        return $qb;
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\ActivityBundle\Export\Export\ListActivityHelper;
 | 
			
		||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
 | 
			
		||||
use Chill\MainBundle\Entity\Scope;
 | 
			
		||||
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
 | 
			
		||||
use Chill\MainBundle\Export\GroupedExportInterface;
 | 
			
		||||
use Chill\MainBundle\Export\Helper\TranslatableStringExportLabelHelper;
 | 
			
		||||
use Chill\MainBundle\Export\ListInterface;
 | 
			
		||||
@@ -25,26 +26,13 @@ use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
{
 | 
			
		||||
    private EntityManagerInterface $entityManager;
 | 
			
		||||
 | 
			
		||||
    private ListActivityHelper $helper;
 | 
			
		||||
 | 
			
		||||
    private TranslatableStringExportLabelHelper $translatableStringExportLabelHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ListActivityHelper $helper,
 | 
			
		||||
        EntityManagerInterface $entityManager,
 | 
			
		||||
        TranslatableStringExportLabelHelper $translatableStringExportLabelHelper
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->helper = $helper;
 | 
			
		||||
        $this->entityManager = $entityManager;
 | 
			
		||||
        $this->translatableStringExportLabelHelper = $translatableStringExportLabelHelper;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly ListActivityHelper $helper, private readonly EntityManagerInterface $entityManager, private readonly TranslatableStringExportLabelHelper $translatableStringExportLabelHelper) {}
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
        $this->helper->buildForm($builder);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -57,7 +45,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
 | 
			
		||||
    public function getDescription()
 | 
			
		||||
    {
 | 
			
		||||
        return ListActivityHelper::MSG_KEY . 'List activities linked to an accompanying course';
 | 
			
		||||
        return ListActivityHelper::MSG_KEY.'List activities linked to an accompanying course';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getGroup(): string
 | 
			
		||||
@@ -67,22 +55,17 @@ class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        switch ($key) {
 | 
			
		||||
            case 'acpId':
 | 
			
		||||
                return static function ($value) {
 | 
			
		||||
                    if ('_header' === $value) {
 | 
			
		||||
                        return ListActivityHelper::MSG_KEY . 'accompanying course id';
 | 
			
		||||
                    }
 | 
			
		||||
        return match ($key) {
 | 
			
		||||
            'acpId' => static function ($value) {
 | 
			
		||||
                if ('_header' === $value) {
 | 
			
		||||
                    return ListActivityHelper::MSG_KEY.'accompanying course id';
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                    return $value ?? '';
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
            case 'scopesNames':
 | 
			
		||||
                return $this->translatableStringExportLabelHelper->getLabelMulti($key, $values, ListActivityHelper::MSG_KEY . 'course circles');
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
                return $this->helper->getLabels($key, $values, $data);
 | 
			
		||||
        }
 | 
			
		||||
                return $value ?? '';
 | 
			
		||||
            },
 | 
			
		||||
            'scopesNames' => $this->translatableStringExportLabelHelper->getLabelMulti($key, $values, ListActivityHelper::MSG_KEY.'course circles'),
 | 
			
		||||
            default => $this->helper->getLabels($key, $values, $data),
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getQueryKeys($data)
 | 
			
		||||
@@ -104,7 +87,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
 | 
			
		||||
    public function getTitle()
 | 
			
		||||
    {
 | 
			
		||||
        return ListActivityHelper::MSG_KEY . 'List activity linked to a course';
 | 
			
		||||
        return ListActivityHelper::MSG_KEY.'List activity linked to a course';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getType()
 | 
			
		||||
@@ -128,7 +111,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->exists(
 | 
			
		||||
                    'SELECT 1
 | 
			
		||||
                    FROM ' . PersonCenterHistory::class . ' acl_count_person_history
 | 
			
		||||
                    FROM '.PersonCenterHistory::class.' acl_count_person_history
 | 
			
		||||
                    WHERE acl_count_person_history.person = person
 | 
			
		||||
                    AND acl_count_person_history.center IN (:authorized_centers)
 | 
			
		||||
                    '
 | 
			
		||||
@@ -145,9 +128,11 @@ class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
        // add select for this step
 | 
			
		||||
        $qb
 | 
			
		||||
            ->addSelect('acp.id AS acpId')
 | 
			
		||||
            ->addSelect('(SELECT AGGREGATE(acpScope.name) FROM ' . Scope::class . ' acpScope WHERE acpScope MEMBER OF acp.scopes) AS scopesNames')
 | 
			
		||||
            ->addSelect('(SELECT AGGREGATE(acpScope.name) FROM '.Scope::class.' acpScope WHERE acpScope MEMBER OF acp.scopes) AS scopesNames')
 | 
			
		||||
            ->addGroupBy('scopesNames');
 | 
			
		||||
 | 
			
		||||
        AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
 | 
			
		||||
 | 
			
		||||
        return $qb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
 | 
			
		||||
use Chill\ActivityBundle\Entity\Activity;
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
 | 
			
		||||
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
 | 
			
		||||
use Chill\MainBundle\Export\ExportInterface;
 | 
			
		||||
use Chill\MainBundle\Export\FormatterInterface;
 | 
			
		||||
use Chill\MainBundle\Export\GroupedExportInterface;
 | 
			
		||||
@@ -23,7 +24,6 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
use Doctrine\ORM\EntityRepository;
 | 
			
		||||
use Doctrine\ORM\Query;
 | 
			
		||||
use LogicException;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class SumActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
@@ -31,7 +31,7 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
    protected EntityRepository $repository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        EntityManagerInterface $em
 | 
			
		||||
        EntityManagerInterface $em,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->repository = $em->getRepository(Activity::class);
 | 
			
		||||
    }
 | 
			
		||||
@@ -40,6 +40,7 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
    {
 | 
			
		||||
        // TODO: Implement buildForm() method.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -63,7 +64,7 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if ('export_sum_activity_duration' !== $key) {
 | 
			
		||||
            throw new LogicException("the key {$key} is not used by this export");
 | 
			
		||||
            throw new \LogicException("the key {$key} is not used by this export");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return static fn ($value) => '_header' === $value ? 'Sum activities linked to an accompanying period duration' : $value;
 | 
			
		||||
@@ -103,14 +104,16 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
        $qb
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->exists(
 | 
			
		||||
                    'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
 | 
			
		||||
                    JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
 | 
			
		||||
                    'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
 | 
			
		||||
                    JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
 | 
			
		||||
                    WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
 | 
			
		||||
                    '
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            ->setParameter('authorized_centers', $centers);
 | 
			
		||||
 | 
			
		||||
        AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
 | 
			
		||||
 | 
			
		||||
        return $qb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
 | 
			
		||||
use Chill\ActivityBundle\Entity\Activity;
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
 | 
			
		||||
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
 | 
			
		||||
use Chill\MainBundle\Export\ExportInterface;
 | 
			
		||||
use Chill\MainBundle\Export\FormatterInterface;
 | 
			
		||||
use Chill\MainBundle\Export\GroupedExportInterface;
 | 
			
		||||
@@ -23,7 +24,6 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
use Doctrine\ORM\EntityRepository;
 | 
			
		||||
use Doctrine\ORM\Query;
 | 
			
		||||
use LogicException;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class SumActivityVisitDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
@@ -31,7 +31,7 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
 | 
			
		||||
    protected EntityRepository $repository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        EntityManagerInterface $em
 | 
			
		||||
        EntityManagerInterface $em,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->repository = $em->getRepository(Activity::class);
 | 
			
		||||
    }
 | 
			
		||||
@@ -40,6 +40,7 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
 | 
			
		||||
    {
 | 
			
		||||
        // TODO: Implement buildForm() method.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -63,7 +64,7 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if ('export_sum_activity_visit_duration' !== $key) {
 | 
			
		||||
            throw new LogicException("the key {$key} is not used by this export");
 | 
			
		||||
            throw new \LogicException("the key {$key} is not used by this export");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return static fn ($value) => '_header' === $value ? 'Sum activities linked to an accompanying period visit duration' : $value;
 | 
			
		||||
@@ -103,14 +104,16 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
 | 
			
		||||
        $qb
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->exists(
 | 
			
		||||
                    'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
 | 
			
		||||
                    JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
 | 
			
		||||
                    'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
 | 
			
		||||
                    JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
 | 
			
		||||
                    WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
 | 
			
		||||
                    '
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            ->setParameter('authorized_centers', $centers);
 | 
			
		||||
 | 
			
		||||
        AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
 | 
			
		||||
 | 
			
		||||
        return $qb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,20 +19,14 @@ use Chill\MainBundle\Export\FormatterInterface;
 | 
			
		||||
use Chill\MainBundle\Export\GroupedExportInterface;
 | 
			
		||||
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
 | 
			
		||||
use Doctrine\ORM\Query;
 | 
			
		||||
use LogicException;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class CountActivity implements ExportInterface, GroupedExportInterface
 | 
			
		||||
{
 | 
			
		||||
    protected ActivityRepository $activityRepository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ActivityRepository $activityRepository
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->activityRepository = $activityRepository;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(protected ActivityRepository $activityRepository) {}
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder) {}
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -56,7 +50,7 @@ class CountActivity implements ExportInterface, GroupedExportInterface
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if ('export_count_activity' !== $key) {
 | 
			
		||||
            throw new LogicException("the key {$key} is not used by this export");
 | 
			
		||||
            throw new \LogicException("the key {$key} is not used by this export");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return static fn ($value) => '_header' === $value ? 'Number of activities linked to a person' : $value;
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,6 @@ use Chill\MainBundle\Export\GroupedExportInterface;
 | 
			
		||||
use Chill\MainBundle\Export\ListInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
 | 
			
		||||
use DateTime;
 | 
			
		||||
use Doctrine\DBAL\Exception\InvalidArgumentException;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
use Doctrine\ORM\Query;
 | 
			
		||||
@@ -30,14 +29,8 @@ use Symfony\Component\Validator\Constraints\Callback;
 | 
			
		||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
 | 
			
		||||
use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
 | 
			
		||||
use function array_key_exists;
 | 
			
		||||
use function count;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
{
 | 
			
		||||
    protected EntityManagerInterface $entityManager;
 | 
			
		||||
 | 
			
		||||
    protected array $fields = [
 | 
			
		||||
        'id',
 | 
			
		||||
        'date',
 | 
			
		||||
@@ -52,23 +45,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
        'person_id',
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    protected TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    protected TranslatorInterface $translator;
 | 
			
		||||
 | 
			
		||||
    private ActivityRepository $activityRepository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        EntityManagerInterface $em,
 | 
			
		||||
        TranslatorInterface $translator,
 | 
			
		||||
        TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        ActivityRepository $activityRepository
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->entityManager = $em;
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
        $this->activityRepository = $activityRepository;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(protected EntityManagerInterface $entityManager, protected TranslatorInterface $translator, protected TranslatableStringHelperInterface $translatableStringHelper, private readonly ActivityRepository $activityRepository) {}
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
@@ -79,7 +56,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
            'label' => 'Fields to include in export',
 | 
			
		||||
            'constraints' => [new Callback([
 | 
			
		||||
                'callback' => static function ($selected, ExecutionContextInterface $context) {
 | 
			
		||||
                    if (count($selected) === 0) {
 | 
			
		||||
                    if (0 === \count($selected)) {
 | 
			
		||||
                        $context->buildViolation('You must select at least one element')
 | 
			
		||||
                            ->atPath('fields')
 | 
			
		||||
                            ->addViolation();
 | 
			
		||||
@@ -88,6 +65,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
            ])],
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -117,7 +95,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
                        return 'date';
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    $date = DateTime::createFromFormat('Y-m-d H:i:s', $value);
 | 
			
		||||
                    $date = \DateTime::createFromFormat('Y-m-d H:i:s', $value);
 | 
			
		||||
 | 
			
		||||
                    return $date->format('d-m-Y');
 | 
			
		||||
                };
 | 
			
		||||
@@ -141,11 +119,11 @@ class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
 | 
			
		||||
                    $activity = $activityRepository->find($value);
 | 
			
		||||
 | 
			
		||||
                    return implode(', ', array_map(fn (ActivityReason $r) => '"' .
 | 
			
		||||
                    return implode(', ', array_map(fn (ActivityReason $r) => '"'.
 | 
			
		||||
                            $this->translatableStringHelper->localize($r->getCategory()->getName())
 | 
			
		||||
                            . ' > ' .
 | 
			
		||||
                            .' > '.
 | 
			
		||||
                            $this->translatableStringHelper->localize($r->getName())
 | 
			
		||||
                            . '"', $activity->getReasons()->toArray()));
 | 
			
		||||
                            .'"', $activity->getReasons()->toArray()));
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
            case 'circle_name':
 | 
			
		||||
@@ -154,7 +132,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
                        return 'circle';
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return $this->translatableStringHelper->localize(json_decode($value, true, 512, JSON_THROW_ON_ERROR));
 | 
			
		||||
                    return $this->translatableStringHelper->localize(json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR));
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
            case 'type_name':
 | 
			
		||||
@@ -163,7 +141,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
                        return 'activity type';
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return $this->translatableStringHelper->localize(json_decode($value, true, 512, JSON_THROW_ON_ERROR));
 | 
			
		||||
                    return $this->translatableStringHelper->localize(json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR));
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
@@ -202,7 +180,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
        $centers = array_map(static fn ($el) => $el['center'], $acl);
 | 
			
		||||
 | 
			
		||||
        // throw an error if any fields are present
 | 
			
		||||
        if (!array_key_exists('fields', $data)) {
 | 
			
		||||
        if (!\array_key_exists('fields', $data)) {
 | 
			
		||||
            throw new InvalidArgumentException('Any fields have been checked.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -226,7 +204,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
            ->setParameter('centers', $centers);
 | 
			
		||||
 | 
			
		||||
        foreach ($this->fields as $f) {
 | 
			
		||||
            if (in_array($f, $data['fields'], true)) {
 | 
			
		||||
            if (\in_array($f, $data['fields'], true)) {
 | 
			
		||||
                switch ($f) {
 | 
			
		||||
                    case 'id':
 | 
			
		||||
                        $qb->addSelect('activity.id AS id');
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,6 @@ use Chill\MainBundle\Export\FormatterInterface;
 | 
			
		||||
use Chill\MainBundle\Export\GroupedExportInterface;
 | 
			
		||||
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
 | 
			
		||||
use Doctrine\ORM\Query;
 | 
			
		||||
use LogicException;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -30,27 +29,21 @@ use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 */
 | 
			
		||||
class StatActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
{
 | 
			
		||||
    public const SUM = 'sum';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The action for this report.
 | 
			
		||||
     */
 | 
			
		||||
    protected string $action;
 | 
			
		||||
 | 
			
		||||
    private ActivityRepository $activityRepository;
 | 
			
		||||
    final public const SUM = 'sum';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param string $action the stat to perform
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ActivityRepository $activityRepository,
 | 
			
		||||
        string $action = 'sum'
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->action = $action;
 | 
			
		||||
        $this->activityRepository = $activityRepository;
 | 
			
		||||
    }
 | 
			
		||||
        private readonly ActivityRepository $activityRepository,
 | 
			
		||||
        /**
 | 
			
		||||
         * The action for this report.
 | 
			
		||||
         */
 | 
			
		||||
        protected string $action = 'sum'
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder) {}
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -67,7 +60,7 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
            return 'Sum activities linked to a person duration by various parameters.';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        throw new LogicException('this action is not supported: ' . $this->action);
 | 
			
		||||
        throw new \LogicException('this action is not supported: '.$this->action);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getGroup(): string
 | 
			
		||||
@@ -78,7 +71,7 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if ('export_stat_activity' !== $key) {
 | 
			
		||||
            throw new LogicException(sprintf('The key %s is not used by this export', $key));
 | 
			
		||||
            throw new \LogicException(sprintf('The key %s is not used by this export', $key));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $header = self::SUM === $this->action ? 'Sum activities linked to a person duration' : false;
 | 
			
		||||
@@ -102,7 +95,7 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
            return 'Sum activity linked to a person duration';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        throw new LogicException('This action is not supported: ' . $this->action);
 | 
			
		||||
        throw new \LogicException('This action is not supported: '.$this->action);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getType(): string
 | 
			
		||||
 
 | 
			
		||||
@@ -23,54 +23,24 @@ use Chill\PersonBundle\Export\Helper\LabelPersonHelper;
 | 
			
		||||
use Chill\ThirdPartyBundle\Export\Helper\LabelThirdPartyHelper;
 | 
			
		||||
use Doctrine\ORM\AbstractQuery;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use LogicException;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
use const SORT_NUMERIC;
 | 
			
		||||
 | 
			
		||||
class ListActivityHelper
 | 
			
		||||
{
 | 
			
		||||
    public const MSG_KEY = 'export.list.activity.';
 | 
			
		||||
 | 
			
		||||
    private ActivityPresenceRepositoryInterface $activityPresenceRepository;
 | 
			
		||||
 | 
			
		||||
    private ActivityTypeRepositoryInterface $activityTypeRepository;
 | 
			
		||||
 | 
			
		||||
    private DateTimeHelper $dateTimeHelper;
 | 
			
		||||
 | 
			
		||||
    private LabelPersonHelper $labelPersonHelper;
 | 
			
		||||
 | 
			
		||||
    private LabelThirdPartyHelper $labelThirdPartyHelper;
 | 
			
		||||
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    private TranslatableStringExportLabelHelper $translatableStringLabelHelper;
 | 
			
		||||
 | 
			
		||||
    private TranslatorInterface $translator;
 | 
			
		||||
 | 
			
		||||
    private UserHelper $userHelper;
 | 
			
		||||
    final public const MSG_KEY = 'export.list.activity.';
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ActivityPresenceRepositoryInterface $activityPresenceRepository,
 | 
			
		||||
        ActivityTypeRepositoryInterface $activityTypeRepository,
 | 
			
		||||
        DateTimeHelper $dateTimeHelper,
 | 
			
		||||
        LabelPersonHelper $labelPersonHelper,
 | 
			
		||||
        LabelThirdPartyHelper $labelThirdPartyHelper,
 | 
			
		||||
        TranslatorInterface $translator,
 | 
			
		||||
        TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        TranslatableStringExportLabelHelper $translatableStringLabelHelper,
 | 
			
		||||
        UserHelper $userHelper
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->activityPresenceRepository = $activityPresenceRepository;
 | 
			
		||||
        $this->activityTypeRepository = $activityTypeRepository;
 | 
			
		||||
        $this->dateTimeHelper = $dateTimeHelper;
 | 
			
		||||
        $this->labelPersonHelper = $labelPersonHelper;
 | 
			
		||||
        $this->labelThirdPartyHelper = $labelThirdPartyHelper;
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
        $this->translatableStringLabelHelper = $translatableStringLabelHelper;
 | 
			
		||||
        $this->userHelper = $userHelper;
 | 
			
		||||
    }
 | 
			
		||||
        private readonly ActivityPresenceRepositoryInterface $activityPresenceRepository,
 | 
			
		||||
        private readonly ActivityTypeRepositoryInterface $activityTypeRepository,
 | 
			
		||||
        private readonly DateTimeHelper $dateTimeHelper,
 | 
			
		||||
        private readonly LabelPersonHelper $labelPersonHelper,
 | 
			
		||||
        private readonly LabelThirdPartyHelper $labelThirdPartyHelper,
 | 
			
		||||
        private readonly TranslatorInterface $translator,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        private readonly TranslatableStringExportLabelHelper $translatableStringLabelHelper,
 | 
			
		||||
        private readonly UserHelper $userHelper
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addSelect(QueryBuilder $qb): void
 | 
			
		||||
    {
 | 
			
		||||
@@ -85,7 +55,7 @@ class ListActivityHelper
 | 
			
		||||
            ->addSelect('AGGREGATE(actPerson.id) AS personsNames')
 | 
			
		||||
            ->leftJoin('activity.users', 'users_u')
 | 
			
		||||
            ->addSelect('AGGREGATE(users_u.id) AS usersIds')
 | 
			
		||||
            ->addSelect('AGGREGATE(users_u.id) AS usersNames')
 | 
			
		||||
            ->addSelect('AGGREGATE(JSON_BUILD_OBJECT(\'uid\', users_u.id, \'d\', activity.date)) AS usersNames')
 | 
			
		||||
            ->leftJoin('activity.thirdParties', 'thirdparty')
 | 
			
		||||
            ->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesIds')
 | 
			
		||||
            ->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesNames')
 | 
			
		||||
@@ -96,9 +66,9 @@ class ListActivityHelper
 | 
			
		||||
            ->leftJoin('activity.location', 'location')
 | 
			
		||||
            ->addSelect('location.name AS locationName')
 | 
			
		||||
            ->addSelect('activity.sentReceived')
 | 
			
		||||
            ->addSelect('IDENTITY(activity.createdBy) AS createdBy')
 | 
			
		||||
            ->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(activity.createdBy), \'d\', activity.createdAt) AS createdBy')
 | 
			
		||||
            ->addSelect('activity.createdAt')
 | 
			
		||||
            ->addSelect('IDENTITY(activity.updatedBy) AS updatedBy')
 | 
			
		||||
            ->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(activity.updatedBy), \'d\', activity.updatedAt) AS updatedBy')
 | 
			
		||||
            ->addSelect('activity.updatedAt')
 | 
			
		||||
            ->addGroupBy('activity.id')
 | 
			
		||||
            ->addGroupBy('location.id');
 | 
			
		||||
@@ -113,113 +83,78 @@ class ListActivityHelper
 | 
			
		||||
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        switch ($key) {
 | 
			
		||||
            case 'createdAt':
 | 
			
		||||
            case 'updatedAt':
 | 
			
		||||
                return $this->dateTimeHelper->getLabel($key);
 | 
			
		||||
        return match ($key) {
 | 
			
		||||
            'createdAt', 'updatedAt' => $this->dateTimeHelper->getLabel($key),
 | 
			
		||||
            'createdBy', 'updatedBy' => $this->userHelper->getLabel($key, $values, $key),
 | 
			
		||||
            'date' => $this->dateTimeHelper->getLabel(self::MSG_KEY.$key),
 | 
			
		||||
            'attendeeName' => function ($value) {
 | 
			
		||||
                if ('_header' === $value) {
 | 
			
		||||
                    return 'Attendee';
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            case 'createdBy':
 | 
			
		||||
            case 'updatedBy':
 | 
			
		||||
                return $this->userHelper->getLabel($key, $values, $key);
 | 
			
		||||
                if (null === $value || null === $presence = $this->activityPresenceRepository->find($value)) {
 | 
			
		||||
                    return '';
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            case 'date':
 | 
			
		||||
                return $this->dateTimeHelper->getLabel(self::MSG_KEY . $key);
 | 
			
		||||
                return $this->translatableStringHelper->localize($presence->getName());
 | 
			
		||||
            },
 | 
			
		||||
            'listReasons' => $this->translatableStringLabelHelper->getLabelMulti($key, $values, 'Activity Reasons'),
 | 
			
		||||
            'typeName' => function ($value) {
 | 
			
		||||
                if ('_header' === $value) {
 | 
			
		||||
                    return 'Activity type';
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            case 'attendeeName':
 | 
			
		||||
                return function ($value) {
 | 
			
		||||
                    if ('_header' === $value) {
 | 
			
		||||
                        return 'Attendee';
 | 
			
		||||
                    }
 | 
			
		||||
                if (null === $value || null === $type = $this->activityTypeRepository->find($value)) {
 | 
			
		||||
                    return '';
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                    if (null === $value || null === $presence = $this->activityPresenceRepository->find($value)) {
 | 
			
		||||
                        return '';
 | 
			
		||||
                    }
 | 
			
		||||
                return $this->translatableStringHelper->localize($type->getName());
 | 
			
		||||
            },
 | 
			
		||||
            'usersNames' => $this->userHelper->getLabelMulti($key, $values, self::MSG_KEY.'users name'),
 | 
			
		||||
            'usersIds', 'thirdPartiesIds', 'personsIds' => static function ($value) use ($key) {
 | 
			
		||||
                if ('_header' === $value) {
 | 
			
		||||
                    return match ($key) {
 | 
			
		||||
                        'usersIds' => self::MSG_KEY.'users ids',
 | 
			
		||||
                        'thirdPartiesIds' => self::MSG_KEY.'third parties ids',
 | 
			
		||||
                        'personsIds' => self::MSG_KEY.'persons ids',
 | 
			
		||||
                    };
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                    return $this->translatableStringHelper->localize($presence->getName());
 | 
			
		||||
                };
 | 
			
		||||
                $decoded = json_decode((string) $value, null, 512, JSON_THROW_ON_ERROR);
 | 
			
		||||
 | 
			
		||||
            case 'listReasons':
 | 
			
		||||
                return $this->translatableStringLabelHelper->getLabelMulti($key, $values, 'Activity Reasons');
 | 
			
		||||
                return implode(
 | 
			
		||||
                    '|',
 | 
			
		||||
                    array_unique(
 | 
			
		||||
                        array_filter($decoded, static fn (?int $id) => null !== $id),
 | 
			
		||||
                        \SORT_NUMERIC
 | 
			
		||||
                    )
 | 
			
		||||
                );
 | 
			
		||||
            },
 | 
			
		||||
            'personsNames' => $this->labelPersonHelper->getLabelMulti($key, $values, self::MSG_KEY.'persons name'),
 | 
			
		||||
            'thirdPartiesNames' => $this->labelThirdPartyHelper->getLabelMulti($key, $values, self::MSG_KEY.'thirds parties'),
 | 
			
		||||
            'sentReceived' => function ($value) {
 | 
			
		||||
                if ('_header' === $value) {
 | 
			
		||||
                    return self::MSG_KEY.'sent received';
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            case 'typeName':
 | 
			
		||||
                return function ($value) {
 | 
			
		||||
                    if ('_header' === $value) {
 | 
			
		||||
                        return 'Activity type';
 | 
			
		||||
                    }
 | 
			
		||||
                if (null === $value) {
 | 
			
		||||
                    return '';
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                    if (null === $value || null === $type = $this->activityTypeRepository->find($value)) {
 | 
			
		||||
                        return '';
 | 
			
		||||
                    }
 | 
			
		||||
                return $this->translator->trans($value);
 | 
			
		||||
            },
 | 
			
		||||
            default => function ($value) use ($key) {
 | 
			
		||||
                if ('_header' === $value) {
 | 
			
		||||
                    return self::MSG_KEY.$key;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                    return $this->translatableStringHelper->localize($type->getName());
 | 
			
		||||
                };
 | 
			
		||||
                if (null === $value) {
 | 
			
		||||
                    return '';
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            case 'usersNames':
 | 
			
		||||
                return $this->userHelper->getLabelMulti($key, $values, self::MSG_KEY . 'users name');
 | 
			
		||||
 | 
			
		||||
            case 'usersIds':
 | 
			
		||||
            case 'thirdPartiesIds':
 | 
			
		||||
            case 'personsIds':
 | 
			
		||||
                return static function ($value) use ($key) {
 | 
			
		||||
                    if ('_header' === $value) {
 | 
			
		||||
                        switch ($key) {
 | 
			
		||||
                            case 'usersIds':
 | 
			
		||||
                                return self::MSG_KEY . 'users ids';
 | 
			
		||||
 | 
			
		||||
                            case 'thirdPartiesIds':
 | 
			
		||||
                                return self::MSG_KEY . 'third parties ids';
 | 
			
		||||
 | 
			
		||||
                            case 'personsIds':
 | 
			
		||||
                                return self::MSG_KEY . 'persons ids';
 | 
			
		||||
 | 
			
		||||
                            default:
 | 
			
		||||
                                throw new LogicException('key not supported');
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    $decoded = json_decode($value, null, 512, JSON_THROW_ON_ERROR);
 | 
			
		||||
 | 
			
		||||
                    return implode(
 | 
			
		||||
                        '|',
 | 
			
		||||
                        array_unique(
 | 
			
		||||
                            array_filter($decoded, static fn (?int $id) => null !== $id),
 | 
			
		||||
                            SORT_NUMERIC
 | 
			
		||||
                        )
 | 
			
		||||
                    );
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
            case 'personsNames':
 | 
			
		||||
                return $this->labelPersonHelper->getLabelMulti($key, $values, self::MSG_KEY . 'persons name');
 | 
			
		||||
 | 
			
		||||
            case 'thirdPartiesNames':
 | 
			
		||||
                return $this->labelThirdPartyHelper->getLabelMulti($key, $values, self::MSG_KEY . 'thirds parties');
 | 
			
		||||
 | 
			
		||||
            case 'sentReceived':
 | 
			
		||||
                return function ($value) {
 | 
			
		||||
                    if ('_header' === $value) {
 | 
			
		||||
                        return self::MSG_KEY . 'sent received';
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (null === $value) {
 | 
			
		||||
                        return '';
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return $this->translator->trans($value);
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
                return function ($value) use ($key) {
 | 
			
		||||
                    if ('_header' === $value) {
 | 
			
		||||
                        return self::MSG_KEY . $key;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (null === $value) {
 | 
			
		||||
                        return '';
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return $this->translator->trans($value);
 | 
			
		||||
                };
 | 
			
		||||
        }
 | 
			
		||||
                return $this->translator->trans($value);
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getQueryKeys($data)
 | 
			
		||||
 
 | 
			
		||||
@@ -21,9 +21,6 @@ use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Filter accompanying period to keep only the one having at list one activity from the given ActivityType.
 | 
			
		||||
 */
 | 
			
		||||
class ActivityTypeFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
@@ -40,7 +37,7 @@ class ActivityTypeFilter implements FilterInterface
 | 
			
		||||
    {
 | 
			
		||||
        $qb->andWhere(
 | 
			
		||||
            $qb->expr()->exists(
 | 
			
		||||
                'SELECT 1 FROM ' . Activity::class . ' act_type_filter_activity
 | 
			
		||||
                'SELECT 1 FROM '.Activity::class.' act_type_filter_activity
 | 
			
		||||
                WHERE act_type_filter_activity.activityType IN (:act_type_filter_activity_types) AND act_type_filter_activity.accompanyingPeriod = acp'
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
@@ -57,13 +54,14 @@ class ActivityTypeFilter implements FilterInterface
 | 
			
		||||
        $builder->add('accepted_activitytypes', EntityType::class, [
 | 
			
		||||
            'class' => ActivityType::class,
 | 
			
		||||
            'choices' => $this->activityTypeRepository->findAllActive(),
 | 
			
		||||
            'choice_label' => fn (ActivityType $aty) => ($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()) . ' > ' : '')
 | 
			
		||||
            'choice_label' => fn (ActivityType $aty) => ($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()).' > ' : '')
 | 
			
		||||
            .
 | 
			
		||||
            $this->translatableStringHelper->localize($aty->getName()),
 | 
			
		||||
            'multiple' => true,
 | 
			
		||||
            'expanded' => true,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -18,16 +18,10 @@ use Chill\PersonBundle\Form\Type\PickSocialActionType;
 | 
			
		||||
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class BySocialActionFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    private SocialActionRender $actionRender;
 | 
			
		||||
 | 
			
		||||
    public function __construct(SocialActionRender $actionRender)
 | 
			
		||||
    {
 | 
			
		||||
        $this->actionRender = $actionRender;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly SocialActionRender $actionRender) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -36,7 +30,7 @@ class BySocialActionFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('actsocialaction', $qb->getAllAliases(), true)) {
 | 
			
		||||
        if (!\in_array('actsocialaction', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->join('activity.socialActions', 'actsocialaction');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -60,6 +54,7 @@ class BySocialActionFilter implements FilterInterface
 | 
			
		||||
            'multiple' => true,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -18,16 +18,10 @@ use Chill\PersonBundle\Form\Type\PickSocialIssueType;
 | 
			
		||||
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class BySocialIssueFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    private SocialIssueRender $issueRender;
 | 
			
		||||
 | 
			
		||||
    public function __construct(SocialIssueRender $issueRender)
 | 
			
		||||
    {
 | 
			
		||||
        $this->issueRender = $issueRender;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly SocialIssueRender $issueRender) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -36,7 +30,7 @@ class BySocialIssueFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('actsocialissue', $qb->getAllAliases(), true)) {
 | 
			
		||||
        if (!\in_array('actsocialissue', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->join('activity.socialIssues', 'actsocialissue');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -60,6 +54,7 @@ class BySocialIssueFilter implements FilterInterface
 | 
			
		||||
            'multiple' => true,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Filter accompanying periods to keep only the one without any activity
 | 
			
		||||
 * Filter accompanying periods to keep only the one without any activity.
 | 
			
		||||
 */
 | 
			
		||||
class HasNoActivityFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
@@ -32,7 +32,7 @@ class HasNoActivityFilter implements FilterInterface
 | 
			
		||||
        $qb
 | 
			
		||||
            ->andWhere('
 | 
			
		||||
                NOT EXISTS (
 | 
			
		||||
                    SELECT 1 FROM ' . Activity::class . ' activity
 | 
			
		||||
                    SELECT 1 FROM '.Activity::class.' activity
 | 
			
		||||
                    WHERE activity.accompanyingPeriod = acp
 | 
			
		||||
                )
 | 
			
		||||
            ');
 | 
			
		||||
@@ -45,8 +45,9 @@ class HasNoActivityFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
        //no form needed
 | 
			
		||||
        // no form needed
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -34,10 +34,10 @@ final readonly class PeriodHavingActivityBetweenDatesFilter implements FilterInt
 | 
			
		||||
    {
 | 
			
		||||
        $builder
 | 
			
		||||
            ->add('start_date', PickRollingDateType::class, [
 | 
			
		||||
                'label' => 'export.filter.activity.course_having_activity_between_date.Receiving an activity after'
 | 
			
		||||
                'label' => 'export.filter.activity.course_having_activity_between_date.Receiving an activity after',
 | 
			
		||||
            ])
 | 
			
		||||
            ->add('end_date', PickRollingDateType::class, [
 | 
			
		||||
                'label' => 'export.filter.activity.course_having_activity_between_date.Receiving an activity before'
 | 
			
		||||
                'label' => 'export.filter.activity.course_having_activity_between_date.Receiving an activity before',
 | 
			
		||||
            ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -45,7 +45,7 @@ final readonly class PeriodHavingActivityBetweenDatesFilter implements FilterInt
 | 
			
		||||
    {
 | 
			
		||||
        return [
 | 
			
		||||
            'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START),
 | 
			
		||||
            'end_date' => new RollingDate(RollingDate::T_TODAY)
 | 
			
		||||
            'end_date' => new RollingDate(RollingDate::T_TODAY),
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -56,7 +56,7 @@ final readonly class PeriodHavingActivityBetweenDatesFilter implements FilterInt
 | 
			
		||||
            [
 | 
			
		||||
                'from' => $this->rollingDateConverter->convert($data['start_date']),
 | 
			
		||||
                'to' => $this->rollingDateConverter->convert($data['end_date']),
 | 
			
		||||
            ]
 | 
			
		||||
            ],
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -73,7 +73,7 @@ final readonly class PeriodHavingActivityBetweenDatesFilter implements FilterInt
 | 
			
		||||
 | 
			
		||||
        $qb->andWhere(
 | 
			
		||||
            $qb->expr()->exists(
 | 
			
		||||
                'SELECT 1 FROM ' . Activity::class . " {$alias} WHERE {$alias}.date >= :{$from} AND {$alias}.date < :{$to} AND {$alias}.accompanyingPeriod = acp"
 | 
			
		||||
                'SELECT 1 FROM '.Activity::class." {$alias} WHERE {$alias}.date >= :{$from} AND {$alias}.date < :{$to} AND {$alias}.accompanyingPeriod = acp"
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -27,17 +27,7 @@ use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
 | 
			
		||||
class ActivityDateFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    protected TranslatorInterface $translator;
 | 
			
		||||
 | 
			
		||||
    private RollingDateConverterInterface $rollingDateConverter;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        TranslatorInterface $translator,
 | 
			
		||||
        RollingDateConverterInterface $rollingDateConverter
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
        $this->rollingDateConverter = $rollingDateConverter;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(protected TranslatorInterface $translator, private readonly RollingDateConverterInterface $rollingDateConverter) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -100,14 +90,14 @@ class ActivityDateFilter implements FilterInterface
 | 
			
		||||
                if (null === $date_from) {
 | 
			
		||||
                    $form->get('date_from')->addError(new FormError(
 | 
			
		||||
                        $this->translator->trans('This field '
 | 
			
		||||
                        . 'should not be empty')
 | 
			
		||||
                        .'should not be empty')
 | 
			
		||||
                    ));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (null === $date_to) {
 | 
			
		||||
                    $form->get('date_to')->addError(new FormError(
 | 
			
		||||
                        $this->translator->trans('This field '
 | 
			
		||||
                        . 'should not be empty')
 | 
			
		||||
                        .'should not be empty')
 | 
			
		||||
                    ));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@@ -118,13 +108,14 @@ class ActivityDateFilter implements FilterInterface
 | 
			
		||||
                ) {
 | 
			
		||||
                    $form->get('date_to')->addError(new FormError(
 | 
			
		||||
                        $this->translator->trans('This date should be after '
 | 
			
		||||
                            . 'the date given in "Implied in an activity after '
 | 
			
		||||
                            . 'this date" field')
 | 
			
		||||
                            .'the date given in "Implied in an activity after '
 | 
			
		||||
                            .'this date" field')
 | 
			
		||||
                    ));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return ['date_from' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), 'date_to' => new RollingDate(RollingDate::T_TODAY)];
 | 
			
		||||
 
 | 
			
		||||
@@ -22,21 +22,12 @@ use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
 | 
			
		||||
 | 
			
		||||
use function count;
 | 
			
		||||
 | 
			
		||||
class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    protected ActivityTypeRepositoryInterface $activityTypeRepository;
 | 
			
		||||
 | 
			
		||||
    protected TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        ActivityTypeRepositoryInterface $activityTypeRepository
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
        $this->activityTypeRepository = $activityTypeRepository;
 | 
			
		||||
    }
 | 
			
		||||
        protected TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        protected ActivityTypeRepositoryInterface $activityTypeRepository
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -61,7 +52,7 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
 | 
			
		||||
        $builder->add('types', EntityType::class, [
 | 
			
		||||
            'choices' => $this->activityTypeRepository->findAllActive(),
 | 
			
		||||
            'class' => ActivityType::class,
 | 
			
		||||
            'choice_label' => fn (ActivityType $aty) => ($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()) . ' > ' : '')
 | 
			
		||||
            'choice_label' => fn (ActivityType $aty) => ($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()).' > ' : '')
 | 
			
		||||
            .
 | 
			
		||||
            $this->translatableStringHelper->localize($aty->getName()),
 | 
			
		||||
            'group_by' => function (ActivityType $type) {
 | 
			
		||||
@@ -78,6 +69,7 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
 | 
			
		||||
            ],
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -103,7 +95,7 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
 | 
			
		||||
 | 
			
		||||
    public function validateForm($data, ExecutionContextInterface $context)
 | 
			
		||||
    {
 | 
			
		||||
        if (null === $data['types'] || count($data['types']) === 0) {
 | 
			
		||||
        if (null === $data['types'] || 0 === \count($data['types'])) {
 | 
			
		||||
            $context
 | 
			
		||||
                ->buildViolation('At least one type must be chosen')
 | 
			
		||||
                ->addViolation();
 | 
			
		||||
 
 | 
			
		||||
@@ -20,12 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class ActivityUsersFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    private UserRender $userRender;
 | 
			
		||||
 | 
			
		||||
    public function __construct(UserRender $userRender)
 | 
			
		||||
    {
 | 
			
		||||
        $this->userRender = $userRender;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly UserRender $userRender) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -37,8 +32,8 @@ class ActivityUsersFilter implements FilterInterface
 | 
			
		||||
        $orX = $qb->expr()->orX();
 | 
			
		||||
 | 
			
		||||
        foreach ($data['accepted_users'] as $key => $user) {
 | 
			
		||||
            $orX->add($qb->expr()->isMemberOf(':activity_users_filter_u' . $key, 'activity.users'));
 | 
			
		||||
            $qb->setParameter('activity_users_filter_u' . $key, $user);
 | 
			
		||||
            $orX->add($qb->expr()->isMemberOf(':activity_users_filter_u'.$key, 'activity.users'));
 | 
			
		||||
            $qb->setParameter('activity_users_filter_u'.$key, $user);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $qb->andWhere($orX);
 | 
			
		||||
@@ -56,6 +51,7 @@ class ActivityUsersFilter implements FilterInterface
 | 
			
		||||
            'label' => 'Users',
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -20,12 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class ByCreatorFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    private UserRender $userRender;
 | 
			
		||||
 | 
			
		||||
    public function __construct(UserRender $userRender)
 | 
			
		||||
    {
 | 
			
		||||
        $this->userRender = $userRender;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly UserRender $userRender) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -52,6 +47,7 @@ class ByCreatorFilter implements FilterInterface
 | 
			
		||||
            'multiple' => true,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -28,12 +28,7 @@ class EmergencyFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    private const DEFAULT_CHOICE = 'false';
 | 
			
		||||
 | 
			
		||||
    private TranslatorInterface $translator;
 | 
			
		||||
 | 
			
		||||
    public function __construct(TranslatorInterface $translator)
 | 
			
		||||
    {
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly TranslatorInterface $translator) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -70,6 +65,7 @@ class EmergencyFilter implements FilterInterface
 | 
			
		||||
            'empty_data' => self::DEFAULT_CHOICE,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return ['accepted_emergency' => self::DEFAULT_CHOICE];
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,6 @@ namespace Chill\ActivityBundle\Export\Filter;
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Export\FilterInterface;
 | 
			
		||||
use Chill\MainBundle\Form\Type\PickUserLocationType;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
@@ -46,6 +45,7 @@ class LocationFilter implements FilterInterface
 | 
			
		||||
            'label' => 'pick location',
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -18,16 +18,10 @@ use Chill\MainBundle\Templating\TranslatableStringHelper;
 | 
			
		||||
use Doctrine\ORM\Query\Expr\Andx;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class LocationTypeFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    private TranslatableStringHelper $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(TranslatableStringHelper $translatableStringHelper)
 | 
			
		||||
    {
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -36,7 +30,7 @@ class LocationTypeFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('actloc', $qb->getAllAliases(), true)) {
 | 
			
		||||
        if (!\in_array('actloc', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->join('activity.location', 'actloc');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -62,9 +56,10 @@ class LocationTypeFilter implements FilterInterface
 | 
			
		||||
    {
 | 
			
		||||
        $builder->add('accepted_locationtype', PickLocationTypeType::class, [
 | 
			
		||||
            'multiple' => true,
 | 
			
		||||
            //'label' => false,
 | 
			
		||||
            // 'label' => false,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -17,29 +17,15 @@ use Chill\ActivityBundle\Repository\ActivityReasonRepository;
 | 
			
		||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
 | 
			
		||||
use Chill\MainBundle\Export\FilterInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Doctrine\ORM\Query\Expr;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
 | 
			
		||||
 | 
			
		||||
use function count;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    protected ActivityReasonRepository $activityReasonRepository;
 | 
			
		||||
 | 
			
		||||
    protected TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        TranslatableStringHelper $helper,
 | 
			
		||||
        ActivityReasonRepository $activityReasonRepository
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->translatableStringHelper = $helper;
 | 
			
		||||
        $this->activityReasonRepository = $activityReasonRepository;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(protected TranslatableStringHelper $translatableStringHelper, protected ActivityReasonRepository $activityReasonRepository) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -52,7 +38,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
 | 
			
		||||
        $join = $qb->getDQLPart('join');
 | 
			
		||||
        $clause = $qb->expr()->in('actreasons', ':selected_activity_reasons');
 | 
			
		||||
 | 
			
		||||
        if (!in_array('actreasons', $qb->getAllAliases(), true)) {
 | 
			
		||||
        if (!\in_array('actreasons', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->join('activity.reasons', 'actreasons');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -82,6 +68,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
 | 
			
		||||
            'expanded' => false,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
@@ -91,7 +78,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
 | 
			
		||||
    {
 | 
			
		||||
        // collect all the reasons'name used in this filter in one array
 | 
			
		||||
        $reasonsNames = array_map(
 | 
			
		||||
            fn (ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"',
 | 
			
		||||
            fn (ActivityReason $r): string => '"'.$this->translatableStringHelper->localize($r->getName()).'"',
 | 
			
		||||
            $this->activityReasonRepository->findBy(['id' => $data['reasons']->toArray()])
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
@@ -110,7 +97,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
 | 
			
		||||
 | 
			
		||||
    public function validateForm($data, ExecutionContextInterface $context)
 | 
			
		||||
    {
 | 
			
		||||
        if (null === $data['reasons'] || count($data['reasons']) === 0) {
 | 
			
		||||
        if (null === $data['reasons'] || 0 === \count($data['reasons'])) {
 | 
			
		||||
            $context
 | 
			
		||||
                ->buildViolation('At least one reason must be chosen')
 | 
			
		||||
                ->addViolation();
 | 
			
		||||
 
 | 
			
		||||
@@ -16,46 +16,23 @@ use Chill\ActivityBundle\Entity\ActivityReason;
 | 
			
		||||
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
 | 
			
		||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
 | 
			
		||||
use Chill\MainBundle\Export\FilterInterface;
 | 
			
		||||
use Chill\MainBundle\Form\Type\Export\FilterType;
 | 
			
		||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
 | 
			
		||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
 | 
			
		||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Chill\PersonBundle\Export\Declarations;
 | 
			
		||||
use DateTime;
 | 
			
		||||
use Doctrine\ORM\Query\Expr;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use Symfony\Component\Form\FormError;
 | 
			
		||||
use Symfony\Component\Form\FormEvent;
 | 
			
		||||
use Symfony\Component\Form\FormEvents;
 | 
			
		||||
use Symfony\Component\Form\FormInterface;
 | 
			
		||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
 | 
			
		||||
use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
 | 
			
		||||
use function count;
 | 
			
		||||
 | 
			
		||||
class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInterface, FilterInterface
 | 
			
		||||
final readonly class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInterface, FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    protected ActivityReasonRepository $activityReasonRepository;
 | 
			
		||||
 | 
			
		||||
    protected TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    protected TranslatorInterface $translator;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        TranslatableStringHelper                       $translatableStringHelper,
 | 
			
		||||
        ActivityReasonRepository                       $activityReasonRepository,
 | 
			
		||||
        TranslatorInterface                            $translator,
 | 
			
		||||
        private readonly RollingDateConverterInterface $rollingDateConverter,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
        $this->activityReasonRepository = $activityReasonRepository;
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
    }
 | 
			
		||||
        private TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
        private ActivityReasonRepository $activityReasonRepository,
 | 
			
		||||
        private RollingDateConverterInterface $rollingDateConverter,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -72,11 +49,11 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
 | 
			
		||||
 | 
			
		||||
        // add clause between date
 | 
			
		||||
        $sqb->where('activity_person_having_activity.date BETWEEN '
 | 
			
		||||
            . ':person_having_activity_between_date_from'
 | 
			
		||||
            . ' AND '
 | 
			
		||||
            . ':person_having_activity_between_date_to'
 | 
			
		||||
            . ' AND '
 | 
			
		||||
            . '(person_person_having_activity.id = person.id OR person MEMBER OF activity_person_having_activity.persons)');
 | 
			
		||||
            .':person_having_activity_between_date_from'
 | 
			
		||||
            .' AND '
 | 
			
		||||
            .':person_having_activity_between_date_to'
 | 
			
		||||
            .' AND '
 | 
			
		||||
            .'(person_person_having_activity.id = person.id OR person MEMBER OF activity_person_having_activity.persons)');
 | 
			
		||||
 | 
			
		||||
        if (isset($data['reasons']) && [] !== $data['reasons']) {
 | 
			
		||||
            // add clause activity reason
 | 
			
		||||
@@ -134,6 +111,7 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
 | 
			
		||||
            ]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [
 | 
			
		||||
@@ -155,7 +133,7 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
 | 
			
		||||
                'reasons' => implode(
 | 
			
		||||
                    ', ',
 | 
			
		||||
                    array_map(
 | 
			
		||||
                        fn (ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"',
 | 
			
		||||
                        fn (ActivityReason $r): string => '"'.$this->translatableStringHelper->localize($r->getName()).'"',
 | 
			
		||||
                        $data['reasons']
 | 
			
		||||
                    )
 | 
			
		||||
                ),
 | 
			
		||||
 
 | 
			
		||||
@@ -29,12 +29,7 @@ class SentReceivedFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    private const DEFAULT_CHOICE = Activity::SENTRECEIVED_SENT;
 | 
			
		||||
 | 
			
		||||
    private TranslatorInterface $translator;
 | 
			
		||||
 | 
			
		||||
    public function __construct(TranslatorInterface $translator)
 | 
			
		||||
    {
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly TranslatorInterface $translator) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -71,6 +66,7 @@ class SentReceivedFilter implements FilterInterface
 | 
			
		||||
            'empty_data' => self::DEFAULT_CHOICE,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return ['accepted_sentreceived' => self::DEFAULT_CHOICE];
 | 
			
		||||
 
 | 
			
		||||
@@ -21,12 +21,7 @@ use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class UserFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    private UserRender $userRender;
 | 
			
		||||
 | 
			
		||||
    public function __construct(UserRender $userRender)
 | 
			
		||||
    {
 | 
			
		||||
        $this->userRender = $userRender;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly UserRender $userRender) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -61,6 +56,7 @@ class UserFilter implements FilterInterface
 | 
			
		||||
            'label' => 'Creators',
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
 
 | 
			
		||||
@@ -13,22 +13,21 @@ namespace Chill\ActivityBundle\Export\Filter;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Entity\Scope;
 | 
			
		||||
use Chill\MainBundle\Entity\User\UserScopeHistory;
 | 
			
		||||
use Chill\MainBundle\Export\FilterInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
 | 
			
		||||
use Doctrine\ORM\Query\Expr\Andx;
 | 
			
		||||
use Doctrine\ORM\Query\Expr\Join;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class UserScopeFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    private TranslatableStringHelper $translatableStringHelper;
 | 
			
		||||
    private const PREFIX = 'acp_act_filter_user_scope';  // creator ? cfr translation
 | 
			
		||||
 | 
			
		||||
    public function __construct(TranslatableStringHelper $translatableStringHelper)
 | 
			
		||||
    {
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -37,22 +36,33 @@ class UserScopeFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('actuser', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->join('activity.user', 'actuser');
 | 
			
		||||
        }
 | 
			
		||||
        $p = self::PREFIX;
 | 
			
		||||
 | 
			
		||||
        $where = $qb->getDQLPart('where');
 | 
			
		||||
 | 
			
		||||
        $clause = $qb->expr()->in('actuser.mainScope', ':userscope');
 | 
			
		||||
 | 
			
		||||
        if ($where instanceof Andx) {
 | 
			
		||||
            $where->add($clause);
 | 
			
		||||
        } else {
 | 
			
		||||
            $where = $qb->expr()->andX($clause);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $qb->add('where', $where);
 | 
			
		||||
        $qb->setParameter('userscope', $data['accepted_userscope']);
 | 
			
		||||
        $qb
 | 
			
		||||
            ->leftJoin('activity.user', "{$p}_user")  // createdBy ? cfr translation
 | 
			
		||||
            ->leftJoin(
 | 
			
		||||
                UserScopeHistory::class,
 | 
			
		||||
                "{$p}_history",
 | 
			
		||||
                Join::WITH,
 | 
			
		||||
                $qb->expr()->eq("{$p}_history.user", "{$p}_user")
 | 
			
		||||
            )
 | 
			
		||||
            // scope_at based on activity.date
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->andX(
 | 
			
		||||
                    $qb->expr()->lte("{$p}_history.startDate", 'activity.date'),
 | 
			
		||||
                    $qb->expr()->orX(
 | 
			
		||||
                        $qb->expr()->isNull("{$p}_history.endDate"),
 | 
			
		||||
                        $qb->expr()->gt("{$p}_history.endDate", 'activity.date')
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->in("{$p}_history.scope", ":{$p}_scopes")
 | 
			
		||||
            )
 | 
			
		||||
            ->setParameter(
 | 
			
		||||
                "{$p}_scopes",
 | 
			
		||||
                $data['scopes'],
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function applyOn(): string
 | 
			
		||||
@@ -62,37 +72,41 @@ class UserScopeFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
        $builder->add('accepted_userscope', EntityType::class, [
 | 
			
		||||
            'class' => Scope::class,
 | 
			
		||||
            'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize(
 | 
			
		||||
                $s->getName()
 | 
			
		||||
            ),
 | 
			
		||||
            'multiple' => true,
 | 
			
		||||
            'expanded' => true,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
        $builder
 | 
			
		||||
            ->add('scopes', EntityType::class, [
 | 
			
		||||
                'class' => Scope::class,
 | 
			
		||||
                'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize(
 | 
			
		||||
                    $s->getName()
 | 
			
		||||
                ),
 | 
			
		||||
                'multiple' => true,
 | 
			
		||||
                'expanded' => true,
 | 
			
		||||
            ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function describeAction($data, $format = 'string'): array
 | 
			
		||||
    {
 | 
			
		||||
        $scopes = [];
 | 
			
		||||
 | 
			
		||||
        foreach ($data['accepted_userscope'] as $s) {
 | 
			
		||||
        foreach ($data['scopes'] as $s) {
 | 
			
		||||
            $scopes[] = $this->translatableStringHelper->localize(
 | 
			
		||||
                $s->getName()
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return ['Filtered activity by userscope: only %scopes%', [
 | 
			
		||||
        return ['export.filter.activity.by_creator_scope.Filtered activity by user scope: only %scopes%', [
 | 
			
		||||
            '%scopes%' => implode(', ', $scopes),
 | 
			
		||||
        ]];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [
 | 
			
		||||
            'scopes' => [],
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'Filter activity by userscope';
 | 
			
		||||
        return 'export.filter.activity.by_creator_scope.Filter activity by user scope';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ namespace Chill\ActivityBundle\Export\Filter;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Entity\Activity;
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Entity\User\UserJobHistory;
 | 
			
		||||
use Chill\MainBundle\Entity\UserJob;
 | 
			
		||||
use Chill\MainBundle\Export\FilterInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
@@ -22,12 +23,11 @@ use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class UsersJobFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
    private const PREFIX = 'act_filter_user_job';
 | 
			
		||||
 | 
			
		||||
    public function __construct(TranslatableStringHelperInterface $translatableStringHelper)
 | 
			
		||||
    {
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -36,14 +36,25 @@ class UsersJobFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        $p = self::PREFIX;
 | 
			
		||||
 | 
			
		||||
        $qb
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->exists(
 | 
			
		||||
                    'SELECT 1 FROM ' . Activity::class . ' activity_users_job_filter_act
 | 
			
		||||
                JOIN activity_users_job_filter_act.users users WHERE users.userJob IN (:activity_users_job_filter_jobs) AND  activity_users_job_filter_act = activity '
 | 
			
		||||
                    'SELECT 1 FROM '.Activity::class." {$p}_act "
 | 
			
		||||
                    ."JOIN {$p}_act.users {$p}_user "
 | 
			
		||||
                    .'JOIN '.UserJobHistory::class." {$p}_history WITH {$p}_history.user = {$p}_user "
 | 
			
		||||
                    ."WHERE {$p}_act = activity "
 | 
			
		||||
                    // job_at based on activity.date
 | 
			
		||||
                    ."AND {$p}_history.startDate <= activity.date "
 | 
			
		||||
                    ."AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > activity.date) "
 | 
			
		||||
                    ."AND {$p}_history.job IN ( :{$p}_jobs )"
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            ->setParameter('activity_users_job_filter_jobs', $data['jobs']);
 | 
			
		||||
            ->setParameter(
 | 
			
		||||
                "{$p}_jobs",
 | 
			
		||||
                $data['jobs']
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function applyOn()
 | 
			
		||||
@@ -53,21 +64,18 @@ class UsersJobFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
        $builder->add('jobs', EntityType::class, [
 | 
			
		||||
            'class' => UserJob::class,
 | 
			
		||||
            'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()),
 | 
			
		||||
            'multiple' => true,
 | 
			
		||||
            'expanded' => true,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
        $builder
 | 
			
		||||
            ->add('jobs', EntityType::class, [
 | 
			
		||||
                'class' => UserJob::class,
 | 
			
		||||
                'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()),
 | 
			
		||||
                'multiple' => true,
 | 
			
		||||
                'expanded' => true,
 | 
			
		||||
            ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function describeAction($data, $format = 'string')
 | 
			
		||||
    {
 | 
			
		||||
        return ['export.filter.activity.by_usersjob.Filtered activity by users job: only %jobs%', [
 | 
			
		||||
        return ['export.filter.activity.by_users_job.Filtered activity by users job: only %jobs%', [
 | 
			
		||||
            '%jobs%' => implode(
 | 
			
		||||
                ', ',
 | 
			
		||||
                array_map(
 | 
			
		||||
@@ -78,8 +86,15 @@ class UsersJobFilter implements FilterInterface
 | 
			
		||||
        ]];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [
 | 
			
		||||
            'jobs' => [],
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle()
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.filter.activity.by_usersjob.Filter by users job';
 | 
			
		||||
        return 'export.filter.activity.by_users_job.Filter by users job';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Filter;
 | 
			
		||||
use Chill\ActivityBundle\Entity\Activity;
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Entity\Scope;
 | 
			
		||||
use Chill\MainBundle\Entity\User\UserScopeHistory;
 | 
			
		||||
use Chill\MainBundle\Export\FilterInterface;
 | 
			
		||||
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
@@ -23,17 +24,12 @@ use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class UsersScopeFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    private ScopeRepositoryInterface $scopeRepository;
 | 
			
		||||
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
    private const PREFIX = 'act_filter_user_scope';
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ScopeRepositoryInterface $scopeRepository,
 | 
			
		||||
        TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->scopeRepository = $scopeRepository;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
        private readonly ScopeRepositoryInterface $scopeRepository,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
@@ -42,39 +38,47 @@ class UsersScopeFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        $p = self::PREFIX;
 | 
			
		||||
 | 
			
		||||
        $qb
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->exists(
 | 
			
		||||
                    'SELECT 1 FROM ' . Activity::class . ' activity_users_scope_filter_act
 | 
			
		||||
                JOIN activity_users_scope_filter_act.users users WHERE users.mainScope IN (:activity_users_scope_filter_scopes) AND  activity_users_scope_filter_act = activity '
 | 
			
		||||
                    'SELECT 1 FROM '.Activity::class." {$p}_act "
 | 
			
		||||
                    ."JOIN {$p}_act.users {$p}_user "
 | 
			
		||||
                    .'JOIN '.UserScopeHistory::class." {$p}_history WITH {$p}_history.user = {$p}_user "
 | 
			
		||||
                    ."WHERE {$p}_act = activity "
 | 
			
		||||
                    // scope_at based on activity.date
 | 
			
		||||
                    ."AND {$p}_history.startDate <= activity.date "
 | 
			
		||||
                    ."AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > activity.date) "
 | 
			
		||||
                    ."AND {$p}_history.scope IN ( :{$p}_scopes )"
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            ->setParameter('activity_users_scope_filter_scopes', $data['scopes']);
 | 
			
		||||
            ->setParameter(
 | 
			
		||||
                "{$p}_scopes",
 | 
			
		||||
                $data['scopes']
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function applyOn()
 | 
			
		||||
    public function applyOn(): string
 | 
			
		||||
    {
 | 
			
		||||
        return Declarations::ACTIVITY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
        $builder->add('scopes', EntityType::class, [
 | 
			
		||||
            'class' => Scope::class,
 | 
			
		||||
            'choices' => $this->scopeRepository->findAllActive(),
 | 
			
		||||
            'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()),
 | 
			
		||||
            'multiple' => true,
 | 
			
		||||
            'expanded' => true,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
        $builder
 | 
			
		||||
            ->add('scopes', EntityType::class, [
 | 
			
		||||
                'class' => Scope::class,
 | 
			
		||||
                'choices' => $this->scopeRepository->findAllActive(),
 | 
			
		||||
                'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()),
 | 
			
		||||
                'multiple' => true,
 | 
			
		||||
                'expanded' => true,
 | 
			
		||||
            ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function describeAction($data, $format = 'string')
 | 
			
		||||
    public function describeAction($data, $format = 'string'): array
 | 
			
		||||
    {
 | 
			
		||||
        return ['export.filter.activity.by_usersscope.Filtered activity by users scope: only %scopes%', [
 | 
			
		||||
        return ['export.filter.activity.by_users_scope.Filtered activity by users scope: only %scopes%', [
 | 
			
		||||
            '%scopes%' => implode(
 | 
			
		||||
                ', ',
 | 
			
		||||
                array_map(
 | 
			
		||||
@@ -85,8 +89,15 @@ class UsersScopeFilter implements FilterInterface
 | 
			
		||||
        ]];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle()
 | 
			
		||||
    public function getFormDefaultData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.filter.activity.by_usersscope.Filter by users scope';
 | 
			
		||||
        return [
 | 
			
		||||
            'scopes' => [],
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.filter.activity.by_users_scope.Filter by users scope';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -34,12 +34,8 @@ use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
 | 
			
		||||
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
 | 
			
		||||
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
 | 
			
		||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
 | 
			
		||||
use DateInterval;
 | 
			
		||||
use DateTime;
 | 
			
		||||
use DateTimeZone;
 | 
			
		||||
use Doctrine\ORM\EntityRepository;
 | 
			
		||||
use Doctrine\Persistence\ObjectManager;
 | 
			
		||||
use RuntimeException;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\AbstractType;
 | 
			
		||||
use Symfony\Component\Form\CallbackTransformer;
 | 
			
		||||
@@ -53,45 +49,24 @@ use Symfony\Component\Form\FormEvents;
 | 
			
		||||
use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
			
		||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
 | 
			
		||||
 | 
			
		||||
use Symfony\Component\Security\Core\Role\Role;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class ActivityType extends AbstractType
 | 
			
		||||
{
 | 
			
		||||
    protected AuthorizationHelper $authorizationHelper;
 | 
			
		||||
 | 
			
		||||
    protected ObjectManager $om;
 | 
			
		||||
 | 
			
		||||
    protected SocialActionRender $socialActionRender;
 | 
			
		||||
 | 
			
		||||
    protected SocialIssueRender $socialIssueRender;
 | 
			
		||||
 | 
			
		||||
    protected array $timeChoices;
 | 
			
		||||
 | 
			
		||||
    protected TranslatableStringHelper $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    protected User $user;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        TokenStorageInterface $tokenStorage,
 | 
			
		||||
        AuthorizationHelper $authorizationHelper,
 | 
			
		||||
        ObjectManager $om,
 | 
			
		||||
        TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
        array $timeChoices,
 | 
			
		||||
        SocialIssueRender $socialIssueRender,
 | 
			
		||||
        SocialActionRender $socialActionRender
 | 
			
		||||
        protected AuthorizationHelper $authorizationHelper,
 | 
			
		||||
        protected ObjectManager $om,
 | 
			
		||||
        protected TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
        protected array $timeChoices,
 | 
			
		||||
        protected SocialIssueRender $socialIssueRender,
 | 
			
		||||
        protected SocialActionRender $socialActionRender
 | 
			
		||||
    ) {
 | 
			
		||||
        if (!$tokenStorage->getToken()->getUser() instanceof User) {
 | 
			
		||||
            throw new RuntimeException('you should have a valid user');
 | 
			
		||||
            throw new \RuntimeException('you should have a valid user');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->user = $tokenStorage->getToken()->getUser();
 | 
			
		||||
        $this->authorizationHelper = $authorizationHelper;
 | 
			
		||||
        $this->om = $om;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
        $this->timeChoices = $timeChoices;
 | 
			
		||||
        $this->socialIssueRender = $socialIssueRender;
 | 
			
		||||
        $this->socialActionRender = $socialActionRender;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder, array $options): void
 | 
			
		||||
@@ -112,8 +87,7 @@ class ActivityType extends AbstractType
 | 
			
		||||
        /** @var \Chill\ActivityBundle\Entity\ActivityType $activityType */
 | 
			
		||||
        $activityType = $options['activityType'];
 | 
			
		||||
 | 
			
		||||
        // TODO revoir la gestion des center au niveau du form des activité.
 | 
			
		||||
        if ($options['center'] instanceof Center && null !== $options['data']->getPerson()) {
 | 
			
		||||
        if (null !== $options['data']->getPerson()) {
 | 
			
		||||
            $builder->add('scope', ScopePickerType::class, [
 | 
			
		||||
                'center' => $options['center'],
 | 
			
		||||
                'role' => ActivityVoter::CREATE === (string) $options['role'] ? ActivityVoter::CREATE_PERSON : (string) $options['role'],
 | 
			
		||||
@@ -121,16 +95,16 @@ class ActivityType extends AbstractType
 | 
			
		||||
            ]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /** @var ? \Chill\PersonBundle\Entity\AccompanyingPeriod  $accompanyingPeriod */
 | 
			
		||||
        /** @var \Chill\PersonBundle\Entity\AccompanyingPeriod|null $accompanyingPeriod */
 | 
			
		||||
        $accompanyingPeriod = null;
 | 
			
		||||
 | 
			
		||||
        if ($options['accompanyingPeriod'] instanceof AccompanyingPeriod) {
 | 
			
		||||
            $accompanyingPeriod = $options['accompanyingPeriod'];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($activityType->isVisible('socialIssues') && $accompanyingPeriod) {
 | 
			
		||||
        if ($activityType->isVisible('socialIssues') && null !== $accompanyingPeriod) {
 | 
			
		||||
            $builder->add('socialIssues', HiddenType::class, [
 | 
			
		||||
                'required' => $activityType->getSocialIssuesVisible() === 2,
 | 
			
		||||
                'required' => 2 === $activityType->getSocialIssuesVisible(),
 | 
			
		||||
            ]);
 | 
			
		||||
            $builder->get('socialIssues')
 | 
			
		||||
                ->addModelTransformer(new CallbackTransformer(
 | 
			
		||||
@@ -156,9 +130,9 @@ class ActivityType extends AbstractType
 | 
			
		||||
                ));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($activityType->isVisible('socialActions') && $accompanyingPeriod) {
 | 
			
		||||
        if ($activityType->isVisible('socialActions') && null !== $accompanyingPeriod) {
 | 
			
		||||
            $builder->add('socialActions', HiddenType::class, [
 | 
			
		||||
                'required' => $activityType->getSocialActionsVisible() === 2,
 | 
			
		||||
                'required' => 2 === $activityType->getSocialActionsVisible(),
 | 
			
		||||
            ]);
 | 
			
		||||
            $builder->get('socialActions')
 | 
			
		||||
                ->addModelTransformer(new CallbackTransformer(
 | 
			
		||||
@@ -217,7 +191,7 @@ class ActivityType extends AbstractType
 | 
			
		||||
            ]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($activityType->isVisible('user') && $options['center'] instanceof Center) {
 | 
			
		||||
        if ($activityType->isVisible('user')) {
 | 
			
		||||
            $builder->add('user', PickUserDynamicType::class, [
 | 
			
		||||
                'label' => $activityType->getLabel('user'),
 | 
			
		||||
                'required' => $activityType->isRequired('user'),
 | 
			
		||||
@@ -342,7 +316,7 @@ class ActivityType extends AbstractType
 | 
			
		||||
 | 
			
		||||
        if ($activityType->isVisible('location')) {
 | 
			
		||||
            $builder->add('location', HiddenType::class, [
 | 
			
		||||
                'required' => $activityType->getLocationVisible() === 2,
 | 
			
		||||
                'required' => 2 === $activityType->getLocationVisible(),
 | 
			
		||||
            ])
 | 
			
		||||
                ->get('location')
 | 
			
		||||
                ->addModelTransformer(new CallbackTransformer(
 | 
			
		||||
@@ -393,16 +367,16 @@ class ActivityType extends AbstractType
 | 
			
		||||
                ) {
 | 
			
		||||
                    // set the timezone to GMT, and fix the difference between current and GMT
 | 
			
		||||
                    // the datetimetransformer will then handle timezone as GMT
 | 
			
		||||
                    $timezoneUTC = new DateTimeZone('GMT');
 | 
			
		||||
                    /** @var DateTime $data */
 | 
			
		||||
                    $data = $formEvent->getData() ?? DateTime::createFromFormat('U', '300');
 | 
			
		||||
                    $timezoneUTC = new \DateTimeZone('GMT');
 | 
			
		||||
                    /** @var \DateTime $data */
 | 
			
		||||
                    $data = $formEvent->getData() ?? \DateTime::createFromFormat('U', '300');
 | 
			
		||||
                    $seconds = $data->getTimezone()->getOffset($data);
 | 
			
		||||
                    $data->setTimeZone($timezoneUTC);
 | 
			
		||||
                    $data->add(new DateInterval('PT' . $seconds . 'S'));
 | 
			
		||||
                    $data->add(new \DateInterval('PT'.$seconds.'S'));
 | 
			
		||||
 | 
			
		||||
                    // test if the timestamp is in the choices.
 | 
			
		||||
                    // If not, recreate the field with the new timestamp
 | 
			
		||||
                    if (!in_array($data->getTimestamp(), $timeChoices, true)) {
 | 
			
		||||
                    if (!\in_array($data->getTimestamp(), $timeChoices, true)) {
 | 
			
		||||
                        // the data are not in the possible values. add them
 | 
			
		||||
                        $timeChoices[$data->format('H:i')] = $data->getTimestamp();
 | 
			
		||||
                        $form = $builder->create($fieldName, ChoiceType::class, array_merge(
 | 
			
		||||
@@ -427,8 +401,8 @@ class ActivityType extends AbstractType
 | 
			
		||||
 | 
			
		||||
        $resolver
 | 
			
		||||
            ->setRequired(['center', 'role', 'activityType', 'accompanyingPeriod'])
 | 
			
		||||
            ->setAllowedTypes('center', ['null', Center::class])
 | 
			
		||||
            ->setAllowedTypes('role', [Role::class, 'string'])
 | 
			
		||||
            ->setAllowedTypes('center', ['null', Center::class, 'array'])
 | 
			
		||||
            ->setAllowedTypes('role', ['string'])
 | 
			
		||||
            ->setAllowedTypes('activityType', \Chill\ActivityBundle\Entity\ActivityType::class)
 | 
			
		||||
            ->setAllowedTypes('accompanyingPeriod', [\Chill\PersonBundle\Entity\AccompanyingPeriod::class, 'null']);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -25,12 +25,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
			
		||||
 | 
			
		||||
class ActivityTypeType extends AbstractType
 | 
			
		||||
{
 | 
			
		||||
    private TranslatableStringHelper $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(TranslatableStringHelper $translatableStringHelper)
 | 
			
		||||
    {
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) {}
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder, array $options)
 | 
			
		||||
    {
 | 
			
		||||
@@ -61,8 +56,8 @@ class ActivityTypeType extends AbstractType
 | 
			
		||||
 | 
			
		||||
        foreach ($fields as $field) {
 | 
			
		||||
            $builder
 | 
			
		||||
                ->add($field . 'Visible', ActivityFieldPresence::class)
 | 
			
		||||
                ->add($field . 'Label', TextType::class, [
 | 
			
		||||
                ->add($field.'Visible', ActivityFieldPresence::class)
 | 
			
		||||
                ->add($field.'Label', TextType::class, [
 | 
			
		||||
                    'required' => false,
 | 
			
		||||
                    'empty_data' => '',
 | 
			
		||||
                ]);
 | 
			
		||||
 
 | 
			
		||||
@@ -24,21 +24,11 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
			
		||||
 */
 | 
			
		||||
class PickActivityReasonType extends AbstractType
 | 
			
		||||
{
 | 
			
		||||
    private ActivityReasonRepository $activityReasonRepository;
 | 
			
		||||
 | 
			
		||||
    private ActivityReasonRender $reasonRender;
 | 
			
		||||
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ActivityReasonRepository $activityReasonRepository,
 | 
			
		||||
        ActivityReasonRender $reasonRender,
 | 
			
		||||
        TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->activityReasonRepository = $activityReasonRepository;
 | 
			
		||||
        $this->reasonRender = $reasonRender;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
        private readonly ActivityReasonRepository $activityReasonRepository,
 | 
			
		||||
        private readonly ActivityReasonRender $reasonRender,
 | 
			
		||||
        private readonly TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function configureOptions(OptionsResolver $resolver)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -23,15 +23,7 @@ use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
 */
 | 
			
		||||
class TranslatableActivityReasonCategoryType extends AbstractType
 | 
			
		||||
{
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    private TranslatorInterface $translator;
 | 
			
		||||
 | 
			
		||||
    public function __construct(TranslatableStringHelperInterface $translatableStringHelper, TranslatorInterface $translator)
 | 
			
		||||
    {
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private readonly TranslatableStringHelperInterface $translatableStringHelper, private readonly TranslatorInterface $translator) {}
 | 
			
		||||
 | 
			
		||||
    public function configureOptions(OptionsResolver $resolver)
 | 
			
		||||
    {
 | 
			
		||||
@@ -39,16 +31,11 @@ class TranslatableActivityReasonCategoryType extends AbstractType
 | 
			
		||||
            [
 | 
			
		||||
                'class' => ActivityReasonCategory::class,
 | 
			
		||||
                'choice_label' => fn (ActivityReasonCategory $category) => $this->translatableStringHelper->localize($category->getName())
 | 
			
		||||
                    . (!$category->getActive() ? ' (' . $this->translator->trans('inactive') . ')' : ''),
 | 
			
		||||
                    .(!$category->getActive() ? ' ('.$this->translator->trans('inactive').')' : ''),
 | 
			
		||||
            ]
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getBlockPrefix()
 | 
			
		||||
    {
 | 
			
		||||
        return 'translatable_activity_reason_category';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getParent()
 | 
			
		||||
    {
 | 
			
		||||
        return EntityType::class;
 | 
			
		||||
 
 | 
			
		||||
@@ -20,17 +20,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
			
		||||
 | 
			
		||||
class TranslatableActivityType extends AbstractType
 | 
			
		||||
{
 | 
			
		||||
    protected ActivityTypeRepositoryInterface $activityTypeRepository;
 | 
			
		||||
 | 
			
		||||
    protected TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        TranslatableStringHelperInterface $helper,
 | 
			
		||||
        ActivityTypeRepositoryInterface $activityTypeRepository
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->translatableStringHelper = $helper;
 | 
			
		||||
        $this->activityTypeRepository = $activityTypeRepository;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(protected TranslatableStringHelperInterface $translatableStringHelper, protected ActivityTypeRepositoryInterface $activityTypeRepository) {}
 | 
			
		||||
 | 
			
		||||
    public function configureOptions(OptionsResolver $resolver)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -23,17 +23,7 @@ use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
 */
 | 
			
		||||
class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
 | 
			
		||||
{
 | 
			
		||||
    protected Security $security;
 | 
			
		||||
 | 
			
		||||
    protected TranslatorInterface $translator;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        Security $security,
 | 
			
		||||
        TranslatorInterface $translator
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->security = $security;
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(protected Security $security, protected TranslatorInterface $translator) {}
 | 
			
		||||
 | 
			
		||||
    public function buildMenu($menuId, MenuItem $menu, array $parameters)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -18,14 +18,9 @@ use Symfony\Component\Security\Core\Security;
 | 
			
		||||
/**
 | 
			
		||||
 * @implements LocalMenuBuilderInterface<array>
 | 
			
		||||
 */
 | 
			
		||||
final class AdminMenuBuilder implements LocalMenuBuilderInterface
 | 
			
		||||
final readonly class AdminMenuBuilder implements LocalMenuBuilderInterface
 | 
			
		||||
{
 | 
			
		||||
    private Security $security;
 | 
			
		||||
 | 
			
		||||
    public function __construct(Security $security)
 | 
			
		||||
    {
 | 
			
		||||
        $this->security = $security;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private Security $security) {}
 | 
			
		||||
 | 
			
		||||
    public function buildMenu($menuId, MenuItem $menu, array $parameters)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -21,25 +21,9 @@ use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
/**
 | 
			
		||||
 * @implements LocalMenuBuilderInterface<array{person: Person}>
 | 
			
		||||
 */
 | 
			
		||||
final class PersonMenuBuilder implements LocalMenuBuilderInterface
 | 
			
		||||
final readonly class PersonMenuBuilder implements LocalMenuBuilderInterface
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var AuthorizationCheckerInterface
 | 
			
		||||
     */
 | 
			
		||||
    private $authorizationChecker;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var TranslatorInterface
 | 
			
		||||
     */
 | 
			
		||||
    private $translator;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        AuthorizationCheckerInterface $authorizationChecker,
 | 
			
		||||
        TranslatorInterface $translator
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
        $this->authorizationChecker = $authorizationChecker;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private AuthorizationCheckerInterface $authorizationChecker, private TranslatorInterface $translator) {}
 | 
			
		||||
 | 
			
		||||
    public function buildMenu($menuId, MenuItem $menu, array $parameters)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -16,14 +16,9 @@ use Chill\ActivityBundle\Repository\ActivityRepository;
 | 
			
		||||
use Chill\MainBundle\Entity\Notification;
 | 
			
		||||
use Chill\MainBundle\Notification\NotificationHandlerInterface;
 | 
			
		||||
 | 
			
		||||
final class ActivityNotificationHandler implements NotificationHandlerInterface
 | 
			
		||||
final readonly class ActivityNotificationHandler implements NotificationHandlerInterface
 | 
			
		||||
{
 | 
			
		||||
    private ActivityRepository $activityRepository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(ActivityRepository $activityRepository)
 | 
			
		||||
    {
 | 
			
		||||
        $this->activityRepository = $activityRepository;
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(private ActivityRepository $activityRepository) {}
 | 
			
		||||
 | 
			
		||||
    public function getTemplate(Notification $notification, array $options = []): string
 | 
			
		||||
    {
 | 
			
		||||
@@ -40,6 +35,6 @@ final class ActivityNotificationHandler implements NotificationHandlerInterface
 | 
			
		||||
 | 
			
		||||
    public function supports(Notification $notification, array $options = []): bool
 | 
			
		||||
    {
 | 
			
		||||
        return $notification->getRelatedEntityClass() === Activity::class;
 | 
			
		||||
        return Activity::class === $notification->getRelatedEntityClass();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -35,9 +35,6 @@ use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\HttpFoundation\RequestStack;
 | 
			
		||||
use Symfony\Component\Security\Core\Security;
 | 
			
		||||
 | 
			
		||||
use function count;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInterface
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
@@ -75,7 +72,6 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
 | 
			
		||||
        return $qb->getQuery()->getSingleScalarResult();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array
 | 
			
		||||
    {
 | 
			
		||||
        $qb = $this->buildBaseQuery($filters);
 | 
			
		||||
@@ -83,7 +79,7 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
 | 
			
		||||
        $qb->andWhere('a.accompanyingPeriod = :period')->setParameter('period', $period);
 | 
			
		||||
 | 
			
		||||
        foreach ($orderBy as $field => $order) {
 | 
			
		||||
            $qb->addOrderBy('a.' . $field, $order);
 | 
			
		||||
            $qb->addOrderBy('a.'.$field, $order);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (null !== $start) {
 | 
			
		||||
@@ -122,9 +118,30 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
 | 
			
		||||
                ->leftJoin('a.user', 'activity_u')
 | 
			
		||||
                ->andWhere(
 | 
			
		||||
                    $qb->expr()->orX(
 | 
			
		||||
                        'creator.userJob IN (:jobs)',
 | 
			
		||||
                        'activity_u.userJob IN (:jobs)',
 | 
			
		||||
                        'EXISTS (SELECT 1 FROM ' . User::class . ' activity_user WHERE activity_user MEMBER OF a.users AND activity_user.userJob IN (:jobs))'
 | 
			
		||||
                        $qb->expr()->exists(
 | 
			
		||||
                            sprintf(
 | 
			
		||||
                                'SELECT 1 FROM %s ujh_creator WHERE ujh_creator.user = a.createdBy '
 | 
			
		||||
                                .'AND ujh_creator.job IN (:jobs) AND a.createdAt > ujh_creator.startDate '
 | 
			
		||||
                                .'AND (ujh_creator.endDate IS NULL or ujh_creator.endDate > a.date)',
 | 
			
		||||
                                User\UserJobHistory::class
 | 
			
		||||
                            )
 | 
			
		||||
                        ),
 | 
			
		||||
                        $qb->expr()->exists(
 | 
			
		||||
                            sprintf(
 | 
			
		||||
                                'SELECT 1 FROM %s ujh_u WHERE ujh_u.user = a.user '
 | 
			
		||||
                                .'AND ujh_u.job IN (:jobs) AND a.createdAt > ujh_u.startDate '
 | 
			
		||||
                                .'AND (ujh_u.endDate IS NULL or ujh_u.endDate > a.date)',
 | 
			
		||||
                                User\UserJobHistory::class
 | 
			
		||||
                            )
 | 
			
		||||
                        ),
 | 
			
		||||
                        $qb->expr()->exists(
 | 
			
		||||
                            sprintf(
 | 
			
		||||
                                'SELECT 1 FROM %s ujh_users WHERE ujh_users.user MEMBER OF a.users '
 | 
			
		||||
                                .'AND ujh_users.job IN (:jobs) AND a.createdAt > ujh_users.startDate '
 | 
			
		||||
                                .'AND (ujh_users.endDate IS NULL or ujh_users.endDate > a.date)',
 | 
			
		||||
                                User\UserJobHistory::class
 | 
			
		||||
                            )
 | 
			
		||||
                        ),
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
                ->setParameter('jobs', $jobs);
 | 
			
		||||
@@ -142,7 +159,6 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param AccompanyingPeriod|Person $associated
 | 
			
		||||
     * @return array<ActivityType>
 | 
			
		||||
     */
 | 
			
		||||
    public function findActivityTypeByAssociated(AccompanyingPeriod|Person $associated): array
 | 
			
		||||
@@ -172,16 +188,17 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
 | 
			
		||||
        return $qb->getQuery()->getResult();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function findUserJobByAssociated(Person|AccompanyingPeriod $associated): array
 | 
			
		||||
    public function findUserJobByAssociated(AccompanyingPeriod|Person $associated): array
 | 
			
		||||
    {
 | 
			
		||||
        $in = $this->em->createQueryBuilder();
 | 
			
		||||
        $in->select('IDENTITY(u.userJob)')
 | 
			
		||||
            ->from(User::class, 'u')
 | 
			
		||||
        $in->select('IDENTITY(u.job)')
 | 
			
		||||
            ->distinct()
 | 
			
		||||
            ->from(User\UserJobHistory::class, 'u')
 | 
			
		||||
            ->join(
 | 
			
		||||
                Activity::class,
 | 
			
		||||
                'a',
 | 
			
		||||
                Join::WITH,
 | 
			
		||||
                'a.createdBy = u OR a.user = u OR u MEMBER OF a.users'
 | 
			
		||||
                'a.createdBy = u.user OR a.user = u.user OR u.user MEMBER OF a.users AND a.date >= u.startDate ANd (u.endDate IS NULL or u.endDate > a.date)'
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
        if ($associated instanceof Person) {
 | 
			
		||||
@@ -203,7 +220,6 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
 | 
			
		||||
        return $qb->getQuery()->getResult();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function findByAccompanyingPeriodSimplified(AccompanyingPeriod $period, ?int $limit = 1000): array
 | 
			
		||||
    {
 | 
			
		||||
        $rsm = new ResultSetMappingBuilder($this->em);
 | 
			
		||||
@@ -291,7 +307,7 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
 | 
			
		||||
        $qb = $this->filterBaseQueryByPerson($qb, $person, $role);
 | 
			
		||||
 | 
			
		||||
        foreach ($orderBy as $field => $direction) {
 | 
			
		||||
            $qb->addOrderBy('a.' . $field, $direction);
 | 
			
		||||
            $qb->addOrderBy('a.'.$field, $direction);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (null !== $start) {
 | 
			
		||||
@@ -318,7 +334,7 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
 | 
			
		||||
            $orX->add(sprintf('a.person = :person AND a.scope IN (:scopes_%d)', $counter));
 | 
			
		||||
            $qb->setParameter(sprintf('scopes_%d', $counter), $scopes);
 | 
			
		||||
            $qb->setParameter('person', $person);
 | 
			
		||||
            $counter++;
 | 
			
		||||
            ++$counter;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ($person->getAccompanyingPeriodParticipations() as $participation) {
 | 
			
		||||
@@ -341,7 +357,7 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
 | 
			
		||||
                    ->setParameter(sprintf('participation_end_%d', $counter), $participation->getEndDate());
 | 
			
		||||
            }
 | 
			
		||||
            $orX->add($and);
 | 
			
		||||
            $counter++;
 | 
			
		||||
            ++$counter;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (0 === $orX->count()) {
 | 
			
		||||
@@ -362,10 +378,10 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
 | 
			
		||||
 | 
			
		||||
        return [
 | 
			
		||||
            'id' => $metadataActivity->getTableName()
 | 
			
		||||
                 . '.' . $metadataActivity->getColumnName('id'),
 | 
			
		||||
                 .'.'.$metadataActivity->getColumnName('id'),
 | 
			
		||||
            'type' => 'activity',
 | 
			
		||||
            'date' => $metadataActivity->getTableName()
 | 
			
		||||
                 . '.' . $metadataActivity->getColumnName('date'),
 | 
			
		||||
                 .'.'.$metadataActivity->getColumnName('date'),
 | 
			
		||||
            'FROM' => $from,
 | 
			
		||||
            'WHERE' => $where,
 | 
			
		||||
            'parameters' => $parameters,
 | 
			
		||||
@@ -378,12 +394,12 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
 | 
			
		||||
        $metadataPerson = $this->em->getClassMetadata(Person::class);
 | 
			
		||||
        $associationMapping = $metadataActivity->getAssociationMapping('person');
 | 
			
		||||
 | 
			
		||||
        return $metadataActivity->getTableName() . ' JOIN '
 | 
			
		||||
            . $metadataPerson->getTableName() . ' ON '
 | 
			
		||||
            . $metadataPerson->getTableName() . '.' .
 | 
			
		||||
        return $metadataActivity->getTableName().' JOIN '
 | 
			
		||||
            .$metadataPerson->getTableName().' ON '
 | 
			
		||||
            .$metadataPerson->getTableName().'.'.
 | 
			
		||||
                $associationMapping['joinColumns'][0]['referencedColumnName']
 | 
			
		||||
            . ' = '
 | 
			
		||||
            . $associationMapping['joinColumns'][0]['name'];
 | 
			
		||||
            .' = '
 | 
			
		||||
            .$associationMapping['joinColumns'][0]['name'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getWhereClause(string $context, array $args): array
 | 
			
		||||
@@ -402,7 +418,7 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
 | 
			
		||||
            ActivityVoter::SEE
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if (count($reachableCenters) === 0) {
 | 
			
		||||
        if (0 === \count($reachableCenters)) {
 | 
			
		||||
            // insert a dummy condition
 | 
			
		||||
            return 'FALSE = TRUE';
 | 
			
		||||
        }
 | 
			
		||||
@@ -419,7 +435,7 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
 | 
			
		||||
 | 
			
		||||
        foreach ($reachableCenters as $center) {
 | 
			
		||||
            // we pass if not in centers
 | 
			
		||||
            if (!in_array($center, $args['centers'], true)) {
 | 
			
		||||
            if (!\in_array($center, $args['centers'], true)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            // we get all the reachable scopes for this center
 | 
			
		||||
@@ -441,7 +457,7 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
 | 
			
		||||
 | 
			
		||||
            // begin loop for scopes
 | 
			
		||||
            $where .= ' AND (';
 | 
			
		||||
            $scopesI = 0; //like scope#i
 | 
			
		||||
            $scopesI = 0; // like scope#i
 | 
			
		||||
 | 
			
		||||
            foreach ($reachablesScopesId as $scopeId) {
 | 
			
		||||
                if (0 < $scopesI) {
 | 
			
		||||
 
 | 
			
		||||
@@ -22,8 +22,8 @@ interface ActivityACLAwareRepositoryInterface
 | 
			
		||||
    /**
 | 
			
		||||
     * Return all the activities associated to an accompanying period and that the user is allowed to apply the given role.
 | 
			
		||||
     *
 | 
			
		||||
     *
 | 
			
		||||
     * @param array{my_activities?: bool, types?: array<ActivityType>, jobs?: array<UserJob>, after?: \DateTimeImmutable|null, before?: \DateTimeImmutable|null} $filters
 | 
			
		||||
     *
 | 
			
		||||
     * @return array<Activity>
 | 
			
		||||
     */
 | 
			
		||||
    public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array;
 | 
			
		||||
@@ -49,20 +49,20 @@ interface ActivityACLAwareRepositoryInterface
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param array{my_activities?: bool, types?: array<ActivityType>, jobs?: array<UserJob>, after?: \DateTimeImmutable|null, before?: \DateTimeImmutable|null} $filters
 | 
			
		||||
     *
 | 
			
		||||
     * @return array<Activity>
 | 
			
		||||
     */
 | 
			
		||||
    public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Return a list of the type for the activities associated to person or accompanying period
 | 
			
		||||
     * Return a list of the type for the activities associated to person or accompanying period.
 | 
			
		||||
     *
 | 
			
		||||
     * @return array<ActivityType>
 | 
			
		||||
     */
 | 
			
		||||
    public function findActivityTypeByAssociated(AccompanyingPeriod|Person $associated): array;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Return a list of the user job for the activities associated to person or accompanying period
 | 
			
		||||
     * Return a list of the user job for the activities associated to person or accompanying period.
 | 
			
		||||
     *
 | 
			
		||||
     * Associated mean the job:
 | 
			
		||||
     * - of the creator;
 | 
			
		||||
 
 | 
			
		||||
@@ -15,25 +15,15 @@ use Chill\ActivityBundle\Entity\Activity;
 | 
			
		||||
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
 | 
			
		||||
use Chill\ActivityBundle\Service\GenericDoc\Providers\AccompanyingPeriodActivityGenericDocProvider;
 | 
			
		||||
use Chill\ActivityBundle\Service\GenericDoc\Providers\PersonActivityGenericDocProvider;
 | 
			
		||||
use Chill\DocStoreBundle\Entity\PersonDocument;
 | 
			
		||||
use Chill\DocStoreBundle\Entity\StoredObject;
 | 
			
		||||
use Chill\DocStoreBundle\GenericDoc\FetchQuery;
 | 
			
		||||
use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface;
 | 
			
		||||
use Chill\DocStoreBundle\GenericDoc\Providers\PersonDocumentGenericDocProvider;
 | 
			
		||||
use Chill\DocStoreBundle\Repository\PersonDocumentACLAwareRepositoryInterface;
 | 
			
		||||
use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter;
 | 
			
		||||
use Chill\MainBundle\Entity\Scope;
 | 
			
		||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface;
 | 
			
		||||
use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
 | 
			
		||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
 | 
			
		||||
use Chill\PersonBundle\Entity\Person;
 | 
			
		||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter;
 | 
			
		||||
use DateTimeImmutable;
 | 
			
		||||
use Doctrine\DBAL\Types\Types;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
use Doctrine\ORM\Mapping\MappingException;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\HttpKernel\HttpCache\Store;
 | 
			
		||||
use Symfony\Component\Security\Core\Security;
 | 
			
		||||
 | 
			
		||||
final readonly class ActivityDocumentACLAwareRepository implements ActivityDocumentACLAwareRepositoryInterface
 | 
			
		||||
@@ -45,14 +35,14 @@ final readonly class ActivityDocumentACLAwareRepository implements ActivityDocum
 | 
			
		||||
        private Security $security
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function buildFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQueryInterface
 | 
			
		||||
    public function buildFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, \DateTimeImmutable $startDate = null, \DateTimeImmutable $endDate = null, string $content = null): FetchQueryInterface
 | 
			
		||||
    {
 | 
			
		||||
        $query = $this->buildBaseFetchQueryActivityDocumentLinkedToPersonFromPersonContext($person, $startDate, $endDate, $content);
 | 
			
		||||
 | 
			
		||||
        return $this->addFetchQueryByPersonACL($query, $person);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildBaseFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery
 | 
			
		||||
    public function buildBaseFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, \DateTimeImmutable $startDate = null, \DateTimeImmutable $endDate = null, string $content = null): FetchQuery
 | 
			
		||||
    {
 | 
			
		||||
        $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
 | 
			
		||||
        $activityMetadata = $this->em->getClassMetadata(Activity::class);
 | 
			
		||||
@@ -81,7 +71,7 @@ final readonly class ActivityDocumentACLAwareRepository implements ActivityDocum
 | 
			
		||||
        return $this->addWhereClauses($query, $startDate, $endDate, $content);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildFetchQueryActivityDocumentLinkedToAccompanyingPeriodFromPersonContext(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery
 | 
			
		||||
    public function buildFetchQueryActivityDocumentLinkedToAccompanyingPeriodFromPersonContext(Person $person, \DateTimeImmutable $startDate = null, \DateTimeImmutable $endDate = null, string $content = null): FetchQuery
 | 
			
		||||
    {
 | 
			
		||||
        $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
 | 
			
		||||
        $activityMetadata = $this->em->getClassMetadata(Activity::class);
 | 
			
		||||
@@ -116,8 +106,8 @@ final readonly class ActivityDocumentACLAwareRepository implements ActivityDocum
 | 
			
		||||
                $storedObjectMetadata->getColumnName('createdAt')
 | 
			
		||||
            );
 | 
			
		||||
            $orParams = [...$orParams, $participation->getAccompanyingPeriod()->getId(),
 | 
			
		||||
                DateTimeImmutable::createFromInterface($participation->getStartDate()),
 | 
			
		||||
                null === $participation->getEndDate() ? null : DateTimeImmutable::createFromInterface($participation->getEndDate())];
 | 
			
		||||
                \DateTimeImmutable::createFromInterface($participation->getStartDate()),
 | 
			
		||||
                null === $participation->getEndDate() ? null : \DateTimeImmutable::createFromInterface($participation->getEndDate())];
 | 
			
		||||
            $orTypes = [...$orTypes, Types::INTEGER, Types::DATE_IMMUTABLE, Types::DATE_IMMUTABLE];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -132,7 +122,7 @@ final readonly class ActivityDocumentACLAwareRepository implements ActivityDocum
 | 
			
		||||
        return $this->addWhereClauses($query, $startDate, $endDate, $content);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function addWhereClauses(FetchQuery $query, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery
 | 
			
		||||
    private function addWhereClauses(FetchQuery $query, \DateTimeImmutable $startDate = null, \DateTimeImmutable $endDate = null, string $content = null): FetchQuery
 | 
			
		||||
    {
 | 
			
		||||
        $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
 | 
			
		||||
 | 
			
		||||
@@ -155,7 +145,7 @@ final readonly class ActivityDocumentACLAwareRepository implements ActivityDocum
 | 
			
		||||
        if (null !== $content and '' !== $content) {
 | 
			
		||||
            $query->addWhereClause(
 | 
			
		||||
                'stored_obj.title ilike ?',
 | 
			
		||||
                ['%' . $content . '%'],
 | 
			
		||||
                ['%'.$content.'%'],
 | 
			
		||||
                [Types::STRING]
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
@@ -172,7 +162,7 @@ final readonly class ActivityDocumentACLAwareRepository implements ActivityDocum
 | 
			
		||||
        foreach ($this->centerResolverManager->resolveCenters($person) as $center) {
 | 
			
		||||
            $reachableScopes = [
 | 
			
		||||
                ...$reachableScopes,
 | 
			
		||||
                ...$this->authorizationHelperForCurrentUser->getReachableScopes(ActivityVoter::SEE, $center)
 | 
			
		||||
                ...$this->authorizationHelperForCurrentUser->getReachableScopes(ActivityVoter::SEE, $center),
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user