Compare commits
	
		
			535 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					3cc14ef6a0 | ||
| 
						 | 
					02613203c9 | ||
| 
						 | 
					6f4af6b68d | ||
| 
						 | 
					ebb8d46420 | ||
| 
						 | 
					6c5406dd99 | ||
| 
						 | 
					4aa4100532 | ||
| 
						 | 
					d90c1a2c23 | ||
| 
						 | 
					22c1f92b2b | ||
| 
						 | 
					d17098e703 | ||
| 
						 | 
					64c6674762 | ||
| 
						 | 
					01febe1411 | ||
| 
						 | 
					839444cc8a | ||
| 
						 | 
					831439120c | ||
| 
						 | 
					6bb886b92a | ||
| 
						 | 
					dd3474c06c | ||
| 
						 | 
					bcd515eed5 | ||
| 
						 | 
					231dfaa8a6 | ||
| 
						 | 
					0826dab575 | ||
| 
						 | 
					1c037f81a0 | ||
| 
						 | 
					71c41fe940 | ||
| 
						 | 
					8ad0707509 | ||
| 
						 | 
					e0dec2278c | ||
| 
						 | 
					7221135849 | ||
| 
						 | 
					a2d5b14a2c | ||
| 
						 | 
					16de6a0d77 | ||
| 
						 | 
					03404adf64 | ||
| 
						 | 
					dd2fa6f902 | ||
| 
						 | 
					b6acf4c0e2 | ||
| 
						 | 
					cf1a7e8852 | ||
| 
						 | 
					c0035061b0 | ||
| 
						 | 
					6c130cd3ca | ||
| 
						 | 
					8db3c45763 | ||
| 
						 | 
					696f2d06d6 | ||
| 
						 | 
					158f9288d3 | ||
| 
						 | 
					e883f22790 | ||
| 
						 | 
					2b5bf490a5 | ||
| 
						 | 
					014d8ca6af | ||
| 
						 | 
					02a99e2f9c | ||
| 
						 | 
					23253fc40e | ||
| 
						 | 
					d348c45c56 | ||
| 
						 | 
					53f6133899 | ||
| 
						 | 
					c3bbddb1ff | ||
| 
						 | 
					a608d7ea0a | ||
| 
						 | 
					fde3a0a949 | ||
| 
						 | 
					2bd2b3a463 | ||
| 
						 | 
					7207cdcd46 | ||
| 
						 | 
					85f247909e | ||
| 
						 | 
					e8882292b5 | ||
| 
						 | 
					bca3eb332e | ||
| 
						 | 
					307c35ff42 | ||
| 
						 | 
					786e9f81c0 | ||
| 
						 | 
					8cd19c0f53 | ||
| 
						 | 
					d5394265ba | ||
| 
						 | 
					0919cb83d8 | ||
| 
						 | 
					b356625268 | ||
| 
						 | 
					4e8ca58a2e | ||
| 
						 | 
					6996e1185f | ||
| 
						 | 
					b7ad4bf47a | ||
| 
						 | 
					75f62663a9 | ||
| 
						 | 
					169fbe6216 | ||
| 
						 | 
					84d80af1ce | ||
| 
						 | 
					d1542c9c00 | ||
| 
						 | 
					4da01b2732 | ||
| 
						 | 
					b44ad48fd5 | ||
| 
						 | 
					3ae92627bc | ||
| 
						 | 
					d46df5c129 | ||
| 
						 | 
					316c57f85b | ||
| 
						 | 
					f11a7f7618 | ||
| 
						 | 
					bb7544021f | ||
| 
						 | 
					11b3811e17 | ||
| 
						 | 
					3e78376be3 | ||
| 
						 | 
					cf2f9d419e | ||
| 
						 | 
					a9630cea0d | ||
| 
						 | 
					4323edcf0c | ||
| 
						 | 
					120101c4df | ||
| 
						 | 
					b9c3ee1a09 | ||
| 
						 | 
					60cdd2224f | ||
| 
						 | 
					e7643e97e4 | ||
| 
						 | 
					10e5f350f7 | ||
| 
						 | 
					1690fa8416 | ||
| 
						 | 
					9168a26a72 | ||
| 
						 | 
					21a0a3ffb5 | ||
| 
						 | 
					27869698e6 | ||
| 
						 | 
					2da7d4db42 | ||
| 
						 | 
					bc64c877de | ||
| 
						 | 
					da7b76e00b | ||
| 
						 | 
					3bf4977460 | ||
| 
						 | 
					315e06da1b | ||
| 
						 | 
					74d06b0c31 | ||
| 
						 | 
					d924c4e277 | ||
| 
						 | 
					3a71d71ef8 | ||
| 
						 | 
					1d15d53eaa | ||
| 
						 | 
					1b363e4b6d | ||
| 
						 | 
					c158131f88 | ||
| 
						 | 
					9f578829ea | ||
| 
						 | 
					f7d75f1b94 | ||
| 
						 | 
					fa95cbd934 | ||
| 
						 | 
					f542a7fef8 | ||
| 
						 | 
					a07d2be837 | ||
| 
						 | 
					b529c05d11 | ||
| 
						 | 
					f8a830802e | ||
| 
						 | 
					47da6adebb | ||
| 
						 | 
					69949b2941 | ||
| 
						 | 
					d676727c1e | ||
| 
						 | 
					e0da21cbf8 | ||
| 
						 | 
					214d035d12 | ||
| 
						 | 
					f005bc1ddd | ||
| 
						 | 
					9beffaae7e | ||
| 
						 | 
					be2f0b3d62 | ||
| 
						 | 
					b72e0f71e5 | ||
| 
						 | 
					9137cab212 | ||
| 
						 | 
					f4a6cd1cdb | ||
| 
						 | 
					0e52a2e673 | ||
| 
						 | 
					c2d61083a7 | ||
| 
						 | 
					f8a1d26b28 | ||
| 
						 | 
					f697d97b6a | ||
| 
						 | 
					9bd5912884 | ||
| 
						 | 
					562e6803c5 | ||
| 
						 | 
					850be91695 | ||
| 
						 | 
					516640b0cd | ||
| 
						 | 
					126f94016f | ||
| 
						 | 
					6bbabaebdd | ||
| 
						 | 
					3bec47778a | ||
| 
						 | 
					215294fcf3 | ||
| 
						 | 
					d32e17df91 | ||
| 
						 | 
					51ca50ec36 | ||
| 
						 | 
					9e45b7f7f5 | ||
| 
						 | 
					5bcd4e1855 | ||
| 
						 | 
					fb88c08e85 | ||
| 
						 | 
					eac353f921 | ||
| 
						 | 
					91dcc78796 | ||
| 
						 | 
					5c04c87ff6 | ||
| 
						 | 
					6a3f1aed99 | ||
| 
						 | 
					f4058ddd69 | ||
| 
						 | 
					17c6ba97d6 | ||
| 
						 | 
					65aa830c87 | ||
| 
						 | 
					ff77046783 | ||
| 
						 | 
					6e305eb541 | ||
| 
						 | 
					608e7a40e4 | ||
| 
						 | 
					c0506c460d | ||
| 
						 | 
					da6df31ee9 | ||
| 
						 | 
					6875e62942 | ||
| 
						 | 
					c07aee6287 | ||
| 
						 | 
					16573daee0 | ||
| 
						 | 
					5ffe66cbfb | ||
| 
						 | 
					0f4c952cbd | ||
| 
						 | 
					52d638e027 | ||
| 
						 | 
					6a20b36700 | ||
| 
						 | 
					a83634c166 | ||
| 
						 | 
					4dd8994270 | ||
| 
						 | 
					4d7d99c0bb | ||
| 
						 | 
					95faf0468a | ||
| 
						 | 
					1a67712447 | ||
| 
						 | 
					14be872724 | ||
| 
						 | 
					63bc47e7b7 | ||
| 
						 | 
					0d410605f9 | ||
| 
						 | 
					22dfab253b | ||
| 
						 | 
					a1c8a49430 | ||
| 
						 | 
					3f0c7c23d2 | ||
| 
						 | 
					8fde1e4762 | ||
| 
						 | 
					3897d7facb | ||
| 
						 | 
					959ea74291 | ||
| 
						 | 
					ac4d974abb | ||
| 
						 | 
					dd8833665d | ||
| 
						 | 
					d54d195b86 | ||
| 
						 | 
					b752d1fadb | ||
| 
						 | 
					57f314badb | ||
| 
						 | 
					6a44af34e1 | ||
| 
						 | 
					7342566c6e | ||
| 
						 | 
					d6eb7532fd | ||
| 
						 | 
					7267fada64 | ||
| 
						 | 
					bfc568967b | ||
| 
						 | 
					154597c09c | ||
| 
						 | 
					8f886155b0 | ||
| 
						 | 
					df1130b4c9 | ||
| 
						 | 
					58ccb93f2d | ||
| 
						 | 
					ff2b19d587 | ||
| 
						 | 
					ba365af020 | ||
| 
						 | 
					b2e25fc501 | ||
| 
						 | 
					f29348c604 | ||
| 
						 | 
					b39fe8595c | ||
| 
						 | 
					5fefc26543 | ||
| 
						 | 
					a37b222878 | ||
| 
						 | 
					c9f2575469 | ||
| 
						 | 
					5101ae5f35 | ||
| 
						 | 
					b09a7d2fd2 | ||
| 
						 | 
					aa09862059 | ||
| 
						 | 
					f9629f3f7b | ||
| 
						 | 
					884f50155c | ||
| 
						 | 
					e6e20e4f93 | ||
| 
						 | 
					82a2d6a39c | ||
| 
						 | 
					2b5efb7fee | ||
| 
						 | 
					099e4888e8 | ||
| 
						 | 
					3eca572866 | ||
| 
						 | 
					c39f5c2174 | ||
| 
						 | 
					cf684c1514 | ||
| 
						 | 
					6c9b6b5309 | ||
| 
						 | 
					a7f283256a | ||
| 
						 | 
					4506e1d2b5 | ||
| 
						 | 
					70f67e6bc6 | ||
| 
						 | 
					c71ed2cecb | ||
| 
						 | 
					05816cb75a | ||
| 
						 | 
					91b189b75f | ||
| 
						 | 
					623c562054 | ||
| 
						 | 
					2a55024640 | ||
| 
						 | 
					8a9f8c66e8 | ||
| 
						 | 
					81f433085a | ||
| 
						 | 
					6e59a0a526 | ||
| 
						 | 
					8397d86313 | ||
| 
						 | 
					b0ac05b608 | ||
| 
						 | 
					48c3989ae3 | ||
| 
						 | 
					b949b7e83a | ||
| 
						 | 
					ad7fad9fbe | ||
| 
						 | 
					34fbf6ec5f | ||
| 
						 | 
					d2db3b16d2 | ||
| 
						 | 
					ae11b1de4a | ||
| 
						 | 
					6f620e3f54 | ||
| 
						 | 
					810b753edf | ||
| 
						 | 
					958fb1b9ad | ||
| 
						 | 
					48992adefa | ||
| 
						 | 
					d95e1e13e5 | ||
| 
						 | 
					381dc5b8f7 | ||
| 
						 | 
					464c1a8ef5 | ||
| 
						 | 
					e5b10a8494 | ||
| 
						 | 
					ffc49b9ea6 | ||
| 
						 | 
					0efc14dd6f | ||
| 
						 | 
					4fb15ccb7d | ||
| 
						 | 
					234b70845c | ||
| 
						 | 
					6abd0b6faa | ||
| 
						 | 
					fef2bd15bf | ||
| 
						 | 
					74d07d8fb8 | ||
| 
						 | 
					473e9153ed | ||
| 
						 | 
					efa10c9afd | ||
| 
						 | 
					7438a2bf19 | ||
| 
						 | 
					2e0995abac | ||
| 
						 | 
					c84afd0f78 | ||
| 
						 | 
					52383edfd0 | ||
| 
						 | 
					b1276dff6c | ||
| 
						 | 
					b413b7ee89 | ||
| 
						 | 
					f19f07ec59 | ||
| 
						 | 
					83761c66c5 | ||
| 
						 | 
					d0e2977746 | ||
| 
						 | 
					1be91e5a2a | ||
| 
						 | 
					15d4d1aa7d | ||
| 
						 | 
					708b90fccd | ||
| 
						 | 
					ac7a4c4aa5 | ||
| 
						 | 
					b90246a239 | ||
| 
						 | 
					a9d327d54f | ||
| 
						 | 
					eb8fd0aa55 | ||
| 
						 | 
					813184f06c | ||
| 
						 | 
					ef2d3a9af9 | ||
| 
						 | 
					9a8bd464a3 | ||
| 
						 | 
					9e2ea7404b | ||
| 
						 | 
					160d11b89b | ||
| 
						 | 
					d860f299fd | ||
| 
						 | 
					33882d4fa7 | ||
| 
						 | 
					85978a4d18 | ||
| 
						 | 
					e1e7696d53 | ||
| 
						 | 
					695428075b | ||
| 
						 | 
					e7c2e721b4 | ||
| 
						 | 
					13fad756ab | ||
| 
						 | 
					699925f797 | ||
| 
						 | 
					920432025f | ||
| 
						 | 
					7ff298af79 | ||
| 
						 | 
					b29acd71cb | ||
| 
						 | 
					dc50e9b316 | ||
| 
						 | 
					7f610fd2f3 | ||
| 
						 | 
					4ae0019e0f | ||
| 
						 | 
					c72ce218f7 | ||
| 
						 | 
					1f0791df0e | ||
| 
						 | 
					34c9d04a35 | ||
| 
						 | 
					aa2868eb17 | ||
| 
						 | 
					a2c832a130 | ||
| 
						 | 
					b17de014ec | ||
| 
						 | 
					b1b72190e1 | ||
| 
						 | 
					2ff2f888bc | ||
| 
						 | 
					57c2389aae | ||
| 
						 | 
					d54c86f813 | ||
| 
						 | 
					05a9697007 | ||
| 
						 | 
					945429abf0 | ||
| 
						 | 
					a016bcb51b | ||
| 
						 | 
					f2b1ce795c | ||
| 
						 | 
					3a8c56acc4 | ||
| 
						 | 
					7b2552f940 | ||
| 
						 | 
					324b202215 | ||
| 
						 | 
					2c2da6082a | ||
| 
						 | 
					dd3fbbd7e4 | ||
| 
						 | 
					9bbcd571ec | ||
| 
						 | 
					bbc185bf3b | ||
| 
						 | 
					d1bcdcda20 | ||
| 
						 | 
					6d55602ef3 | ||
| 
						 | 
					6e7c9f7c4b | ||
| 
						 | 
					5427aab456 | ||
| 
						 | 
					4879d64989 | ||
| 
						 | 
					dab8ea63fc | ||
| 
						 | 
					b03d7a04a0 | ||
| 
						 | 
					ef5b93e3f7 | ||
| 
						 | 
					69ae1c08ef | ||
| 
						 | 
					8e4f828cc6 | ||
| 
						 | 
					c4f92f4569 | ||
| 
						 | 
					c4d2b99656 | ||
| 
						 | 
					d4fe88adab | ||
| 
						 | 
					69d0e8313a | ||
| 
						 | 
					11a234e135 | ||
| 
						 | 
					2f30e4e2f6 | ||
| 
						 | 
					118ca9f11f | ||
| 
						 | 
					24fc41ee0d | ||
| 
						 | 
					c00dbac5e0 | ||
| 
						 | 
					d7857c5126 | ||
| 
						 | 
					ac6be0d3c0 | ||
| 
						 | 
					7ff6f09f67 | ||
| 
						 | 
					00b576c5a3 | ||
| 
						 | 
					2a33510c96 | ||
| 
						 | 
					d1f79d906d | ||
| 
						 | 
					aa043f14ac | ||
| 
						 | 
					638b28399e | ||
| 
						 | 
					1d86f036a3 | ||
| 
						 | 
					2f6e0f0a22 | ||
| 
						 | 
					1b1b00a10c | ||
| 
						 | 
					8693418d39 | ||
| 
						 | 
					8ff15368ce | ||
| 
						 | 
					32cde534bd | ||
| 
						 | 
					c0e26133bd | ||
| 
						 | 
					592c2ff9ff | ||
| 
						 | 
					30efd0a2db | ||
| 
						 | 
					20c3f14cc8 | ||
| 
						 | 
					80313c88c8 | ||
| 
						 | 
					cab1c09ffc | ||
| 
						 | 
					c421919092 | ||
| 
						 | 
					d350876bc1 | ||
| 
						 | 
					de09c8af56 | ||
| 
						 | 
					998f4576fe | ||
| 
						 | 
					06c57f7da6 | ||
| 
						 | 
					4d5418a601 | ||
| 
						 | 
					95cc7f627f | ||
| 
						 | 
					2aab4eea3b | ||
| 
						 | 
					5bbff9f5a6 | ||
| 
						 | 
					b5fcf1636a | ||
| 
						 | 
					13012be5d7 | ||
| 
						 | 
					ca2ef814fb | ||
| 
						 | 
					b9407f6aee | ||
| 
						 | 
					9bcb5f9456 | ||
| 
						 | 
					f412099f69 | ||
| 
						 | 
					0aa5999bb3 | ||
| 
						 | 
					16dda0743c | ||
| 
						 | 
					d079838818 | ||
| 
						 | 
					81ce4688df | ||
| 
						 | 
					ee33cc1832 | ||
| 
						 | 
					82bb18fe10 | ||
| 
						 | 
					8987ca7db6 | ||
| 
						 | 
					8066fd8982 | ||
| 
						 | 
					a96d8c05a7 | ||
| 
						 | 
					4238a5dd50 | ||
| 
						 | 
					94da55d15e | ||
| 
						 | 
					09979b8551 | ||
| 
						 | 
					5b82efa0be | ||
| 
						 | 
					8502a36481 | ||
| 
						 | 
					bcba64b2a1 | ||
| 
						 | 
					e40d922eef | ||
| 
						 | 
					7e226b43d3 | ||
| 
						 | 
					9171bfd1ab | ||
| 
						 | 
					be4774c95c | ||
| 
						 | 
					bbf1a1882a | ||
| 
						 | 
					9644784a79 | ||
| 
						 | 
					1940d5c0b5 | ||
| 
						 | 
					7c7e3cd1f1 | ||
| 
						 | 
					3e2f95a152 | ||
| 
						 | 
					92de88ba13 | ||
| 
						 | 
					5322cdf609 | ||
| 
						 | 
					02d0f0923e | ||
| 
						 | 
					765a86ba90 | ||
| 
						 | 
					34309e34c3 | ||
| 
						 | 
					2176d1cde2 | ||
| 
						 | 
					45d53e8d21 | ||
| 
						 | 
					b36b8e3afb | ||
| 
						 | 
					801af66a4e | ||
| 
						 | 
					df6ffdf420 | ||
| 
						 | 
					b3368071ac | ||
| 
						 | 
					67b80ee11c | ||
| 
						 | 
					dc31155de1 | ||
| 
						 | 
					0bae69908b | ||
| 
						 | 
					47a077bc82 | ||
| 
						 | 
					836ff71364 | ||
| 
						 | 
					0afa07b2bd | ||
| 
						 | 
					4ee3d471fe | ||
| 
						 | 
					29c7fed81b | ||
| 
						 | 
					fb62061e5a | ||
| 
						 | 
					9b92b7139f | ||
| 
						 | 
					5ea4b02205 | ||
| 
						 | 
					12d3eef3d1 | ||
| 
						 | 
					576c06ffaf | ||
| 
						 | 
					352dc3e179 | ||
| 
						 | 
					aa164936f4 | ||
| 
						 | 
					9a93acd1a5 | ||
| 
						 | 
					587aa11cda | ||
| 
						 | 
					d04ecd60c4 | ||
| 
						 | 
					ecef510f78 | ||
| 
						 | 
					4976c20935 | ||
| 
						 | 
					5553c37ccd | ||
| 
						 | 
					346b2c6cf8 | ||
| 
						 | 
					aa68fe3485 | ||
| 
						 | 
					e408fe8733 | ||
| 
						 | 
					836986462a | ||
| 
						 | 
					51c6cdb20d | ||
| 
						 | 
					766232f29b | ||
| 
						 | 
					2ed021f30b | ||
| 
						 | 
					899fe561df | ||
| 
						 | 
					67d8936083 | ||
| 
						 | 
					78f5cef5bd | ||
| 
						 | 
					8928b1654c | ||
| 
						 | 
					977fa0d1d4 | ||
| 
						 | 
					1d89cec2cf | ||
| 
						 | 
					6c6b7d6bb2 | ||
| 
						 | 
					f92e88e9b4 | ||
| 
						 | 
					6e58899fdf | ||
| 
						 | 
					1513598420 | ||
| 
						 | 
					9cfc060760 | ||
| 
						 | 
					a531e34ec2 | ||
| 
						 | 
					2cce23b5b4 | ||
| 
						 | 
					e518bc9b68 | ||
| 
						 | 
					8e02d05ba9 | ||
| 
						 | 
					f131083315 | ||
| 
						 | 
					39ba5b37ef | ||
| 
						 | 
					002fa05c7f | ||
| 
						 | 
					1a52133fd4 | ||
| 
						 | 
					30900f7196 | ||
| 
						 | 
					b753cf0837 | ||
| 
						 | 
					53ab5b6aff | ||
| 
						 | 
					78a0402351 | ||
| 
						 | 
					5b5705fe90 | ||
| 
						 | 
					f08b5c5e3f | ||
| 
						 | 
					aa87acd432 | ||
| 
						 | 
					7af7ef8357 | ||
| 
						 | 
					627bc4e45f | ||
| 
						 | 
					909c76ebfb | ||
| 
						 | 
					0899ba8515 | ||
| 
						 | 
					b7c0b40491 | ||
| 
						 | 
					48257ccfed | ||
| 
						 | 
					269949a65f | ||
| 
						 | 
					c2de7123e4 | ||
| 
						 | 
					e0c6dcd5a4 | ||
| 
						 | 
					734ddda363 | ||
| 
						 | 
					02cd448f89 | ||
| 
						 | 
					5fc3a987de | ||
| 
						 | 
					be39d72d3c | ||
| 
						 | 
					045eb766f1 | ||
| 
						 | 
					22d4bd0e6f | ||
| 
						 | 
					5a7bf49cbb | ||
| 
						 | 
					a3dd1c45f3 | ||
| 
						 | 
					be7725694e | ||
| 
						 | 
					366d278182 | ||
| 
						 | 
					5f008a14f5 | ||
| 
						 | 
					21a8c281ec | ||
| 
						 | 
					51dde5766d | ||
| 
						 | 
					61d7b4a58d | ||
| 
						 | 
					19b35565a2 | ||
| 
						 | 
					baa88412b9 | ||
| 
						 | 
					6fb9b72e22 | ||
| 
						 | 
					b75884c57e | ||
| 
						 | 
					603188f6ce | ||
| 
						 | 
					15442140cf | ||
| 
						 | 
					9f877d4309 | ||
| 
						 | 
					8631529268 | ||
| 
						 | 
					96bc198b0f | ||
| 
						 | 
					146ffb5f4c | ||
| 
						 | 
					867c3d3382 | ||
| 
						 | 
					75b0f27fe2 | ||
| 
						 | 
					4b001d8f03 | ||
| 
						 | 
					a7bec96a80 | ||
| 
						 | 
					a8706e38ca | ||
| 
						 | 
					265fd41717 | ||
| 
						 | 
					67c23ffe24 | ||
| 
						 | 
					e9a09889e4 | ||
| 
						 | 
					e6756a2072 | ||
| 
						 | 
					f4050b8a76 | ||
| 
						 | 
					bb4fa7ca2f | ||
| 
						 | 
					2648603f24 | ||
| 
						 | 
					b7a9a1c8fd | ||
| 
						 | 
					d45566d692 | ||
| 
						 | 
					4411086f29 | ||
| 
						 | 
					0b3ce03036 | ||
| 
						 | 
					027886737d | ||
| 
						 | 
					35f45015ea | ||
| 
						 | 
					618f412bed | ||
| 
						 | 
					6ab9c754a5 | ||
| 
						 | 
					c59332c8f8 | ||
| 
						 | 
					32d9d04b4b | ||
| 
						 | 
					62d0fb6eee | ||
| 
						 | 
					bc82ee24d8 | ||
| 
						 | 
					6ab1f4a4f0 | ||
| 
						 | 
					3e6527bab3 | ||
| 
						 | 
					9b7691c1ae | ||
| 
						 | 
					c3cd494386 | ||
| 
						 | 
					fba5841bdc | ||
| 
						 | 
					da7fc3e7e3 | ||
| 
						 | 
					00ebe1633c | ||
| 
						 | 
					f63bfcb4f6 | ||
| 
						 | 
					177cf836b4 | ||
| 
						 | 
					04069871bb | ||
| 
						 | 
					31469204e0 | ||
| 
						 | 
					9b148c8c4a | ||
| 
						 | 
					98f4eac82a | ||
| 
						 | 
					29d966cdb3 | ||
| 
						 | 
					23d2bd552c | ||
| 
						 | 
					41cfbbd0d9 | ||
| 
						 | 
					cc89a7e6f8 | ||
| 
						 | 
					c486fe98fb | ||
| 
						 | 
					f0ac256ff6 | ||
| 
						 | 
					e4b3adb2f5 | ||
| 
						 | 
					58a5bc46d9 | ||
| 
						 | 
					6e5c3a551d | ||
| 
						 | 
					52f8261d8c | ||
| 
						 | 
					721c385993 | ||
| 
						 | 
					9c80de19d7 | ||
| 
						 | 
					4ffd11caf5 | ||
| 
						 | 
					f2c4faf054 | ||
| 
						 | 
					bc54b663e0 | ||
| 
						 | 
					6f1bb309d4 | ||
| 
						 | 
					cdedaa4604 | ||
| 
						 | 
					2130b327df | ||
| 
						 | 
					3e238bea0b | ||
| 
						 | 
					266c297632 | ||
| 
						 | 
					4477b07bc6 | ||
| 
						 | 
					74b44186d2 | ||
| 
						 | 
					c2bf1bac38 | ||
| 
						 | 
					c279313048 | ||
| 
						 | 
					0301ba0336 | ||
| 
						 | 
					5e6d61b3a7 | ||
| 
						 | 
					4e00051a10 | ||
| 
						 | 
					38e6e4f8d3 | ||
| 
						 | 
					dfa223b39e | ||
| 
						 | 
					0a8d771c11 | ||
| 
						 | 
					5afd073ff3 | ||
| 
						 | 
					46fda14e08 | ||
| 
						 | 
					bbf9ef8b3d | 
							
								
								
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
src/IDF/version.php     export-subst
 | 
			
		||||
							
								
								
									
										21
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,11 +1,20 @@
 | 
			
		||||
*~
 | 
			
		||||
tmp
 | 
			
		||||
.buildpath
 | 
			
		||||
.externalToolBuilders
 | 
			
		||||
.project
 | 
			
		||||
.settings
 | 
			
		||||
.tx/config
 | 
			
		||||
attachments
 | 
			
		||||
backups
 | 
			
		||||
indefero-*.zip
 | 
			
		||||
src/IDF/conf/idf.php
 | 
			
		||||
src/IDF/conf/idf.test.php
 | 
			
		||||
www/test.php
 | 
			
		||||
www/media/upload
 | 
			
		||||
src/IDF/gettexttemplates
 | 
			
		||||
indefero-*.zip
 | 
			
		||||
src/IDF/conf/path.php
 | 
			
		||||
.tx/config
 | 
			
		||||
src/IDF/gettexttemplates
 | 
			
		||||
src/IDF/locale/idf.pot.bak
 | 
			
		||||
test/config.php
 | 
			
		||||
test/test.db
 | 
			
		||||
test/tmp
 | 
			
		||||
tmp
 | 
			
		||||
www/media/upload
 | 
			
		||||
www/test.php
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										64
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								AUTHORS
									
									
									
									
									
								
							@@ -1,30 +1,52 @@
 | 
			
		||||
InDefero was originally created during summer 2008 
 | 
			
		||||
InDefero was originally created during summer 2008
 | 
			
		||||
by Loïc d'Anterroches with the support of Céondo Ltd.
 | 
			
		||||
 | 
			
		||||
Much appreciated contributors:
 | 
			
		||||
Much appreciated contributors (in alphabetical order):
 | 
			
		||||
 | 
			
		||||
    Nicolas Lassalle <http://www.beroot.org/> - Subversion support
 | 
			
		||||
    bohwaz <http://bohwaz.net/>
 | 
			
		||||
    Benjamin Jorand <benjamin.jorand@gmail.com> - Mercurial support
 | 
			
		||||
    Baptiste Michaud <bactisme@gmail.com> - Subversion synchronization
 | 
			
		||||
    Julien Issler 
 | 
			
		||||
    Adrien Bustany <madcat@mymadcat.com>
 | 
			
		||||
    Andrew Nguyen <andrew-git-indefero@na-consulting.net>
 | 
			
		||||
    Baptiste Durand-Bret <bathizte@ozazar.org>
 | 
			
		||||
    Baptiste Michaud <bactisme@gmail.com>           - Subversion sync
 | 
			
		||||
    Benjamin Danon <benjamin@sphax3d.org>           - French translation
 | 
			
		||||
    Benjamin Jorand <benjamin.jorand@gmail.com>     - Mercurial support
 | 
			
		||||
    Brenda Wallace <shiny@cpan.org>
 | 
			
		||||
    Brian Armstrong <brianar>
 | 
			
		||||
    Charles Melbye <charlie@yourwiki.net>
 | 
			
		||||
    Ciaran Gultnieks <ciaran@ciarang.com>
 | 
			
		||||
    Daniel Steudler <steudlerdaniel@gmail.com>
 | 
			
		||||
    David Feeney <davidf>
 | 
			
		||||
    Denis Kot <denis.kot@gmail.com>                 - Russian translation
 | 
			
		||||
    Dmitry Dulepov <dmitryd>
 | 
			
		||||
    Fernando Sayago Gil <mikados.mikados@gmail.com> - Spanish translation
 | 
			
		||||
    Gert van Valkenhoef <gertvv>
 | 
			
		||||
    Jakub Viták <mainiak@gmail.com>                 - Czech translation
 | 
			
		||||
    Janez Troha <http://www.dz0ny.info>             - Slovenian translation
 | 
			
		||||
    Jean-Philippe Fleury <jpfleury>
 | 
			
		||||
    Jerry <lxb429@gmail.com>                        - Chinese translation
 | 
			
		||||
    Jonathan Aillet <jonathan.aillet@gmail.com>     - French translation
 | 
			
		||||
    Julien Issler <julien@issler.net>
 | 
			
		||||
    Litew <litew9@gmail.com>                        - Russian translation
 | 
			
		||||
    Ludovic Bellière <xrogaan>
 | 
			
		||||
    Manuel Eidenberger <eidenberger@gmail.com>
 | 
			
		||||
    Ciaran Gultnieks
 | 
			
		||||
    Matthew Dawson <mjd>
 | 
			
		||||
    Matías Halles <matias@halles.cl>
 | 
			
		||||
    Mehdi Kabab <http://pioupioum.fr/>
 | 
			
		||||
    Sindre R. Myren
 | 
			
		||||
    Nicolas Lassalle <nicolas@beroot.org>           - Subversion support
 | 
			
		||||
    Ozan <uobasar@gmail.com>                        - Turkish translation
 | 
			
		||||
    Patrick Georgi <patrick.georgi@coresystems.de>
 | 
			
		||||
    Adrien Bustany
 | 
			
		||||
    Charles Melbye
 | 
			
		||||
    Baptiste Durand-Bret
 | 
			
		||||
    Andrew Nguyen
 | 
			
		||||
    David Feeney
 | 
			
		||||
    Denis Kot <denis.kot@gmail.com>
 | 
			
		||||
    Samuel Suther
 | 
			
		||||
    Ludovic Bellière
 | 
			
		||||
    Brian Armstrong
 | 
			
		||||
    Raphaël Emourgeon
 | 
			
		||||
    Jakub Viták
 | 
			
		||||
    Vladimir Solomatin
 | 
			
		||||
    Pedro Kiefer <pedro@kiefer.com.br>              - Brazilian Portuguese translation
 | 
			
		||||
    Raphaël Emourgeon <raphael>
 | 
			
		||||
    Samuel Suther <info@suther.de>                  - German translation
 | 
			
		||||
    Simon Holywell <treffynnon@php.net>
 | 
			
		||||
    Sindre R. Myren <sindrero@stud.ntnu.no>
 | 
			
		||||
    Stewart Platt <stew@futurete.ch>
 | 
			
		||||
    Stéphane Baron <sbaron>
 | 
			
		||||
    Thomas Keller <me@thomaskeller.biz>             - Monotone support
 | 
			
		||||
    Victor Quinault <victor.quinault@gmail.com>     - French translation
 | 
			
		||||
    Vladimir Solomatin <slash>
 | 
			
		||||
    William Martin <william.martin@lcpc.fr>
 | 
			
		||||
    Xavier Brochard <xavier@alternatif.org>
 | 
			
		||||
    bohwaz <http://bohwaz.net/>
 | 
			
		||||
 | 
			
		||||
And all the nice users who spent time reporting issues and promoting
 | 
			
		||||
the project. The project could not live without them.
 | 
			
		||||
 
 | 
			
		||||
@@ -104,12 +104,13 @@ without first talking to us.
 | 
			
		||||
 | 
			
		||||
## I am a translator
 | 
			
		||||
 | 
			
		||||
We currently use (transifex)[http://trac.transifex.org] to help our
 | 
			
		||||
users to translate indefero. You don't have to use it, but it's an
 | 
			
		||||
easy way to do the job. You can visit the indefero page at transifex
 | 
			
		||||
here : http://www.transifex.net/projects/p/indefero/c/indefero/
 | 
			
		||||
We currently use [transifex](http://trac.transifex.org) to help our
 | 
			
		||||
users translate indefero. You don't have to use it, but it's an easy
 | 
			
		||||
way to do the job. You can visit the indefero page at transifex here:
 | 
			
		||||
 | 
			
		||||
    http://www.transifex.net/projects/p/indefero/
 | 
			
		||||
 | 
			
		||||
Please understand that your changes will not be commited instantly,
 | 
			
		||||
but are sent to the maintainers e-mails before. Then, your changes
 | 
			
		||||
will not be in the main repository until da-loic push the changes. In
 | 
			
		||||
that way, try to do big changes with less submissions.
 | 
			
		||||
will not be in the main repository until the maintainer pushs the
 | 
			
		||||
changes. In that way, try to do big changes with less submissions.
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,18 @@ The installation of InDefero is composed of 2 parts, first the
 | 
			
		||||
installation of the [Pluf framework](http://www.pluf.org) and second,
 | 
			
		||||
the installation of InDefero by itself.
 | 
			
		||||
 | 
			
		||||
## PHP modules for indefero
 | 
			
		||||
 | 
			
		||||
Indefero needs additional PHP modules to function correctly, namely
 | 
			
		||||
 | 
			
		||||
 - gd (for graphic operations)
 | 
			
		||||
 - zip (for upload archive processing)
 | 
			
		||||
 | 
			
		||||
The package names of these modules might vary between distributions,
 | 
			
		||||
for Debian they are
 | 
			
		||||
 | 
			
		||||
    $ apt-get install php5-gd php5-zip
 | 
			
		||||
 | 
			
		||||
## Recommended Layout of the Files
 | 
			
		||||
 | 
			
		||||
If your server document root is in `/var/www` a good thing is to keep
 | 
			
		||||
@@ -37,6 +49,7 @@ docroot.
 | 
			
		||||
    $ sudo pear upgrade-all
 | 
			
		||||
    $ sudo pear install --alldeps Mail
 | 
			
		||||
    $ sudo pear install --alldeps Mail_mime
 | 
			
		||||
    $ sudo pear install --alldeps Console_Getopt
 | 
			
		||||
 | 
			
		||||
If you already have some of the PEAR packages installed with your
 | 
			
		||||
distribution, the `Mail` package is often not up-to-date, 
 | 
			
		||||
@@ -125,6 +138,7 @@ The documentation is available in the `doc` folder.
 | 
			
		||||
* Subversion: `doc/syncsvn.mdtext`.
 | 
			
		||||
* Mercurial: `doc/syncmercurial.mdtext`.
 | 
			
		||||
* Git: `doc/syncgit.mdtext`.
 | 
			
		||||
* Monotone: `doc/syncmonotone.mdtext`
 | 
			
		||||
 | 
			
		||||
## For the Apache Webserver Users
 | 
			
		||||
 | 
			
		||||
@@ -222,4 +236,4 @@ functions. You need to prevent the overload as it does not make sense
 | 
			
		||||
anyway (magic in the background is bad!). 
 | 
			
		||||
See the [corresponding ticket][reglink].
 | 
			
		||||
 | 
			
		||||
[reglink]: http://projects.ceondo.com/p/indefero/issues/481/
 | 
			
		||||
[reglink]: http://projects.ceondo.com/p/indefero/issues/481/
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										134
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										134
									
								
								Makefile
									
									
									
									
									
								
							@@ -22,46 +22,63 @@
 | 
			
		||||
#   sudo apt-get install python-setuptools
 | 
			
		||||
#   sudo easy_install -U transifex-client
 | 
			
		||||
 | 
			
		||||
PLUF_PATH=$(shell php -r "require_once('src/IDF/conf/path.php'); echo PLUF_PATH;")
 | 
			
		||||
 | 
			
		||||
all help:
 | 
			
		||||
	@echo "Rules for generate tarball :"
 | 
			
		||||
 | 
			
		||||
.PHONY: help
 | 
			
		||||
help:
 | 
			
		||||
	@printf "Rules for generating distributable files :\n"
 | 
			
		||||
	@for b in `git branch | sed "s/^. //g"`; do \
 | 
			
		||||
		echo -e "\t"$$b"_tarball - Generate a zip archive of the "$$b" branch."; \
 | 
			
		||||
		printf "\t"$$b"-zipfile - Generate a zip archive of the "$$b" branch.\n"; \
 | 
			
		||||
	done
 | 
			
		||||
	@echo -e "\nRules for internationnalization :";
 | 
			
		||||
	@echo -e "\tpot-update - Update the POT file from HTML template and PHP source, then merge it with PO file"
 | 
			
		||||
	@echo -e "\tpot-push - Send the POT file on transifex server"
 | 
			
		||||
	@echo -e "\tpo-update - Merge POT file into PO file. POT is not regenerated."
 | 
			
		||||
	@echo -e "\tpo-push - Send the all PO file on transifex server"
 | 
			
		||||
	@echo -e "\tpo-pull - Get all PO file from transifex server"
 | 
			
		||||
	@printf "\nRules for internationalization :\n";
 | 
			
		||||
	@printf "\tpot-update - Update the POT file from HTML templates and PHP sources, then merge it with PO file.\n"
 | 
			
		||||
	@printf "\tpot-push   - Send the POT file to the transifex server.\n"
 | 
			
		||||
	@printf "\tpo-update  - Merge the POT file into the PO file. The POT is not regenerated.\n"
 | 
			
		||||
	@printf "\tpo-push    - Send the all PO files to the transifex server.\n"
 | 
			
		||||
	@printf "\tpo-pull    - Get all PO files from the transifex server.\n"
 | 
			
		||||
	@printf "\tpo-stats   - Show translation statistics of all PO files.\n"
 | 
			
		||||
	@printf "\nRules for managing the database :\n";
 | 
			
		||||
	@printf "\tdb-install	- Install the database schema.\n"
 | 
			
		||||
	@printf "\tdb-update	- Update the database schema.\n"
 | 
			
		||||
	@printf "\tdb-backup-foo	- Create a named backup 'foo' with data from the current database.\n"
 | 
			
		||||
	@printf "\tdb-restore-foo	- Restore schema and the data from a named backup 'foo' to an empty database.\n"
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
#   Internationnalization rule, POT & PO file manipulation
 | 
			
		||||
#   
 | 
			
		||||
#   Internationalization rule, POT & PO file manipulation
 | 
			
		||||
#
 | 
			
		||||
.PHONY: pluf_path
 | 
			
		||||
pluf_path:
 | 
			
		||||
ifeq (src/IDF/conf/path.php, $(wildcard src/IDF/conf/path.php))
 | 
			
		||||
PLUF_PATH=$(shell php -r "require_once('src/IDF/conf/path.php'); echo PLUF_PATH;")
 | 
			
		||||
else
 | 
			
		||||
	@printf "File 'src/IDF/conf/path.php' don't exist. Please configure it !\n"
 | 
			
		||||
	@exit 1
 | 
			
		||||
endif
 | 
			
		||||
 
 | 
			
		||||
.PHONY: pot-update po-update
 | 
			
		||||
pot-update:
 | 
			
		||||
pot-update: pluf_path
 | 
			
		||||
	# Backup pot file
 | 
			
		||||
	@if [ -e src/IDF/locale/idf.pot ]; then                     \
 | 
			
		||||
	mv -f src/IDF/locale/idf.pot src/IDF/locale/idf.pot.bak;    \
 | 
			
		||||
	fi
 | 
			
		||||
	touch src/IDF/locale/idf.pot;
 | 
			
		||||
	# Extract string
 | 
			
		||||
	@cd src; php $(PLUF_PATH)/extracttemplates.php IDF/conf/idf.php IDF/gettexttemplates
 | 
			
		||||
	@cd src; php "$(PLUF_PATH)/extracttemplates.php" IDF/conf/idf.php IDF/gettexttemplates
 | 
			
		||||
	@cd src; for phpfile in `find . -iname "*.php"`; do \
 | 
			
		||||
		echo "Parsing file : "$$phpfile; \
 | 
			
		||||
		xgettext -o idf.pot -p ./IDF/locale/ --from-code=UTF-8 -j --keyword --keyword=__ --keyword=_n:1,2 -L PHP $$phpfile ; \
 | 
			
		||||
		printf "Parsing file : "$$phpfile"\n"; \
 | 
			
		||||
		xgettext -o idf.pot -p ./IDF/locale/ --from-code=UTF-8 -j \
 | 
			
		||||
			--keyword --keyword=__ --keyword=_n:1,2 -L PHP "$$phpfile" ; \
 | 
			
		||||
		done
 | 
			
		||||
	#	Remove tmp folder
 | 
			
		||||
	rm -Rf src/IDF/gettexttemplates
 | 
			
		||||
	# Update PO
 | 
			
		||||
	@make po-update
 | 
			
		||||
 | 
			
		||||
po-update:
 | 
			
		||||
po-update: pluf_path
 | 
			
		||||
	@for pofile in `ls src/IDF/locale/*/idf.po`; do \
 | 
			
		||||
		echo "Updating file : "$$pofile; \
 | 
			
		||||
		msgmerge -v -U $$pofile src/IDF/locale/idf.pot; \
 | 
			
		||||
		echo ; \
 | 
			
		||||
		printf "Updating file : "$$pofile"\n"; \
 | 
			
		||||
		msgmerge -v -U "$$pofile" src/IDF/locale/idf.pot; \
 | 
			
		||||
		printf "\n"; \
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
@@ -72,22 +89,22 @@ check-tx-config:
 | 
			
		||||
	@if [ ! -e .tx/config ]; then                                       \
 | 
			
		||||
	mkdir -p .tx;                                                       \
 | 
			
		||||
	touch .tx/config;                                                   \
 | 
			
		||||
	echo "[main]" >> .tx/config;                                        \
 | 
			
		||||
	echo "host = http://www.transifex.net" >> .tx/config;               \
 | 
			
		||||
	echo "" >> .tx/config;                                              \
 | 
			
		||||
	echo "[indefero.idfpot]" >> .tx/config;                             \
 | 
			
		||||
	echo "file_filter = src/IDF/locale/<lang>/idf.po" >> .tx/config;    \
 | 
			
		||||
	echo "source_file = src/IDF/locale/idf.pot" >> .tx/config;          \
 | 
			
		||||
	echo "source_lang = en" >> .tx/config;                              \
 | 
			
		||||
	printf "[main]\n" >> .tx/config;                                        \
 | 
			
		||||
	printf "host = http://www.transifex.net\n" >> .tx/config;               \
 | 
			
		||||
	printf "\n" >> .tx/config;                                              \
 | 
			
		||||
	printf "[indefero.idfpot]\n" >> .tx/config;                             \
 | 
			
		||||
	printf "file_filter = src/IDF/locale/<lang>/idf.po\n" >> .tx/config;    \
 | 
			
		||||
	printf "source_file = src/IDF/locale/idf.pot\n" >> .tx/config;          \
 | 
			
		||||
	printf "source_lang = en\n" >> .tx/config;                              \
 | 
			
		||||
	fi
 | 
			
		||||
	@if [ ! -e $(HOME)/.transifexrc ]; then								\
 | 
			
		||||
	@if [ ! -e $(HOME)/.transifexrc ]; then					\
 | 
			
		||||
	touch $(HOME)/.transifexrc;												\
 | 
			
		||||
	echo "[http://www.transifex.net]" >> $(HOME)/.transifexrc;				\
 | 
			
		||||
	echo "username = " >> $(HOME)/.transifexrc;								\
 | 
			
		||||
	echo "token = " >> $(HOME)/.transifexrc;									\
 | 
			
		||||
	echo "password = " >> $(HOME)/.transifexrc;								\
 | 
			
		||||
	echo "hostname = http://www.transifex.net" >> $(HOME)/.transifexrc;		\
 | 
			
		||||
	echo "You must edit the file ~/.transifexrc to setup your transifex account (login & password) !";		\
 | 
			
		||||
	printf "[http://www.transifex.net]\n" >> $(HOME)/.transifexrc;						\
 | 
			
		||||
	printf "username = \n" >> $(HOME)/.transifexrc;								\
 | 
			
		||||
	printf "token = \n" >> $(HOME)/.transifexrc;								\
 | 
			
		||||
	printf "password = \n" >> $(HOME)/.transifexrc;								\
 | 
			
		||||
	printf "hostname = http://www.transifex.net\n" >> $(HOME)/.transifexrc;					\
 | 
			
		||||
	printf "You must edit the file ~/.transifexrc to setup your transifex account (login & password) !\n";	\
 | 
			
		||||
	exit 1;																\
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
@@ -98,13 +115,52 @@ po-push: check-tx-config
 | 
			
		||||
	@tx push -t
 | 
			
		||||
 | 
			
		||||
po-pull: check-tx-config
 | 
			
		||||
	# Save PO
 | 
			
		||||
	@for pofile in `ls src/IDF/locale/*/idf.po`; do \
 | 
			
		||||
	    cp $$pofile $$pofile".save"; \
 | 
			
		||||
	done
 | 
			
		||||
	# Get new one
 | 
			
		||||
	@tx pull -a
 | 
			
		||||
	# Merge Transifex PO into local PO (so fuzzy entry is correctly saved)
 | 
			
		||||
	@for pofile in `ls src/IDF/locale/*/idf.po`; do \
 | 
			
		||||
	    msgmerge -U $$pofile".save" $$pofile; \
 | 
			
		||||
	    rm -f $$pofile; \
 | 
			
		||||
	    mv $$pofile".save" $$pofile; \
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
po-stats:
 | 
			
		||||
	@msgfmt --statistics -v src/IDF/locale/idf.pot
 | 
			
		||||
	@for pofile in `ls src/IDF/locale/*/idf.po`; do \
 | 
			
		||||
	    msgfmt --statistics -v $$pofile; \
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
#   Generic rule to build a tarball of indefero for a specified branch
 | 
			
		||||
#   ex: make master_tarball
 | 
			
		||||
#       make dev_tarball
 | 
			
		||||
#   Generic rule to build a zipfile of indefero for a specified branch
 | 
			
		||||
#   ex: make master_zipfile
 | 
			
		||||
#       make develop_zipfile
 | 
			
		||||
#
 | 
			
		||||
%_tarball:
 | 
			
		||||
	@git archive --format=zip --prefix="indefero/" $(@:_tarball=) > indefero-$(@:_tarball=)-`git log $(@:_tarball=) -n 1 --pretty=format:%H`.zip
 | 
			
		||||
%-zipfile:
 | 
			
		||||
	@git archive --format=zip --prefix="indefero/" $* \
 | 
			
		||||
		> indefero-$*-`git log $* -n 1 \
 | 
			
		||||
		--pretty=format:%h`.zip
 | 
			
		||||
 | 
			
		||||
%-tarfile:
 | 
			
		||||
	@git archive --format=tar --prefix="indefero/" $* \
 | 
			
		||||
		> indefero-$*-`git log $* -n 1 \
 | 
			
		||||
		--pretty=format:%h`.tar
 | 
			
		||||
 | 
			
		||||
db-install:
 | 
			
		||||
	@cd src && php "$(PLUF_PATH)/migrate.php" --conf=IDF/conf/idf.php -a -d -i
 | 
			
		||||
 | 
			
		||||
db-update:
 | 
			
		||||
	@cd src && php "$(PLUF_PATH)/migrate.php" --conf=IDF/conf/idf.php -a -d
 | 
			
		||||
 | 
			
		||||
db-backup-%:
 | 
			
		||||
	@[ -e backups ] || mkdir backups
 | 
			
		||||
	@cd src && php "$(PLUF_PATH)/migrate.php" --conf=IDF/conf/idf.php -a -b ../backups $*
 | 
			
		||||
	@echo Files for named backup $* have been saved into backups/ directory.
 | 
			
		||||
 | 
			
		||||
db-restore-%:
 | 
			
		||||
	@cd src && php "$(PLUF_PATH)/migrate.php" --conf=IDF/conf/idf.php -a -r ../backups $*
 | 
			
		||||
	@echo Files for named backup $* have been restored from the backups/ directory.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										328
									
								
								NEWS.mdtext
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										328
									
								
								NEWS.mdtext
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,328 @@
 | 
			
		||||
# InDefero 1.4 - xxx xxx xx xx:xx 2012 UTC
 | 
			
		||||
 | 
			
		||||
## New Features
 | 
			
		||||
 | 
			
		||||
- Indefero can now record the due date of an issue and lets
 | 
			
		||||
  you filter and search by overdue issues (fixes issue 584,
 | 
			
		||||
  thanks to Simon Holywell!)
 | 
			
		||||
 | 
			
		||||
# InDefero 1.3.3 - Sun Nov 18 22:54:00 UTC 2012
 | 
			
		||||
 | 
			
		||||
**ATTENTION**: InDefero needs Pluf [a45dc195](http://projects.ceondo.com/p/pluf/source/commit/a45dc195)
 | 
			
		||||
or newer to run properly!
 | 
			
		||||
 | 
			
		||||
## Bugfixes
 | 
			
		||||
 | 
			
		||||
- A long standing bug in the Mercurial plugin that lead to corruption
 | 
			
		||||
  of boolean configuration values in the `hgrc` of the served repository
 | 
			
		||||
  has been fixed (issue 523).
 | 
			
		||||
 
 | 
			
		||||
- If an anonymous or authenticated user had no access to any project in a 
 | 
			
		||||
  forge, all projects were listed for him (but still no one was actually
 | 
			
		||||
  accessible). This has been fixed. 
 | 
			
		||||
 | 
			
		||||
- Fixed a problem where the SyncGit plugin doesn't properly updates the
 | 
			
		||||
  authorized_keys file when the public key data contained slashes (thanks
 | 
			
		||||
  to Simon Gareste for the fix!)
 | 
			
		||||
 | 
			
		||||
- Under PostgreSQL indefero could not be set up because of a circular
 | 
			
		||||
  foreign key dependency. This has been fixed (issue 800).
 | 
			
		||||
 | 
			
		||||
- Under PostgreSQL new projects could not be created due to a failing
 | 
			
		||||
  foreign key relation. Adding project tags was not possible for a similar
 | 
			
		||||
  reason. This has been fixed (issue 800, continued).
 | 
			
		||||
 | 
			
		||||
- If a project was created based on the settings of an existing project,
 | 
			
		||||
  not all settings, like for example the new notification settings, have
 | 
			
		||||
  been copied. This has been changed insofar that now all properties except
 | 
			
		||||
  the project's URL, logo and individual SCM settings are copied by default.
 | 
			
		||||
 | 
			
		||||
- Wiki pages couldn't be properly saved with E_NOTICE enabled because
 | 
			
		||||
  of a syntax error (fixes issue 808).
 | 
			
		||||
 | 
			
		||||
- Indefero now shows detected copies in git changesets.
 | 
			
		||||
 | 
			
		||||
- A user is no longer redirected to the Help page if he enters 'H' in the
 | 
			
		||||
  password text field on the login page (fixes issue 821).
 | 
			
		||||
 | 
			
		||||
# InDefero 1.3.2 - Wed May 09 20:05 2012 UTC
 | 
			
		||||
 | 
			
		||||
## Bugfixes
 | 
			
		||||
 | 
			
		||||
- Fix two bugs in the project list view if no project
 | 
			
		||||
  is visible to the user or available in the forge (issue 805)
 | 
			
		||||
 | 
			
		||||
# InDefero 1.3.1 - Sun May 06 20:32 2012 UTC
 | 
			
		||||
 | 
			
		||||
## Bugfixes
 | 
			
		||||
 | 
			
		||||
- Compatiblity fixes for PostgreSQL (issue 800)
 | 
			
		||||
- Fix TOC generation in wiki (issue 803)
 | 
			
		||||
- Make the display of large files and diffs faster (issue 804)
 | 
			
		||||
- Make the project list faster and its tag list more accurate by not
 | 
			
		||||
  counting projects that are invisible to the current user
 | 
			
		||||
 | 
			
		||||
## Language and Translations
 | 
			
		||||
 | 
			
		||||
- French translation updated (thanks to Jonathan Aillet!)
 | 
			
		||||
 | 
			
		||||
# InDefero 1.3 - Sun Apr 15 21:10 2012 UTC
 | 
			
		||||
 | 
			
		||||
This new major release of Indefero is possible thanks to the sponsor of
 | 
			
		||||
[Scilab Enterprises](http://www.scilab-enterprises.com/).
 | 
			
		||||
Scilab Enterprises is proud to share with the Indefero community the new
 | 
			
		||||
changes which greatly improves the overall quality of the Indefero
 | 
			
		||||
forge.
 | 
			
		||||
 | 
			
		||||
**ATTENTION**: InDefero now requires a PHP 5.3 compatible setup! You also 
 | 
			
		||||
need Pluf [4121ca4](http://projects.ceondo.com/p/pluf/source/commit/4121ca4)
 | 
			
		||||
or newer to properly run this version of Indefero!
 | 
			
		||||
 | 
			
		||||
## Changes
 | 
			
		||||
 | 
			
		||||
- Indefero's post-commit web hook now by default issues HTTP PUT instead of
 | 
			
		||||
  HTTP POST requests and carries the authentication digest in the new
 | 
			
		||||
  `Web-Hook-Hmac` header.  The old behaviour can be re-enabled by setting the
 | 
			
		||||
  `$cfg['webhook_processing']` flag to "compat", we urge you to change the
 | 
			
		||||
  implementations of this web hook as this setting is likely to be removed
 | 
			
		||||
  in future versions of Indefero.
 | 
			
		||||
- Indefero now needs PHP's zip module which is usually not enabled by default.
 | 
			
		||||
- Previously configured email notifications now have to be explicitely
 | 
			
		||||
  activated in the project's administrative area.
 | 
			
		||||
 | 
			
		||||
## New Features
 | 
			
		||||
 | 
			
		||||
- It is now possible to upload and embed resources like images or text
 | 
			
		||||
  files into wiki pages. If no preview for a resource's mime type is
 | 
			
		||||
  available, than a download link is provided for it instead.
 | 
			
		||||
- The notification system has been overhauled; it is now possible to configure
 | 
			
		||||
  what kind of user group, project administrators, members and / or additional
 | 
			
		||||
  mail addresses are notified about updates in a certain section, such as 
 | 
			
		||||
  issues, downloads, reviews, and so on. We now also ensure that notification
 | 
			
		||||
  emails for one object are uniquely identifyable to support a grouped view
 | 
			
		||||
  in email clients that support that. (fixes issues  334, 452, 480, and 791)
 | 
			
		||||
- Indefero can now be configured to record activity metrics for all projects
 | 
			
		||||
  in a forge. This needs a special cron job named `activitycron.php` 
 | 
			
		||||
  (under `scripts`) that is run on a regular basis. The metrics can be
 | 
			
		||||
  fine-tuned via `activity_section_weights` and `activity_lookback` in
 | 
			
		||||
  `idf.php` and the result is visible as green bar in the project list view.
 | 
			
		||||
- The forge's project list has been overhauled - its now possible to attach
 | 
			
		||||
  labels on projects and to filter and order the project list by various
 | 
			
		||||
  criteria. Additionally, projects can now get an external project URL
 | 
			
		||||
  configured that is displayed as linkable icon right beside the project name
 | 
			
		||||
  (if available)
 | 
			
		||||
- Forge administrators can furthermore configure an alternative entry page
 | 
			
		||||
  for the forge that is displayed instead of the plain project list. This
 | 
			
		||||
  page accepts standard Markdown syntax and has support for the new
 | 
			
		||||
  `projectlist` macro that allows the (partial) inline rendering of the
 | 
			
		||||
  known global project list. 
 | 
			
		||||
- It is now also possible to configure a web hook that informs an external
 | 
			
		||||
  URL about new and updated downloads for a specific project, similar to the
 | 
			
		||||
  available post-commit web hook.
 | 
			
		||||
- One can now upload multiple files at once by using a special archive format
 | 
			
		||||
  which Indefero processes in the background and for which individual upload
 | 
			
		||||
  records are created.
 | 
			
		||||
 | 
			
		||||
## Bugfixes
 | 
			
		||||
 | 
			
		||||
- Indefero no longer confuses a non-owner of an issue with a notification that
 | 
			
		||||
  a particular ticket has been opened and assigned to him (fixes issue 562)
 | 
			
		||||
- The diff view now renders properly in Firefox when a minimum font size
 | 
			
		||||
  is configured or the user zooms the web page (fixes issue 773)
 | 
			
		||||
- Ensure that IDF does not break UTF-8 encoded strings when
 | 
			
		||||
  shortening them for view rendering (issue 785)
 | 
			
		||||
- Two XSS holes in the issue and review details views are closed (fixes issue 793)
 | 
			
		||||
 | 
			
		||||
## Language and Translations
 | 
			
		||||
 | 
			
		||||
- Multiple fixes to English source strings (fixes issues 763, 766, and 772,
 | 
			
		||||
  thanks to JP Fleury!)
 | 
			
		||||
- Updates to the French translation (thanks to Victor Quinault)
 | 
			
		||||
 | 
			
		||||
# InDefero 1.2 - Sun Nov 6 23:04:00 UTC 2011
 | 
			
		||||
 | 
			
		||||
ATTENTION: You need Pluf [46b7f251](http://projects.ceondo.com/p/pluf/source/commit/46b7f251)
 | 
			
		||||
or newer to properly run this version of Indefero!
 | 
			
		||||
 | 
			
		||||
## New Features
 | 
			
		||||
 | 
			
		||||
- Indefero's issue tracker can now bi-directionally link issues with variable,
 | 
			
		||||
  configurable terms, such as "is related to", "is blocked by" or
 | 
			
		||||
  "is duplicated by" (issue 638)
 | 
			
		||||
- When you search for issues, the results can further be refined by issue state
 | 
			
		||||
  (open or closed) and label (partially implements issue 548)
 | 
			
		||||
- Source and diff views now make characters like line endings, tabs and other
 | 
			
		||||
  "invisible" control characters visible on hover and cope with long lines much
 | 
			
		||||
  better (issue 636)
 | 
			
		||||
- Mercurial source views now show parent revisions (if any) and detailed change
 | 
			
		||||
  information
 | 
			
		||||
- Subversion source views now show detailed change information (issue 622)
 | 
			
		||||
- File download URLs now contain the file name rather than the upload id;
 | 
			
		||||
  old links still work though (issues 559 and 686)
 | 
			
		||||
- monotone file and directory attributes are displayed in the tree and file view
 | 
			
		||||
  (needs a monotone with an interface version of 13.1 or newer)
 | 
			
		||||
- The context area is now kept in view when a page scrolls down several pages
 | 
			
		||||
- A summary section has been added to the issue tracker with statistics about
 | 
			
		||||
  open / closed  issues, unresolved issues grouped by tags and owners
 | 
			
		||||
- The project list and title has gathered a customizable icon for each project
 | 
			
		||||
- The download section now provides MD5 checksums for uploaded files
 | 
			
		||||
- Wiki pages now come with a designated stylesheet for printer output (issue 713)
 | 
			
		||||
 | 
			
		||||
## Bugfixes
 | 
			
		||||
 | 
			
		||||
- Git's cron job doesn't erase manually added keys anymore (issue 247)
 | 
			
		||||
- The SVN interface acts more robust if an underlying repository has been
 | 
			
		||||
  restructured (issues 364 and 721)
 | 
			
		||||
- monotone zip archive entries now all carry the revision date as mtime (issue 645)
 | 
			
		||||
- The timeline only now only displays filter options for items a user has
 | 
			
		||||
  actually access to (issue 655)
 | 
			
		||||
- The log, tags and branches parsers for Mercurial are more robust now (issue 663)
 | 
			
		||||
- Several SSH public key parsing issues have been fixed and the check for existing,
 | 
			
		||||
  uploaded keys has been improved (issue 679)
 | 
			
		||||
- Diff views now show empty context lines for git and hg again (issue 688)
 | 
			
		||||
- The SVN command line client no longer accidential tries to store the login
 | 
			
		||||
  credentials we give him as arguments for the user executing the SVN command
 | 
			
		||||
- The usher section in the forge administration no longer displays a bogus
 | 
			
		||||
  server enty in case no monotone server is configured in the connected
 | 
			
		||||
  usher instance
 | 
			
		||||
- A timeout that popped up when Usher is restarted has been fixed (issue 695)
 | 
			
		||||
- The SyncMonotone plugin now cleans up partial artifacts it created during the
 | 
			
		||||
  addition of a new project or monotone key, in case an error popped up in the
 | 
			
		||||
  middle (issue 697)
 | 
			
		||||
- Indefero now sends the MD5 checksum as HTTP header when downloading a file from the
 | 
			
		||||
  download area; additionally, a unneeded redirect has been removed (issue 716)
 | 
			
		||||
- Source links without a specific revision did not work due to a wrong regex
 | 
			
		||||
  (issue 730)
 | 
			
		||||
- Avatar URL generation use correctly the configuration (issue 732)
 | 
			
		||||
- The SyncGit plugin no longer fails to remove a non-existing post-update hook
 | 
			
		||||
  on repository creation (issue 752)
 | 
			
		||||
- When uploading a project logo, an existing uploaded file with the same name
 | 
			
		||||
  no longer leads to an error, but is simple overwritten (fixes issue 740)
 | 
			
		||||
- The error detection and reporting in the SyncMonotone plugin has been improved
 | 
			
		||||
- The branch links users of the Subversion frontend get when they enter a wrong
 | 
			
		||||
  revision are fixed; this list is now also only displayed (for any SCM) if
 | 
			
		||||
  there are actually branches available in the repository
 | 
			
		||||
- If git's author name is not encoded in an UTF-8 compatible encoding, skip the
 | 
			
		||||
  author lookup, as we have no information what the author string is actually
 | 
			
		||||
  encoded in
 | 
			
		||||
- Indefero no longer displays an empty parents paragraph in the commit view for
 | 
			
		||||
  root revisions of a git repository
 | 
			
		||||
- Indefero now only shows the tags of the closed and not the open issues in the
 | 
			
		||||
  closed issues list
 | 
			
		||||
 | 
			
		||||
## Documentation
 | 
			
		||||
 | 
			
		||||
- The documentation on the setup of the monotone plugin has been improved.
 | 
			
		||||
 | 
			
		||||
## Translations
 | 
			
		||||
 | 
			
		||||
- The Russian translation has been enabled by default (thanks for all the great
 | 
			
		||||
  work, Denis Kot and Litew!)
 | 
			
		||||
- Brazilian Portuguese translation started (thanks to Pedro Kiefer!)
 | 
			
		||||
- Turkish translation started (thanks to Ozan!)
 | 
			
		||||
 | 
			
		||||
# InDefero 1.1.2 - Thu May 26 07:42:25 2011 UTC
 | 
			
		||||
 | 
			
		||||
## Bugfixes
 | 
			
		||||
 | 
			
		||||
- Fix tags extraction from git repository (issue 675)
 | 
			
		||||
- Fix SSH validation method (issue 671)
 | 
			
		||||
- Fix malformed URL in the RSS (issue 666)
 | 
			
		||||
- Fix validateRevision call for Mercurial Scm (issue 657)
 | 
			
		||||
 | 
			
		||||
## Translations
 | 
			
		||||
 | 
			
		||||
- Missing word in French translation (issue 672)
 | 
			
		||||
- Update Spanish translation
 | 
			
		||||
 | 
			
		||||
# InDefero 1.1.1 - Mon Mar 28 15:52 2011 UTC
 | 
			
		||||
 | 
			
		||||
## Bugfixes
 | 
			
		||||
 | 
			
		||||
- Fix an incompatibility with Python 3.1 in gitserve.py (issue 554)
 | 
			
		||||
- Fix PHP error when the commit view shows a commit with changed binary files (issue 643)
 | 
			
		||||
- A migration problem prevented the preferences page being displayed properly (issues 644 and 653)
 | 
			
		||||
- Fix PHP error when trying to create Mercurial source archives (issue 648)
 | 
			
		||||
- Improve the French translation (issue 651)
 | 
			
		||||
- Registration page missed a link to password recovery that was mentioned in a form error (issue 652)
 | 
			
		||||
 | 
			
		||||
# InDefero 1.1 - Sun Mar 20 11:44 2011 UTC
 | 
			
		||||
 | 
			
		||||
## New Features
 | 
			
		||||
 | 
			
		||||
* _Version control_:
 | 
			
		||||
 - Support for the monotone Version Control system (see [[InstallationScmMonotone]])
 | 
			
		||||
 - Display detailed changeset information in the commit details (git, mtn) (issue 544)
 | 
			
		||||
 - Show branch in the commit details (git, mtn, hg) (issue 450)
 | 
			
		||||
 - Render branch and tag names in a popup and make them filterable (git, hg, mtn) (issue 601)
 | 
			
		||||
 | 
			
		||||
* _Issue tracking_:
 | 
			
		||||
 - Forge-wide and per-project watch lists of starred issues (issue 589)
 | 
			
		||||
 - Configure a default issue template for each project (issues 212 and 540)
 | 
			
		||||
 - Pick default issue labels from the configured project settings (issue 556)
 | 
			
		||||
 - Navigate to a preceding / following issue in the issue detail view
 | 
			
		||||
 - Many new text syntaxes to auto-link revisions (see [[AutomaticLinks]], issue 569)
 | 
			
		||||
 | 
			
		||||
* _Documentation wiki_:
 | 
			
		||||
 - Automatically create a table of contents on wiki pages (issue 350)
 | 
			
		||||
 - Allow the usage of text labels for Wiki text links (issue 456)
 | 
			
		||||
 | 
			
		||||
* _Other_:
 | 
			
		||||
 - Enhanced user profile page (issue 510)
 | 
			
		||||
 - Manage multiple (commit) emails in the account settings (issues 136 and 500)
 | 
			
		||||
 - Filter the timeline and its feed by item type (issue 543)
 | 
			
		||||
 - Add multiple email addresses for project notifications (issue 372)
 | 
			
		||||
 - Direct links to other projects via the new `Project List` dropdown
 | 
			
		||||
 - InDefero gained a favicon (issue 594)
 | 
			
		||||
 | 
			
		||||
## Bugfixes
 | 
			
		||||
 | 
			
		||||
- Fix `Need SSH_ORIGINAL_COMMAND in environment` error for git sync (issue 198)
 | 
			
		||||
- Added an option to disable lengthy project size calculation in the forge (issue 403)
 | 
			
		||||
- Fix a problem when deleting an orphaned git repository (issue 467)
 | 
			
		||||
- Ignore XML parsing problems when trying to retrieve commit messages for svn (issues 469 and 518)
 | 
			
		||||
- Sort the project list by the display name of the project (issue 477)
 | 
			
		||||
- Project creation form now has a short description field as well (issue 479)
 | 
			
		||||
- Add more file extensions supported by our in-tree prettify version (issues 490 and 567)
 | 
			
		||||
- Improve the parsing of hg's log output (issues 507 and 508)
 | 
			
		||||
- Do not clean `<ins>` and `<del>` HTML markup from user input (issue 509)
 | 
			
		||||
- Improve HTML validation by switching from `strict` to `transitional` DOCTYPE (issue 511)
 | 
			
		||||
- Properly handle git commits without a changelog title (issue 520)
 | 
			
		||||
- Improve BSD compatibility in shell scripts (issue 526)
 | 
			
		||||
- Properly render inner whitespaces in viewed issue attachments (issue 528)
 | 
			
		||||
- Support for uploading SSH keys without optional comment (issue 531)
 | 
			
		||||
- Recognize irc: and git: protocols in Markdown renderer (issue 546)
 | 
			
		||||
- New config option `git_core_quotepath` to handle non-ASCII git file names (issue 553)
 | 
			
		||||
- Ensured that active views are rendered in the menu as such (issue 555)
 | 
			
		||||
- Add CSS for nested and mixed ordered and unordered lists (issue 557)
 | 
			
		||||
- Directories are now sorted before files in source tree views (issue 573)
 | 
			
		||||
- File attachments now have explicit view and download links in issue views (issue 575)
 | 
			
		||||
- Display anonymous access URL when user has no SSH key registered (issue 588)
 | 
			
		||||
- Improve the rendering of tag lists in issue views (issue 591)
 | 
			
		||||
- Improved error page when a commit or branch was not found (issue 609)
 | 
			
		||||
- Disable browser autocomplete of password fields in the account settings (issue 616)
 | 
			
		||||
- Improvements in the automatic linker parser (issue 618)
 | 
			
		||||
- The `createIssue` API method did not check the API authentication (issue 619)
 | 
			
		||||
- Reduce the memory footprint and compatibility of the internal diff parser (issues 627 and 633)
 | 
			
		||||
- Print the git branches and tags in bold which contain the currently displayed revision
 | 
			
		||||
 | 
			
		||||
## Documentation
 | 
			
		||||
 | 
			
		||||
- Document how to contribute to Indefero in `CONTRIBUTE.mdtext` (issue 486)
 | 
			
		||||
- Note possible problems with mbstring.func_overload in `INSTALL.mdtext` (issue 481)
 | 
			
		||||
- Improve links to Markdown documentation (issue 489)
 | 
			
		||||
- Explain purpose of `idf_strong_key_check` in `idf.php-dist` (issue 516)
 | 
			
		||||
 | 
			
		||||
## Translations
 | 
			
		||||
 | 
			
		||||
- Spanish translation added
 | 
			
		||||
- Started with a Simplified Chinese translation (issue 521)
 | 
			
		||||
- Started with a Russian translation
 | 
			
		||||
- Updates and fixes to the French translation (issue 574)
 | 
			
		||||
- Updates and fixes to the German translation
 | 
			
		||||
- English source language has been improved (issues 441, 478, and 631)
 | 
			
		||||
 | 
			
		||||
# InDefero 1.0 - Tue Apr 20 07:00 2010 UTC
 | 
			
		||||
 | 
			
		||||
First stable release.
 | 
			
		||||
 | 
			
		||||
@@ -25,7 +25,7 @@ If you install monotone from source (<http://monotone.ca/downloads.php>),
 | 
			
		||||
please follow the `INSTALL` document which comes with the software.
 | 
			
		||||
It contains detailed instructions, including all needed dependencies.
 | 
			
		||||
 | 
			
		||||
## Choose your indefero setup
 | 
			
		||||
## Choose your indefero (IDF) setup
 | 
			
		||||
 | 
			
		||||
The monotone plugin can be used in several different ways:
 | 
			
		||||
 | 
			
		||||
@@ -112,14 +112,40 @@ The monotone plugin can be used in several different ways:
 | 
			
		||||
            ^D
 | 
			
		||||
            $ chmod 600 usher.conf
 | 
			
		||||
 | 
			
		||||
    **ATTENTION:** Do _not_ configure a default monotone server key in `usher.conf`,
 | 
			
		||||
    otherwise the individual server key that IDF creates for each project is
 | 
			
		||||
    not used and this could cause problems.
 | 
			
		||||
 | 
			
		||||
    Your indefero www user needs later write access to `usher.conf` and
 | 
			
		||||
    `projects/`. There are two ways of setting this up:
 | 
			
		||||
 | 
			
		||||
    * Make the usher user the web user, for example via Apache's `suexec`
 | 
			
		||||
    * Use acls, like this:
 | 
			
		||||
    * Make the usher user the web user, for example via Apache's `suexec`.
 | 
			
		||||
      This is however a bit clumsy.
 | 
			
		||||
    * Preferred: Use Access Control Lists (ACLs), like this:
 | 
			
		||||
 | 
			
		||||
            #
 | 
			
		||||
            # Linux
 | 
			
		||||
            #
 | 
			
		||||
            $ setfacl -m u:www:rw usher.conf
 | 
			
		||||
            $ setfacl -m d:u:www:rwx projects/
 | 
			
		||||
            $ setfacl -m d:u:usher:rwx projects/
 | 
			
		||||
            #
 | 
			
		||||
            # FreeBSD
 | 
			
		||||
            #
 | 
			
		||||
            $ setfacl -m user:www:rw::allow usher.conf
 | 
			
		||||
            $ setfacl -m user:www:rwxp:fd:allow projects/
 | 
			
		||||
            $ setfacl -m user:usher:rwxp:fd:allow projects/
 | 
			
		||||
            #
 | 
			
		||||
            # Mac OS X
 | 
			
		||||
            #
 | 
			
		||||
            chmod +a '_www allow read,write' usher.conf
 | 
			
		||||
            chmod +a '_www allow read,write,delete,add_file,add_subdirectory,file_inherit,directory_inherit' projects/
 | 
			
		||||
            chmod +a 'usher allow read,write,delete,add_file,add_subdirectory,file_inherit,directory_inherit' projects/
 | 
			
		||||
 | 
			
		||||
      In each example's last line, `usher` is the user which is executing
 | 
			
		||||
      the usher instance. **It is very important to add this line, otherwise
 | 
			
		||||
      usher won't be able to read and write into the initial file system
 | 
			
		||||
      setup IDF creates!**
 | 
			
		||||
 | 
			
		||||
5. Wrap a daemonizer around usher, for example supervise from daemontools
 | 
			
		||||
   (<http://cr.yp.to/damontools.html>):
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										284
									
								
								logo/external_link.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										284
									
								
								logo/external_link.svg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,284 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="190.51302"
 | 
			
		||||
   height="182.16527"
 | 
			
		||||
   id="svg2"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:version="0.47 r22583"
 | 
			
		||||
   sodipodi:docname="external_link.svg"
 | 
			
		||||
   inkscape:export-filename="/Users/tommyd/Entwicklung/Open Source/indefero/www/media/idf/img/external_link.png"
 | 
			
		||||
   inkscape:export-xdpi="7.4108529"
 | 
			
		||||
   inkscape:export-ydpi="7.4108529"
 | 
			
		||||
   enable-background="new">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs4">
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="skeletal"
 | 
			
		||||
       id="path-effect4079"
 | 
			
		||||
       is_visible="true"
 | 
			
		||||
       pattern="M 0,5 10,10 10,0 z"
 | 
			
		||||
       copytype="single_stretched"
 | 
			
		||||
       prop_scale="1"
 | 
			
		||||
       scale_y_rel="false"
 | 
			
		||||
       spacing="0"
 | 
			
		||||
       normal_offset="0"
 | 
			
		||||
       tang_offset="0"
 | 
			
		||||
       prop_units="false"
 | 
			
		||||
       vertical_pattern="false"
 | 
			
		||||
       fuse_tolerance="0" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="skeletal"
 | 
			
		||||
       id="path-effect4071"
 | 
			
		||||
       is_visible="true"
 | 
			
		||||
       pattern="M 0,5 10,10 10,0 z"
 | 
			
		||||
       copytype="single_stretched"
 | 
			
		||||
       prop_scale="1"
 | 
			
		||||
       scale_y_rel="false"
 | 
			
		||||
       spacing="0"
 | 
			
		||||
       normal_offset="0"
 | 
			
		||||
       tang_offset="0"
 | 
			
		||||
       prop_units="false"
 | 
			
		||||
       vertical_pattern="false"
 | 
			
		||||
       fuse_tolerance="0" />
 | 
			
		||||
    <marker
 | 
			
		||||
       inkscape:stockid="Arrow1Lend"
 | 
			
		||||
       orient="auto"
 | 
			
		||||
       refY="0"
 | 
			
		||||
       refX="0"
 | 
			
		||||
       id="Arrow1Lend"
 | 
			
		||||
       style="overflow:visible">
 | 
			
		||||
      <path
 | 
			
		||||
         id="path3627"
 | 
			
		||||
         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
 | 
			
		||||
         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
 | 
			
		||||
         transform="matrix(-0.8,0,0,-0.8,-10,0)" />
 | 
			
		||||
    </marker>
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="skeletal"
 | 
			
		||||
       id="path-effect3619"
 | 
			
		||||
       is_visible="true"
 | 
			
		||||
       pattern="M 0,5 10,10 10,0 z"
 | 
			
		||||
       copytype="single_stretched"
 | 
			
		||||
       prop_scale="1"
 | 
			
		||||
       scale_y_rel="false"
 | 
			
		||||
       spacing="0"
 | 
			
		||||
       normal_offset="0"
 | 
			
		||||
       tang_offset="0"
 | 
			
		||||
       prop_units="false"
 | 
			
		||||
       vertical_pattern="false"
 | 
			
		||||
       fuse_tolerance="0" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="skeletal"
 | 
			
		||||
       id="path-effect3615"
 | 
			
		||||
       is_visible="true"
 | 
			
		||||
       pattern="M 0,5 10,10 10,0 z"
 | 
			
		||||
       copytype="single_stretched"
 | 
			
		||||
       prop_scale="1"
 | 
			
		||||
       scale_y_rel="false"
 | 
			
		||||
       spacing="0"
 | 
			
		||||
       normal_offset="0"
 | 
			
		||||
       tang_offset="0"
 | 
			
		||||
       prop_units="false"
 | 
			
		||||
       vertical_pattern="false"
 | 
			
		||||
       fuse_tolerance="0" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="skeletal"
 | 
			
		||||
       id="path-effect3611"
 | 
			
		||||
       is_visible="true"
 | 
			
		||||
       pattern="M 0,5 10,10 10,0 z"
 | 
			
		||||
       copytype="single_stretched"
 | 
			
		||||
       prop_scale="1"
 | 
			
		||||
       scale_y_rel="false"
 | 
			
		||||
       spacing="0"
 | 
			
		||||
       normal_offset="0"
 | 
			
		||||
       tang_offset="0"
 | 
			
		||||
       prop_units="false"
 | 
			
		||||
       vertical_pattern="false"
 | 
			
		||||
       fuse_tolerance="0" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="skeletal"
 | 
			
		||||
       id="path-effect3607"
 | 
			
		||||
       is_visible="true"
 | 
			
		||||
       pattern="M 0,5 10,10 10,0 z"
 | 
			
		||||
       copytype="single_stretched"
 | 
			
		||||
       prop_scale="1"
 | 
			
		||||
       scale_y_rel="false"
 | 
			
		||||
       spacing="0"
 | 
			
		||||
       normal_offset="0"
 | 
			
		||||
       tang_offset="0"
 | 
			
		||||
       prop_units="false"
 | 
			
		||||
       vertical_pattern="false"
 | 
			
		||||
       fuse_tolerance="0" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="skeletal"
 | 
			
		||||
       id="path-effect3603"
 | 
			
		||||
       is_visible="true"
 | 
			
		||||
       pattern="M 0,5 10,10 10,0 z"
 | 
			
		||||
       copytype="single_stretched"
 | 
			
		||||
       prop_scale="1"
 | 
			
		||||
       scale_y_rel="false"
 | 
			
		||||
       spacing="0"
 | 
			
		||||
       normal_offset="0"
 | 
			
		||||
       tang_offset="0"
 | 
			
		||||
       prop_units="false"
 | 
			
		||||
       vertical_pattern="false"
 | 
			
		||||
       fuse_tolerance="0" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="skeletal"
 | 
			
		||||
       id="path-effect3599"
 | 
			
		||||
       is_visible="true"
 | 
			
		||||
       pattern="M 0,5 10,10 10,0 z"
 | 
			
		||||
       copytype="single_stretched"
 | 
			
		||||
       prop_scale="1"
 | 
			
		||||
       scale_y_rel="false"
 | 
			
		||||
       spacing="0"
 | 
			
		||||
       normal_offset="0"
 | 
			
		||||
       tang_offset="0"
 | 
			
		||||
       prop_units="false"
 | 
			
		||||
       vertical_pattern="false"
 | 
			
		||||
       fuse_tolerance="0" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="skeletal"
 | 
			
		||||
       id="path-effect3595"
 | 
			
		||||
       is_visible="true"
 | 
			
		||||
       pattern="M 0,5 10,10 10,0 z"
 | 
			
		||||
       copytype="single_stretched"
 | 
			
		||||
       prop_scale="1"
 | 
			
		||||
       scale_y_rel="false"
 | 
			
		||||
       spacing="0"
 | 
			
		||||
       normal_offset="0"
 | 
			
		||||
       tang_offset="0"
 | 
			
		||||
       prop_units="false"
 | 
			
		||||
       vertical_pattern="false"
 | 
			
		||||
       fuse_tolerance="0" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       sodipodi:type="inkscape:persp3d"
 | 
			
		||||
       inkscape:vp_x="0 : 526.18109 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_z="744.09448 : 526.18109 : 1"
 | 
			
		||||
       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
 | 
			
		||||
       id="perspective10" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective4900"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
    <filter
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       id="filter4921"
 | 
			
		||||
       x="-0.12982728"
 | 
			
		||||
       width="1.2596545"
 | 
			
		||||
       y="-0.092135489"
 | 
			
		||||
       height="1.184271"
 | 
			
		||||
       color-interpolation-filters="sRGB">
 | 
			
		||||
      <feGaussianBlur
 | 
			
		||||
         inkscape:collect="always"
 | 
			
		||||
         stdDeviation="6.8004762"
 | 
			
		||||
         id="feGaussianBlur4923" />
 | 
			
		||||
    </filter>
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective4933"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
    <filter
 | 
			
		||||
       color-interpolation-filters="sRGB"
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       id="filter4921-3"
 | 
			
		||||
       x="-0.12982728"
 | 
			
		||||
       width="1.2596545"
 | 
			
		||||
       y="-0.092135489"
 | 
			
		||||
       height="1.184271">
 | 
			
		||||
      <feGaussianBlur
 | 
			
		||||
         inkscape:collect="always"
 | 
			
		||||
         stdDeviation="6.8004762"
 | 
			
		||||
         id="feGaussianBlur4923-8" />
 | 
			
		||||
    </filter>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     id="base"
 | 
			
		||||
     pagecolor="#ffffff"
 | 
			
		||||
     bordercolor="#666666"
 | 
			
		||||
     borderopacity="1.0"
 | 
			
		||||
     inkscape:pageopacity="1"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:zoom="1.78"
 | 
			
		||||
     inkscape:cx="138.94497"
 | 
			
		||||
     inkscape:cy="111.09667"
 | 
			
		||||
     inkscape:document-units="px"
 | 
			
		||||
     inkscape:current-layer="layer1"
 | 
			
		||||
     showgrid="false"
 | 
			
		||||
     inkscape:window-width="1389"
 | 
			
		||||
     inkscape:window-height="803"
 | 
			
		||||
     inkscape:window-x="47"
 | 
			
		||||
     inkscape:window-y="0"
 | 
			
		||||
     inkscape:window-maximized="0" />
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata7">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title></dc:title>
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     id="layer2"
 | 
			
		||||
     inkscape:label="Ebene"
 | 
			
		||||
     transform="translate(16.297732,13.906157)"
 | 
			
		||||
     style="display:inline"
 | 
			
		||||
     sodipodi:insensitive="true">
 | 
			
		||||
    <g
 | 
			
		||||
       id="g2818-7"
 | 
			
		||||
       style="fill:#e6e6e6;fill-opacity:1;stroke:#a0a0a0;stroke-width:2.26057386;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;filter:url(#filter4921-3)"
 | 
			
		||||
       transform="matrix(0.97722285,0,0,-0.85847241,-166.837,487.59193)">
 | 
			
		||||
      <rect
 | 
			
		||||
         ry="9.2957697"
 | 
			
		||||
         rx="8.07693"
 | 
			
		||||
         y="389.50504"
 | 
			
		||||
         x="171.42857"
 | 
			
		||||
         height="177.14285"
 | 
			
		||||
         width="125.71429"
 | 
			
		||||
         id="rect2816-9"
 | 
			
		||||
         style="opacity:0.79710143;fill:#000000;fill-opacity:1;stroke:#a0a0a0;stroke-width:2.26057386;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
  <g
 | 
			
		||||
     inkscape:label="Ebene 1"
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     id="layer1"
 | 
			
		||||
     transform="translate(-155.26623,-395.13431)"
 | 
			
		||||
     style="display:inline;">
 | 
			
		||||
    <rect
 | 
			
		||||
       style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:#a0a0a0;stroke-width:2.41343927;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
 | 
			
		||||
       id="rect4985"
 | 
			
		||||
       width="129.92365"
 | 
			
		||||
       height="152.95734"
 | 
			
		||||
       x="168.88869"
 | 
			
		||||
       y="407.28156"
 | 
			
		||||
       rx="9.9356585"
 | 
			
		||||
       ry="11.003931" />
 | 
			
		||||
    <path
 | 
			
		||||
       style="fill:#00000f;fill-opacity:0.94117647;stroke:none;stroke-width:2.17028474999999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
 | 
			
		||||
       d="m 205.32036,460.1042 67.83031,0 0,-32.45771 71.54343,60.58773 -72.50161,61.39918 0,-33.26916 -66.75258,0 0,-56.26004"
 | 
			
		||||
       id="path4081"
 | 
			
		||||
       sodipodi:nodetypes="cccccccc" />
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 8.6 KiB  | 
							
								
								
									
										173
									
								
								logo/no_logo.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								logo/no_logo.svg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,173 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   sodipodi:docname="no_logo.svg"
 | 
			
		||||
   inkscape:version="0.47 r22583"
 | 
			
		||||
   id="svg2985"
 | 
			
		||||
   height="32"
 | 
			
		||||
   width="32"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:export-filename="/Users/tommyd/Entwicklung/indefero/www/media/idf/img/no_logo.png"
 | 
			
		||||
   inkscape:export-xdpi="89.989998"
 | 
			
		||||
   inkscape:export-ydpi="89.989998">
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     pagecolor="#ffffff"
 | 
			
		||||
     bordercolor="#666666"
 | 
			
		||||
     borderopacity="1"
 | 
			
		||||
     objecttolerance="10"
 | 
			
		||||
     gridtolerance="10"
 | 
			
		||||
     guidetolerance="10"
 | 
			
		||||
     inkscape:pageopacity="0"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:window-width="1440"
 | 
			
		||||
     inkscape:window-height="852"
 | 
			
		||||
     id="namedview9"
 | 
			
		||||
     showgrid="false"
 | 
			
		||||
     inkscape:zoom="16.0625"
 | 
			
		||||
     inkscape:cx="8.5507561"
 | 
			
		||||
     inkscape:cy="16.122403"
 | 
			
		||||
     inkscape:window-x="0"
 | 
			
		||||
     inkscape:window-y="0"
 | 
			
		||||
     inkscape:window-maximized="0"
 | 
			
		||||
     inkscape:current-layer="g2847"
 | 
			
		||||
     showguides="true"
 | 
			
		||||
     inkscape:guide-bbox="true">
 | 
			
		||||
    <sodipodi:guide
 | 
			
		||||
       orientation="1,0"
 | 
			
		||||
       position="16,25.836575"
 | 
			
		||||
       id="guide3752" />
 | 
			
		||||
    <sodipodi:guide
 | 
			
		||||
       orientation="0,1"
 | 
			
		||||
       position="-18.677042,16"
 | 
			
		||||
       id="guide3754" />
 | 
			
		||||
  </sodipodi:namedview>
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs2987">
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       sodipodi:type="inkscape:persp3d"
 | 
			
		||||
       inkscape:vp_x="0 : 16 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_z="32 : 16 : 1"
 | 
			
		||||
       inkscape:persp3d-origin="16 : 10.666667 : 1"
 | 
			
		||||
       id="perspective13" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective2863"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective3676"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective3717"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
    <filter
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       id="filter3816"
 | 
			
		||||
       x="-0.14434362"
 | 
			
		||||
       width="1.2886872"
 | 
			
		||||
       y="-0.11562817"
 | 
			
		||||
       height="1.2312563">
 | 
			
		||||
      <feGaussianBlur
 | 
			
		||||
         inkscape:collect="always"
 | 
			
		||||
         stdDeviation="1.1799243"
 | 
			
		||||
         id="feGaussianBlur3818" />
 | 
			
		||||
    </filter>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata2990">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title></dc:title>
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     id="layer2"
 | 
			
		||||
     inkscape:label="shadow"
 | 
			
		||||
     style="display:inline"
 | 
			
		||||
     sodipodi:insensitive="true">
 | 
			
		||||
    <g
 | 
			
		||||
       transform="translate(0.44042901,0.78704792)"
 | 
			
		||||
       id="g2847-8"
 | 
			
		||||
       style="opacity:0.79710143;fill:#000000;stroke:#000000;stroke-opacity:1;filter:url(#filter3816)">
 | 
			
		||||
      <g
 | 
			
		||||
         id="g3838-0"
 | 
			
		||||
         style="fill:#000000;stroke:#000000;stroke-opacity:1" />
 | 
			
		||||
      <g
 | 
			
		||||
         id="g2401-2"
 | 
			
		||||
         transform="matrix(0.21219597,0,0,0.21219597,-70.751966,-27.73328)"
 | 
			
		||||
         style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2.4000001;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
 | 
			
		||||
         inkscape:export-filename="/home/loa/Projects/indefero/logo/powered-by-indefero.png"
 | 
			
		||||
         inkscape:export-xdpi="12.330909"
 | 
			
		||||
         inkscape:export-ydpi="12.330909">
 | 
			
		||||
        <path
 | 
			
		||||
           id="path2383-4"
 | 
			
		||||
           d="m 396.19089,173.14471 c -7.67621,0.80661 -14.40195,5.39406 -19.58101,10.89131 -7.23597,7.88004 -11.69742,18.07908 -13.32198,28.60362 -1.7236,11.28173 -0.25925,23.20635 5.07686,33.37271 3.78607,7.24384 9.53161,13.92339 17.29701,16.96772 3.86478,1.53937 8.98362,1.03284 11.67912,-2.41036 2.64357,-3.5671 2.69463,-8.234 2.85756,-12.48867 0.045,-7.61054 -0.54749,-15.25544 0.45618,-22.83193 0.87131,-9.50623 4.03944,-18.56751 6.71612,-27.66851 1.16242,-4.44333 2.25094,-9.02808 1.97499,-13.64988 -0.48817,-4.62476 -3.58059,-9.31042 -8.2964,-10.4067 -1.57489,-0.44882 -3.23412,-0.48948 -4.85845,-0.37931 z"
 | 
			
		||||
           style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.4000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
 | 
			
		||||
           inkscape:connector-curvature="0" />
 | 
			
		||||
        <path
 | 
			
		||||
           id="path2391-8"
 | 
			
		||||
           d="m 433.14691,149.28687 c 7.2059,2.76589 12.51512,8.93778 16.09494,15.58815 4.94991,9.48434 6.61962,20.49058 5.46486,31.07695 -1.25505,11.34342 -5.75582,22.48271 -13.54134,30.92159 -5.53192,6.01709 -12.81048,10.98198 -21.09918,11.91276 -4.13154,0.4866 -8.94486,-1.32748 -10.65734,-5.35104 -1.63027,-4.12976 -0.4717,-8.65084 0.47212,-12.80269 1.92628,-7.36287 4.47721,-14.59393 5.4687,-22.17201 1.61875,-9.40784 0.90381,-18.98034 0.67386,-28.46402 0.0272,-4.59278 0.1624,-9.30303 1.62515,-13.69592 1.66851,-4.34082 5.86829,-8.06645 10.70716,-7.90484 1.63738,-0.0259 3.25061,0.36424 4.79107,0.89107 z"
 | 
			
		||||
           style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.4000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
 | 
			
		||||
           inkscape:connector-curvature="0" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
  <g
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     id="layer3"
 | 
			
		||||
     inkscape:label="logo"
 | 
			
		||||
     style="display:inline">
 | 
			
		||||
    <g
 | 
			
		||||
       id="layer1"
 | 
			
		||||
       transform="translate(-0.06540759,0.09444087)">
 | 
			
		||||
      <g
 | 
			
		||||
         id="g2847">
 | 
			
		||||
        <g
 | 
			
		||||
           id="g3838" />
 | 
			
		||||
        <g
 | 
			
		||||
           id="g2401"
 | 
			
		||||
           transform="matrix(0.21219597,0,0,0.21219597,-70.751966,-27.73328)"
 | 
			
		||||
           style="fill:#e6e6e6;fill-opacity:1;stroke:#a0a0a0;stroke-width:2.4000001;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
 | 
			
		||||
           inkscape:export-filename="/home/loa/Projects/indefero/logo/powered-by-indefero.png"
 | 
			
		||||
           inkscape:export-xdpi="12.330909"
 | 
			
		||||
           inkscape:export-ydpi="12.330909">
 | 
			
		||||
          <path
 | 
			
		||||
             id="path2383"
 | 
			
		||||
             d="m 396.19089,173.14471 c -7.67621,0.80661 -14.40195,5.39406 -19.58101,10.89131 -7.23597,7.88004 -11.69742,18.07908 -13.32198,28.60362 -1.7236,11.28173 -0.25925,23.20635 5.07686,33.37271 3.78607,7.24384 9.53161,13.92339 17.29701,16.96772 3.86478,1.53937 8.98362,1.03284 11.67912,-2.41036 2.64357,-3.5671 2.69463,-8.234 2.85756,-12.48867 0.045,-7.61054 -0.54749,-15.25544 0.45618,-22.83193 0.87131,-9.50623 4.03944,-18.56751 6.71612,-27.66851 1.16242,-4.44333 2.25094,-9.02808 1.97499,-13.64988 -0.48817,-4.62476 -3.58059,-9.31042 -8.2964,-10.4067 -1.57489,-0.44882 -3.23412,-0.48948 -4.85845,-0.37931 z"
 | 
			
		||||
             style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:#a0a0a0;stroke-width:2.4000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
 | 
			
		||||
             inkscape:connector-curvature="0" />
 | 
			
		||||
          <path
 | 
			
		||||
             id="path2391"
 | 
			
		||||
             d="m 433.14691,149.28687 c 7.2059,2.76589 12.51512,8.93778 16.09494,15.58815 4.94991,9.48434 6.61962,20.49058 5.46486,31.07695 -1.25505,11.34342 -5.75582,22.48271 -13.54134,30.92159 -5.53192,6.01709 -12.81048,10.98198 -21.09918,11.91276 -4.13154,0.4866 -8.94486,-1.32748 -10.65734,-5.35104 -1.63027,-4.12976 -0.4717,-8.65084 0.47212,-12.80269 1.92628,-7.36287 4.47721,-14.59393 5.4687,-22.17201 1.61875,-9.40784 0.90381,-18.98034 0.67386,-28.46402 0.0272,-4.59278 0.1624,-9.30303 1.62515,-13.69592 1.66851,-4.34082 5.86829,-8.06645 10.70716,-7.90484 1.63738,-0.0259 3.25061,0.36424 4.79107,0.89107 z"
 | 
			
		||||
             style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:#a0a0a0;stroke-width:2.4000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
 | 
			
		||||
             inkscape:connector-curvature="0" />
 | 
			
		||||
        </g>
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 8.4 KiB  | 
							
								
								
									
										27
									
								
								phpunit.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								phpunit.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
<phpunit backupGlobals="true"
 | 
			
		||||
         backupStaticAttributes="false"
 | 
			
		||||
         bootstrap="test/bootstrap.php"
 | 
			
		||||
         convertErrorsToExceptions="true"
 | 
			
		||||
         convertNoticesToExceptions="true"
 | 
			
		||||
         convertWarningsToExceptions="true"
 | 
			
		||||
         strict="false"
 | 
			
		||||
         verbose="true">
 | 
			
		||||
 | 
			
		||||
    <testsuites>
 | 
			
		||||
        <testsuite name="Everything">
 | 
			
		||||
            <directory>test/IDF/</directory>
 | 
			
		||||
        </testsuite>
 | 
			
		||||
    </testsuites>
 | 
			
		||||
 | 
			
		||||
    <filter>
 | 
			
		||||
        <whitelist>
 | 
			
		||||
            <directory suffix=".php">src/IDF</directory>
 | 
			
		||||
            <exclude>
 | 
			
		||||
                <directory suffix=".php">src/IDF/Tests</directory>
 | 
			
		||||
                <directory suffix=".php">src/IDF/conf</directory>
 | 
			
		||||
                <file>src/IDF/version.php</file>
 | 
			
		||||
            </exclude>
 | 
			
		||||
        </whitelist>
 | 
			
		||||
    </filter>
 | 
			
		||||
</phpunit>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								run-tests
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										14
									
								
								run-tests
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
#!/usr/bin/env php
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
$xmlfile = dirname(__FILE__) .'/test/report.xml';
 | 
			
		||||
passthru('phpunit --coverage-clover='.escapeshellarg($xmlfile));
 | 
			
		||||
$xml = simplexml_load_string(file_get_contents($xmlfile));
 | 
			
		||||
unlink($xmlfile);
 | 
			
		||||
printf(
 | 
			
		||||
   '>>> code coverage %s/%s (%s%%)'."\n",
 | 
			
		||||
   $xml->project->metrics['coveredstatements'],
 | 
			
		||||
   $xml->project->metrics['statements'],
 | 
			
		||||
   round(($xml->project->metrics['coveredstatements']/(float)$xml->project->metrics['statements']) * 100.0, 2)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										48
									
								
								scripts/activitycron.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								scripts/activitycron.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This script recalculates the "project activity" for all of the
 | 
			
		||||
 * forge's projects for the given date.
 | 
			
		||||
 * If no date is given, yesterday's date is used.
 | 
			
		||||
 *
 | 
			
		||||
 * This script should run once a day. You can configure its behaviour
 | 
			
		||||
 * with $cfg['activity_section_weights'] and $cfg['activity_lookback'].
 | 
			
		||||
 *
 | 
			
		||||
 * If the script runs more than once with the same date argument,
 | 
			
		||||
 * previously recorded project activity values are replaced with the
 | 
			
		||||
 * newly created ones.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
require dirname(__FILE__).'/../src/IDF/conf/path.php';
 | 
			
		||||
require 'Pluf.php';
 | 
			
		||||
Pluf::start(dirname(__FILE__).'/../src/IDF/conf/idf.php');
 | 
			
		||||
 | 
			
		||||
$date = new DateTime('yesterday');
 | 
			
		||||
if (count($_SERVER['argv']) > 1) {
 | 
			
		||||
    $date = new DateTime($_SERVER['argv'][1]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
echo 'recalculating project activity for '.$date->format('Y-m-d')."\n";
 | 
			
		||||
IDF_ActivityTaxonomy::recalculateTaxnomies($date);
 | 
			
		||||
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2010 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
# 
 | 
			
		||||
#
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -23,14 +23,17 @@
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import sys
 | 
			
		||||
import commands
 | 
			
		||||
import traceback
 | 
			
		||||
import subprocess
 | 
			
		||||
 | 
			
		||||
SCRIPTDIR = os.path.abspath(__file__).rsplit(os.path.sep, 1)[0]
 | 
			
		||||
GITSERVEPHP = '%s/gitserve.php' % SCRIPTDIR
 | 
			
		||||
process = subprocess.Popen(['php', GITSERVEPHP, sys.argv[1]],
 | 
			
		||||
                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 | 
			
		||||
output = str.encode("\n").join(process.communicate()).strip()
 | 
			
		||||
status = process.wait()
 | 
			
		||||
 | 
			
		||||
n = len("/gitserve.py")
 | 
			
		||||
GITSERVEPHP = '%s/gitserve.php' % traceback.extract_stack(limit=1)[0][0][0:-n]
 | 
			
		||||
status, output = commands.getstatusoutput('php %s %s' % (GITSERVEPHP, sys.argv[1]))
 | 
			
		||||
if status == 0:
 | 
			
		||||
    os.execvp('git', ['git', 'shell', '-c', output.strip()])
 | 
			
		||||
else:
 | 
			
		||||
    sys.stderr.write("%s\n" % output)
 | 
			
		||||
    sys.stderr.write("%s\n" % output.strip())
 | 
			
		||||
sys.exit(1)
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2010 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2010 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2010 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2010 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										165
									
								
								src/IDF/ActivityTaxonomy.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								src/IDF/ActivityTaxonomy.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,165 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class that calculates the activity value for all projects on a
 | 
			
		||||
 * specific date and time.
 | 
			
		||||
 *
 | 
			
		||||
 * We do this by counting adds or updates of database objects in
 | 
			
		||||
 * the particular section (according to the timeline) and relate this
 | 
			
		||||
 * value to the overall activity of a section in the forge.
 | 
			
		||||
 *
 | 
			
		||||
 * To illustrate the behaviour, a simple example could be a forge with
 | 
			
		||||
 * only two projects that both have only issue tracking enabled.
 | 
			
		||||
 * The first project created or updated 10 tickets during the past period,
 | 
			
		||||
 * the other 20. The activity index for the first should therefor be
 | 
			
		||||
 * calculated as 0.33 and the second as 0.66.
 | 
			
		||||
 * Note that this simple example doesn't take activity in other
 | 
			
		||||
 * sections into account, so the the total activity of all projects
 | 
			
		||||
 * for a certain time period might add up to more than 1.0.
 | 
			
		||||
 *
 | 
			
		||||
 * @author tommyd
 | 
			
		||||
 */
 | 
			
		||||
class IDF_ActivityTaxonomy
 | 
			
		||||
{
 | 
			
		||||
    public static function recalculateTaxnomies(DateTime $date)
 | 
			
		||||
    {
 | 
			
		||||
        $sectionWeights = Pluf::f('activity_section_weights', null);
 | 
			
		||||
        $lookback = Pluf::f('activity_lookback', null);
 | 
			
		||||
        if ($sectionWeights === null || $lookback === null) {
 | 
			
		||||
            throw new LogicException('activity configuration is missing in idf.php');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        // query and normalize the section weights
 | 
			
		||||
        //
 | 
			
		||||
        $allWeights = array_sum($sectionWeights);
 | 
			
		||||
        if ($allWeights == 0) {
 | 
			
		||||
            throw new LogicException('the sum of all "activity_section_weights" must not be 0');
 | 
			
		||||
        }
 | 
			
		||||
        foreach ($sectionWeights as $section => $weight) {
 | 
			
		||||
            $sectionWeights[$section] = $weight / (float) $allWeights;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        // determine the date boundaries
 | 
			
		||||
        //
 | 
			
		||||
        if ($lookback < 1) {
 | 
			
		||||
            throw new LogicException('lookback must be greater or equal to 1');
 | 
			
		||||
        }
 | 
			
		||||
        $dateCopy = new DateTime();
 | 
			
		||||
        $dateCopy->setTimestamp($date->getTimestamp());
 | 
			
		||||
        $dateBoundaries = array(
 | 
			
		||||
            $dateCopy->format('Y-m-d 23:59:59'),
 | 
			
		||||
            $dateCopy->sub(new DateInterval('P'.$lookback.'D'))->format('Y-m-d 00:00:00')
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        // now recalculate the values for all projects
 | 
			
		||||
        //
 | 
			
		||||
        $projects = Pluf::factory('IDF_Project')->getList();
 | 
			
		||||
        foreach ($projects as $project) {
 | 
			
		||||
            self::recalculateTaxonomy($date, $project, $dateBoundaries, $sectionWeights);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static function recalculateTaxonomy(DateTime $date, IDF_Project $project, array $dateBoundaries, array $sectionWeights)
 | 
			
		||||
    {
 | 
			
		||||
        $conf = new IDF_Conf();
 | 
			
		||||
        $conf->setProject($project);
 | 
			
		||||
 | 
			
		||||
        $sectionClasses = array(
 | 
			
		||||
            'source'    => array('IDF_Commit'),
 | 
			
		||||
            'issues'    => array('IDF_Issue'),
 | 
			
		||||
            'wiki'      => array('IDF_Wiki_Page', 'IDF_Wiki_Resource'),
 | 
			
		||||
            'review'    => array('IDF_Review'),
 | 
			
		||||
            'downloads' => array('IDF_Upload')
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $value = 0;
 | 
			
		||||
        foreach ($sectionWeights as $section => $weight) {
 | 
			
		||||
            // skip closed / non-existant sections
 | 
			
		||||
            if ($conf->getVal($section.'_access_rights') === 'none')
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            if (!array_key_exists($section, $sectionClasses))
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            $sectionValue = self::calculateActivityValue(
 | 
			
		||||
                $dateBoundaries, $sectionClasses[$section], $project->id);
 | 
			
		||||
            $value = ((1 - $weight) * $value) + ($weight * $sectionValue);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        echo "project {$project->name} has an activity value of $value\n";
 | 
			
		||||
 | 
			
		||||
        $sql = new Pluf_SQL('project=%s AND date=%s', array($project->id, $date->format('Y-m-d')));
 | 
			
		||||
        $activity = Pluf::factory('IDF_ProjectActivity')->getOne(array('filter' => $sql->gen()));
 | 
			
		||||
 | 
			
		||||
        if ($activity == null) {
 | 
			
		||||
            $activity = new IDF_ProjectActivity();
 | 
			
		||||
            $activity->project = $project;
 | 
			
		||||
            $activity->date = $date->format('Y-m-d');
 | 
			
		||||
            $activity->value = $value;
 | 
			
		||||
            $activity->create();
 | 
			
		||||
        } else {
 | 
			
		||||
            $activity->value = $value;
 | 
			
		||||
            $activity->update();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static function calculateActivityValue(array $dateBoundaries, array $classes, $projectId)
 | 
			
		||||
    {
 | 
			
		||||
        $allCount = self::countActivityFor($dateBoundaries, $classes);
 | 
			
		||||
        if ($allCount == 0) return 0;
 | 
			
		||||
        $prjCount = self::countActivityFor($dateBoundaries, $classes, $projectId);
 | 
			
		||||
        return $prjCount / (float) $allCount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static function countActivityFor(array $dateBoundaries, array $classes, $projectId = null)
 | 
			
		||||
    {
 | 
			
		||||
        static $cache = array();
 | 
			
		||||
        $argIdent = md5(serialize(func_get_args()));
 | 
			
		||||
        if (array_key_exists($argIdent, $cache)) {
 | 
			
		||||
            return $cache[$argIdent];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $cache[$argIdent] = 0;
 | 
			
		||||
        list($higher, $lower) = $dateBoundaries;
 | 
			
		||||
        $db = Pluf::db();
 | 
			
		||||
        $classes_esc = array();
 | 
			
		||||
        foreach ($classes as $class) {
 | 
			
		||||
            $classes_esc[] = $db->esc($class);
 | 
			
		||||
        }
 | 
			
		||||
        $sql = new Pluf_SQL('model_class IN ('.implode(',', $classes_esc).') '.
 | 
			
		||||
                            'AND creation_dtime >= %s AND creation_dtime <= %s',
 | 
			
		||||
                         array($lower, $higher));
 | 
			
		||||
 | 
			
		||||
        if ($projectId !== null) {
 | 
			
		||||
            $sql->SAnd(new Pluf_SQL('project=%s', array($projectId)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $cache[$argIdent] = Pluf::factory('IDF_Timeline')->getCount(array('filter' => $sql->gen()));
 | 
			
		||||
 | 
			
		||||
        return $cache[$argIdent];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -235,7 +235,7 @@ class IDF_Commit extends Pluf_Model
 | 
			
		||||
</tr>
 | 
			
		||||
<tr class="extra">
 | 
			
		||||
<td colspan="2">
 | 
			
		||||
<div class="helptext right">'.sprintf(__('Commit %s, by %s'), '<a href="'.$url.'" class="mono">'.$this->scm_id.'</a>', $user).'</div></td></tr>';
 | 
			
		||||
<div class="helptext right">'.sprintf(__('Commit %1$s, by %2$s'), '<a href="'.$url.'" class="mono">'.$this->scm_id.'</a>', $user).'</div></td></tr>';
 | 
			
		||||
        return Pluf_Template::markSafe($out);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -287,6 +287,12 @@ class IDF_Commit extends Pluf_Model
 | 
			
		||||
        $url = str_replace(array('%p', '%r'),
 | 
			
		||||
                           array($project->shortname, $this->scm_id),
 | 
			
		||||
                           $conf->getVal('webhook_url', ''));
 | 
			
		||||
 | 
			
		||||
        // trigger a POST instead of the standard PUT if we're asked for
 | 
			
		||||
        $method = 'PUT';
 | 
			
		||||
        if (Pluf::f('webhook_processing', '') === 'compat') {
 | 
			
		||||
            $method = 'POST';
 | 
			
		||||
        }
 | 
			
		||||
        $payload = array('to_send' => array(
 | 
			
		||||
                                            'project' => $project->shortname,
 | 
			
		||||
                                            'rev' => $this->scm_id,
 | 
			
		||||
@@ -297,41 +303,51 @@ class IDF_Commit extends Pluf_Model
 | 
			
		||||
                                            'creation_date' => $this->creation_dtime,
 | 
			
		||||
                                            ),
 | 
			
		||||
                         'project_id' => $project->id,
 | 
			
		||||
                         'authkey' => $project->getPostCommitHookKey(),
 | 
			
		||||
                         'authkey' => $project->getWebHookKey(),
 | 
			
		||||
                         'url' => $url,
 | 
			
		||||
                         'method' => $method,
 | 
			
		||||
                         );
 | 
			
		||||
        $item = new IDF_Queue();
 | 
			
		||||
        $item->type = 'new_commit';
 | 
			
		||||
        $item->payload = $payload;
 | 
			
		||||
        $item->create();
 | 
			
		||||
 | 
			
		||||
        if ('' == $conf->getVal('source_notification_email', '')) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $current_locale = Pluf_Translation::getLocale();
 | 
			
		||||
        $langs = Pluf::f('languages', array('en'));
 | 
			
		||||
        Pluf_Translation::loadSetLocale($langs[0]);
 | 
			
		||||
 | 
			
		||||
        $context = new Pluf_Template_Context(
 | 
			
		||||
                       array(
 | 
			
		||||
                             'c' => $this,
 | 
			
		||||
                             'project' => $this->get_project(),
 | 
			
		||||
                             'url_base' => Pluf::f('url_base'),
 | 
			
		||||
                             )
 | 
			
		||||
                                             );
 | 
			
		||||
        $tmpl = new Pluf_Template('idf/source/commit-created-email.txt');
 | 
			
		||||
        $text_email = $tmpl->render($context);
 | 
			
		||||
        $addresses = explode(',', $conf->getVal('source_notification_email'));
 | 
			
		||||
        foreach ($addresses as $address) {
 | 
			
		||||
            $email = new Pluf_Mail(Pluf::f('from_email'),
 | 
			
		||||
        $from_email = Pluf::f('from_email');
 | 
			
		||||
        $recipients = $project->getNotificationRecipientsForTab('source');
 | 
			
		||||
 | 
			
		||||
        foreach ($recipients as $address => $language) {
 | 
			
		||||
 | 
			
		||||
            if (!empty($this->author) && $this->author->email === $address) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Pluf_Translation::loadSetLocale($language);
 | 
			
		||||
 | 
			
		||||
            $context = new Pluf_Template_Context(array(
 | 
			
		||||
                'commit'   => $this,
 | 
			
		||||
                'project'  => $project,
 | 
			
		||||
                'url_base' => Pluf::f('url_base'),
 | 
			
		||||
            ));
 | 
			
		||||
 | 
			
		||||
            // commits are usually not updated, therefor we do not
 | 
			
		||||
            // distinguish between create and update here
 | 
			
		||||
            $tplfile = 'idf/source/commit-created-email.txt';
 | 
			
		||||
            $subject = __('New Commit %1$s - %2$s (%3$s)');
 | 
			
		||||
 | 
			
		||||
            $tmpl = new Pluf_Template($tplfile);
 | 
			
		||||
            $text_email = $tmpl->render($context);
 | 
			
		||||
 | 
			
		||||
            $email = new Pluf_Mail($from_email,
 | 
			
		||||
                                   $address,
 | 
			
		||||
                                   sprintf(__('New Commit %s - %s (%s)'),
 | 
			
		||||
                                   sprintf($subject,
 | 
			
		||||
                                           $this->scm_id, $this->summary,
 | 
			
		||||
                                           $this->get_project()->shortname));
 | 
			
		||||
                                           $project->shortname));
 | 
			
		||||
            $email->addTextMessage($text_email);
 | 
			
		||||
            $email->sendMail();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Pluf_Translation::loadSetLocale($current_locale);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -44,9 +44,9 @@ class IDF_Conf extends Pluf_Model
 | 
			
		||||
                            array(
 | 
			
		||||
                                  'type' => 'Pluf_DB_Field_Sequence',
 | 
			
		||||
                                  //It is automatically added.
 | 
			
		||||
                                  'blank' => true, 
 | 
			
		||||
                                  'blank' => true,
 | 
			
		||||
                                  ),
 | 
			
		||||
                            'project' => 
 | 
			
		||||
                            'project' =>
 | 
			
		||||
                            array(
 | 
			
		||||
                                  'type' => 'Pluf_DB_Field_Foreignkey',
 | 
			
		||||
                                  'model' => 'IDF_Project',
 | 
			
		||||
@@ -84,7 +84,7 @@ class IDF_Conf extends Pluf_Model
 | 
			
		||||
 | 
			
		||||
    function initCache()
 | 
			
		||||
    {
 | 
			
		||||
        $this->datacache = new ArrayObject();
 | 
			
		||||
        $this->datacache = array();
 | 
			
		||||
        $sql = new Pluf_SQL('project=%s', $this->_project->id);
 | 
			
		||||
        foreach ($this->getList(array('filter' => $sql->gen())) as $val) {
 | 
			
		||||
            $this->datacache[$val->vkey] = $val->vdesc;
 | 
			
		||||
@@ -97,7 +97,7 @@ class IDF_Conf extends Pluf_Model
 | 
			
		||||
     */
 | 
			
		||||
    function setVal($key, $value)
 | 
			
		||||
    {
 | 
			
		||||
        if (!is_null($this->getVal($key, null)) 
 | 
			
		||||
        if (!is_null($this->getVal($key, null))
 | 
			
		||||
            and $value == $this->getVal($key)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -129,4 +129,12 @@ class IDF_Conf extends Pluf_Model
 | 
			
		||||
            $this->initCache();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getKeys()
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->datacache === null) {
 | 
			
		||||
            $this->initCache();
 | 
			
		||||
        }
 | 
			
		||||
        return array_keys($this->datacache);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										428
									
								
								src/IDF/Diff.php
									
									
									
									
									
								
							
							
						
						
									
										428
									
								
								src/IDF/Diff.php
									
									
									
									
									
								
							@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -27,17 +27,15 @@
 | 
			
		||||
 */
 | 
			
		||||
class IDF_Diff
 | 
			
		||||
{
 | 
			
		||||
    public $repo = '';
 | 
			
		||||
    public $diff = '';
 | 
			
		||||
    public $path_strip_level = 0;
 | 
			
		||||
    protected $lines = array();
 | 
			
		||||
 | 
			
		||||
    public $files = array();
 | 
			
		||||
 | 
			
		||||
    public function __construct($diff, $repo='')
 | 
			
		||||
    public function __construct($diff, $path_strip_level = 0)
 | 
			
		||||
    {
 | 
			
		||||
        $this->repo = $repo;
 | 
			
		||||
        $this->diff = $diff;
 | 
			
		||||
        $this->lines = preg_split("/\015\012|\015|\012/", $diff);
 | 
			
		||||
        $this->path_strip_level = $path_strip_level;
 | 
			
		||||
        $this->lines = IDF_FileUtil::splitIntoLines($diff, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function parse()
 | 
			
		||||
@@ -49,178 +47,191 @@ class IDF_Diff
 | 
			
		||||
        $files = array();
 | 
			
		||||
        $indiff = false; // Used to skip the headers in the git patches
 | 
			
		||||
        $i = 0; // Used to skip the end of a git patch with --\nversion number
 | 
			
		||||
        foreach ($this->lines as $line) {
 | 
			
		||||
            $i++;
 | 
			
		||||
            if (0 === strpos($line, '--') and isset($this->lines[$i])
 | 
			
		||||
                and preg_match('/^\d+\.\d+\.\d+\.\d+$/', $this->lines[$i])) {
 | 
			
		||||
                break;
 | 
			
		||||
        $diffsize = count($this->lines);
 | 
			
		||||
        while ($i < $diffsize) {
 | 
			
		||||
            // look for the potential beginning of a diff
 | 
			
		||||
            if (substr($this->lines[$i], 0, 4) !== '--- ') {
 | 
			
		||||
                $i++;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (0 === strpos($line, 'diff --git a')) {
 | 
			
		||||
                $current_file = self::getFile($line);
 | 
			
		||||
                $files[$current_file] = array();
 | 
			
		||||
                $files[$current_file]['chunks'] = array();
 | 
			
		||||
                $files[$current_file]['chunks_def'] = array();
 | 
			
		||||
                $current_chunk = 0;
 | 
			
		||||
                $indiff = true;
 | 
			
		||||
 | 
			
		||||
            // we're inside a diff candiate
 | 
			
		||||
            $oldfileline = $this->lines[$i++];
 | 
			
		||||
            $newfileline = $this->lines[$i++];
 | 
			
		||||
            if (substr($newfileline, 0, 4) !== '+++ ') {
 | 
			
		||||
                // not a valid diff here, move on
 | 
			
		||||
                continue;
 | 
			
		||||
            } else if (preg_match('#^diff -r [^\s]+ -r [^\s]+ (.+)$#', $line, $matches)) {
 | 
			
		||||
                $current_file = $matches[1];
 | 
			
		||||
                $files[$current_file] = array();
 | 
			
		||||
                $files[$current_file]['chunks'] = array();
 | 
			
		||||
                $files[$current_file]['chunks_def'] = array();
 | 
			
		||||
                $current_chunk = 0;
 | 
			
		||||
                $indiff = true;
 | 
			
		||||
                continue;
 | 
			
		||||
            } else if (!$indiff && 0 === strpos($line, '=========')) {
 | 
			
		||||
                // ignore pseudo stanzas with a hint of a binary file
 | 
			
		||||
                if (preg_match("/^# (.+) is binary/", $this->lines[$i]))
 | 
			
		||||
                    continue;
 | 
			
		||||
                // by default always use the new name of a possibly renamed file
 | 
			
		||||
                $current_file = self::getMtnFile($this->lines[$i+1]);
 | 
			
		||||
                // mtn 0.48 and newer set /dev/null as file path for dropped files
 | 
			
		||||
                // so we display the old name here
 | 
			
		||||
                if ($current_file == "/dev/null") {
 | 
			
		||||
                    $current_file = self::getMtnFile($this->lines[$i]);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // use new file name by default
 | 
			
		||||
            preg_match("/^\+\+\+ ([^\t\n\r]+)/", $newfileline, $m);
 | 
			
		||||
            $current_file = $m[1];
 | 
			
		||||
            if ($current_file === '/dev/null') {
 | 
			
		||||
                // except if it's /dev/null, use the old one instead
 | 
			
		||||
                // eg. mtn 0.48 and newer
 | 
			
		||||
                preg_match("/^--- ([^\t\r\n]+)/", $oldfileline, $m);
 | 
			
		||||
                $current_file = $m[1];
 | 
			
		||||
            }
 | 
			
		||||
            if ($this->path_strip_level > 0) {
 | 
			
		||||
                $fileparts = explode('/', $current_file, $this->path_strip_level+1);
 | 
			
		||||
                $current_file = array_pop($fileparts);
 | 
			
		||||
            }
 | 
			
		||||
            $current_chunk = 0;
 | 
			
		||||
            $files[$current_file] = array();
 | 
			
		||||
            $files[$current_file]['chunks'] = array();
 | 
			
		||||
            $files[$current_file]['chunks_def'] = array();
 | 
			
		||||
 | 
			
		||||
            while ($i < $diffsize && substr($this->lines[$i], 0, 3) === '@@ ') {
 | 
			
		||||
                $elems = preg_match('/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@.*/',
 | 
			
		||||
                                    $this->lines[$i++], $results);
 | 
			
		||||
                if ($elems != 1) {
 | 
			
		||||
                    // hunk is badly formatted
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                if ($current_file == "/dev/null") {
 | 
			
		||||
                    throw new Exception(
 | 
			
		||||
                        "could not determine path from diff"
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
                $files[$current_file] = array();
 | 
			
		||||
                $files[$current_file]['chunks'] = array();
 | 
			
		||||
                $files[$current_file]['chunks_def'] = array();
 | 
			
		||||
                $current_chunk = 0;
 | 
			
		||||
                $indiff = true;
 | 
			
		||||
                continue;
 | 
			
		||||
            } else if (0 === strpos($line, 'Index: ')) {
 | 
			
		||||
                $current_file = self::getSvnFile($line);
 | 
			
		||||
                $files[$current_file] = array();
 | 
			
		||||
                $files[$current_file]['chunks'] = array();
 | 
			
		||||
                $files[$current_file]['chunks_def'] = array();
 | 
			
		||||
                $current_chunk = 0;
 | 
			
		||||
                $indiff = true;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (!$indiff) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (0 === strpos($line, '@@ ')) {
 | 
			
		||||
                $files[$current_file]['chunks_def'][] = self::getChunk($line);
 | 
			
		||||
                $delstart = $results[1];
 | 
			
		||||
                $dellines = $results[2] === '' ? 1 : $results[2];
 | 
			
		||||
                $addstart = $results[3];
 | 
			
		||||
                $addlines = $results[4] === '' ? 1 : $results[4];
 | 
			
		||||
 | 
			
		||||
                $files[$current_file]['chunks_def'][] = array(
 | 
			
		||||
                    array($delstart, $dellines), array($addstart, $addlines)
 | 
			
		||||
                );
 | 
			
		||||
                $files[$current_file]['chunks'][] = array();
 | 
			
		||||
 | 
			
		||||
                while ($i < $diffsize && ($addlines >= 0 || $dellines >= 0)) {
 | 
			
		||||
                    $linetype = $this->lines[$i] != '' ? $this->lines[$i][0] : false;
 | 
			
		||||
                    $content = substr($this->lines[$i], 1);
 | 
			
		||||
                    switch ($linetype) {
 | 
			
		||||
                        case ' ':
 | 
			
		||||
                            $files[$current_file]['chunks'][$current_chunk][] =
 | 
			
		||||
                                array($delstart, $addstart, $content);
 | 
			
		||||
                            $dellines--;
 | 
			
		||||
                            $addlines--;
 | 
			
		||||
                            $delstart++;
 | 
			
		||||
                            $addstart++;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case '+':
 | 
			
		||||
                            $files[$current_file]['chunks'][$current_chunk][] =
 | 
			
		||||
                                array('', $addstart, $content);
 | 
			
		||||
                            $addlines--;
 | 
			
		||||
                            $addstart++;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case '-':
 | 
			
		||||
                            $files[$current_file]['chunks'][$current_chunk][] =
 | 
			
		||||
                                array($delstart, '', $content);
 | 
			
		||||
                            $dellines--;
 | 
			
		||||
                            $delstart++;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case '\\':
 | 
			
		||||
                            // no new line at the end of this file; remove pseudo new line from last line
 | 
			
		||||
                            $cur = count($files[$current_file]['chunks'][$current_chunk]) - 1;
 | 
			
		||||
                            $files[$current_file]['chunks'][$current_chunk][$cur][2] =
 | 
			
		||||
                                rtrim($files[$current_file]['chunks'][$current_chunk][$cur][2], "\r\n");
 | 
			
		||||
                            continue;
 | 
			
		||||
                        default:
 | 
			
		||||
                            break 2;
 | 
			
		||||
                    }
 | 
			
		||||
                    $i++;
 | 
			
		||||
                }
 | 
			
		||||
                $current_chunk++;
 | 
			
		||||
                $lline = $files[$current_file]['chunks_def'][$current_chunk-1][0][0];
 | 
			
		||||
                $rline = $files[$current_file]['chunks_def'][$current_chunk-1][1][0];
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (0 === strpos($line, '---') or 0 === strpos($line, '+++')) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (0 === strpos($line, '-')) {
 | 
			
		||||
                $files[$current_file]['chunks'][$current_chunk-1][] = array($lline, '', substr($line, 1));
 | 
			
		||||
                $lline++;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (0 === strpos($line, '+')) {
 | 
			
		||||
                $files[$current_file]['chunks'][$current_chunk-1][] = array('', $rline, substr($line, 1));
 | 
			
		||||
                $rline++;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (0 === strpos($line, ' ')) {
 | 
			
		||||
                $files[$current_file]['chunks'][$current_chunk-1][] = array($lline, $rline, substr($line, 1));
 | 
			
		||||
                $rline++;
 | 
			
		||||
                $lline++;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if ($line == '') {
 | 
			
		||||
                $files[$current_file]['chunks'][$current_chunk-1][] = array($lline, $rline, $line);
 | 
			
		||||
                $rline++;
 | 
			
		||||
                $lline++;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        $this->files = $files;
 | 
			
		||||
        return $files;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function getFile($line)
 | 
			
		||||
    {
 | 
			
		||||
        $line = substr(trim($line), 10);
 | 
			
		||||
        $n = (int) strlen($line)/2;
 | 
			
		||||
        return trim(substr($line, 3, $n-3));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function getSvnFile($line)
 | 
			
		||||
    {
 | 
			
		||||
        return substr(trim($line), 7);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function getMtnFile($line)
 | 
			
		||||
    {
 | 
			
		||||
        preg_match("/^[+-]{3} ([^\t]+)/", $line, $m);
 | 
			
		||||
        return $m[1];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Return the html version of a parsed diff.
 | 
			
		||||
     */
 | 
			
		||||
    public function as_html()
 | 
			
		||||
    {
 | 
			
		||||
        $out = '';
 | 
			
		||||
        foreach ($this->files as $filename=>$file) {
 | 
			
		||||
        foreach ($this->files as $filename => $file) {
 | 
			
		||||
            $pretty = '';
 | 
			
		||||
            $fileinfo = IDF_FileUtil::getMimeType($filename);
 | 
			
		||||
            if (IDF_FileUtil::isSupportedExtension($fileinfo[2])) {
 | 
			
		||||
                $pretty = ' prettyprint';
 | 
			
		||||
            }
 | 
			
		||||
            $out .= "\n".'<table class="diff" summary="">'."\n";
 | 
			
		||||
            $out .= '<tr id="diff-'.md5($filename).'"><th colspan="3">'.Pluf_esc($filename).'</th></tr>'."\n";
 | 
			
		||||
 | 
			
		||||
            $cc = 1;
 | 
			
		||||
            $offsets = array();
 | 
			
		||||
            $contents = array();
 | 
			
		||||
 | 
			
		||||
            foreach ($file['chunks'] as $chunk) {
 | 
			
		||||
                foreach ($chunk as $line) {
 | 
			
		||||
                    if ($line[0] and $line[1]) {
 | 
			
		||||
                        $class = 'diff-c';
 | 
			
		||||
                    } elseif ($line[0]) {
 | 
			
		||||
                        $class = 'diff-r';
 | 
			
		||||
                    list($left, $right, $content) = $line;
 | 
			
		||||
                    if ($left and $right) {
 | 
			
		||||
                        $class = 'context';
 | 
			
		||||
                    } elseif ($left) {
 | 
			
		||||
                        $class = 'removed';
 | 
			
		||||
                    } else {
 | 
			
		||||
                        $class = 'diff-a';
 | 
			
		||||
                        $class = 'added';
 | 
			
		||||
                    }
 | 
			
		||||
                    $line_content = self::padLine(Pluf_esc($line[2]));
 | 
			
		||||
                    $out .= sprintf('<tr class="diff-line"><td class="diff-lc">%s</td><td class="diff-lc">%s</td><td class="%s%s mono">%s</td></tr>'."\n", $line[0], $line[1], $class, $pretty, $line_content);
 | 
			
		||||
 | 
			
		||||
                    $offsets[] = sprintf('<td>%s</td><td>%s</td>', $left, $right);
 | 
			
		||||
                    $content = IDF_FileUtil::emphasizeControlCharacters(Pluf_esc($content));
 | 
			
		||||
                    $contents[] = sprintf('<td class="%s%s mono">%s</td>', $class, $pretty, $content);
 | 
			
		||||
                }
 | 
			
		||||
                if (count($file['chunks']) > $cc) {
 | 
			
		||||
                    $offsets[]  = '<td class="next">...</td><td class="next">...</td>';
 | 
			
		||||
                    $contents[] = '<td class="next"></td>';
 | 
			
		||||
                }
 | 
			
		||||
                if (count($file['chunks']) > $cc)
 | 
			
		||||
                $out .= '<tr class="diff-next"><td>...</td><td>...</td><td> </td></tr>'."\n";
 | 
			
		||||
                $cc++;
 | 
			
		||||
            }
 | 
			
		||||
            $out .= '</table>';
 | 
			
		||||
        }
 | 
			
		||||
        return Pluf_Template::markSafe($out);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
            list($added, $removed) = end($file['chunks_def']);
 | 
			
		||||
 | 
			
		||||
    public static function padLine($line)
 | 
			
		||||
    {
 | 
			
		||||
        $line = str_replace("\t", '    ', $line);
 | 
			
		||||
        $n = strlen($line);
 | 
			
		||||
        for ($i=0;$i<$n;$i++) {
 | 
			
		||||
            if (substr($line, $i, 1) != ' ') {
 | 
			
		||||
                break;
 | 
			
		||||
            $added = $added[0] + $added[1];
 | 
			
		||||
            $leftwidth = 0;
 | 
			
		||||
            if ($added > 0)
 | 
			
		||||
                $leftwidth = ((ceil(log10($added)) + 1) * 8) + 17;
 | 
			
		||||
 | 
			
		||||
            $removed = $removed[0] + $removed[1];
 | 
			
		||||
            $rightwidth = 0;
 | 
			
		||||
            if ($removed > 0)
 | 
			
		||||
                $rightwidth = ((ceil(log10($removed)) + 1) * 8) + 17;
 | 
			
		||||
 | 
			
		||||
            // we need to correct the width of a single column a little
 | 
			
		||||
            // to take less space and to hide the empty one
 | 
			
		||||
            $class = '';
 | 
			
		||||
            if ($leftwidth == 0) {
 | 
			
		||||
                $class = 'left-hidden';
 | 
			
		||||
                $rightwidth -= floor(log10($removed));
 | 
			
		||||
            }
 | 
			
		||||
            else if ($rightwidth == 0) {
 | 
			
		||||
                $class = 'right-hidden';
 | 
			
		||||
                $leftwidth -= floor(log10($added));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return str_repeat(' ', $i).substr($line, $i);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return array array(array(start, n), array(start, n))
 | 
			
		||||
     */
 | 
			
		||||
    public static function getChunk($line)
 | 
			
		||||
    {
 | 
			
		||||
        $elts = explode(' ', $line);
 | 
			
		||||
        $res = array();
 | 
			
		||||
        for ($i=1;$i<3;$i++) {
 | 
			
		||||
            $res[] = explode(',', trim(substr($elts[$i], 1)));
 | 
			
		||||
            $inner_linecounts =
 | 
			
		||||
              '<table class="diff-linecounts '.$class.'">' ."\n".
 | 
			
		||||
                '<colgroup><col width="'.$leftwidth.'" /><col width="'. $rightwidth.'" /></colgroup>' ."\n".
 | 
			
		||||
                '<tr class="line">' .
 | 
			
		||||
                  implode('</tr>'."\n".'<tr class="line">', $offsets).
 | 
			
		||||
                '</tr>' ."\n".
 | 
			
		||||
              '</table>' ."\n";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            $inner_contents =
 | 
			
		||||
              '<table class="diff-contents">' ."\n".
 | 
			
		||||
                '<tr class="line">' .
 | 
			
		||||
                  implode('</tr>'."\n".'<tr class="line">', $contents) .
 | 
			
		||||
                '</tr>' ."\n".
 | 
			
		||||
              '</table>' ."\n";
 | 
			
		||||
 | 
			
		||||
            $out .= '<table class="diff unified">' ."\n".
 | 
			
		||||
                      '<colgroup><col width="'.($leftwidth + $rightwidth + 1).'" /><col width="*" /></colgroup>' ."\n".
 | 
			
		||||
                      '<tr id="diff-'.md5($filename).'">'.
 | 
			
		||||
                        '<th colspan="2">'.Pluf_esc($filename).'</th>'.
 | 
			
		||||
                      '</tr>' ."\n".
 | 
			
		||||
                      '<tr>' .
 | 
			
		||||
                        '<td>'. $inner_linecounts .'</td>'. "\n".
 | 
			
		||||
                        '<td><div class="scroll">'. $inner_contents .'</div></td>'.
 | 
			
		||||
                      '</tr>' ."\n".
 | 
			
		||||
                    '</table>' ."\n";
 | 
			
		||||
        }
 | 
			
		||||
        return $res;
 | 
			
		||||
 | 
			
		||||
        return Pluf_Template::markSafe($out);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -245,12 +256,12 @@ class IDF_Diff
 | 
			
		||||
     */
 | 
			
		||||
    public function fileCompare($orig, $chunks, $filename, $context=10)
 | 
			
		||||
    {
 | 
			
		||||
        $orig_lines = preg_split("/\015\012|\015|\012/", $orig);
 | 
			
		||||
        $orig_lines = IDF_FileUtil::splitIntoLines($orig);
 | 
			
		||||
        $new_chunks = $this->mergeChunks($orig_lines, $chunks, $context);
 | 
			
		||||
        return $this->renderCompared($new_chunks, $filename);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function mergeChunks($orig_lines, $chunks, $context=10)
 | 
			
		||||
    private function mergeChunks($orig_lines, $chunks, $context=10)
 | 
			
		||||
    {
 | 
			
		||||
        $spans = array();
 | 
			
		||||
        $new_chunks = array();
 | 
			
		||||
@@ -347,40 +358,115 @@ class IDF_Diff
 | 
			
		||||
        return $nnew_chunks;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function renderCompared($chunks, $filename)
 | 
			
		||||
    private function renderCompared($chunks, $filename)
 | 
			
		||||
    {
 | 
			
		||||
        $fileinfo = IDF_FileUtil::getMimeType($filename);
 | 
			
		||||
        $pretty = '';
 | 
			
		||||
        if (IDF_FileUtil::isSupportedExtension($fileinfo[2])) {
 | 
			
		||||
            $pretty = ' prettyprint';
 | 
			
		||||
        }
 | 
			
		||||
        $out = '';
 | 
			
		||||
 | 
			
		||||
        $cc = 1;
 | 
			
		||||
        $i = 0;
 | 
			
		||||
        $left_offsets   = array();
 | 
			
		||||
        $left_contents  = array();
 | 
			
		||||
        $right_offsets  = array();
 | 
			
		||||
        $right_contents = array();
 | 
			
		||||
 | 
			
		||||
        $max_lineno_left = $max_lineno_right = 0;
 | 
			
		||||
 | 
			
		||||
        foreach ($chunks as $chunk) {
 | 
			
		||||
            foreach ($chunk as $line) {
 | 
			
		||||
                $line1 = ' ';
 | 
			
		||||
                $line2 = ' ';
 | 
			
		||||
                $line[2] = (strlen($line[2])) ? self::padLine(Pluf_esc($line[2])) : ' ';
 | 
			
		||||
                if ($line[0] and $line[1]) {
 | 
			
		||||
                    $class = 'diff-c';
 | 
			
		||||
                    $line1 = $line2 = $line[2];
 | 
			
		||||
                } elseif ($line[0]) {
 | 
			
		||||
                    $class = 'diff-r';
 | 
			
		||||
                    $line1 = $line[2];
 | 
			
		||||
                } else {
 | 
			
		||||
                    $class = 'diff-a';
 | 
			
		||||
                    $line2 = $line[2];
 | 
			
		||||
                }
 | 
			
		||||
                $out .= sprintf('<tr class="diff-line"><td class="diff-lc">%s</td><td class="%s mono%s"><code>%s</code></td><td class="diff-lc">%s</td><td class="%s mono%s"><code>%s</code></td></tr>'."\n", $line[0], $class, $pretty, $line1, $line[1], $class, $pretty, $line2);
 | 
			
		||||
            }
 | 
			
		||||
            if (count($chunks) > $cc)
 | 
			
		||||
                $out .= '<tr class="diff-next"><td>...</td><td> </td><td>...</td><td> </td></tr>'."\n";
 | 
			
		||||
            $cc++;
 | 
			
		||||
            $i++;
 | 
			
		||||
        }
 | 
			
		||||
        return Pluf_Template::markSafe($out);
 | 
			
		||||
                $left    = '';
 | 
			
		||||
                $right   = '';
 | 
			
		||||
                $content = IDF_FileUtil::emphasizeControlCharacters(Pluf_esc($line[2]));
 | 
			
		||||
 | 
			
		||||
                if ($line[0] and $line[1]) {
 | 
			
		||||
                    $class = 'context';
 | 
			
		||||
                    $left = $right = $content;
 | 
			
		||||
                } elseif ($line[0]) {
 | 
			
		||||
                    $class = 'removed';
 | 
			
		||||
                    $left = $content;
 | 
			
		||||
                } else {
 | 
			
		||||
                    $class = 'added';
 | 
			
		||||
                    $right = $content;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                $left_offsets[]   = sprintf('<td>%s</td>', $line[0]);
 | 
			
		||||
                $right_offsets[]  = sprintf('<td>%s</td>', $line[1]);
 | 
			
		||||
                $left_contents[]  = sprintf('<td class="%s%s mono">%s</td>', $class, $pretty, $left);
 | 
			
		||||
                $right_contents[] = sprintf('<td class="%s%s mono">%s</td>', $class, $pretty, $right);
 | 
			
		||||
 | 
			
		||||
                $max_lineno_left  = max($max_lineno_left, $line[0]);
 | 
			
		||||
                $max_lineno_right = max($max_lineno_right, $line[1]);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (count($chunks) > $cc) {
 | 
			
		||||
                $left_offsets[]   = '<td class="next">...</td>';
 | 
			
		||||
                $right_offsets[]  = '<td class="next">...</td>';
 | 
			
		||||
                $left_contents[]  = '<td></td>';
 | 
			
		||||
                $right_contents[] = '<td></td>';
 | 
			
		||||
            }
 | 
			
		||||
            $cc++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $leftwidth = 1;
 | 
			
		||||
        if ($max_lineno_left > 0)
 | 
			
		||||
            $leftwidth = ((ceil(log10($max_lineno_left)) + 1) * 8) + 17;
 | 
			
		||||
 | 
			
		||||
        $rightwidth = 1;
 | 
			
		||||
        if ($max_lineno_right > 0)
 | 
			
		||||
            $rightwidth = ((ceil(log10($max_lineno_right)) + 1) * 8) + 17;
 | 
			
		||||
 | 
			
		||||
        $inner_linecounts_left =
 | 
			
		||||
          '<table class="diff-linecounts">' ."\n".
 | 
			
		||||
            '<colgroup><col width="'.$leftwidth.'" /></colgroup>' ."\n".
 | 
			
		||||
            '<tr class="line">' .
 | 
			
		||||
              implode('</tr>'."\n".'<tr class="line">', $left_offsets).
 | 
			
		||||
            '</tr>' ."\n".
 | 
			
		||||
          '</table>' ."\n";
 | 
			
		||||
 | 
			
		||||
        $inner_linecounts_right =
 | 
			
		||||
          '<table class="diff-linecounts">' ."\n".
 | 
			
		||||
            '<colgroup><col width="'.$rightwidth.'" /></colgroup>' ."\n".
 | 
			
		||||
            '<tr class="line">' .
 | 
			
		||||
              implode('</tr>'."\n".'<tr class="line">', $right_offsets).
 | 
			
		||||
            '</tr>' ."\n".
 | 
			
		||||
          '</table>' ."\n";
 | 
			
		||||
 | 
			
		||||
        $inner_contents_left =
 | 
			
		||||
          '<table class="diff-contents">' ."\n".
 | 
			
		||||
            '<tr class="line">' .
 | 
			
		||||
              implode('</tr>'."\n".'<tr class="line">', $left_contents) .
 | 
			
		||||
            '</tr>' ."\n".
 | 
			
		||||
          '</table>' ."\n";
 | 
			
		||||
 | 
			
		||||
        $inner_contents_right =
 | 
			
		||||
          '<table class="diff-contents">' ."\n".
 | 
			
		||||
            '<tr class="line">' .
 | 
			
		||||
              implode('</tr>'."\n".'<tr class="line">', $right_contents) .
 | 
			
		||||
            '</tr>' ."\n".
 | 
			
		||||
          '</table>' ."\n";
 | 
			
		||||
 | 
			
		||||
        $out =
 | 
			
		||||
          '<table class="diff context">' ."\n".
 | 
			
		||||
            '<colgroup>' .
 | 
			
		||||
              '<col width="'.($leftwidth + 1).'" /><col width="*" />' .
 | 
			
		||||
              '<col width="'.($rightwidth + 1).'" /><col width="*" />' .
 | 
			
		||||
            '</colgroup>' ."\n".
 | 
			
		||||
            '<tr id="diff-'.md5($filename).'">'.
 | 
			
		||||
              '<th colspan="4">'.Pluf_esc($filename).'</th>'.
 | 
			
		||||
            '</tr>' ."\n".
 | 
			
		||||
            '<tr>' .
 | 
			
		||||
              '<th colspan="2">'.__('Old').'</th><th colspan="2">'.__('New').'</th>' .
 | 
			
		||||
            '</tr>'.
 | 
			
		||||
            '<tr>' .
 | 
			
		||||
              '<td>'. $inner_linecounts_left .'</td>'. "\n".
 | 
			
		||||
              '<td><div class="scroll">'. $inner_contents_left .'</div></td>'. "\n".
 | 
			
		||||
              '<td>'. $inner_linecounts_right .'</td>'. "\n".
 | 
			
		||||
              '<td><div class="scroll">'. $inner_contents_right .'</div></td>'. "\n".
 | 
			
		||||
            '</tr>' ."\n".
 | 
			
		||||
            '</table>' ."\n";
 | 
			
		||||
 | 
			
		||||
        return Pluf_Template::markSafe($out);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										96
									
								
								src/IDF/EmailAddress.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/IDF/EmailAddress.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Storage of Email addresses
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
class IDF_EmailAddress extends Pluf_Model
 | 
			
		||||
{
 | 
			
		||||
    public $_model = __CLASS__;
 | 
			
		||||
 | 
			
		||||
    function init()
 | 
			
		||||
    {
 | 
			
		||||
        $this->_a['table'] = 'idf_emailaddresses';
 | 
			
		||||
        $this->_a['model'] = __CLASS__;
 | 
			
		||||
        $this->_a['cols'] = array(
 | 
			
		||||
                             // It is mandatory to have an "id" column.
 | 
			
		||||
                            'id' =>
 | 
			
		||||
                            array(
 | 
			
		||||
                                  'type' => 'Pluf_DB_Field_Sequence',
 | 
			
		||||
                                  //It is automatically added.
 | 
			
		||||
                                  'blank' => true,
 | 
			
		||||
                                  ),
 | 
			
		||||
                            'user' =>
 | 
			
		||||
                            array(
 | 
			
		||||
                                  'type' => 'Pluf_DB_Field_Foreignkey',
 | 
			
		||||
                                  'model' => 'Pluf_User',
 | 
			
		||||
                                  'blank' => false,
 | 
			
		||||
                                  'verbose' => __('user'),
 | 
			
		||||
                                  ),
 | 
			
		||||
                            'address' =>
 | 
			
		||||
                            array(
 | 
			
		||||
                                  'type' => 'Pluf_DB_Field_Email',
 | 
			
		||||
                                  'blank' => false,
 | 
			
		||||
                                  'verbose' => __('email'),
 | 
			
		||||
                                  'unique' => true,
 | 
			
		||||
                                  ),
 | 
			
		||||
                            );
 | 
			
		||||
        // WARNING: Not using getSqlTable on the Pluf_User object to
 | 
			
		||||
        // avoid recursion.
 | 
			
		||||
        $t_users = $this->_con->pfx.'users';
 | 
			
		||||
        $this->_a['views'] = array(
 | 
			
		||||
                              'join_user' =>
 | 
			
		||||
                              array(
 | 
			
		||||
                                    'join' => 'LEFT JOIN '.$t_users
 | 
			
		||||
                                    .' ON '.$t_users.'.id='.$this->_con->qn('user'),
 | 
			
		||||
                                    'select' => $this->getSelect().', '
 | 
			
		||||
                                    .$t_users.'.login AS login',
 | 
			
		||||
                                    'props' => array('login' => 'login'),
 | 
			
		||||
                                    )
 | 
			
		||||
                                   );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function get_email_addresses_for_user($user)
 | 
			
		||||
    {
 | 
			
		||||
        $addr = $user->get_idf_emailaddress_list();
 | 
			
		||||
        $addr[] = (object)array("address" => $user->email, "id" => -1, "user" => $user);
 | 
			
		||||
        return $addr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function get_user_for_email_address($email)
 | 
			
		||||
    {
 | 
			
		||||
        $sql = new Pluf_SQL('email=%s', array($email));
 | 
			
		||||
        $users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen()));
 | 
			
		||||
        if ($users->count() > 0) {
 | 
			
		||||
            return $users[0];
 | 
			
		||||
        }
 | 
			
		||||
        $sql = new Pluf_SQL('address=%s', array($email));
 | 
			
		||||
        $matches = Pluf::factory('IDF_EmailAddress')->getList(array('filter'=>$sql->gen()));
 | 
			
		||||
        if ($matches->count() > 0) {
 | 
			
		||||
            return new Pluf_User($matches[0]->user);
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2010 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -65,9 +65,9 @@ class IDF_FileUtil
 | 
			
		||||
        }
 | 
			
		||||
        $table = array();
 | 
			
		||||
        $i = 1;
 | 
			
		||||
        foreach (preg_split("/\015\012|\015|\012/", $content) as $line) {
 | 
			
		||||
        foreach (self::splitIntoLines($content) as $line) {
 | 
			
		||||
            $table[] = '<tr class="c-line"><td class="code-lc" id="L'.$i.'"><a href="#L'.$i.'">'.$i.'</a></td>'
 | 
			
		||||
                .'<td class="code mono'.$pretty.'">'.IDF_Diff::padLine(Pluf_esc($line)).'</td></tr>';
 | 
			
		||||
                .'<td class="code mono'.$pretty.'">'.self::emphasizeControlCharacters(Pluf_esc($line)).'</td></tr>';
 | 
			
		||||
            $i++;
 | 
			
		||||
        }
 | 
			
		||||
        return Pluf_Template::markSafe(implode("\n", $table));
 | 
			
		||||
@@ -143,6 +143,53 @@ class IDF_FileUtil
 | 
			
		||||
        return $res;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Splits a string into separate lines while retaining the individual
 | 
			
		||||
     * line ending character for every line.
 | 
			
		||||
     *
 | 
			
		||||
     * OS 9 line endings are not supported.
 | 
			
		||||
     *
 | 
			
		||||
     * @param string content
 | 
			
		||||
     * @param boolean if true, skip completely empty lines
 | 
			
		||||
     * @return string
 | 
			
		||||
     */
 | 
			
		||||
    public static function splitIntoLines($content, $skipEmpty = false)
 | 
			
		||||
    {
 | 
			
		||||
        $last_off = 0;
 | 
			
		||||
        $lines = array();
 | 
			
		||||
        while (preg_match("/\r\n|\n/", $content, $m, PREG_OFFSET_CAPTURE, $last_off)) {
 | 
			
		||||
            $next_off = strlen($m[0][0]) + $m[0][1];
 | 
			
		||||
            $line = substr($content, $last_off, $next_off - $last_off);
 | 
			
		||||
            $last_off = $next_off;
 | 
			
		||||
            if ($line !== $m[0][0] || !$skipEmpty) $lines[] = $line;
 | 
			
		||||
        }
 | 
			
		||||
        $line = substr($content, $last_off);
 | 
			
		||||
        if ($line !== false && strlen($line) > 0) $lines[] = $line;
 | 
			
		||||
        return $lines;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This translates most of the C0 ASCII control characters into
 | 
			
		||||
     * their visual counterparts in the 0x24## unicode plane
 | 
			
		||||
     * (http://en.wikipedia.org/wiki/C0_and_C1_control_codes).
 | 
			
		||||
     *
 | 
			
		||||
     * We could add DEL (0x7F) to this set, but unfortunately this
 | 
			
		||||
     * is not nicely mapped to 0x247F in the control plane, but 0x2421
 | 
			
		||||
     * and adding an if expression below just for this is a little bit
 | 
			
		||||
     * of a hassle. And of course, the more esoteric ones from C1 are
 | 
			
		||||
     * missing as well...
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $content
 | 
			
		||||
     * @return string
 | 
			
		||||
     */
 | 
			
		||||
    public static function emphasizeControlCharacters($content)
 | 
			
		||||
    {
 | 
			
		||||
        return preg_replace(
 | 
			
		||||
            '/([\x00-\x1F])/ue',
 | 
			
		||||
            '"<span class=\"ctrl-char\" title=\"0x".bin2hex("\\1")."\">$".bin2hex("\\1")."</span>"',
 | 
			
		||||
            $content);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Find if a given mime type is a text file.
 | 
			
		||||
     * This uses the output of the self::getMimeType function.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										70
									
								
								src/IDF/Forge.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/IDF/Forge.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A lightweight model for the singleton forge entity
 | 
			
		||||
 */
 | 
			
		||||
class IDF_Forge
 | 
			
		||||
{
 | 
			
		||||
    public $_model = __CLASS__;
 | 
			
		||||
 | 
			
		||||
    public $id = 1;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var IDF_Gconf
 | 
			
		||||
     */
 | 
			
		||||
    private $conf;
 | 
			
		||||
 | 
			
		||||
    private function __construct() {
 | 
			
		||||
        $this->conf = new IDF_Gconf();
 | 
			
		||||
        $this->conf->setModel($this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function instance() {
 | 
			
		||||
        return new IDF_Forge();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getProjectLabels($default = '') {
 | 
			
		||||
        return $this->conf->getVal('project_labels', $default);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setProjectLabels($labels) {
 | 
			
		||||
        $this->conf->setVal('project_labels', $labels);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setCustomForgePageEnabled($enabled) {
 | 
			
		||||
        $this->conf->setVal('custom_forge_page_enabled', $enabled);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function isCustomForgePageEnabled($default = false) {
 | 
			
		||||
        return $this->conf->getVal('custom_forge_page_enabled', $default);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getCustomForgePageContent($default = '') {
 | 
			
		||||
        return $this->conf->getVal('custom_forge_page_content', $default);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setCustomForgePageContent($content) {
 | 
			
		||||
        $this->conf->setVal('custom_forge_page_content', $content);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								src/IDF/Form/Admin/ForgeConf.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/IDF/Form/Admin/ForgeConf.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright(C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
#(at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Configuration of the forge's start page.
 | 
			
		||||
 */
 | 
			
		||||
class IDF_Form_Admin_ForgeConf extends Pluf_Form
 | 
			
		||||
{
 | 
			
		||||
    public function initFields($extra=array())
 | 
			
		||||
    {
 | 
			
		||||
        $this->fields['enabled'] = new Pluf_Form_Field_Boolean(
 | 
			
		||||
                              array('required' => false,
 | 
			
		||||
                                    'label' => __('Custom forge page enabled'),
 | 
			
		||||
                                    'widget' => 'Pluf_Form_Widget_CheckboxInput',
 | 
			
		||||
                                    ));
 | 
			
		||||
        $this->fields['content'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                              array('required' => true,
 | 
			
		||||
                                    'label' => __('Content'),
 | 
			
		||||
                                    'widget' => 'Pluf_Form_Widget_TextareaInput',
 | 
			
		||||
                                    'widget_attrs' => array(
 | 
			
		||||
                                        'cols' => 68,
 | 
			
		||||
                                        'rows' => 26,
 | 
			
		||||
                                    ),
 | 
			
		||||
                                    ));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										62
									
								
								src/IDF/Form/Admin/LabelConf.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/IDF/Form/Admin/LabelConf.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright(C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
#(at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Configuration of forge labels.
 | 
			
		||||
 */
 | 
			
		||||
class IDF_Form_Admin_LabelConf extends Pluf_Form
 | 
			
		||||
{
 | 
			
		||||
    const init_project_labels = 'UI:GUI = Applications with graphical user interfaces
 | 
			
		||||
UI:CLI = Applications with no graphical user interfaces
 | 
			
		||||
License:BSD = Applications with BSD license
 | 
			
		||||
License:GPL = Applications with GPL license
 | 
			
		||||
';
 | 
			
		||||
 | 
			
		||||
    public function initFields($extra=array())
 | 
			
		||||
    {
 | 
			
		||||
               $this->fields['project_labels'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                      array('required' => true,
 | 
			
		||||
                                            'label' => __('Predefined project labels'),
 | 
			
		||||
                                            'initial' => self::init_project_labels,
 | 
			
		||||
                                            'widget_attrs' => array('rows' => 13,
 | 
			
		||||
                                                                    'cols' => 75),
 | 
			
		||||
                                            'widget' => 'Pluf_Form_Widget_TextareaInput',
 | 
			
		||||
                                            ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function clean_project_labels()
 | 
			
		||||
    {
 | 
			
		||||
        $labels = preg_split("/\s*\n\s*/", $this->cleaned_data['project_labels'], -1, PREG_SPLIT_NO_EMPTY);
 | 
			
		||||
        for ($i=0; $i<count($labels); ++$i) {
 | 
			
		||||
            $labels[$i] = trim($labels[$i]);
 | 
			
		||||
            if (!preg_match('/^[\w-]+(:[\w-]+)?(\s*=\s*[^=]+)?$/', $labels[$i])) {
 | 
			
		||||
                throw new Pluf_Form_Invalid(sprintf(
 | 
			
		||||
                   __('The label "%s" is invalid: A label must only consist of alphanumeric '.
 | 
			
		||||
                      'characters and dashes, and can optionally contain a ":" with a group prefix.'),
 | 
			
		||||
                $labels[$i]));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return implode("\n", $labels);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -72,6 +72,13 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
 | 
			
		||||
                                            'widget_attrs' => array('size' => '35'),
 | 
			
		||||
                                            ));
 | 
			
		||||
 | 
			
		||||
        $this->fields['external_project_url'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                    array('required' => false,
 | 
			
		||||
                                          'label' => __('External URL'),
 | 
			
		||||
                                          'widget_attrs' => array('size' => '35'),
 | 
			
		||||
                                          'initial' => '',
 | 
			
		||||
        ));
 | 
			
		||||
 | 
			
		||||
        $this->fields['scm'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                    array('required' => true,
 | 
			
		||||
                          'label' => __('Repository type'),
 | 
			
		||||
@@ -127,6 +134,18 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
 | 
			
		||||
                                            'widget' => 'Pluf_Form_Widget_TextareaInput',
 | 
			
		||||
                                            ));
 | 
			
		||||
 | 
			
		||||
        for ($i=1;$i<7;$i++) {
 | 
			
		||||
            $this->fields['label'.$i] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                            array('required' => false,
 | 
			
		||||
                                                  'label' => __('Labels'),
 | 
			
		||||
                                                  'initial' => '',
 | 
			
		||||
                                                  'widget_attrs' => array(
 | 
			
		||||
                                                  'maxlength' => 50,
 | 
			
		||||
                                                  'size' => 20,
 | 
			
		||||
                                                ),
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $projects = array('--' => '--');
 | 
			
		||||
        foreach (Pluf::factory('IDF_Project')->getList(array('order' => 'name ASC')) as $proj) {
 | 
			
		||||
            $projects[$proj->name] = $proj->shortname;
 | 
			
		||||
@@ -182,7 +201,7 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
 | 
			
		||||
        // we accept only starting with http(s):// to avoid people
 | 
			
		||||
        // trying to access the local filesystem.
 | 
			
		||||
        if (!preg_match('#^(http|https)://#', $url)) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('Only a remote repository available throught http or https are allowed. For example "http://somewhere.com/svn/trunk".'));
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('Only a remote repository available through HTTP or HTTPS is allowed. For example "http://somewhere.com/svn/trunk".'));
 | 
			
		||||
        }
 | 
			
		||||
        return $url;
 | 
			
		||||
    }
 | 
			
		||||
@@ -199,7 +218,7 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
 | 
			
		||||
                        $mtn_master_branch)) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__(
 | 
			
		||||
                'The master branch is empty or contains illegal characters, '.
 | 
			
		||||
                'please use only letters, digits, dashs and dots as separators.'
 | 
			
		||||
                'please use only letters, digits, dashes and dots as separators.'
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -235,6 +254,11 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
 | 
			
		||||
        return $shortname;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function clean_external_project_url()
 | 
			
		||||
    {
 | 
			
		||||
        return IDF_Form_ProjectConf::checkWebURL($this->cleaned_data['external_project_url']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function clean()
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->cleaned_data['scm'] != 'svn') {
 | 
			
		||||
@@ -278,11 +302,29 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
 | 
			
		||||
        if (!$this->isValid()) {
 | 
			
		||||
            throw new Exception(__('Cannot save the model from an invalid form.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Add a tag for each label
 | 
			
		||||
        $tagids = array();
 | 
			
		||||
        for ($i=1;$i<7;$i++) {
 | 
			
		||||
            if (strlen($this->cleaned_data['label'.$i]) > 0) {
 | 
			
		||||
                if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
 | 
			
		||||
                    list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
 | 
			
		||||
                    list($class, $name) = array(trim($class), trim($name));
 | 
			
		||||
                } else {
 | 
			
		||||
                    $class = 'Other';
 | 
			
		||||
                    $name = trim($this->cleaned_data['label'.$i]);
 | 
			
		||||
                }
 | 
			
		||||
                $tag = IDF_Tag::addGlobal($name, $class);
 | 
			
		||||
                $tagids[] = $tag->id;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $project = new IDF_Project();
 | 
			
		||||
        $project->name = $this->cleaned_data['name'];
 | 
			
		||||
        $project->shortname = $this->cleaned_data['shortname'];
 | 
			
		||||
        $project->shortdesc = $this->cleaned_data['shortdesc'];
 | 
			
		||||
 | 
			
		||||
        $tagids = array();
 | 
			
		||||
        if ($this->cleaned_data['template'] != '--') {
 | 
			
		||||
            // Find the template project
 | 
			
		||||
            $sql = new Pluf_SQL('shortname=%s',
 | 
			
		||||
@@ -290,51 +332,63 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
 | 
			
		||||
            $tmpl = Pluf::factory('IDF_Project')->getOne(array('filter' => $sql->gen()));
 | 
			
		||||
            $project->private = $tmpl->private;
 | 
			
		||||
            $project->description = $tmpl->description;
 | 
			
		||||
 | 
			
		||||
            foreach ($tmpl->get_tags_list() as $tag) {
 | 
			
		||||
                $tagids[] = $tag->id;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            $project->private = $this->cleaned_data['private_project'];
 | 
			
		||||
            $project->description = __('Click on the Project Management tab to set the description of your project.');
 | 
			
		||||
 | 
			
		||||
            // Add a tag for each label
 | 
			
		||||
            for ($i=1;$i<7;$i++) {
 | 
			
		||||
                if (strlen($this->cleaned_data['label'.$i]) > 0) {
 | 
			
		||||
                    if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
 | 
			
		||||
                        list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
 | 
			
		||||
                        list($class, $name) = array(trim($class), trim($name));
 | 
			
		||||
                    } else {
 | 
			
		||||
                        $class = 'Other';
 | 
			
		||||
                        $name = trim($this->cleaned_data['label'.$i]);
 | 
			
		||||
                    }
 | 
			
		||||
                    $tag = IDF_Tag::addGlobal($name, $class);
 | 
			
		||||
                    $tagids[] = $tag->id;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        $project->create();
 | 
			
		||||
        $project->batchAssoc('IDF_Tag', $tagids);
 | 
			
		||||
 | 
			
		||||
        $conf = new IDF_Conf();
 | 
			
		||||
        $conf->setProject($project);
 | 
			
		||||
        $keys = array('scm', 'svn_remote_url', 'svn_username',
 | 
			
		||||
                      'svn_password', 'mtn_master_branch');
 | 
			
		||||
        foreach ($keys as $key) {
 | 
			
		||||
            $this->cleaned_data[$key] = (!empty($this->cleaned_data[$key])) ?
 | 
			
		||||
                $this->cleaned_data[$key] : '';
 | 
			
		||||
            $conf->setVal($key, $this->cleaned_data[$key]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($this->cleaned_data['template'] != '--') {
 | 
			
		||||
            $tmplconf = new IDF_Conf();
 | 
			
		||||
            $tmplconf->setProject($tmpl);
 | 
			
		||||
            // We need to get all the configuration variables we want from
 | 
			
		||||
            // the old project and put them into the new project.
 | 
			
		||||
            $props = array(
 | 
			
		||||
                           'labels_download_predefined' => IDF_Form_UploadConf::init_predefined,
 | 
			
		||||
                           'labels_download_one_max' => IDF_Form_UploadConf::init_one_max,
 | 
			
		||||
                           'labels_wiki_predefined' => IDF_Form_WikiConf::init_predefined,
 | 
			
		||||
                           'labels_wiki_one_max' => IDF_Form_WikiConf::init_one_max,
 | 
			
		||||
                           'labels_issue_template' => IDF_Form_IssueTrackingConf::init_template,
 | 
			
		||||
                           'labels_issue_open' => IDF_Form_IssueTrackingConf::init_open,
 | 
			
		||||
                           'labels_issue_closed' => IDF_Form_IssueTrackingConf::init_closed,
 | 
			
		||||
                           'labels_issue_predefined' =>  IDF_Form_IssueTrackingConf::init_predefined,
 | 
			
		||||
                           'labels_issue_one_max' => IDF_Form_IssueTrackingConf::init_one_max,
 | 
			
		||||
                           'webhook_url' => '',
 | 
			
		||||
                           'downloads_access_rights' => 'all',
 | 
			
		||||
                           'review_access_rights' => 'all',
 | 
			
		||||
                           'wiki_access_rights' => 'all',
 | 
			
		||||
                           'source_access_rights' => 'all',
 | 
			
		||||
                           'issues_access_rights' => 'all',
 | 
			
		||||
                           'downloads_notification_email' => '',
 | 
			
		||||
                           'review_notification_email' => '',
 | 
			
		||||
                           'wiki_notification_email' => '',
 | 
			
		||||
                           'source_notification_email' => '',
 | 
			
		||||
                           'issues_notification_email' => '',
 | 
			
		||||
                           );
 | 
			
		||||
            foreach ($props as $prop => $def) {
 | 
			
		||||
                $conf->setVal($prop, $tmplconf->getVal($prop, $def));
 | 
			
		||||
 | 
			
		||||
            $allKeys =  $tmplconf->getKeys();
 | 
			
		||||
            $scm = $this->cleaned_data['scm'];
 | 
			
		||||
            $ignoreKeys = array('scm', 'external_project_url', 'logo');
 | 
			
		||||
 | 
			
		||||
            // copy over all existing variables, except scm-related data and
 | 
			
		||||
            // the project url / logo
 | 
			
		||||
            foreach ($allKeys as $key) {
 | 
			
		||||
                if (in_array($key, $ignoreKeys) || strpos($key, $scm.'_') === 0) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                $conf->setVal($key, $tmplconf->getVal($key));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $keys = array(
 | 
			
		||||
            'scm', 'svn_remote_url', 'svn_username',
 | 
			
		||||
            'svn_password', 'mtn_master_branch',
 | 
			
		||||
            'external_project_url'
 | 
			
		||||
        );
 | 
			
		||||
        foreach ($keys as $key) {
 | 
			
		||||
            $this->cleaned_data[$key] = !empty($this->cleaned_data[$key]) ?
 | 
			
		||||
                $this->cleaned_data[$key] : '';
 | 
			
		||||
            $conf->setVal($key, $this->cleaned_data[$key]);
 | 
			
		||||
        }
 | 
			
		||||
        $project->created();
 | 
			
		||||
 | 
			
		||||
        if ($this->cleaned_data['template'] == '--') {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -53,6 +53,13 @@ class IDF_Form_Admin_ProjectUpdate extends Pluf_Form
 | 
			
		||||
                                            'widget_attrs' => array('size' => '35'),
 | 
			
		||||
                                            ));
 | 
			
		||||
 | 
			
		||||
        $this->fields['external_project_url'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                array('required' => false,
 | 
			
		||||
                                      'label' => __('External URL'),
 | 
			
		||||
                                      'widget_attrs' => array('size' => '35'),
 | 
			
		||||
                                      'initial' => $conf->getVal('external_project_url'),
 | 
			
		||||
        ));
 | 
			
		||||
 | 
			
		||||
        if ($this->project->getConf()->getVal('scm') == 'mtn') {
 | 
			
		||||
            $this->fields['mtn_master_branch'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                          array('required' => false,
 | 
			
		||||
@@ -63,6 +70,26 @@ class IDF_Form_Admin_ProjectUpdate extends Pluf_Form
 | 
			
		||||
                                                ));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $tags = $this->project->get_tags_list();
 | 
			
		||||
        for ($i=1;$i<7;$i++) {
 | 
			
		||||
            $initial = '';
 | 
			
		||||
            if (isset($tags[$i-1])) {
 | 
			
		||||
                if ($tags[$i-1]->class != 'Other') {
 | 
			
		||||
                    $initial = (string) $tags[$i-1];
 | 
			
		||||
                } else {
 | 
			
		||||
                    $initial = $tags[$i-1]->name;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            $this->fields['label'.$i] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                    array('required' => false,
 | 
			
		||||
                                          'label' => __('Labels'),
 | 
			
		||||
                                          'initial' => $initial,
 | 
			
		||||
                                          'widget_attrs' => array(
 | 
			
		||||
                                          'maxlength' => 50,
 | 
			
		||||
                                          'size' => 20,
 | 
			
		||||
                                          ),
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
        $this->fields['owners'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                      array('required' => false,
 | 
			
		||||
                                            'label' => __('Project owners'),
 | 
			
		||||
@@ -88,7 +115,7 @@ class IDF_Form_Admin_ProjectUpdate extends Pluf_Form
 | 
			
		||||
                        $mtn_master_branch)) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__(
 | 
			
		||||
                'The master branch is empty or contains illegal characters, '.
 | 
			
		||||
                'please use only letters, digits, dashs and dots as separators.'
 | 
			
		||||
                'please use only letters, digits, dashes and dots as separators.'
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -115,22 +142,52 @@ class IDF_Form_Admin_ProjectUpdate extends Pluf_Form
 | 
			
		||||
        return IDF_Form_MembersConf::checkBadLogins($this->cleaned_data['members']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function clean_external_project_url()
 | 
			
		||||
    {
 | 
			
		||||
        return IDF_Form_ProjectConf::checkWebURL($this->cleaned_data['external_project_url']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function save($commit=true)
 | 
			
		||||
    {
 | 
			
		||||
        if (!$this->isValid()) {
 | 
			
		||||
            throw new Exception(__('Cannot save the model from an invalid form.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Add a tag for each label
 | 
			
		||||
        $tagids = array();
 | 
			
		||||
        for ($i=1;$i<7;$i++) {
 | 
			
		||||
            if (strlen($this->cleaned_data['label'.$i]) > 0) {
 | 
			
		||||
                if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
 | 
			
		||||
                    list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
 | 
			
		||||
                    list($class, $name) = array(trim($class), trim($name));
 | 
			
		||||
                } else {
 | 
			
		||||
                    $class = 'Other';
 | 
			
		||||
                    $name = trim($this->cleaned_data['label'.$i]);
 | 
			
		||||
                }
 | 
			
		||||
                $tag = IDF_Tag::addGlobal($name, $class);
 | 
			
		||||
                $tagids[] = $tag->id;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        $this->project->batchAssoc('IDF_Tag', $tagids);
 | 
			
		||||
 | 
			
		||||
        IDF_Form_MembersConf::updateMemberships($this->project,
 | 
			
		||||
                                                $this->cleaned_data);
 | 
			
		||||
        $this->project->membershipsUpdated();
 | 
			
		||||
 | 
			
		||||
        $this->project->name = $this->cleaned_data['name'];
 | 
			
		||||
        $this->project->shortdesc = $this->cleaned_data['shortdesc'];
 | 
			
		||||
        $this->project->update();
 | 
			
		||||
 | 
			
		||||
        $keys = array('mtn_master_branch');
 | 
			
		||||
        $conf = $this->project->getConf();
 | 
			
		||||
        $keys = array('mtn_master_branch', 'external_project_url');
 | 
			
		||||
        foreach ($keys as $key) {
 | 
			
		||||
            if (!empty($this->cleaned_data[$key])) {
 | 
			
		||||
                $this->project->getConf()->setVal($key, $this->cleaned_data[$key]);
 | 
			
		||||
            if (array_key_exists($key, $this->cleaned_data)) {
 | 
			
		||||
                if (!empty($this->cleaned_data[$key])) {
 | 
			
		||||
                    $conf->setVal($key, $this->cleaned_data[$key]);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    $conf->delVal($key);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -68,7 +68,7 @@ class IDF_Form_Admin_UserCreate extends Pluf_Form
 | 
			
		||||
                                      array('required' => true,
 | 
			
		||||
                                            'label' => __('Email'),
 | 
			
		||||
                                            'initial' => '',
 | 
			
		||||
                                            'help_text' => __('Double check the email address as the password is directly sent to the user.'),
 | 
			
		||||
                                            'help_text' => __('Double check the email address as the password is sent directly to the user.'),
 | 
			
		||||
                                            ));
 | 
			
		||||
 | 
			
		||||
        $this->fields['language'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -78,7 +78,7 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
 | 
			
		||||
                                            'label' => __('Password'),
 | 
			
		||||
                                            'initial' => '',
 | 
			
		||||
                                            'widget' => 'Pluf_Form_Widget_PasswordInput',
 | 
			
		||||
                                            'help_text' => Pluf_Template::markSafe(__('Leave blank if you do not want to change the password.').'<br />'.__('The password must be hard for other people to find it, but easy for the user to remember.')),
 | 
			
		||||
                                            'help_text' => Pluf_Template::markSafe(__('Leave blank if you do not want to change the password.').'<br />'.__('The password must be hard for other people to guess, but easy for the user to remember.')),
 | 
			
		||||
                                            'widget_attrs' => array(
 | 
			
		||||
                                                       'maxlength' => 50,
 | 
			
		||||
                                                       'size' => 15,
 | 
			
		||||
@@ -173,7 +173,7 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
 | 
			
		||||
                          'initial' => $this->user->active,
 | 
			
		||||
                          'widget' => 'Pluf_Form_Widget_CheckboxInput',
 | 
			
		||||
                          'widget_attrs' => $attrs,
 | 
			
		||||
                          'help_text' => __('If the user is not getting the confirmation email or is abusing the system, you can directly enable or disable his account here.'),
 | 
			
		||||
                          'help_text' => __('If the user is not getting the confirmation email or is abusing the system, you can directly enable or disable their account here.'),
 | 
			
		||||
                          ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,19 +3,19 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2010 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# Plume Framework is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2.1 of the License, or
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# Plume Framework is distributed in the hope that it will be useful,
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU Lesser General Public License for more details.
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -36,6 +36,7 @@ class IDF_Form_IssueCreate extends Pluf_Form
 | 
			
		||||
    public $user = null;
 | 
			
		||||
    public $project = null;
 | 
			
		||||
    public $show_full = false;
 | 
			
		||||
    public $relation_types = null;
 | 
			
		||||
 | 
			
		||||
    public function initFields($extra=array())
 | 
			
		||||
    {
 | 
			
		||||
@@ -45,9 +46,12 @@ class IDF_Form_IssueCreate extends Pluf_Form
 | 
			
		||||
            or $this->user->hasPerm('IDF.project-member', $this->project)) {
 | 
			
		||||
            $this->show_full = true;
 | 
			
		||||
        }
 | 
			
		||||
        $this->relation_types = $this->project->getRelationsFromConfig();
 | 
			
		||||
 | 
			
		||||
        $contentTemplate = $this->project->getConf()->getVal(
 | 
			
		||||
            'labels_issue_template', IDF_Form_IssueTrackingConf::init_template
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $this->fields['summary'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                      array('required' => true,
 | 
			
		||||
                                            'label' => __('Summary'),
 | 
			
		||||
@@ -76,11 +80,11 @@ class IDF_Form_IssueCreate extends Pluf_Form
 | 
			
		||||
        // case of someone allowing the upload path to be accessible
 | 
			
		||||
        // to everybody.
 | 
			
		||||
        for ($i=1;$i<4;$i++) {
 | 
			
		||||
            $filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy'; 
 | 
			
		||||
            $filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy';
 | 
			
		||||
            $this->fields['attachment'.$i] = new Pluf_Form_Field_File(
 | 
			
		||||
                array('required' => false,
 | 
			
		||||
                      'label' => __('Attach a file'),
 | 
			
		||||
                      'move_function_params' => 
 | 
			
		||||
                      'move_function_params' =>
 | 
			
		||||
                      array('upload_path' => $upload_path,
 | 
			
		||||
                            'upload_path_create' => true,
 | 
			
		||||
                            'file_name' => $filename,
 | 
			
		||||
@@ -108,6 +112,26 @@ class IDF_Form_IssueCreate extends Pluf_Form
 | 
			
		||||
                                                       'size' => 15,
 | 
			
		||||
                                                                    ),
 | 
			
		||||
                                            ));
 | 
			
		||||
            $this->fields['due_dtime'] = new Pluf_Form_Field_Date(
 | 
			
		||||
                                          array('required' => false,
 | 
			
		||||
                                                'label' => __('Due date'),
 | 
			
		||||
                                                'initial' => '',
 | 
			
		||||
                                                'widget_attrs' => array('size' => 15,),
 | 
			
		||||
                                              ));
 | 
			
		||||
 | 
			
		||||
            $this->fields['relation_type0'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                          array('required' => false,
 | 
			
		||||
                                'label' => __('This issue'),
 | 
			
		||||
                                'initial' => current($this->relation_types),
 | 
			
		||||
                                'widget_attrs' => array('size' => 15),
 | 
			
		||||
                                ));
 | 
			
		||||
 | 
			
		||||
            $this->fields['relation_issue0'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                          array('required' => false,
 | 
			
		||||
                                'label' => null,
 | 
			
		||||
                                'initial' => '',
 | 
			
		||||
                                'widget_attrs' => array('size' => 10),
 | 
			
		||||
                                ));
 | 
			
		||||
 | 
			
		||||
            /*
 | 
			
		||||
             * get predefined tags for issues from current project
 | 
			
		||||
@@ -181,7 +205,7 @@ class IDF_Form_IssueCreate extends Pluf_Form
 | 
			
		||||
            $this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]);
 | 
			
		||||
            if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
 | 
			
		||||
                list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
 | 
			
		||||
                list($class, $name) = array(mb_strtolower(trim($class)), 
 | 
			
		||||
                list($class, $name) = array(mb_strtolower(trim($class)),
 | 
			
		||||
                                            trim($name));
 | 
			
		||||
            } else {
 | 
			
		||||
                $class = 'other';
 | 
			
		||||
@@ -196,7 +220,7 @@ class IDF_Form_IssueCreate extends Pluf_Form
 | 
			
		||||
            else $count[$class] += 1;
 | 
			
		||||
            if (in_array($class, $onemax) and $count[$class] > 1) {
 | 
			
		||||
                if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array();
 | 
			
		||||
                $this->errors['label'.$i][] = sprintf(__('You cannot provide more than label from the %s class to an issue.'), $class);
 | 
			
		||||
                $this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to an issue.'), $class);
 | 
			
		||||
                throw new Pluf_Form_Invalid(__('You provided an invalid label.'));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -215,10 +239,10 @@ class IDF_Form_IssueCreate extends Pluf_Form
 | 
			
		||||
    function clean_status()
 | 
			
		||||
    {
 | 
			
		||||
        // Check that the status is in the list of official status
 | 
			
		||||
        $tags = $this->project->getTagsFromConfig('labels_issue_open', 
 | 
			
		||||
        $tags = $this->project->getTagsFromConfig('labels_issue_open',
 | 
			
		||||
                                          IDF_Form_IssueTrackingConf::init_open,
 | 
			
		||||
                                          'Status');
 | 
			
		||||
        $tags = array_merge($this->project->getTagsFromConfig('labels_issue_closed', 
 | 
			
		||||
        $tags = array_merge($this->project->getTagsFromConfig('labels_issue_closed',
 | 
			
		||||
                                          IDF_Form_IssueTrackingConf::init_closed,
 | 
			
		||||
                                          'Status')
 | 
			
		||||
                            , $tags);
 | 
			
		||||
@@ -235,6 +259,63 @@ class IDF_Form_IssueCreate extends Pluf_Form
 | 
			
		||||
        return $this->cleaned_data['status'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // this method is not called from Pluf_Form directly, but shared for
 | 
			
		||||
    // among all similar fields
 | 
			
		||||
    function clean_relation_type($value)
 | 
			
		||||
    {
 | 
			
		||||
        $relation_type = trim($value);
 | 
			
		||||
        if (empty($relation_type))
 | 
			
		||||
            return '';
 | 
			
		||||
 | 
			
		||||
        $found = false;
 | 
			
		||||
        foreach ($this->relation_types as $type) {
 | 
			
		||||
            if ($type == $relation_type) {
 | 
			
		||||
                $found = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (!$found) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('You provided an invalid relation type.'));
 | 
			
		||||
        }
 | 
			
		||||
        return $relation_type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function clean_relation_type0()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->clean_relation_type($this->cleaned_data['relation_type0']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // this method is not called from Pluf_Form directly, but shared for
 | 
			
		||||
    // among all similar fields
 | 
			
		||||
    function clean_relation_issue($value)
 | 
			
		||||
    {
 | 
			
		||||
        $issues = trim($value);
 | 
			
		||||
        if (empty($issues))
 | 
			
		||||
            return '';
 | 
			
		||||
 | 
			
		||||
        $issue_ids = preg_split('/\s*,\s*/', $issues, -1, PREG_SPLIT_NO_EMPTY);
 | 
			
		||||
        foreach ($issue_ids as $issue_id) {
 | 
			
		||||
            if (!ctype_digit($issue_id) || (int)$issue_id < 1) {
 | 
			
		||||
                throw new Pluf_Form_Invalid(sprintf(
 | 
			
		||||
                    __('The value "%s" is not a valid issue id.'), $issue_id
 | 
			
		||||
                ));
 | 
			
		||||
            }
 | 
			
		||||
            $issue = new IDF_Issue($issue_id);
 | 
			
		||||
            if ($issue->id != $issue_id || $issue->project != $this->project->id) {
 | 
			
		||||
                throw new Pluf_Form_Invalid(sprintf(
 | 
			
		||||
                    __('The issue "%s" does not exist.'), $issue_id
 | 
			
		||||
                ));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return implode(', ', $issue_ids);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function clean_relation_issue0()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->clean_relation_issue($this->cleaned_data['relation_issue0']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Clean the attachments post failure.
 | 
			
		||||
     */
 | 
			
		||||
@@ -293,11 +374,36 @@ class IDF_Form_IssueCreate extends Pluf_Form
 | 
			
		||||
            $issue->status = new IDF_Tag($_t[0]); // first one is the default
 | 
			
		||||
            $issue->owner = null;
 | 
			
		||||
        }
 | 
			
		||||
        $issue->due_dtime = $this->cleaned_data['due_dtime'];
 | 
			
		||||
        $issue->summary = trim($this->cleaned_data['summary']);
 | 
			
		||||
        $issue->create();
 | 
			
		||||
        foreach ($tags as $tag) {
 | 
			
		||||
            $issue->setAssoc($tag);
 | 
			
		||||
        }
 | 
			
		||||
        // add relations (if any)
 | 
			
		||||
        if (!empty($this->cleaned_data['relation_type0'])) {
 | 
			
		||||
            $verb = $this->cleaned_data['relation_type0'];
 | 
			
		||||
            $other_verb = $this->relation_types[$verb];
 | 
			
		||||
            $related_issues = preg_split('/\s*,\s*/', $this->cleaned_data['relation_issue0'], -1, PREG_SPLIT_NO_EMPTY);
 | 
			
		||||
 | 
			
		||||
            foreach ($related_issues as $related_issue_id) {
 | 
			
		||||
                $related_issue = new IDF_Issue($related_issue_id);
 | 
			
		||||
                $rel = new IDF_IssueRelation();
 | 
			
		||||
                $rel->issue = $issue;
 | 
			
		||||
                $rel->verb = $verb;
 | 
			
		||||
                $rel->other_issue = $related_issue;
 | 
			
		||||
                $rel->submitter = $this->user;
 | 
			
		||||
                $rel->create();
 | 
			
		||||
 | 
			
		||||
                $other_rel = new IDF_IssueRelation();
 | 
			
		||||
                $other_rel->issue = $related_issue;
 | 
			
		||||
                $other_rel->verb = $other_verb;
 | 
			
		||||
                $other_rel->other_issue = $issue;
 | 
			
		||||
                $other_rel->submitter = $this->user;
 | 
			
		||||
                $other_rel->create();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // add the first comment
 | 
			
		||||
        $comment = new IDF_IssueComment();
 | 
			
		||||
        $comment->issue = $issue;
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -72,6 +72,23 @@ Performance          = Performance issue
 | 
			
		||||
Usability            = Affects program usability
 | 
			
		||||
Maintainability      = Hinders future changes';
 | 
			
		||||
    const init_one_max = 'Type, Priority, Milestone';
 | 
			
		||||
    // ATTENTION: if you change something here, change the values below as well!
 | 
			
		||||
    const init_relations = 'is related to
 | 
			
		||||
blocks, is blocked by
 | 
			
		||||
duplicates, is duplicated by';
 | 
			
		||||
 | 
			
		||||
    // These are actually all noop's, but we have no other chance to
 | 
			
		||||
    // tell IDF's translation mechanism to mark the strings as translatable
 | 
			
		||||
    // FIXME: IDF should get a internal translation system for strings like
 | 
			
		||||
    // that, that can also be easily expanded by users
 | 
			
		||||
    private function noop()
 | 
			
		||||
    {
 | 
			
		||||
        __('is related to');
 | 
			
		||||
        __('blocks');
 | 
			
		||||
        __('is blocked by');
 | 
			
		||||
        __('duplicates');
 | 
			
		||||
        __('is duplicated by');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function initFields($extra=array())
 | 
			
		||||
    {
 | 
			
		||||
@@ -113,11 +130,20 @@ Maintainability      = Hinders future changes';
 | 
			
		||||
 | 
			
		||||
        $this->fields['labels_issue_one_max'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                      array('required' => false,
 | 
			
		||||
                                            'label' => __('Each issue may have at most one label with each of these classes'),
 | 
			
		||||
                                            'initial' => self::init_one_max, 
 | 
			
		||||
                                            'label' => __('Each issue may have at most one label with each of these classes.'),
 | 
			
		||||
                                            'initial' => self::init_one_max,
 | 
			
		||||
                                            'widget_attrs' => array('size' => 60),
 | 
			
		||||
                                            ));
 | 
			
		||||
 | 
			
		||||
        $this->fields['issue_relations'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                      array('required' => true,
 | 
			
		||||
                                            'label' => __('Issue relations'),
 | 
			
		||||
                                            'initial' => self::init_relations,
 | 
			
		||||
                                            'help_text' => __('You can define bidirectional relations like "is related to" or "blocks, is blocked by". For standard relations pre-configured translations exist, new relations should however be defined in a language that is understood by all project members.'),
 | 
			
		||||
                                            'widget_attrs' => array('rows' => 7,
 | 
			
		||||
                                                                    'cols' => 75),
 | 
			
		||||
                                            'widget' => 'Pluf_Form_Widget_TextareaInput',
 | 
			
		||||
                                            ));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -39,6 +39,7 @@ class IDF_Form_IssueUpdate  extends IDF_Form_IssueCreate
 | 
			
		||||
            or $this->user->hasPerm('IDF.project-member', $this->project)) {
 | 
			
		||||
            $this->show_full = true;
 | 
			
		||||
        }
 | 
			
		||||
        $this->relation_types = $this->project->getRelationsFromConfig();
 | 
			
		||||
        if ($this->show_full) {
 | 
			
		||||
            $this->fields['summary'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                      array('required' => true,
 | 
			
		||||
@@ -69,11 +70,11 @@ class IDF_Form_IssueUpdate  extends IDF_Form_IssueCreate
 | 
			
		||||
        // case of someone allowing the upload path to be accessible
 | 
			
		||||
        // to everybody.
 | 
			
		||||
        for ($i=1;$i<4;$i++) {
 | 
			
		||||
            $filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy'; 
 | 
			
		||||
            $filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy';
 | 
			
		||||
            $this->fields['attachment'.$i] = new Pluf_Form_Field_File(
 | 
			
		||||
                array('required' => false,
 | 
			
		||||
                      'label' => __('Attach a file'),
 | 
			
		||||
                      'move_function_params' => 
 | 
			
		||||
                      'move_function_params' =>
 | 
			
		||||
                      array('upload_path' => $upload_path,
 | 
			
		||||
                            'upload_path_create' => true,
 | 
			
		||||
                            'file_name' => $filename,
 | 
			
		||||
@@ -102,6 +103,59 @@ class IDF_Form_IssueUpdate  extends IDF_Form_IssueCreate
 | 
			
		||||
                                                       'size' => 15,
 | 
			
		||||
                                                                    ),
 | 
			
		||||
                                            ));
 | 
			
		||||
            $due_dtime = substr($this->issue->due_dtime, 0, 10);
 | 
			
		||||
            $this->fields['due_dtime'] = new Pluf_Form_Field_Date(
 | 
			
		||||
                                array('required' => false,
 | 
			
		||||
                                    'label' => __('Due date'),
 | 
			
		||||
                                    'initial' => $due_dtime,
 | 
			
		||||
                                    'widget_attrs' => array('size' => 15,),
 | 
			
		||||
                                    ));
 | 
			
		||||
 | 
			
		||||
            $idx = 0;
 | 
			
		||||
            // note: clean_relation_type0 and clean_relation_issue0 already
 | 
			
		||||
            //       exist in the base class
 | 
			
		||||
            $this->fields['relation_type'.$idx] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                          array('required' => false,
 | 
			
		||||
                                'label' => __('This issue'),
 | 
			
		||||
                                'initial' => current($this->relation_types),
 | 
			
		||||
                                'widget_attrs' => array('size' => 15),
 | 
			
		||||
                                ));
 | 
			
		||||
 | 
			
		||||
            $this->fields['relation_issue'.$idx] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                          array('required' => false,
 | 
			
		||||
                                'label' => null,
 | 
			
		||||
                                'initial' => '',
 | 
			
		||||
                                'widget_attrs' => array('size' => 10),
 | 
			
		||||
                                ));
 | 
			
		||||
 | 
			
		||||
            ++$idx;
 | 
			
		||||
            $relatedIssues = $this->issue->getGroupedRelatedIssues(array(), true);
 | 
			
		||||
            foreach ($relatedIssues as $verb => $ids) {
 | 
			
		||||
                $this->fields['relation_type'.$idx] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                          array('required' => false,
 | 
			
		||||
                                'label' => __('This issue'),
 | 
			
		||||
                                'initial' => $verb,
 | 
			
		||||
                                'widget_attrs' => array('size' => 15),
 | 
			
		||||
                                ));
 | 
			
		||||
                $m = 'clean_relation_type'.$idx;
 | 
			
		||||
                $this->$m = create_function('$form', '
 | 
			
		||||
                    return $form->clean_relation_type($form->cleaned_data["relation_type'.$idx.'"]);
 | 
			
		||||
                ');
 | 
			
		||||
 | 
			
		||||
                $this->fields['relation_issue'.$idx] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                              array('required' => false,
 | 
			
		||||
                                    'label' => null,
 | 
			
		||||
                                    'initial' => implode(', ', $ids),
 | 
			
		||||
                                    'widget_attrs' => array('size' => 10),
 | 
			
		||||
                                    ));
 | 
			
		||||
                $m = 'clean_relation_issue'.$idx;
 | 
			
		||||
                $this->$m = create_function('$form', '
 | 
			
		||||
                    return $form->clean_relation_issue($form->cleaned_data["relation_issue'.$idx.'"]);
 | 
			
		||||
                ');
 | 
			
		||||
 | 
			
		||||
                ++$idx;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $tags = $this->issue->get_tags_list();
 | 
			
		||||
            for ($i=1;$i<7;$i++) {
 | 
			
		||||
                $initial = '';
 | 
			
		||||
@@ -155,6 +209,51 @@ class IDF_Form_IssueUpdate  extends IDF_Form_IssueCreate
 | 
			
		||||
    public function clean()
 | 
			
		||||
    {
 | 
			
		||||
        $this->cleaned_data = parent::clean();
 | 
			
		||||
 | 
			
		||||
        // normalize the user's input by removing dublettes and by combining
 | 
			
		||||
        // ids from identical verbs in different input fields into one array
 | 
			
		||||
        $normRelatedIssues = array();
 | 
			
		||||
        for ($idx = 0; isset($this->cleaned_data['relation_type'.$idx]); ++$idx) {
 | 
			
		||||
            $verb = $this->cleaned_data['relation_type'.$idx];
 | 
			
		||||
            if (empty($verb))
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            $ids = preg_split('/\s*,\s*/', $this->cleaned_data['relation_issue'.$idx],
 | 
			
		||||
                              -1, PREG_SPLIT_NO_EMPTY);
 | 
			
		||||
            if (count($ids) == 0)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            if (!array_key_exists($verb, $normRelatedIssues))
 | 
			
		||||
                $normRelatedIssues[$verb] = array();
 | 
			
		||||
            foreach ($ids as $id) {
 | 
			
		||||
                if (!in_array($id, $normRelatedIssues[$verb]))
 | 
			
		||||
                    $normRelatedIssues[$verb][] = $id;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // now look at any added / removed ids
 | 
			
		||||
        $added = $removed = array();
 | 
			
		||||
        $relatedIssues = $this->issue->getGroupedRelatedIssues(array(), true);
 | 
			
		||||
        $added = array_diff_key($normRelatedIssues, $relatedIssues);
 | 
			
		||||
        $removed = array_diff_key($relatedIssues, $normRelatedIssues);
 | 
			
		||||
 | 
			
		||||
        $keysToLookAt = array_keys(
 | 
			
		||||
            array_intersect_key($relatedIssues, $normRelatedIssues)
 | 
			
		||||
        );
 | 
			
		||||
        foreach ($keysToLookAt as $key) {
 | 
			
		||||
            $a = array_diff($normRelatedIssues[$key], $relatedIssues[$key]);
 | 
			
		||||
            if (count($a) > 0)
 | 
			
		||||
                $added[$key] = $a;
 | 
			
		||||
            $r = array_diff($relatedIssues[$key], $normRelatedIssues[$key]);
 | 
			
		||||
            if (count($r) > 0)
 | 
			
		||||
                $removed[$key] = $r;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // cache the added / removed data, so we do not have to
 | 
			
		||||
        // calculate that again
 | 
			
		||||
        $this->cleaned_data['_added_issue_relations'] = $added;
 | 
			
		||||
        $this->cleaned_data['_removed_issue_relations'] = $removed;
 | 
			
		||||
 | 
			
		||||
        // As soon as we know that at least one change was done, we
 | 
			
		||||
        // return the cleaned data and do not go further.
 | 
			
		||||
        if (strlen(trim($this->cleaned_data['content']))) {
 | 
			
		||||
@@ -174,6 +273,9 @@ class IDF_Form_IssueUpdate  extends IDF_Form_IssueCreate
 | 
			
		||||
                or ((!is_null($owner) and !is_null($this->issue->get_owner())) and $owner->id != $this->issue->get_owner()->id)) {
 | 
			
		||||
                return $this->cleaned_data;
 | 
			
		||||
            }
 | 
			
		||||
            if (trim($this->issue->due_dtime) != trim($this->cleaned_data['due_dtime'])) {
 | 
			
		||||
                return $this->cleaned_data;
 | 
			
		||||
            }
 | 
			
		||||
            $tags = array();
 | 
			
		||||
            for ($i=1;$i<7;$i++) {
 | 
			
		||||
                if (strlen($this->cleaned_data['label'.$i]) > 0) {
 | 
			
		||||
@@ -214,6 +316,11 @@ class IDF_Form_IssueUpdate  extends IDF_Form_IssueCreate
 | 
			
		||||
                    return $this->cleaned_data;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (count($this->cleaned_data['_added_issue_relations']) != 0 ||
 | 
			
		||||
                count($this->cleaned_data['_removed_issue_relations']) != 0) {
 | 
			
		||||
                return $this->cleaned_data;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // no changes!
 | 
			
		||||
        throw new Pluf_Form_Invalid(__('No changes were entered.'));
 | 
			
		||||
@@ -255,20 +362,22 @@ class IDF_Form_IssueUpdate  extends IDF_Form_IssueCreate
 | 
			
		||||
            foreach ($tags as $tag) {
 | 
			
		||||
                if (!Pluf_Model_InArray($tag, $oldtags)) {
 | 
			
		||||
                    if (!isset($changes['lb'])) $changes['lb'] = array();
 | 
			
		||||
                    if (!isset($changes['lb']['add'])) $changes['lb']['add'] = array();
 | 
			
		||||
                    if ($tag->class != 'Other') {
 | 
			
		||||
                        $changes['lb'][] = (string) $tag; //new tag
 | 
			
		||||
                        $changes['lb']['add'][] = (string) $tag; //new tag
 | 
			
		||||
                    } else {
 | 
			
		||||
                        $changes['lb'][] = (string) $tag->name;
 | 
			
		||||
                        $changes['lb']['add'][] = (string) $tag->name;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            foreach ($oldtags as $tag) {
 | 
			
		||||
                if (!Pluf_Model_InArray($tag, $tags)) {
 | 
			
		||||
                    if (!isset($changes['lb'])) $changes['lb'] = array();
 | 
			
		||||
                    if (!isset($changes['lb']['rem'])) $changes['lb']['rem'] = array();
 | 
			
		||||
                    if ($tag->class != 'Other') {
 | 
			
		||||
                        $changes['lb'][] = '-'.(string) $tag; //new tag
 | 
			
		||||
                        $changes['lb']['rem'][] = (string) $tag; //new tag
 | 
			
		||||
                    } else {
 | 
			
		||||
                        $changes['lb'][] = '-'.(string) $tag->name;
 | 
			
		||||
                        $changes['lb']['rem'][] = (string) $tag->name;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -286,11 +395,56 @@ class IDF_Form_IssueUpdate  extends IDF_Form_IssueCreate
 | 
			
		||||
                or ((!is_null($owner) and !is_null($this->issue->get_owner())) and $owner->id != $this->issue->get_owner()->id)) {
 | 
			
		||||
                $changes['ow'] = (is_null($owner)) ? '---' : $owner->login;
 | 
			
		||||
            }
 | 
			
		||||
            if (trim($this->issue->due_dtime) != trim($this->cleaned_data['due_dtime'])) {
 | 
			
		||||
                $changes['du'] = Pluf_Template_dateFormat($this->cleaned_data['due_dtime']);
 | 
			
		||||
            }
 | 
			
		||||
            // Issue relations - additions
 | 
			
		||||
            foreach ($this->cleaned_data['_added_issue_relations'] as $verb => $ids) {
 | 
			
		||||
                $other_verb = $this->relation_types[$verb];
 | 
			
		||||
                foreach ($ids as $id) {
 | 
			
		||||
                    $related_issue = new IDF_Issue($id);
 | 
			
		||||
                    $rel = new IDF_IssueRelation();
 | 
			
		||||
                    $rel->issue = $this->issue;
 | 
			
		||||
                    $rel->verb = $verb;
 | 
			
		||||
                    $rel->other_issue = $related_issue;
 | 
			
		||||
                    $rel->submitter = $this->user;
 | 
			
		||||
                    $rel->create();
 | 
			
		||||
 | 
			
		||||
                    $other_rel = new IDF_IssueRelation();
 | 
			
		||||
                    $other_rel->issue = $related_issue;
 | 
			
		||||
                    $other_rel->verb = $other_verb;
 | 
			
		||||
                    $other_rel->other_issue = $this->issue;
 | 
			
		||||
                    $other_rel->submitter = $this->user;
 | 
			
		||||
                    $other_rel->create();
 | 
			
		||||
                }
 | 
			
		||||
                if (!isset($changes['rel'])) $changes['rel'] = array();
 | 
			
		||||
                if (!isset($changes['rel']['add'])) $changes['rel']['add'] = array();
 | 
			
		||||
                $changes['rel']['add'][] = $verb.' '.implode(', ', $ids);
 | 
			
		||||
            }
 | 
			
		||||
            // Issue relations - removals
 | 
			
		||||
            foreach ($this->cleaned_data['_removed_issue_relations'] as $verb => $ids) {
 | 
			
		||||
                foreach ($ids as $id) {
 | 
			
		||||
                    $db = &Pluf::db();
 | 
			
		||||
                    $table = Pluf::factory('IDF_IssueRelation')->getSqlTable();
 | 
			
		||||
                    $sql = new Pluf_SQL('verb=%s AND (
 | 
			
		||||
                                        (issue=%s AND other_issue=%s) OR
 | 
			
		||||
                                        (other_issue=%s AND issue=%s))',
 | 
			
		||||
                                        array($verb,
 | 
			
		||||
                                              $this->issue->id, $id,
 | 
			
		||||
                                              $this->issue->id, $id));
 | 
			
		||||
                    $db->execute('DELETE FROM '.$table.' WHERE '.$sql->gen());
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (!isset($changes['rel'])) $changes['rel'] = array();
 | 
			
		||||
                if (!isset($changes['rel']['rem'])) $changes['rel']['rem'] = array();
 | 
			
		||||
                $changes['rel']['rem'][] = $verb.' '.implode(', ', $ids);
 | 
			
		||||
            }
 | 
			
		||||
            // Update the issue
 | 
			
		||||
            $this->issue->batchAssoc('IDF_Tag', $tagids);
 | 
			
		||||
            $this->issue->summary = trim($this->cleaned_data['summary']);
 | 
			
		||||
            $this->issue->status = $status;
 | 
			
		||||
            $this->issue->owner = $owner;
 | 
			
		||||
            $this->issue->due_dtime = $this->cleaned_data['due_dtime'];
 | 
			
		||||
        }
 | 
			
		||||
        // Create the comment
 | 
			
		||||
        $comment = new IDF_IssueComment();
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -86,7 +86,7 @@ class IDF_Form_Password extends Pluf_Form
 | 
			
		||||
                $return_url = Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecoveryInputCode');
 | 
			
		||||
                $tmpl = new Pluf_Template('idf/user/passrecovery-email.txt');
 | 
			
		||||
                $cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
 | 
			
		||||
                $code = trim($cr->encrypt($user->email.':'.$user->id.':'.time()), 
 | 
			
		||||
                $code = trim($cr->encrypt($user->email.':'.$user->id.':'.time().':primary'), 
 | 
			
		||||
                             '~');
 | 
			
		||||
                $code = substr(md5(Pluf::f('secret_key').$code), 0, 2).$code;
 | 
			
		||||
                $url = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecovery', array($code), array(), false);
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										211
									
								
								src/IDF/Form/ProjectConf.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								src/IDF/Form/ProjectConf.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,211 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright(C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
#(at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Configuration of the project.
 | 
			
		||||
 */
 | 
			
		||||
class IDF_Form_ProjectConf extends Pluf_Form
 | 
			
		||||
{
 | 
			
		||||
    public $project = null;
 | 
			
		||||
 | 
			
		||||
    public function initFields($extra=array())
 | 
			
		||||
    {
 | 
			
		||||
        $this->project = $extra['project'];
 | 
			
		||||
        $conf = $this->project->getConf();
 | 
			
		||||
 | 
			
		||||
        // Basic part
 | 
			
		||||
        $this->fields['name'] = new Pluf_Form_Field_Varchar(array('required' => true,
 | 
			
		||||
                                                                  'label' => __('Name'),
 | 
			
		||||
                                                                  'initial' => $this->project->name,
 | 
			
		||||
                                                                 ));
 | 
			
		||||
        $this->fields['shortdesc'] = new Pluf_Form_Field_Varchar(array('required' => true,
 | 
			
		||||
                                                                       'label' => __('Short Description'),
 | 
			
		||||
                                                                       'initial' => $this->project->shortdesc,
 | 
			
		||||
                                                                       'widget_attrs' => array('size' => '68'),
 | 
			
		||||
                                                                      ));
 | 
			
		||||
        $this->fields['description'] = new Pluf_Form_Field_Varchar(array('required' => true,
 | 
			
		||||
                                                                         'label' => __('Description'),
 | 
			
		||||
                                                                         'initial' => $this->project->description,
 | 
			
		||||
                                                                         'widget_attrs' => array('cols' => 68,
 | 
			
		||||
                                                                                                 'rows' => 26,
 | 
			
		||||
                                                                                                ),
 | 
			
		||||
                                                                         'widget' => 'Pluf_Form_Widget_TextareaInput',
 | 
			
		||||
                                                                        ));
 | 
			
		||||
        $this->fields['external_project_url'] = new Pluf_Form_Field_Varchar(array('required' => false,
 | 
			
		||||
                                                                 'label' => __('External URL'),
 | 
			
		||||
                                                                 'widget_attrs' => array('size' => '68'),
 | 
			
		||||
                                                                 'initial' => $conf->getVal('external_project_url'),
 | 
			
		||||
        ));
 | 
			
		||||
 | 
			
		||||
        $tags = $this->project->get_tags_list();
 | 
			
		||||
        for ($i=1;$i<7;$i++) {
 | 
			
		||||
            $initial = '';
 | 
			
		||||
            if (isset($tags[$i-1])) {
 | 
			
		||||
                if ($tags[$i-1]->class != 'Other') {
 | 
			
		||||
                    $initial = (string) $tags[$i-1];
 | 
			
		||||
                } else {
 | 
			
		||||
                    $initial = $tags[$i-1]->name;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            $this->fields['label'.$i] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                array('required' => false,
 | 
			
		||||
                      'label' => __('Labels'),
 | 
			
		||||
                      'initial' => $initial,
 | 
			
		||||
                      'widget_attrs' => array(
 | 
			
		||||
                      'maxlength' => 50,
 | 
			
		||||
                      'size' => 20,
 | 
			
		||||
                ),
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Logo part
 | 
			
		||||
        $upload_path = Pluf::f('upload_path', false);
 | 
			
		||||
        if (false === $upload_path) {
 | 
			
		||||
            throw new Pluf_Exception_SettingError(__('The "upload_path" configuration variable was not set.'));
 | 
			
		||||
        }
 | 
			
		||||
        $upload_path .= '/' . $this->project->shortname;
 | 
			
		||||
        $filename = '/%s';
 | 
			
		||||
        $this->fields['logo'] = new Pluf_Form_Field_File(array('required' => false,
 | 
			
		||||
                                                         'label' => __('Update the logo'),
 | 
			
		||||
                                                         'initial' => '',
 | 
			
		||||
                                                         'help_text' => __('The logo must be a picture with a size of 32 by 32.'),
 | 
			
		||||
                                                         'max_size' => Pluf::f('max_upload_size', 5 * 1024),
 | 
			
		||||
                                                         'move_function_params' =>
 | 
			
		||||
                                                         array('upload_path' => $upload_path,
 | 
			
		||||
                                                               'upload_path_create' => true,
 | 
			
		||||
                                                               'upload_overwrite' => true,
 | 
			
		||||
                                                               'file_name' => $filename,
 | 
			
		||||
                                                               )
 | 
			
		||||
                                                         ));
 | 
			
		||||
 | 
			
		||||
        $this->fields['logo_remove'] = new Pluf_Form_Field_Boolean(array('required' => false,
 | 
			
		||||
                                                                         'label' => __('Remove the current logo'),
 | 
			
		||||
                                                                         'initial' => false,
 | 
			
		||||
                                                                         'widget' => 'Pluf_Form_Widget_CheckboxInput',
 | 
			
		||||
                                                                         ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * If we have uploaded a file, but the form failed remove it.
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    function failed()
 | 
			
		||||
    {
 | 
			
		||||
        if (!empty($this->cleaned_data['logo'])
 | 
			
		||||
            && file_exists(Pluf::f('upload_path').'/'.$this->cleaned_data['logo'])) {
 | 
			
		||||
            unlink(Pluf::f('upload_path').'/'.$this->cleaned_data['logo']);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function clean()
 | 
			
		||||
    {
 | 
			
		||||
        if (!isset($this->cleaned_data['logo_remove'])) {
 | 
			
		||||
            $this->cleaned_data['logo_remove'] = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->cleaned_data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function clean_logo()
 | 
			
		||||
    {
 | 
			
		||||
        if (empty($this->cleaned_data['logo'])) {
 | 
			
		||||
            return '';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $meta = getimagesize(Pluf::f('upload_path') . '/' . $this->project->shortname . $this->cleaned_data['logo']);
 | 
			
		||||
 | 
			
		||||
        if ($meta === false) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('Could not determine the size of the uploaded picture.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($meta[0] !== 32 || $meta[1] !== 32) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('The picture must have a size of 32 by 32.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->cleaned_data['logo'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function clean_external_project_url()
 | 
			
		||||
    {
 | 
			
		||||
        return self::checkWebURL($this->cleaned_data['external_project_url']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function checkWebURL($url)
 | 
			
		||||
    {
 | 
			
		||||
        $url = trim($url);
 | 
			
		||||
        if (empty($url)) {
 | 
			
		||||
            return '';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $parsed = parse_url($url);
 | 
			
		||||
        if ($parsed === false || !array_key_exists('scheme', $parsed) ||
 | 
			
		||||
            ($parsed['scheme'] != 'http' && $parsed['scheme'] != 'https')) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('The entered URL is invalid. Only http and https URLs are allowed.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $url;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function save($commit=true)
 | 
			
		||||
    {
 | 
			
		||||
        // Add a tag for each label
 | 
			
		||||
        $tagids = array();
 | 
			
		||||
        for ($i=1;$i<7;$i++) {
 | 
			
		||||
            if (strlen($this->cleaned_data['label'.$i]) > 0) {
 | 
			
		||||
                if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
 | 
			
		||||
                    list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
 | 
			
		||||
                    list($class, $name) = array(trim($class), trim($name));
 | 
			
		||||
                } else {
 | 
			
		||||
                    $class = 'Other';
 | 
			
		||||
                    $name = trim($this->cleaned_data['label'.$i]);
 | 
			
		||||
                }
 | 
			
		||||
                $tag = IDF_Tag::addGlobal($name, $class);
 | 
			
		||||
                $tagids[] = $tag->id;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Basic part
 | 
			
		||||
        $this->project->name = $this->cleaned_data['name'];
 | 
			
		||||
        $this->project->shortdesc = $this->cleaned_data['shortdesc'];
 | 
			
		||||
        $this->project->description = $this->cleaned_data['description'];
 | 
			
		||||
        $this->project->batchAssoc('IDF_Tag', $tagids);
 | 
			
		||||
        $this->project->update();
 | 
			
		||||
 | 
			
		||||
        $conf = $this->project->getConf();
 | 
			
		||||
        if (!empty($this->cleaned_data['logo'])) {
 | 
			
		||||
            $conf->setVal('logo', $this->cleaned_data['logo']);
 | 
			
		||||
        }
 | 
			
		||||
        if (!empty($this->cleaned_data['external_project_url'])) {
 | 
			
		||||
            $conf->setVal('external_project_url', $this->cleaned_data['external_project_url']);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            $conf->delVal('external_project_url');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($this->cleaned_data['logo_remove'] === true) {
 | 
			
		||||
            @unlink(Pluf::f('upload_path') . '/' . $this->project->shortname . $conf->getVal('logo'));
 | 
			
		||||
            $conf->delVal('logo');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -42,7 +42,7 @@ class IDF_Form_Register extends Pluf_Form
 | 
			
		||||
                                            'max_length' => 15,
 | 
			
		||||
                                            'min_length' => 3,
 | 
			
		||||
                                            'initial' => $login,
 | 
			
		||||
                                            'help_text' => __('The login must be between 3 and 15 characters long and contains only letters and digits.'),
 | 
			
		||||
                                            'help_text' => __('The login must be between 3 and 15 characters long and contain only letters and digits.'),
 | 
			
		||||
                                            'widget_attrs' => array(
 | 
			
		||||
                                                       'maxlength' => 15,
 | 
			
		||||
                                                       'size' => 10,
 | 
			
		||||
@@ -52,7 +52,7 @@ class IDF_Form_Register extends Pluf_Form
 | 
			
		||||
                                      array('required' => true,
 | 
			
		||||
                                            'label' => __('Your email'),
 | 
			
		||||
                                            'initial' => '',
 | 
			
		||||
                                            'help_text' => __('We will never send you any unsolicited emails. We hate spams too!'),
 | 
			
		||||
                                            'help_text' => __('We will never send you any unsolicited emails. We hate spam too!'),
 | 
			
		||||
                                            ));
 | 
			
		||||
 | 
			
		||||
        $this->fields['terms'] = new Pluf_Form_Field_Boolean(
 | 
			
		||||
@@ -93,10 +93,8 @@ class IDF_Form_Register extends Pluf_Form
 | 
			
		||||
    function clean_email()
 | 
			
		||||
    {
 | 
			
		||||
        $this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email']));
 | 
			
		||||
        $guser = new Pluf_User();
 | 
			
		||||
        $sql = new Pluf_SQL('email=%s', $this->cleaned_data['email']);
 | 
			
		||||
        if ($guser->getCount(array('filter' => $sql->gen())) > 0) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(sprintf(__('The email "%s" is already used. If you need, click on the help link to recover your password.'), $this->cleaned_data['email']));
 | 
			
		||||
        if (Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($this->cleaned_data['email']) != null) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(sprintf(__('The email "%1$s" is already used. If you need to, you can <a href="%2$s">recover your password</a>.'), $this->cleaned_data['email'], Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecoveryAsk')));
 | 
			
		||||
        }
 | 
			
		||||
        return $this->cleaned_data['email'];
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -69,7 +69,7 @@ class IDF_Form_RegisterConfirmation extends Pluf_Form
 | 
			
		||||
                                            'label' => __('Your password'),
 | 
			
		||||
                                            'initial' => '',
 | 
			
		||||
                                            'widget' => 'Pluf_Form_Widget_PasswordInput',
 | 
			
		||||
                                            'help_text' => __('Your password must be hard for other people to find it, but easy for you to remember.'),
 | 
			
		||||
                                            'help_text' => __('Your password must be hard for other people to guess, but easy for you to remember.'),
 | 
			
		||||
                                            'widget_attrs' => array(
 | 
			
		||||
                                                       'maxlength' => 50,
 | 
			
		||||
                                                       'size' => 15,
 | 
			
		||||
@@ -107,7 +107,7 @@ class IDF_Form_RegisterConfirmation extends Pluf_Form
 | 
			
		||||
            throw new Pluf_Form_Invalid($error);
 | 
			
		||||
        }
 | 
			
		||||
        if ($users[0]->active) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('This account has already been confirmed. Maybe should you try to recover your password using the help link.'));
 | 
			
		||||
            throw new Pluf_Form_Invalid(sprintf(__('This account has already been confirmed. Maybe should you try to <a href="%s">recover your password</a>.'), Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecoveryAsk')));
 | 
			
		||||
        }
 | 
			
		||||
        $this->_user_id = $email_id[1];
 | 
			
		||||
        return $this->cleaned_data['key'];
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -52,7 +52,7 @@ class IDF_Form_ReviewFileComment extends Pluf_Form
 | 
			
		||||
                                            ));
 | 
			
		||||
        }
 | 
			
		||||
        $this->fields['content'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                      array('required' => true,
 | 
			
		||||
                                      array('required' => false,
 | 
			
		||||
                                            'label' => __('General comment'),
 | 
			
		||||
                                            'initial' => '',
 | 
			
		||||
                                            'widget' => 'Pluf_Form_Widget_TextareaInput',
 | 
			
		||||
@@ -64,6 +64,8 @@ class IDF_Form_ReviewFileComment extends Pluf_Form
 | 
			
		||||
        if ($this->user->hasPerm('IDF.project-owner', $this->project)
 | 
			
		||||
            or $this->user->hasPerm('IDF.project-member', $this->project)) {
 | 
			
		||||
            $this->show_full = true;
 | 
			
		||||
        } else {
 | 
			
		||||
            $this->show_full = false;
 | 
			
		||||
        }
 | 
			
		||||
        if ($this->show_full) {
 | 
			
		||||
            $this->fields['summary'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
@@ -94,24 +96,40 @@ class IDF_Form_ReviewFileComment extends Pluf_Form
 | 
			
		||||
     */
 | 
			
		||||
    public function clean()
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($this->files as $filename => $def) {
 | 
			
		||||
            if (!empty($this->cleaned_data[md5($filename)])) {
 | 
			
		||||
                return $this->cleaned_data;
 | 
			
		||||
        $isOk = false;
 | 
			
		||||
        
 | 
			
		||||
        foreach($this->files as $filename => $def) {
 | 
			
		||||
            $this->cleaned_data[md5($filename)] = trim($this->cleaned_data[md5($filename)]);
 | 
			
		||||
            if(!empty($this->cleaned_data[md5($filename)])) {
 | 
			
		||||
                $isOk = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        throw new Pluf_Form_Invalid(__('You need to provide comments on at least one file.'));
 | 
			
		||||
        
 | 
			
		||||
        if(!empty($this->cleaned_data['content'])) {
 | 
			
		||||
            $isOk = true;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if (!$isOk) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('You need to provide your general comment about the proposal, or comments on at least one file.'));
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        return $this->cleaned_data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function clean_content()
 | 
			
		||||
    {
 | 
			
		||||
        $content = trim($this->cleaned_data['content']);
 | 
			
		||||
        if (!$this->show_full and strlen($content) == 0) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('You need to provide your general comment about the proposal.'));
 | 
			
		||||
        if(empty($content)) {
 | 
			
		||||
            if ($this->fields['status']->initial != $this->fields['status']->value) {
 | 
			
		||||
                return __('The status have been updated.');
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            return $content;
 | 
			
		||||
        }
 | 
			
		||||
        return $content;
 | 
			
		||||
        
 | 
			
		||||
        throw new Pluf_Form_Invalid(__('This field is required.'));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Save the model in the database.
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -49,13 +49,10 @@ class IDF_Form_SourceConf extends Pluf_Form
 | 
			
		||||
                          'widget' => 'Pluf_Form_Widget_PasswordInput',
 | 
			
		||||
                          ));
 | 
			
		||||
        }
 | 
			
		||||
        Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
 | 
			
		||||
        $url = Pluf_HTTP_URL_urlForView('idf_faq').'#webhooks';
 | 
			
		||||
        $this->fields['webhook_url'] = new Pluf_Form_Field_Url(
 | 
			
		||||
                    array('required' => false,
 | 
			
		||||
                          'label' => __('Webhook URL'),
 | 
			
		||||
                          'initial' => $this->conf->getVal('webhook_url', ''),
 | 
			
		||||
                          'help_text' => sprintf(__('Learn more about the <a href="%s">post-commit web hooks</a>.'), $url),
 | 
			
		||||
                          'widget_attrs' => array('size' => 35),
 | 
			
		||||
                          ));
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -57,20 +57,44 @@ class IDF_Form_TabsConf extends Pluf_Form
 | 
			
		||||
                                            'widget' => 'Pluf_Form_Widget_SelectInput',
 | 
			
		||||
                                            ));
 | 
			
		||||
        }
 | 
			
		||||
        $ak = array('downloads_notification_email',
 | 
			
		||||
                    'review_notification_email',
 | 
			
		||||
                    'wiki_notification_email',
 | 
			
		||||
                    'source_notification_email',
 | 
			
		||||
                    'issues_notification_email',);
 | 
			
		||||
        foreach ($ak as $key) {
 | 
			
		||||
            $this->fields[$key] = new IDF_Form_Field_EmailList(
 | 
			
		||||
                                      array('required' => false,
 | 
			
		||||
                                            'label' => $key,
 | 
			
		||||
                                            'initial' => $this->conf->getVal($key, ''),
 | 
			
		||||
                                            'widget_attrs' => array('size' => 40),
 | 
			
		||||
                                            ));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $sections = array(
 | 
			
		||||
            'downloads_notification',
 | 
			
		||||
            'review_notification',
 | 
			
		||||
            'wiki_notification',
 | 
			
		||||
            'source_notification',
 | 
			
		||||
            'issues_notification',
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        foreach ($sections as $section) {
 | 
			
		||||
            $this->fields[$section.'_owners_enabled'] = new Pluf_Form_Field_Boolean(
 | 
			
		||||
                array('required' => false,
 | 
			
		||||
                      'label' => __('Project owners'),
 | 
			
		||||
                      'initial' => $this->conf->getVal($section.'_owners_enabled', false),
 | 
			
		||||
                      'widget' => 'Pluf_Form_Widget_CheckboxInput',
 | 
			
		||||
                      ));
 | 
			
		||||
            $this->fields[$section.'_members_enabled'] = new Pluf_Form_Field_Boolean(
 | 
			
		||||
                array('required' => false,
 | 
			
		||||
                      'label' => __('Project members'),
 | 
			
		||||
                      'initial' => $this->conf->getVal($section.'_members_enabled', false),
 | 
			
		||||
                      'widget' => 'Pluf_Form_Widget_CheckboxInput',
 | 
			
		||||
                      ));
 | 
			
		||||
            $this->fields[$section.'_email_enabled'] = new Pluf_Form_Field_Boolean(
 | 
			
		||||
                array('required' => false,
 | 
			
		||||
                      'label' => __('Others'),
 | 
			
		||||
                      'initial' => $this->conf->getVal($section.'_email_enabled', false),
 | 
			
		||||
                      'widget' => 'Pluf_Form_Widget_CheckboxInput',
 | 
			
		||||
                      ));
 | 
			
		||||
            if ($this->conf->getVal($section.'_email_enabled', false)) {
 | 
			
		||||
                $attrs['readonly'] = 'readonly';
 | 
			
		||||
            }
 | 
			
		||||
            $this->fields[$section.'_email'] = new IDF_Form_Field_EmailList(
 | 
			
		||||
                array('required' => false,
 | 
			
		||||
                      'label' => null,
 | 
			
		||||
                      'initial' => $this->conf->getVal($section.'_email', ''),
 | 
			
		||||
                      'widget_attrs' => array('size' => 20),
 | 
			
		||||
                      ));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->fields['private_project'] = new Pluf_Form_Field_Boolean(
 | 
			
		||||
                    array('required' => false,
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -96,7 +96,7 @@ class IDF_Form_UpdateUpload extends Pluf_Form
 | 
			
		||||
            $this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]);
 | 
			
		||||
            if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
 | 
			
		||||
                list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
 | 
			
		||||
                list($class, $name) = array(mb_strtolower(trim($class)), 
 | 
			
		||||
                list($class, $name) = array(mb_strtolower(trim($class)),
 | 
			
		||||
                                            trim($name));
 | 
			
		||||
            } else {
 | 
			
		||||
                $class = 'other';
 | 
			
		||||
@@ -106,7 +106,7 @@ class IDF_Form_UpdateUpload extends Pluf_Form
 | 
			
		||||
            else $count[$class] += 1;
 | 
			
		||||
            if (in_array($class, $onemax) and $count[$class] > 1) {
 | 
			
		||||
                if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array();
 | 
			
		||||
                $this->errors['label'.$i][] = sprintf(__('You cannot provide more than label from the %s class to an issue.'), $class);
 | 
			
		||||
                $this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to an issue.'), $class);
 | 
			
		||||
                throw new Pluf_Form_Invalid(__('You provided an invalid label.'));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -146,6 +146,9 @@ class IDF_Form_UpdateUpload extends Pluf_Form
 | 
			
		||||
        $this->upload->modif_dtime = gmdate('Y-m-d H:i:s');
 | 
			
		||||
        $this->upload->update();
 | 
			
		||||
        $this->upload->batchAssoc('IDF_Tag', $tags);
 | 
			
		||||
 | 
			
		||||
        // Send the notification
 | 
			
		||||
        $this->upload->notify($this->project->getConf(), false);
 | 
			
		||||
        /**
 | 
			
		||||
         * [signal]
 | 
			
		||||
         *
 | 
			
		||||
@@ -166,7 +169,7 @@ class IDF_Form_UpdateUpload extends Pluf_Form
 | 
			
		||||
         *
 | 
			
		||||
         */
 | 
			
		||||
        $params = array('upload' => $this->upload);
 | 
			
		||||
        Pluf_Signal::send('IDF_Upload::update', 
 | 
			
		||||
        Pluf_Signal::send('IDF_Upload::update',
 | 
			
		||||
                          'IDF_Form_UpdateUpload', $params);
 | 
			
		||||
        return $this->upload;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -79,11 +79,12 @@ class IDF_Form_Upload extends Pluf_Form
 | 
			
		||||
 | 
			
		||||
    public function clean_file()
 | 
			
		||||
    {
 | 
			
		||||
        // FIXME: we do the same in IDF_Form_WikiResourceCreate and a couple of other places as well
 | 
			
		||||
        $extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext'))));
 | 
			
		||||
        if (strlen($extra)) $extra .= '|';
 | 
			
		||||
        if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|jar|mdtext|mid|mov|mp3|mpg|ogg|pdf|ppt|ps|qt|ra|ram|rm|rtf|sdd|sdw|sit|sxi|sxw|swf|tgz|txt|wav|xls|xml|war|wmv|zip)$/i', $this->cleaned_data['file'])) {
 | 
			
		||||
            @unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file']);
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('For security reason, you cannot upload a file with this extension.'));
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('For security reasons, you cannot upload a file with this extension.'));
 | 
			
		||||
        }
 | 
			
		||||
        return $this->cleaned_data['file'];
 | 
			
		||||
    }
 | 
			
		||||
@@ -106,7 +107,7 @@ class IDF_Form_Upload extends Pluf_Form
 | 
			
		||||
            $this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]);
 | 
			
		||||
            if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
 | 
			
		||||
                list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
 | 
			
		||||
                list($class, $name) = array(mb_strtolower(trim($class)), 
 | 
			
		||||
                list($class, $name) = array(mb_strtolower(trim($class)),
 | 
			
		||||
                                            trim($name));
 | 
			
		||||
            } else {
 | 
			
		||||
                $class = 'other';
 | 
			
		||||
@@ -116,7 +117,7 @@ class IDF_Form_Upload extends Pluf_Form
 | 
			
		||||
            else $count[$class] += 1;
 | 
			
		||||
            if (in_array($class, $onemax) and $count[$class] > 1) {
 | 
			
		||||
                if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array();
 | 
			
		||||
                $this->errors['label'.$i][] = sprintf(__('You cannot provide more than label from the %s class to an issue.'), $class);
 | 
			
		||||
                $this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to a download.'), $class);
 | 
			
		||||
                throw new Pluf_Form_Invalid(__('You provided an invalid label.'));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -129,7 +130,7 @@ class IDF_Form_Upload extends Pluf_Form
 | 
			
		||||
     */
 | 
			
		||||
    function failed()
 | 
			
		||||
    {
 | 
			
		||||
        if (!empty($this->cleaned_data['file']) 
 | 
			
		||||
        if (!empty($this->cleaned_data['file'])
 | 
			
		||||
            and file_exists(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file'])) {
 | 
			
		||||
            @unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file']);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										227
									
								
								src/IDF/Form/UploadArchive.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								src/IDF/Form/UploadArchive.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,227 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Upload and process an archive file.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
class IDF_Form_UploadArchive extends Pluf_Form
 | 
			
		||||
{
 | 
			
		||||
    public $user = null;
 | 
			
		||||
    public $project = null;
 | 
			
		||||
    private $archiveHelper = null;
 | 
			
		||||
 | 
			
		||||
    public function initFields($extra=array())
 | 
			
		||||
    {
 | 
			
		||||
        $this->user = $extra['user'];
 | 
			
		||||
        $this->project = $extra['project'];
 | 
			
		||||
 | 
			
		||||
        $this->fields['archive'] = new Pluf_Form_Field_File(
 | 
			
		||||
                                      array('required' => true,
 | 
			
		||||
                                            'label' => __('Archive file'),
 | 
			
		||||
                                            'initial' => '',
 | 
			
		||||
                                            'max_size' => Pluf::f('max_upload_archive_size', 20971520),
 | 
			
		||||
                                            'move_function_params' => array(
 | 
			
		||||
                                                'upload_path' => Pluf::f('upload_path').'/'.$this->project->shortname.'/archives',
 | 
			
		||||
                                                'upload_path_create' => true,
 | 
			
		||||
                                                'upload_overwrite' => true,
 | 
			
		||||
                                            )));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function clean_archive()
 | 
			
		||||
    {
 | 
			
		||||
        $this->archiveHelper = new IDF_Form_UploadArchiveHelper(
 | 
			
		||||
            Pluf::f('upload_path').'/'.$this->project->shortname.'/archives/'.$this->cleaned_data['archive']);
 | 
			
		||||
 | 
			
		||||
        // basic archive validation
 | 
			
		||||
        $this->archiveHelper->validate();
 | 
			
		||||
 | 
			
		||||
        // extension validation
 | 
			
		||||
        $fileNames = $this->archiveHelper->getEntryNames();
 | 
			
		||||
        foreach ($fileNames as $fileName) {
 | 
			
		||||
            $extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext'))));
 | 
			
		||||
            if (strlen($extra)) $extra .= '|';
 | 
			
		||||
            if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|jar|mdtext|mid|mov|mp3|mpg|ogg|pdf|ppt|ps|qt|ra|ram|rm|rtf|sdd|sdw|sit|sxi|sxw|swf|tgz|txt|wav|xls|xml|war|wmv|zip)$/i', $fileName)) {
 | 
			
		||||
                @unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['archive']);
 | 
			
		||||
                throw new Pluf_Form_Invalid(sprintf(__('For security reasons, you cannot upload a file (%s) with this extension.'), $fileName));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // label and file name validation
 | 
			
		||||
        $conf = new IDF_Conf();
 | 
			
		||||
        $conf->setProject($this->project);
 | 
			
		||||
        $onemax = array();
 | 
			
		||||
        foreach (explode(',', $conf->getVal('labels_download_one_max', IDF_Form_UploadConf::init_one_max)) as $class) {
 | 
			
		||||
            if (trim($class) != '') {
 | 
			
		||||
                $onemax[] = mb_strtolower(trim($class));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ($fileNames as $fileName) {
 | 
			
		||||
            $meta = $this->archiveHelper->getMetaData($fileName);
 | 
			
		||||
            $count = array();
 | 
			
		||||
            foreach ($meta['labels'] as $label) {
 | 
			
		||||
                $label = trim($label);
 | 
			
		||||
                if (strpos($label, ':') !== false) {
 | 
			
		||||
                    list($class, $name) = explode(':', $label, 2);
 | 
			
		||||
                    list($class, $name) = array(mb_strtolower(trim($class)),
 | 
			
		||||
                    trim($name));
 | 
			
		||||
                } else {
 | 
			
		||||
                    $class = 'other';
 | 
			
		||||
                    $name = $label;
 | 
			
		||||
                }
 | 
			
		||||
                if (!isset($count[$class])) $count[$class] = 1;
 | 
			
		||||
                else $count[$class] += 1;
 | 
			
		||||
                if (in_array($class, $onemax) and $count[$class] > 1) {
 | 
			
		||||
                    throw new Pluf_Form_Invalid(
 | 
			
		||||
                       sprintf(__('You cannot provide more than label from the %1$s class to a download (%2$s).'), $class, $name)
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $sql = new Pluf_SQL('file=%s AND project=%s', array($fileName, $this->project->id));
 | 
			
		||||
            $upload = Pluf::factory('IDF_Upload')->getOne(array('filter' => $sql->gen()));
 | 
			
		||||
 | 
			
		||||
            $meta = $this->archiveHelper->getMetaData($fileName);
 | 
			
		||||
            if ($upload != null && $meta['replaces'] !== $fileName) {
 | 
			
		||||
                throw new Pluf_Form_Invalid(
 | 
			
		||||
                    sprintf(__('A file with the name "%s" has already been uploaded and is not marked to be replaced.'), $fileName));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->cleaned_data['archive'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * If we have uploaded a file, but the form failed remove it.
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    function failed()
 | 
			
		||||
    {
 | 
			
		||||
        if (!empty($this->cleaned_data['archive'])
 | 
			
		||||
            and file_exists(Pluf::f('upload_path').'/'.$this->project->shortname.'/archives/'.$this->cleaned_data['archive'])) {
 | 
			
		||||
            @unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/archives/'.$this->cleaned_data['archive']);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Save the model in the database.
 | 
			
		||||
     *
 | 
			
		||||
     * @param bool Commit in the database or not. If not, the object
 | 
			
		||||
     *             is returned but not saved in the database.
 | 
			
		||||
     */
 | 
			
		||||
    function save($commit=true)
 | 
			
		||||
    {
 | 
			
		||||
        if (!$this->isValid()) {
 | 
			
		||||
            throw new Exception(__('Cannot save the model from an invalid form.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $uploadDir = Pluf::f('upload_path').'/'.$this->project->shortname.'/files/';
 | 
			
		||||
        $fileNames = $this->archiveHelper->getEntryNames();
 | 
			
		||||
 | 
			
		||||
        foreach ($fileNames as $fileName) {
 | 
			
		||||
            $meta = $this->archiveHelper->getMetaData($fileName);
 | 
			
		||||
 | 
			
		||||
            // add a tag for each label
 | 
			
		||||
            $tags = array();
 | 
			
		||||
            foreach ($meta['labels'] as $label) {
 | 
			
		||||
                $label = trim($label);
 | 
			
		||||
                if (strlen($label) > 0) {
 | 
			
		||||
                    if (strpos($label, ':') !== false) {
 | 
			
		||||
                        list($class, $name) = explode(':', $label, 2);
 | 
			
		||||
                        list($class, $name) = array(trim($class), trim($name));
 | 
			
		||||
                    } else {
 | 
			
		||||
                        $class = 'Other';
 | 
			
		||||
                        $name = $label;
 | 
			
		||||
                    }
 | 
			
		||||
                    $tags[] = IDF_Tag::add($name, $this->project, $class);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // process a possible replacement
 | 
			
		||||
            if (!empty($meta['replaces'])) {
 | 
			
		||||
                $sql = new Pluf_SQL('file=%s AND project=%s', array($meta['replaces'], $this->project->id));
 | 
			
		||||
                $oldUpload = Pluf::factory('IDF_Upload')->getOne(array('filter' => $sql->gen()));
 | 
			
		||||
 | 
			
		||||
                if ($oldUpload) {
 | 
			
		||||
                    if ($meta['replaces'] === $fileName) {
 | 
			
		||||
                        $oldUpload->delete();
 | 
			
		||||
                    } else {
 | 
			
		||||
                        $tags = $this->project->getTagsFromConfig('labels_download_predefined',
 | 
			
		||||
                                                                  IDF_Form_UploadConf::init_predefined);
 | 
			
		||||
                        // the deprecate tag is - by definition - always the last one
 | 
			
		||||
                        $deprecatedTag = array_pop($tags);
 | 
			
		||||
                        $oldUpload->setAssoc($deprecatedTag);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // extract the file
 | 
			
		||||
            $this->archiveHelper->extract($fileName, $uploadDir);
 | 
			
		||||
 | 
			
		||||
            // create the upload
 | 
			
		||||
            $upload = new IDF_Upload();
 | 
			
		||||
            $upload->project = $this->project;
 | 
			
		||||
            $upload->submitter = $this->user;
 | 
			
		||||
            $upload->summary = trim($meta['summary']);
 | 
			
		||||
            $upload->changelog = trim($meta['description']);
 | 
			
		||||
            $upload->file = $fileName;
 | 
			
		||||
            $upload->filesize = filesize($uploadDir.$fileName);
 | 
			
		||||
            $upload->downloads = 0;
 | 
			
		||||
            $upload->create();
 | 
			
		||||
            foreach ($tags as $tag) {
 | 
			
		||||
                $upload->setAssoc($tag);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // send the notification
 | 
			
		||||
            $upload->notify($this->project->getConf());
 | 
			
		||||
            /**
 | 
			
		||||
             * [signal]
 | 
			
		||||
             *
 | 
			
		||||
             * IDF_Upload::create
 | 
			
		||||
             *
 | 
			
		||||
             * [sender]
 | 
			
		||||
             *
 | 
			
		||||
             * IDF_Form_Upload
 | 
			
		||||
             *
 | 
			
		||||
             * [description]
 | 
			
		||||
             *
 | 
			
		||||
             * This signal allows an application to perform a set of tasks
 | 
			
		||||
             * just after the upload of a file and after the notification run.
 | 
			
		||||
             *
 | 
			
		||||
             * [parameters]
 | 
			
		||||
             *
 | 
			
		||||
             * array('upload' => $upload);
 | 
			
		||||
             *
 | 
			
		||||
             */
 | 
			
		||||
            $params = array('upload' => $upload);
 | 
			
		||||
            Pluf_Signal::send('IDF_Upload::create', 'IDF_Form_Upload',
 | 
			
		||||
                              $params);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // finally unlink the uploaded archive
 | 
			
		||||
        @unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/archives/'.$this->cleaned_data['archive']);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										158
									
								
								src/IDF/Form/UploadArchiveHelper.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								src/IDF/Form/UploadArchiveHelper.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,158 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
class IDF_Form_UploadArchiveHelper
 | 
			
		||||
{
 | 
			
		||||
    private $file = null;
 | 
			
		||||
    private $entries = array();
 | 
			
		||||
 | 
			
		||||
    public function __construct($file)
 | 
			
		||||
    {
 | 
			
		||||
        $this->file = $file;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Validates the archive; throws a invalid form exception in case the
 | 
			
		||||
     * archive contains invalid data or cannot be read.
 | 
			
		||||
     */
 | 
			
		||||
    public function validate()
 | 
			
		||||
    {
 | 
			
		||||
        if (!file_exists($this->file)) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('The archive does not exist.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $za = new ZipArchive();
 | 
			
		||||
        $res = $za->open($this->file);
 | 
			
		||||
        if ($res !== true) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(
 | 
			
		||||
                sprintf(__('The archive could not be read (code %d).'), $res));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $manifest = $za->getFromName('manifest.xml');
 | 
			
		||||
        if ($manifest === false) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('The archive does not contain a manifest.xml.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        libxml_use_internal_errors(true);
 | 
			
		||||
        $xml = @simplexml_load_string($manifest);
 | 
			
		||||
        if ($xml === false) {
 | 
			
		||||
            $error = libxml_get_last_error();
 | 
			
		||||
            throw new Pluf_Form_Invalid(
 | 
			
		||||
                sprintf(__('The archive\'s manifest is invalid: %s'), $error->message));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach (@$xml->file as $idx => $file)
 | 
			
		||||
        {
 | 
			
		||||
            $entry = array(
 | 
			
		||||
                'name' => (string)@$file->name,
 | 
			
		||||
                'summary' => (string)@$file->summary,
 | 
			
		||||
                'description' => (string)@$file->description,
 | 
			
		||||
                'replaces' => (string)@$file->replaces,
 | 
			
		||||
                'labels' => array(),
 | 
			
		||||
                'stream' => null
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            if (empty($entry['name'])) {
 | 
			
		||||
                throw new Pluf_Form_Invalid(
 | 
			
		||||
                    sprintf(__('The entry %d in the manifest is missing a file name.'), $idx));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (empty($entry['summary'])) {
 | 
			
		||||
                throw new Pluf_Form_Invalid(
 | 
			
		||||
                    sprintf(__('The entry %d in the manifest is missing a summary.'), $idx));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($entry['name'] === 'manifest.xml') {
 | 
			
		||||
                throw new Pluf_Form_Invalid(__('The manifest must not reference itself.'));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($za->locateName($entry['name']) === false) {
 | 
			
		||||
                throw new Pluf_Form_Invalid(
 | 
			
		||||
                    sprintf(__('The entry %s in the manifest does not exist in the archive.'), $entry['name']));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (in_array($entry['name'], $this->entries)) {
 | 
			
		||||
                throw new Pluf_Form_Invalid(
 | 
			
		||||
                    sprintf(__('The entry %s in the manifest is referenced more than once.'), $entry['name']));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($file->labels) {
 | 
			
		||||
                foreach (@$file->labels->label as $label) {
 | 
			
		||||
                    $entry['labels'][] = (string)$label;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // FIXME: remove this once we allow more than six labels everywhere
 | 
			
		||||
            if (count($entry['labels']) > 6) {
 | 
			
		||||
                throw new Pluf_Form_Invalid(
 | 
			
		||||
                    sprintf(__('The entry %s in the manifest has more than the six allowed labels set.'), $entry['name']));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $this->entries[$entry['name']] = $entry;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $za->close();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns all entry names
 | 
			
		||||
     *
 | 
			
		||||
     * @return array of string
 | 
			
		||||
     */
 | 
			
		||||
    public function getEntryNames()
 | 
			
		||||
    {
 | 
			
		||||
        return array_keys($this->entries);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns meta data for the given entry
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $name
 | 
			
		||||
     * @throws Exception
 | 
			
		||||
     */
 | 
			
		||||
    public function getMetaData($name)
 | 
			
		||||
    {
 | 
			
		||||
        if (!array_key_exists($name, $this->entries)) {
 | 
			
		||||
            throw new Exception('unknown file ' . $name);
 | 
			
		||||
        }
 | 
			
		||||
        return $this->entries[$name];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Extracts the file entry $name at $path
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $name
 | 
			
		||||
     * @param string $path
 | 
			
		||||
     * @throws Exception
 | 
			
		||||
     */
 | 
			
		||||
    public function extract($name, $path)
 | 
			
		||||
    {
 | 
			
		||||
        if (!array_key_exists($name, $this->entries)) {
 | 
			
		||||
            throw new Exception('unknown file ' . $name);
 | 
			
		||||
        }
 | 
			
		||||
        $za = new ZipArchive();
 | 
			
		||||
        $za->open($this->file);
 | 
			
		||||
        $za->extractTo($path, $name);
 | 
			
		||||
        $za->close();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -60,10 +60,18 @@ Deprecated           = Most users should NOT download this';
 | 
			
		||||
        $this->fields['labels_download_one_max'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                      array('required' => false,
 | 
			
		||||
                                            'label' => __('Each download may have at most one label with each of these classes'),
 | 
			
		||||
                                            'initial' => self::init_one_max, 
 | 
			
		||||
                                            'initial' => self::init_one_max,
 | 
			
		||||
                                            'widget_attrs' => array('size' => 60),
 | 
			
		||||
                                            ));
 | 
			
		||||
 | 
			
		||||
        $this->conf = $extra['conf'];
 | 
			
		||||
        $this->fields['upload_webhook_url'] = new Pluf_Form_Field_Url(
 | 
			
		||||
                                      array('required' => false,
 | 
			
		||||
                                            'label' => __('Webhook URL'),
 | 
			
		||||
                                            'initial' => $this->conf->getVal('upload_webhook_url', ''),
 | 
			
		||||
                                            'widget_attrs' => array('size' => 60),
 | 
			
		||||
        ));
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -56,7 +56,7 @@ class IDF_Form_UserAccount  extends Pluf_Form
 | 
			
		||||
 | 
			
		||||
        $this->fields['email'] = new Pluf_Form_Field_Email(
 | 
			
		||||
                                      array('required' => true,
 | 
			
		||||
                                            'label' => __('Your mail'),
 | 
			
		||||
                                            'label' => __('Your email'),
 | 
			
		||||
                                            'initial' => $this->user->email,
 | 
			
		||||
                                            'help_text' => __('If you change your email address, an email will be sent to the new address to confirm it.'),
 | 
			
		||||
                                            ));
 | 
			
		||||
@@ -79,6 +79,7 @@ class IDF_Form_UserAccount  extends Pluf_Form
 | 
			
		||||
                                            'widget' => 'Pluf_Form_Widget_PasswordInput',
 | 
			
		||||
                                            'help_text' => Pluf_Template::markSafe(__('Leave blank if you do not want to change your password.').'<br />'.__('Your password must be hard for other people to find it, but easy for you to remember.')),
 | 
			
		||||
                                            'widget_attrs' => array(
 | 
			
		||||
                                                       'autocomplete' => 'off',
 | 
			
		||||
                                                       'maxlength' => 50,
 | 
			
		||||
                                                       'size' => 15,
 | 
			
		||||
                                                                    ),
 | 
			
		||||
@@ -89,6 +90,7 @@ class IDF_Form_UserAccount  extends Pluf_Form
 | 
			
		||||
                                            'initial' => '',
 | 
			
		||||
                                            'widget' => 'Pluf_Form_Widget_PasswordInput',
 | 
			
		||||
                                            'widget_attrs' => array(
 | 
			
		||||
                                                       'autocomplete' => 'off',
 | 
			
		||||
                                                       'maxlength' => 50,
 | 
			
		||||
                                                       'size' => 15,
 | 
			
		||||
                                                                    ),
 | 
			
		||||
@@ -161,8 +163,44 @@ class IDF_Form_UserAccount  extends Pluf_Form
 | 
			
		||||
                                            'widget_attrs' => array('rows' => 3,
 | 
			
		||||
                                                                    'cols' => 40),
 | 
			
		||||
                                            'widget' => 'Pluf_Form_Widget_TextareaInput',
 | 
			
		||||
                                            'help_text' => __('Paste a SSH or monotone public key. Be careful to not provide your private key here!')
 | 
			
		||||
                                            'help_text' => __('Paste an SSH or monotone public key. Be careful to not provide your private key here!')
 | 
			
		||||
                                            ));
 | 
			
		||||
 | 
			
		||||
        $this->fields['secondary_mail'] = new Pluf_Form_Field_Email(
 | 
			
		||||
                                      array('required' => false,
 | 
			
		||||
                                            'label' => __('Add a secondary email address'),
 | 
			
		||||
                                            'initial' => '',
 | 
			
		||||
                                            'help_text' => __('You will get an email to confirm that you own the address you specify.'),
 | 
			
		||||
                                            ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function send_validation_mail($new_email, $secondary_mail=false)
 | 
			
		||||
    {
 | 
			
		||||
        if ($secondary_mail) {
 | 
			
		||||
            $type = "secondary";
 | 
			
		||||
        } else {
 | 
			
		||||
            $type = "primary";
 | 
			
		||||
        }
 | 
			
		||||
        $cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
 | 
			
		||||
        $encrypted = trim($cr->encrypt($new_email.':'.$this->user->id.':'.time().':'.$type), '~');
 | 
			
		||||
        $key = substr(md5(Pluf::f('secret_key').$encrypted), 0, 2).$encrypted;
 | 
			
		||||
        $url = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views_User::changeEmailDo', array($key), array(), false);
 | 
			
		||||
        $urlik = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views_User::changeEmailInputKey', array(), array(), false);
 | 
			
		||||
        $context = new Pluf_Template_Context(
 | 
			
		||||
             array('key' => Pluf_Template::markSafe($key),
 | 
			
		||||
                   'url' => Pluf_Template::markSafe($url),
 | 
			
		||||
                   'urlik' => Pluf_Template::markSafe($urlik),
 | 
			
		||||
                   'email' => $new_email,
 | 
			
		||||
                   'user'=> $this->user,
 | 
			
		||||
                   )
 | 
			
		||||
        );
 | 
			
		||||
        $tmpl = new Pluf_Template('idf/user/changeemail-email.txt');
 | 
			
		||||
        $text_email = $tmpl->render($context);
 | 
			
		||||
        $email = new Pluf_Mail(Pluf::f('from_email'), $new_email,
 | 
			
		||||
                               __('Confirm your new email address.'));
 | 
			
		||||
        $email->addTextMessage($text_email);
 | 
			
		||||
        $email->sendMail();
 | 
			
		||||
        $this->user->setMessage(sprintf(__('A validation email has been sent to "%s" to validate the email address change.'), Pluf_esc($new_email)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -188,26 +226,7 @@ class IDF_Form_UserAccount  extends Pluf_Form
 | 
			
		||||
        $new_email = $this->cleaned_data['email'];
 | 
			
		||||
        unset($this->cleaned_data['email']);
 | 
			
		||||
        if ($old_email != $new_email) {
 | 
			
		||||
            $cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
 | 
			
		||||
            $encrypted = trim($cr->encrypt($new_email.':'.$this->user->id.':'.time()), '~');
 | 
			
		||||
            $key = substr(md5(Pluf::f('secret_key').$encrypted), 0, 2).$encrypted;
 | 
			
		||||
            $url = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views_User::changeEmailDo', array($key), array(), false);
 | 
			
		||||
            $urlik = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views_User::changeEmailInputKey', array(), array(), false);
 | 
			
		||||
            $context = new Pluf_Template_Context(
 | 
			
		||||
                 array('key' => Pluf_Template::markSafe($key),
 | 
			
		||||
                       'url' => Pluf_Template::markSafe($url),
 | 
			
		||||
                       'urlik' => Pluf_Template::markSafe($urlik),
 | 
			
		||||
                       'email' => $new_email,
 | 
			
		||||
                       'user'=> $this->user,
 | 
			
		||||
                       )
 | 
			
		||||
            );
 | 
			
		||||
            $tmpl = new Pluf_Template('idf/user/changeemail-email.txt');
 | 
			
		||||
            $text_email = $tmpl->render($context);
 | 
			
		||||
            $email = new Pluf_Mail(Pluf::f('from_email'), $new_email,
 | 
			
		||||
                                   __('Confirm your new email address.'));
 | 
			
		||||
            $email->addTextMessage($text_email);
 | 
			
		||||
            $email->sendMail();
 | 
			
		||||
            $this->user->setMessage(sprintf(__('A validation email has been sent to "%s" to validate the email address change.'), Pluf_esc($new_email)));
 | 
			
		||||
            $this->send_validation_mail($new_email);
 | 
			
		||||
        }
 | 
			
		||||
        $this->user->setFromFormData($this->cleaned_data);
 | 
			
		||||
        // Add key as needed.
 | 
			
		||||
@@ -219,6 +238,9 @@ class IDF_Form_UserAccount  extends Pluf_Form
 | 
			
		||||
                $key->create();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if ('' !== $this->cleaned_data['secondary_mail']) {
 | 
			
		||||
            $this->send_validation_mail($this->cleaned_data['secondary_mail'], true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($commit) {
 | 
			
		||||
            $this->user->update();
 | 
			
		||||
@@ -295,8 +317,15 @@ class IDF_Form_UserAccount  extends Pluf_Form
 | 
			
		||||
            return '';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (preg_match('#^ssh\-[a-z]{3}\s\S+(\s\S+)?$#', $key)) {
 | 
			
		||||
            $key = str_replace(array("\n", "\r"), '', $key);
 | 
			
		||||
        $keysearch = '';
 | 
			
		||||
        if (preg_match('#^(ssh\-(?:dss|rsa)\s+\S+)(.*)#', $key, $m)) {
 | 
			
		||||
            $basekey = preg_replace('/\s+/', ' ', $m[1]);
 | 
			
		||||
            $comment = trim(preg_replace('/[\r\n]/', ' ', $m[2]));
 | 
			
		||||
           
 | 
			
		||||
            $keysearch = $basekey.'%';
 | 
			
		||||
            $key = $basekey;
 | 
			
		||||
            if (!empty($comment))
 | 
			
		||||
                $key .= ' '.$comment;
 | 
			
		||||
 | 
			
		||||
            if (Pluf::f('idf_strong_key_check', false)) {
 | 
			
		||||
 | 
			
		||||
@@ -315,7 +344,9 @@ class IDF_Form_UserAccount  extends Pluf_Form
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (preg_match('#^\[pubkey [^\]]+\]\s*\S+\s*\[end\]$#', $key)) {
 | 
			
		||||
        else if (preg_match('#^\[pubkey [^\]]+\]\s*(\S+)\s*\[end\]$#', $key, $m)) {
 | 
			
		||||
            $keysearch = '%'.$m[1].'%';
 | 
			
		||||
            
 | 
			
		||||
            if (Pluf::f('idf_strong_key_check', false)) {
 | 
			
		||||
 | 
			
		||||
                // if monotone can read it, it should be valid
 | 
			
		||||
@@ -337,7 +368,7 @@ class IDF_Form_UserAccount  extends Pluf_Form
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            throw new Pluf_Form_Invalid(
 | 
			
		||||
                __('Public key looks neither like a SSH '.
 | 
			
		||||
                __('Public key looks like neither an SSH '.
 | 
			
		||||
                   'nor monotone public key.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -345,7 +376,7 @@ class IDF_Form_UserAccount  extends Pluf_Form
 | 
			
		||||
        if ($user) {
 | 
			
		||||
            $ruser = Pluf::factory('Pluf_User', $user);
 | 
			
		||||
            if ($ruser->id > 0) {
 | 
			
		||||
                $sql = new Pluf_SQL('content=%s', array($key));
 | 
			
		||||
                $sql = new Pluf_SQL('content LIKE %s AND user=%s', array($keysearch, $ruser->id));
 | 
			
		||||
                $keys = Pluf::factory('IDF_Key')->getList(array('filter' => $sql->gen()));
 | 
			
		||||
                if (count($keys) > 0) {
 | 
			
		||||
                    throw new Pluf_Form_Invalid(
 | 
			
		||||
@@ -393,15 +424,22 @@ class IDF_Form_UserAccount  extends Pluf_Form
 | 
			
		||||
    function clean_email()
 | 
			
		||||
    {
 | 
			
		||||
        $this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email']));
 | 
			
		||||
        $guser = new Pluf_User();
 | 
			
		||||
        $sql = new Pluf_SQL('email=%s AND id!=%s',
 | 
			
		||||
                            array($this->cleaned_data['email'], $this->user->id));
 | 
			
		||||
        if ($guser->getCount(array('filter' => $sql->gen())) > 0) {
 | 
			
		||||
        $user = Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($this->cleaned_data['email']);
 | 
			
		||||
        if ($user != null and $user->id != $this->user->id) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(sprintf(__('The email "%s" is already used.'), $this->cleaned_data['email']));
 | 
			
		||||
        }
 | 
			
		||||
        return $this->cleaned_data['email'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function clean_secondary_mail()
 | 
			
		||||
    {
 | 
			
		||||
        $this->cleaned_data['secondary_mail'] = mb_strtolower(trim($this->cleaned_data['secondary_mail']));
 | 
			
		||||
        if (Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($this->cleaned_data['secondary_mail']) != null) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(sprintf(__('The email "%s" is already used.'), $this->cleaned_data['secondary_mail']));
 | 
			
		||||
        }
 | 
			
		||||
        return $this->cleaned_data['secondary_mail'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function clean_public_key()
 | 
			
		||||
    {
 | 
			
		||||
        $this->cleaned_data['public_key'] =
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -53,7 +53,7 @@ class IDF_Form_UserChangeEmail extends Pluf_Form
 | 
			
		||||
     * Throw a Pluf_Form_Invalid exception if the key is not valid.
 | 
			
		||||
     *
 | 
			
		||||
     * @param string Key
 | 
			
		||||
     * @return array array($new_email, $user_id, time())
 | 
			
		||||
     * @return array array($new_email, $user_id, time(), [primary|secondary])
 | 
			
		||||
     */
 | 
			
		||||
    public static function validateKey($key)
 | 
			
		||||
    {
 | 
			
		||||
@@ -63,7 +63,7 @@ class IDF_Form_UserChangeEmail extends Pluf_Form
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('The validation key is not valid. Please copy/paste it from your confirmation email.'));
 | 
			
		||||
        }
 | 
			
		||||
        $cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
 | 
			
		||||
        return explode(':', $cr->decrypt($encrypted), 3);
 | 
			
		||||
        return explode(':', $cr->decrypt($encrypted), 4);
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -27,7 +27,7 @@
 | 
			
		||||
 * This create a new page and the corresponding revision.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
class IDF_Form_WikiCreate extends Pluf_Form
 | 
			
		||||
class IDF_Form_WikiPageCreate extends Pluf_Form
 | 
			
		||||
{
 | 
			
		||||
    public $user = null;
 | 
			
		||||
    public $project = null;
 | 
			
		||||
@@ -107,9 +107,9 @@ Add your content here. Format your content with:
 | 
			
		||||
        if (preg_match('/[^a-zA-Z0-9\-]/', $title)) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('The title contains invalid characters.'));
 | 
			
		||||
        }
 | 
			
		||||
        $sql = new Pluf_SQL('project=%s AND title=%s', 
 | 
			
		||||
        $sql = new Pluf_SQL('project=%s AND title=%s',
 | 
			
		||||
                            array($this->project->id, $title));
 | 
			
		||||
        $pages = Pluf::factory('IDF_WikiPage')->getList(array('filter'=>$sql->gen()));
 | 
			
		||||
        $pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen()));
 | 
			
		||||
        if ($pages->count() > 0) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('A page with this title already exists.'));
 | 
			
		||||
        }
 | 
			
		||||
@@ -137,7 +137,7 @@ Add your content here. Format your content with:
 | 
			
		||||
            $this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]);
 | 
			
		||||
            if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
 | 
			
		||||
                list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
 | 
			
		||||
                list($class, $name) = array(mb_strtolower(trim($class)), 
 | 
			
		||||
                list($class, $name) = array(mb_strtolower(trim($class)),
 | 
			
		||||
                                            trim($name));
 | 
			
		||||
            } else {
 | 
			
		||||
                $class = 'other';
 | 
			
		||||
@@ -147,7 +147,7 @@ Add your content here. Format your content with:
 | 
			
		||||
            else $count[$class] += 1;
 | 
			
		||||
            if (in_array($class, $onemax) and $count[$class] > 1) {
 | 
			
		||||
                if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array();
 | 
			
		||||
                $this->errors['label'.$i][] = sprintf(__('You cannot provide more than label from the %s class to a page.'), $class);
 | 
			
		||||
                $this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to a page.'), $class);
 | 
			
		||||
                throw new Pluf_Form_Invalid(__('You provided an invalid label.'));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -181,9 +181,9 @@ Add your content here. Format your content with:
 | 
			
		||||
                    $tags[] = IDF_Tag::add($name, $this->project, $class);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } 
 | 
			
		||||
        }
 | 
			
		||||
        // Create the page
 | 
			
		||||
        $page = new IDF_WikiPage();
 | 
			
		||||
        $page = new IDF_Wiki_Page();
 | 
			
		||||
        $page->project = $this->project;
 | 
			
		||||
        $page->submitter = $this->user;
 | 
			
		||||
        $page->summary = trim($this->cleaned_data['summary']);
 | 
			
		||||
@@ -193,7 +193,7 @@ Add your content here. Format your content with:
 | 
			
		||||
            $page->setAssoc($tag);
 | 
			
		||||
        }
 | 
			
		||||
        // add the first revision
 | 
			
		||||
        $rev = new IDF_WikiRevision();
 | 
			
		||||
        $rev = new IDF_Wiki_PageRevision();
 | 
			
		||||
        $rev->wikipage = $page;
 | 
			
		||||
        $rev->content = $this->cleaned_data['content'];
 | 
			
		||||
        $rev->submitter = $this->user;
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -27,7 +27,7 @@
 | 
			
		||||
 * This is a hard delete of the page and the revisions.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
class IDF_Form_WikiDelete extends Pluf_Form
 | 
			
		||||
class IDF_Form_WikiPageDelete extends Pluf_Form
 | 
			
		||||
{
 | 
			
		||||
    protected $page = null;
 | 
			
		||||
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -27,13 +27,13 @@
 | 
			
		||||
 * This add a corresponding revision.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
class IDF_Form_WikiUpdate extends Pluf_Form
 | 
			
		||||
class IDF_Form_WikiPageUpdate extends Pluf_Form
 | 
			
		||||
{
 | 
			
		||||
    public $user = null;
 | 
			
		||||
    public $project = null;
 | 
			
		||||
    public $page = null;
 | 
			
		||||
    public $show_full = false;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function initFields($extra=array())
 | 
			
		||||
    {
 | 
			
		||||
@@ -118,9 +118,9 @@ class IDF_Form_WikiUpdate extends Pluf_Form
 | 
			
		||||
        if (preg_match('/[^a-zA-Z0-9\-]/', $title)) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('The title contains invalid characters.'));
 | 
			
		||||
        }
 | 
			
		||||
        $sql = new Pluf_SQL('project=%s AND title=%s', 
 | 
			
		||||
        $sql = new Pluf_SQL('project=%s AND title=%s',
 | 
			
		||||
                            array($this->project->id, $title));
 | 
			
		||||
        $pages = Pluf::factory('IDF_WikiPage')->getList(array('filter'=>$sql->gen()));
 | 
			
		||||
        $pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen()));
 | 
			
		||||
        if ($pages->count() > 0 and $pages[0]->id != $this->page->id) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('A page with this title already exists.'));
 | 
			
		||||
        }
 | 
			
		||||
@@ -148,7 +148,7 @@ class IDF_Form_WikiUpdate extends Pluf_Form
 | 
			
		||||
            $this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]);
 | 
			
		||||
            if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
 | 
			
		||||
                list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
 | 
			
		||||
                list($class, $name) = array(mb_strtolower(trim($class)), 
 | 
			
		||||
                list($class, $name) = array(mb_strtolower(trim($class)),
 | 
			
		||||
                                            trim($name));
 | 
			
		||||
            } else {
 | 
			
		||||
                $class = 'other';
 | 
			
		||||
@@ -158,7 +158,7 @@ class IDF_Form_WikiUpdate extends Pluf_Form
 | 
			
		||||
            else $count[$class] += 1;
 | 
			
		||||
            if (in_array($class, $onemax) and $count[$class] > 1) {
 | 
			
		||||
                if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array();
 | 
			
		||||
                $this->errors['label'.$i][] = sprintf(__('You cannot provide more than label from the %s class to a page.'), $class);
 | 
			
		||||
                $this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to a page.'), $class);
 | 
			
		||||
                throw new Pluf_Form_Invalid(__('You provided an invalid label.'));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -229,7 +229,7 @@ class IDF_Form_WikiUpdate extends Pluf_Form
 | 
			
		||||
        }
 | 
			
		||||
        $this->page->update();
 | 
			
		||||
        // add the new revision
 | 
			
		||||
        $rev = new IDF_WikiRevision();
 | 
			
		||||
        $rev = new IDF_Wiki_PageRevision();
 | 
			
		||||
        $rev->wikipage = $this->page;
 | 
			
		||||
        $rev->content = $this->cleaned_data['content'];
 | 
			
		||||
        $rev->submitter = $this->user;
 | 
			
		||||
							
								
								
									
										169
									
								
								src/IDF/Form/WikiResourceCreate.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								src/IDF/Form/WikiResourceCreate.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,169 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Create a new resource.
 | 
			
		||||
 *
 | 
			
		||||
 * This create a new resource and the corresponding revision.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
class IDF_Form_WikiResourceCreate extends Pluf_Form
 | 
			
		||||
{
 | 
			
		||||
    public $user = null;
 | 
			
		||||
    public $project = null;
 | 
			
		||||
    public $show_full = false;
 | 
			
		||||
 | 
			
		||||
    public function initFields($extra=array())
 | 
			
		||||
    {
 | 
			
		||||
        $this->project = $extra['project'];
 | 
			
		||||
        $this->user = $extra['user'];
 | 
			
		||||
        $initname = (!empty($extra['name'])) ? $extra['name'] : __('ResourceName');
 | 
			
		||||
 | 
			
		||||
        $this->fields['title'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                      array('required' => true,
 | 
			
		||||
                                            'label' => __('Resource title'),
 | 
			
		||||
                                            'initial' => $initname,
 | 
			
		||||
                                            'widget_attrs' => array(
 | 
			
		||||
                                                       'maxlength' => 200,
 | 
			
		||||
                                                       'size' => 67,
 | 
			
		||||
                                                                    ),
 | 
			
		||||
                                            'help_text' => __('The resource name must contains only letters, digits and the dash (-) character.'),
 | 
			
		||||
                                            ));
 | 
			
		||||
        $this->fields['summary'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                      array('required' => true,
 | 
			
		||||
                                            'label' => __('Description'),
 | 
			
		||||
                                            'help_text' => __('This one line description is displayed in the list of resources.'),
 | 
			
		||||
                                            'initial' => '',
 | 
			
		||||
                                            'widget_attrs' => array(
 | 
			
		||||
                                                       'maxlength' => 200,
 | 
			
		||||
                                                       'size' => 67,
 | 
			
		||||
                                                                    ),
 | 
			
		||||
                                            ));
 | 
			
		||||
 | 
			
		||||
        $this->fields['file'] = new Pluf_Form_Field_File(
 | 
			
		||||
                                     array('required' => true,
 | 
			
		||||
                                           'label' => __('File'),
 | 
			
		||||
                                           'initial' => '',
 | 
			
		||||
                                           'max_size' => Pluf::f('max_upload_size', 2097152),
 | 
			
		||||
                                           'move_function_params' => array('upload_path' => $this->getTempUploadPath(),
 | 
			
		||||
                                           'upload_path_create' => true,
 | 
			
		||||
                                           'upload_overwrite' => true),
 | 
			
		||||
                                           ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function clean_title()
 | 
			
		||||
    {
 | 
			
		||||
        $title = $this->cleaned_data['title'];
 | 
			
		||||
        if (preg_match('/[^a-zA-Z0-9\-]/', $title)) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('The title contains invalid characters.'));
 | 
			
		||||
        }
 | 
			
		||||
        $sql = new Pluf_SQL('project=%s AND title=%s',
 | 
			
		||||
                            array($this->project->id, $title));
 | 
			
		||||
        $resources = Pluf::factory('IDF_Wiki_Resource')->getList(array('filter'=>$sql->gen()));
 | 
			
		||||
        if ($resources->count() > 0) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('A resource with this title already exists.'));
 | 
			
		||||
        }
 | 
			
		||||
        return $title;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function clean_file()
 | 
			
		||||
    {
 | 
			
		||||
        // FIXME: we do the same in IDF_Form_Upload and a couple of other places as well
 | 
			
		||||
        $extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext'))));
 | 
			
		||||
        if (strlen($extra)) $extra .= '|';
 | 
			
		||||
        if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|jar|mdtext|mid|mov|mp3|mpg|ogg|pdf|ppt|ps|qt|ra|ram|rm|rtf|sdd|sdw|sit|sxi|sxw|swf|tgz|txt|wav|xls|xml|war|wmv|zip)$/i', $this->cleaned_data['file'])) {
 | 
			
		||||
            @unlink($this->getTempUploadPath().$this->cleaned_data['file']);
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('For security reasons, you cannot upload a file with this extension.'));
 | 
			
		||||
        }
 | 
			
		||||
        return $this->cleaned_data['file'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * If we have uploaded a file, but the form failed remove it.
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    function failed()
 | 
			
		||||
    {
 | 
			
		||||
        if (!empty($this->cleaned_data['file'])
 | 
			
		||||
            and file_exists($this->getTempUploadPath().$this->cleaned_data['file'])) {
 | 
			
		||||
            @unlink($this->getTempUploadPath().$this->cleaned_data['file']);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Save the model in the database.
 | 
			
		||||
     *
 | 
			
		||||
     * @param bool Commit in the database or not. If not, the object
 | 
			
		||||
     *             is returned but not saved in the database.
 | 
			
		||||
     * @return Object Model with data set from the form.
 | 
			
		||||
     */
 | 
			
		||||
    function save($commit=true)
 | 
			
		||||
    {
 | 
			
		||||
        if (!$this->isValid()) {
 | 
			
		||||
            throw new Exception(__('Cannot save the model from an invalid form.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $tempFile = $this->getTempUploadPath().$this->cleaned_data['file'];
 | 
			
		||||
        list($mimeType, , $extension) = IDF_FileUtil::getMimeType($tempFile);
 | 
			
		||||
 | 
			
		||||
        // create the resource
 | 
			
		||||
        $resource = new IDF_Wiki_Resource();
 | 
			
		||||
        $resource->project = $this->project;
 | 
			
		||||
        $resource->submitter = $this->user;
 | 
			
		||||
        $resource->summary = trim($this->cleaned_data['summary']);
 | 
			
		||||
        $resource->title = trim($this->cleaned_data['title']);
 | 
			
		||||
        $resource->mime_type = $mimeType;
 | 
			
		||||
        $resource->create();
 | 
			
		||||
 | 
			
		||||
        // add the first revision
 | 
			
		||||
        $rev = new IDF_Wiki_ResourceRevision();
 | 
			
		||||
        $rev->wikiresource = $resource;
 | 
			
		||||
        $rev->submitter = $this->user;
 | 
			
		||||
        $rev->summary = __('Initial resource creation');
 | 
			
		||||
        $rev->filesize = filesize($tempFile);
 | 
			
		||||
        $rev->fileext = $extension;
 | 
			
		||||
        $rev->create();
 | 
			
		||||
 | 
			
		||||
        $finalFile = $rev->getFilePath();
 | 
			
		||||
        if (!@mkdir(dirname($finalFile), 0755, true)) {
 | 
			
		||||
            @unlink($tempFile);
 | 
			
		||||
            $rev->delete();
 | 
			
		||||
            $resource->delete();
 | 
			
		||||
            throw new Exception('could not create final resource path');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!@rename($tempFile, $finalFile)) {
 | 
			
		||||
            @unlink($tempFile);
 | 
			
		||||
            $rev->delete();
 | 
			
		||||
            $resource->delete();
 | 
			
		||||
            throw new Exception('could not move resource to final location');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $resource;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getTempUploadPath()
 | 
			
		||||
    {
 | 
			
		||||
        return Pluf::f('upload_path').'/'.$this->project->shortname.'/wiki/temp/';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										64
									
								
								src/IDF/Form/WikiResourceDelete.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								src/IDF/Form/WikiResourceDelete.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Delete a documentation page.
 | 
			
		||||
 *
 | 
			
		||||
 * This is a hard delete of the page and the revisions.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
class IDF_Form_WikiResourceDelete extends Pluf_Form
 | 
			
		||||
{
 | 
			
		||||
    protected $resource = null;
 | 
			
		||||
 | 
			
		||||
    public function initFields($extra=array())
 | 
			
		||||
    {
 | 
			
		||||
        $this->resource = $extra['resource'];
 | 
			
		||||
        $this->fields['confirm'] = new Pluf_Form_Field_Boolean(
 | 
			
		||||
                                      array('required' => true,
 | 
			
		||||
                                            'label' => __('Yes, I understand that the resource and all its revisions will be deleted.'),
 | 
			
		||||
                                            'initial' => '',
 | 
			
		||||
                                            ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check the confirmation.
 | 
			
		||||
     */
 | 
			
		||||
    public function clean_confirm()
 | 
			
		||||
    {
 | 
			
		||||
        if (!$this->cleaned_data['confirm']) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('You need to confirm the deletion.'));
 | 
			
		||||
        }
 | 
			
		||||
        return $this->cleaned_data['confirm'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function save($commit=true)
 | 
			
		||||
    {
 | 
			
		||||
        if (!$this->isValid()) {
 | 
			
		||||
            throw new Exception(__('Cannot save the model from an invalid form.'));
 | 
			
		||||
        }
 | 
			
		||||
        $this->resource->delete();
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										161
									
								
								src/IDF/Form/WikiResourceUpdate.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								src/IDF/Form/WikiResourceUpdate.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,161 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Update a documentation page.
 | 
			
		||||
 *
 | 
			
		||||
 * This add a corresponding revision.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
class IDF_Form_WikiResourceUpdate extends Pluf_Form
 | 
			
		||||
{
 | 
			
		||||
    public $user = null;
 | 
			
		||||
    public $project = null;
 | 
			
		||||
    public $page = null;
 | 
			
		||||
    public $show_full = false;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function initFields($extra=array())
 | 
			
		||||
    {
 | 
			
		||||
        $this->resource = $extra['resource'];
 | 
			
		||||
        $this->user = $extra['user'];
 | 
			
		||||
        $this->project = $extra['project'];
 | 
			
		||||
 | 
			
		||||
        $this->fields['summary'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                      array('required' => true,
 | 
			
		||||
                                        'label' => __('Description'),
 | 
			
		||||
                                        'help_text' => __('This one line description is displayed in the list of resources.'),
 | 
			
		||||
                                        'initial' => $this->resource->summary,
 | 
			
		||||
                                        'widget_attrs' => array(
 | 
			
		||||
                                                   'maxlength' => 200,
 | 
			
		||||
                                                   'size' => 67,
 | 
			
		||||
                                                                ),
 | 
			
		||||
                                        ));
 | 
			
		||||
        $this->fields['file'] = new Pluf_Form_Field_File(
 | 
			
		||||
                                      array('required' => true,
 | 
			
		||||
                                            'label' => __('File'),
 | 
			
		||||
                                            'initial' => '',
 | 
			
		||||
                                            'max_size' => Pluf::f('max_upload_size', 2097152),
 | 
			
		||||
                                            'move_function_params' => array('upload_path' => $this->getTempUploadPath(),
 | 
			
		||||
                                            'upload_path_create' => true,
 | 
			
		||||
                                            'upload_overwrite' => true),
 | 
			
		||||
                                            ));
 | 
			
		||||
 | 
			
		||||
        $this->fields['comment'] = new Pluf_Form_Field_Varchar(
 | 
			
		||||
                                      array('required' => true,
 | 
			
		||||
                                            'label' => __('Comment'),
 | 
			
		||||
                                            'help_text' => __('One line to describe the changes you made.'),
 | 
			
		||||
                                            'initial' => '',
 | 
			
		||||
                                            'widget_attrs' => array(
 | 
			
		||||
                                                       'maxlength' => 200,
 | 
			
		||||
                                                       'size' => 67,
 | 
			
		||||
                                                                    ),
 | 
			
		||||
                                            ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function clean_file()
 | 
			
		||||
    {
 | 
			
		||||
        // FIXME: we do the same in IDF_Form_Upload and a couple of other places as well
 | 
			
		||||
        $extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext'))));
 | 
			
		||||
        if (strlen($extra)) $extra .= '|';
 | 
			
		||||
        if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|jar|mdtext|mid|mov|mp3|mpg|ogg|pdf|ppt|ps|qt|ra|ram|rm|rtf|sdd|sdw|sit|sxi|sxw|swf|tgz|txt|wav|xls|xml|war|wmv|zip)$/i', $this->cleaned_data['file'])) {
 | 
			
		||||
            @unlink($this->getTempUploadPath().$this->cleaned_data['file']);
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('For security reasons, you cannot upload a file with this extension.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        list($mimeType, , $extension) = IDF_FileUtil::getMimeType($this->getTempUploadPath().$this->cleaned_data['file']);
 | 
			
		||||
        if ($this->resource->mime_type != $mimeType) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(sprintf(
 | 
			
		||||
                __('The mime type of the uploaded file "%1$s" does not match the mime type of this resource "%2$s"'),
 | 
			
		||||
                $mimeType, $this->resource->mime_type
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
        $this->cleaned_data['fileext'] = $extension;
 | 
			
		||||
 | 
			
		||||
        if (md5_file($this->getTempUploadPath().$this->cleaned_data['file']) ===
 | 
			
		||||
            md5_file($this->resource->get_current_revision()->getFilePath())) {
 | 
			
		||||
            throw new Pluf_Form_Invalid(__('The current version of the resource and the uploaded file are equal.'));
 | 
			
		||||
        }
 | 
			
		||||
        return $this->cleaned_data['file'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * If we have uploaded a file, but the form failed remove it.
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    function failed()
 | 
			
		||||
    {
 | 
			
		||||
        if (!empty($this->cleaned_data['file'])
 | 
			
		||||
            and file_exists($this->getTempUploadPath().$this->cleaned_data['file'])) {
 | 
			
		||||
            @unlink($this->getTempUploadPath().$this->cleaned_data['file']);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Save the model in the database.
 | 
			
		||||
     *
 | 
			
		||||
     * @param bool Commit in the database or not. If not, the object
 | 
			
		||||
     *             is returned but not saved in the database.
 | 
			
		||||
     * @return Object Model with data set from the form.
 | 
			
		||||
     */
 | 
			
		||||
    function save($commit=true)
 | 
			
		||||
    {
 | 
			
		||||
        if (!$this->isValid()) {
 | 
			
		||||
            throw new Exception(__('Cannot save the model from an invalid form.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $tempFile = $this->getTempUploadPath().$this->cleaned_data['file'];
 | 
			
		||||
 | 
			
		||||
        $this->resource->summary = trim($this->cleaned_data['summary']);
 | 
			
		||||
        $this->resource->update();
 | 
			
		||||
 | 
			
		||||
        // add the new revision
 | 
			
		||||
        $rev = new IDF_Wiki_ResourceRevision();
 | 
			
		||||
        $rev->wikiresource = $this->resource;
 | 
			
		||||
        $rev->submitter = $this->user;
 | 
			
		||||
        $rev->summary = $this->cleaned_data['comment'];
 | 
			
		||||
        $rev->filesize = filesize($tempFile);
 | 
			
		||||
        $rev->fileext = $this->cleaned_data['fileext'];
 | 
			
		||||
        $rev->create();
 | 
			
		||||
 | 
			
		||||
        $finalFile = $rev->getFilePath();
 | 
			
		||||
        if (!is_dir(dirname($finalFile))) {
 | 
			
		||||
            @unlink($tempFile);
 | 
			
		||||
            $rev->delete();
 | 
			
		||||
            throw new Exception('resource path does not exist');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!@rename($tempFile, $finalFile)) {
 | 
			
		||||
            @unlink($tempFile);
 | 
			
		||||
            $rev->delete();
 | 
			
		||||
            throw new Exception('could not move resource to final location');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->resource;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getTempUploadPath()
 | 
			
		||||
    {
 | 
			
		||||
        return Pluf::f('upload_path').'/'.$this->project->shortname.'/wiki/temp/';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -91,6 +91,13 @@ class IDF_Issue extends Pluf_Model
 | 
			
		||||
                                  'model' => 'IDF_Tag',
 | 
			
		||||
                                  'verbose' => __('labels'),
 | 
			
		||||
                                  ),
 | 
			
		||||
                            'due_dtime' =>
 | 
			
		||||
                            array(
 | 
			
		||||
                                  'type' => 'Pluf_DB_Field_Datetime',
 | 
			
		||||
                                  'blank' => true,
 | 
			
		||||
                                  'is_null' => true,
 | 
			
		||||
                                  'verbose' => __('due date'),
 | 
			
		||||
                                  ),
 | 
			
		||||
                            'status' =>
 | 
			
		||||
                            array(
 | 
			
		||||
                                  'type' => 'Pluf_DB_Field_Foreignkey',
 | 
			
		||||
@@ -149,11 +156,28 @@ class IDF_Issue extends Pluf_Model
 | 
			
		||||
        IDF_Search::remove($this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function restore()
 | 
			
		||||
    {
 | 
			
		||||
        // Note: If a due date has not been set then it should
 | 
			
		||||
        // be set to null and not a useless/confusing date so...
 | 
			
		||||
        if ('0000-00-00 00:00:00' === $this->due_dtime) {
 | 
			
		||||
            $this->due_dtime = null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function preSave($create=false)
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->id == '') {
 | 
			
		||||
            $this->creation_dtime = gmdate('Y-m-d H:i:s');
 | 
			
		||||
        }
 | 
			
		||||
        // Note: If a due date is supplied then it must have
 | 
			
		||||
        // a time appended to it so that calculations of when
 | 
			
		||||
        // an issue falls overdue are accurate. In this case
 | 
			
		||||
        // 23:59:59 is added to signify the end of the day.
 | 
			
		||||
        if ($this->due_dtime and !empty($this->due_dtime)) {
 | 
			
		||||
            $this->due_dtime = date('Y-m-d 23:59:59',
 | 
			
		||||
                strtotime($this->due_dtime));
 | 
			
		||||
        }
 | 
			
		||||
        $this->modif_dtime = gmdate('Y-m-d H:i:s');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -169,6 +193,24 @@ class IDF_Issue extends Pluf_Model
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getGroupedRelatedIssues($opts = array(), $idsOnly = false)
 | 
			
		||||
    {
 | 
			
		||||
        $rels = $this->get_related_issues_list(array_merge($opts, array(
 | 
			
		||||
               'view' => 'with_other_issue',
 | 
			
		||||
        )));
 | 
			
		||||
 | 
			
		||||
        $res = array();
 | 
			
		||||
        foreach ($rels as $rel) {
 | 
			
		||||
            $verb = $rel->verb;
 | 
			
		||||
            if (!array_key_exists($verb, $res)) {
 | 
			
		||||
                $res[$verb] = array();
 | 
			
		||||
            }
 | 
			
		||||
            $res[$verb][] = $idsOnly ? $rel->other_issue : $rel;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $res;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns an HTML fragment used to display this issue in the
 | 
			
		||||
     * timeline.
 | 
			
		||||
@@ -193,7 +235,7 @@ class IDF_Issue extends Pluf_Model
 | 
			
		||||
        $ic = (in_array($this->status, $request->project->getTagIdsByStatus('closed'))) ? 'issue-c' : 'issue-o';
 | 
			
		||||
        $out .= sprintf(__('<a href="%1$s" class="%2$s" title="View issue">Issue %3$d</a>, %4$s'), $url, $ic, $this->id, Pluf_esc($this->summary)).'</td>';
 | 
			
		||||
        $out .= "\n".'<tr class="extra"><td colspan="2">
 | 
			
		||||
<div class="helptext right">'.sprintf(__('Creation of <a href="%s" class="%s">issue %d</a>, by %s'), $url, $ic, $this->id, $user).'</div></td></tr>';
 | 
			
		||||
<div class="helptext right">'.sprintf(__('Creation of <a href="%1$s" class="%2$s">issue %3$d</a>, by %4$s'), $url, $ic, $this->id, $user).'</div></td></tr>';
 | 
			
		||||
        return Pluf_Template::markSafe($out);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -203,7 +245,7 @@ class IDF_Issue extends Pluf_Model
 | 
			
		||||
            .Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
 | 
			
		||||
                                      array($request->project->shortname,
 | 
			
		||||
                                            $this->id));
 | 
			
		||||
        $title = sprintf(__('%s: Issue %d created - %s'),
 | 
			
		||||
        $title = sprintf(__('%1$s: Issue %2$d created - %3$s'),
 | 
			
		||||
                         $request->project->name,
 | 
			
		||||
                         $this->id, $this->summary);
 | 
			
		||||
        $cts = $this->get_comments_list(array('order' => 'id ASC',
 | 
			
		||||
@@ -238,91 +280,72 @@ class IDF_Issue extends Pluf_Model
 | 
			
		||||
     */
 | 
			
		||||
    public function notify($conf, $create=true)
 | 
			
		||||
    {
 | 
			
		||||
        $prj = $this->get_project();
 | 
			
		||||
        $to_email = array();
 | 
			
		||||
        if ('' != $conf->getVal('issues_notification_email', '')) {
 | 
			
		||||
            $langs     = Pluf::f('languages', array('en'));
 | 
			
		||||
            $addresses = explode(',', $conf->getVal('issues_notification_email'));
 | 
			
		||||
            foreach ($addresses as $address) {
 | 
			
		||||
                $to_email[] = array($address, $langs[0]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        $project = $this->get_project();
 | 
			
		||||
        $current_locale = Pluf_Translation::getLocale();
 | 
			
		||||
        $id = '<'.md5($this->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>';
 | 
			
		||||
        if ($create) {
 | 
			
		||||
            if (null != $this->get_owner() and $this->owner != $this->submitter) {
 | 
			
		||||
                $email_lang = array($this->get_owner()->email,
 | 
			
		||||
                                    $this->get_owner()->language);
 | 
			
		||||
                if (!in_array($email_lang, $to_email)) {
 | 
			
		||||
                    $to_email[] = $email_lang;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            $comments = $this->get_comments_list(array('order' => 'id ASC'));
 | 
			
		||||
            $context = new Pluf_Template_Context(
 | 
			
		||||
                                   array(
 | 
			
		||||
                                         'issue' => $this,
 | 
			
		||||
                                         'comment' => $comments[0],
 | 
			
		||||
                                         'project' => $prj,
 | 
			
		||||
                                         'url_base' => Pluf::f('url_base'),
 | 
			
		||||
                                         )
 | 
			
		||||
                                                 );
 | 
			
		||||
            foreach ($to_email as $email_lang) {
 | 
			
		||||
                Pluf_Translation::loadSetLocale($email_lang[1]);
 | 
			
		||||
                $email = new Pluf_Mail(Pluf::f('from_email'), $email_lang[0],
 | 
			
		||||
                                       sprintf(__('Issue %s - %s (%s)'),
 | 
			
		||||
                                               $this->id, $this->summary, $prj->shortname));
 | 
			
		||||
                $tmpl = new Pluf_Template('idf/issues/issue-created-email.txt');
 | 
			
		||||
                $email->addTextMessage($tmpl->render($context));
 | 
			
		||||
                $email->addHeaders(array('Message-ID'=>$id));
 | 
			
		||||
                $email->sendMail();
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            $comments = $this->get_comments_list(array('order' => 'id DESC'));
 | 
			
		||||
            $email_sender = '';
 | 
			
		||||
            if (isset($comments[0])) {
 | 
			
		||||
                $email_sender = $comments[0]->get_submitter()->email;
 | 
			
		||||
            }
 | 
			
		||||
            foreach ($this->get_interested_list() as $interested) {
 | 
			
		||||
                $email_lang = array($interested->email,
 | 
			
		||||
                                    $interested->language);
 | 
			
		||||
                if (!in_array($email_lang, $to_email)) {
 | 
			
		||||
                    $to_email[] = $email_lang;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            $email_lang = array($this->get_submitter()->email,
 | 
			
		||||
                                $this->get_submitter()->language);
 | 
			
		||||
            if (!in_array($email_lang, $to_email)) {
 | 
			
		||||
                $to_email[] = $email_lang;
 | 
			
		||||
            }
 | 
			
		||||
            if (null != $this->get_owner()) {
 | 
			
		||||
                $email_lang = array($this->get_owner()->email,
 | 
			
		||||
                                    $this->get_owner()->language);
 | 
			
		||||
                if (!in_array($email_lang, $to_email)) {
 | 
			
		||||
                    $to_email[] = $email_lang;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            $context = new Pluf_Template_Context(
 | 
			
		||||
                            array(
 | 
			
		||||
                                  'issue' => $this,
 | 
			
		||||
                                  'comments' => $comments,
 | 
			
		||||
                                  'project' => $prj,
 | 
			
		||||
                                  'url_base' => Pluf::f('url_base'),
 | 
			
		||||
                                  ));
 | 
			
		||||
            foreach ($to_email as $email_lang) {
 | 
			
		||||
                if ($email_lang[0] == $email_sender) {
 | 
			
		||||
                    continue; // Do not notify the one having created
 | 
			
		||||
                              // the comment
 | 
			
		||||
                }
 | 
			
		||||
                Pluf_Translation::loadSetLocale($email_lang[1]);
 | 
			
		||||
                $email = new Pluf_Mail(Pluf::f('from_email'), $email_lang[0],
 | 
			
		||||
                                       sprintf(__('Updated Issue %s - %s (%s)'),
 | 
			
		||||
                                               $this->id, $this->summary, $prj->shortname));
 | 
			
		||||
                $tmpl = new Pluf_Template('idf/issues/issue-updated-email.txt');
 | 
			
		||||
                $email->addTextMessage($tmpl->render($context));
 | 
			
		||||
                $email->addHeaders(array('References'=>$id));
 | 
			
		||||
                $email->sendMail();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        $from_email = Pluf::f('from_email');
 | 
			
		||||
        $comments   = $this->get_comments_list(array('order' => 'id DESC'));
 | 
			
		||||
        $messageId  = '<'.md5('issue'.$this->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>';
 | 
			
		||||
        $recipients = $project->getNotificationRecipientsForTab('issues');
 | 
			
		||||
 | 
			
		||||
        // the submitter (might be skipped later on if he is the one who also
 | 
			
		||||
        // submitted the last comment)
 | 
			
		||||
        if (!array_key_exists($this->get_submitter()->email, $recipients)) {
 | 
			
		||||
            $recipients[$this->get_submitter()->email] = $this->get_submitter()->language;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // the owner of the issue, if we have one
 | 
			
		||||
        $owner = $this->get_owner();
 | 
			
		||||
        if (null != $owner && !array_key_exists($owner->email, $recipients)) {
 | 
			
		||||
            $recipients[$owner->email] = $owner->language;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // additional users who starred the issue
 | 
			
		||||
        foreach ($this->get_interested_list() as $interested) {
 | 
			
		||||
            if (array_key_exists($interested->email, $recipients))
 | 
			
		||||
                continue;
 | 
			
		||||
            $recipients[$interested->email] = $interested->language;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ($recipients as $address => $language) {
 | 
			
		||||
 | 
			
		||||
            // do not notify the creator of the last comment,
 | 
			
		||||
            // i.e. the user who triggered this notification
 | 
			
		||||
            if ($comments[0]->get_submitter()->email === $address) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Pluf_Translation::loadSetLocale($language);
 | 
			
		||||
 | 
			
		||||
            $context = new Pluf_Template_Context(array(
 | 
			
		||||
                'issue'      => $this,
 | 
			
		||||
                'owns_issue' => $owner !== null && $owner->email === $address,
 | 
			
		||||
                // the initial comment for create, the last for update
 | 
			
		||||
                'comment'    => $comments[0],
 | 
			
		||||
                'comments'   => $comments,
 | 
			
		||||
                'project'    => $project,
 | 
			
		||||
                'url_base'   => Pluf::f('url_base'),
 | 
			
		||||
            ));
 | 
			
		||||
 | 
			
		||||
            $tplfile = 'idf/issues/issue-created-email.txt';
 | 
			
		||||
            $subject = __('Issue %1$s - %2$s (%3$s)');
 | 
			
		||||
            $headers = array('Message-ID' => $messageId);
 | 
			
		||||
            if (!$create) {
 | 
			
		||||
                $tplfile = 'idf/issues/issue-updated-email.txt';
 | 
			
		||||
                $subject = __('Updated Issue %1$s - %2$s (%3$s)');
 | 
			
		||||
                $headers = array('References' => $messageId);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $tmpl = new Pluf_Template($tplfile);
 | 
			
		||||
            $text_email = $tmpl->render($context);
 | 
			
		||||
 | 
			
		||||
            $email = new Pluf_Mail($from_email, $address,
 | 
			
		||||
                                   sprintf($subject, $this->id, $this->summary, $project->shortname));
 | 
			
		||||
            $email->addTextMessage($text_email);
 | 
			
		||||
            $email->addHeaders($headers);
 | 
			
		||||
            $email->sendMail();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Pluf_Translation::loadSetLocale($current_locale);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -153,12 +153,23 @@ class IDF_IssueComment extends Pluf_Model
 | 
			
		||||
                    $out .= __('Status:'); break;
 | 
			
		||||
                case 'ow':
 | 
			
		||||
                    $out .= __('Owner:'); break;
 | 
			
		||||
                case 'du':
 | 
			
		||||
                    $out .= __('Due date:'); break;
 | 
			
		||||
                case 'lb':
 | 
			
		||||
                    $out .= __('Labels:'); break;
 | 
			
		||||
                case 'rel':
 | 
			
		||||
                    $out .= __('Relations:'); break;
 | 
			
		||||
                }
 | 
			
		||||
                $out .= '</strong> ';
 | 
			
		||||
                if ($w == 'lb') {
 | 
			
		||||
                    $out .= Pluf_esc(implode(', ', $v));
 | 
			
		||||
                if ($w == 'lb' || $w == 'rel') {
 | 
			
		||||
                    foreach ($v as $t => $ls) {
 | 
			
		||||
                        foreach ($ls as $l) {
 | 
			
		||||
                            if ($t == 'rem') $out .= '<s>';
 | 
			
		||||
                            $out .= Pluf_esc($l);
 | 
			
		||||
                            if ($t == 'rem') $out .= '</s>';
 | 
			
		||||
                            $out .= ' ';
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    $out .= Pluf_esc($v);
 | 
			
		||||
                }
 | 
			
		||||
@@ -168,7 +179,7 @@ class IDF_IssueComment extends Pluf_Model
 | 
			
		||||
        }
 | 
			
		||||
        $out .= '</td></tr>';
 | 
			
		||||
        $out .= "\n".'<tr class="extra"><td colspan="2">
 | 
			
		||||
<div class="helptext right">'.sprintf(__('Comment on <a href="%s" class="%s">issue %d</a>, by %s'), $url, $ic, $issue->id, $user).'</div></td></tr>';
 | 
			
		||||
<div class="helptext right">'.sprintf(__('Comment on <a href="%1$s" class="%2$s">issue %3$d</a>, by %4$s'), $url, $ic, $issue->id, $user).'</div></td></tr>';
 | 
			
		||||
        return Pluf_Template::markSafe($out);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -179,7 +190,7 @@ class IDF_IssueComment extends Pluf_Model
 | 
			
		||||
            .Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
 | 
			
		||||
                                      array($request->project->shortname,
 | 
			
		||||
                                            $issue->id));
 | 
			
		||||
        $title = sprintf(__('%s: Comment on issue %d - %s'),
 | 
			
		||||
        $title = sprintf(__('%1$s: Comment on issue %2$d - %3$s'),
 | 
			
		||||
                         Pluf_esc($request->project->name),
 | 
			
		||||
                         $issue->id, Pluf_esc($issue->summary));
 | 
			
		||||
        $url .= '#ic'.$this->id;
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										100
									
								
								src/IDF/IssueRelation.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/IDF/IssueRelation.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A relation of one issue to another
 | 
			
		||||
 */
 | 
			
		||||
class IDF_IssueRelation extends Pluf_Model
 | 
			
		||||
{
 | 
			
		||||
    public $_model = __CLASS__;
 | 
			
		||||
 | 
			
		||||
    function init()
 | 
			
		||||
    {
 | 
			
		||||
        $this->_a['table'] = 'idf_issuerelations';
 | 
			
		||||
        $this->_a['model'] = __CLASS__;
 | 
			
		||||
        $this->_a['cols'] = array(
 | 
			
		||||
                             // It is mandatory to have an "id" column.
 | 
			
		||||
                            'id' =>
 | 
			
		||||
                            array(
 | 
			
		||||
                                  'type' => 'Pluf_DB_Field_Sequence',
 | 
			
		||||
                                  'blank' => true,
 | 
			
		||||
                                  ),
 | 
			
		||||
                            'issue' =>
 | 
			
		||||
                            array(
 | 
			
		||||
                                  'type' => 'Pluf_DB_Field_Foreignkey',
 | 
			
		||||
                                  'model' => 'IDF_Issue',
 | 
			
		||||
                                  'blank' => false,
 | 
			
		||||
                                  'verbose' => __('issue'),
 | 
			
		||||
                                  'relate_name' => 'related_issues',
 | 
			
		||||
                                  ),
 | 
			
		||||
                            'verb' =>
 | 
			
		||||
                            array(
 | 
			
		||||
                                  'type' => 'Pluf_DB_Field_Text',
 | 
			
		||||
                                  'blank' => false,
 | 
			
		||||
                                  'verbose' => __('verb'),
 | 
			
		||||
                                  ),
 | 
			
		||||
                            'other_issue' =>
 | 
			
		||||
                            array(
 | 
			
		||||
                                  'type' => 'Pluf_DB_Field_Foreignkey',
 | 
			
		||||
                                  'model' => 'IDF_Issue',
 | 
			
		||||
                                  'blank' => false,
 | 
			
		||||
                                  'verbose' => __('other issue'),
 | 
			
		||||
                                  'relate_name' => 'related_other_issues',
 | 
			
		||||
                                  ),
 | 
			
		||||
                            'submitter' =>
 | 
			
		||||
                            array(
 | 
			
		||||
                                  'type' => 'Pluf_DB_Field_Foreignkey',
 | 
			
		||||
                                  'model' => 'Pluf_User',
 | 
			
		||||
                                  'blank' => false,
 | 
			
		||||
                                  'verbose' => __('submitter'),
 | 
			
		||||
                                   ),
 | 
			
		||||
                            'creation_dtime' =>
 | 
			
		||||
                            array(
 | 
			
		||||
                                  'type' => 'Pluf_DB_Field_Datetime',
 | 
			
		||||
                                  'blank' => true,
 | 
			
		||||
                                  'verbose' => __('creation date'),
 | 
			
		||||
                                  ),
 | 
			
		||||
                            );
 | 
			
		||||
        $this->_a['idx'] = array(
 | 
			
		||||
                            'creation_dtime_idx' =>
 | 
			
		||||
                            array(
 | 
			
		||||
                                  'col' => 'creation_dtime',
 | 
			
		||||
                                  'type' => 'normal',
 | 
			
		||||
                                  ),
 | 
			
		||||
                            );
 | 
			
		||||
        $issuetbl = $this->_con->pfx.'idf_issues';
 | 
			
		||||
        $this->_a['views'] = array(
 | 
			
		||||
            'with_other_issue' => array(
 | 
			
		||||
                'join' => 'INNER JOIN '.$issuetbl.' ON other_issue='.$issuetbl.'.id',
 | 
			
		||||
                'select' => $this->getSelect().', summary',
 | 
			
		||||
                'props' => array('summary' => 'other_summary'),
 | 
			
		||||
        ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function preSave($create=false)
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->id == '') {
 | 
			
		||||
            $this->creation_dtime = gmdate('Y-m-d H:i:s');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -80,7 +80,10 @@ class IDF_Key extends Pluf_Model
 | 
			
		||||
        if (preg_match('#^\[pubkey ([^\]]+)\]\s*(\S+)\s*\[end\]$#', $this->content, $m)) {
 | 
			
		||||
            return array('mtn', $m[1], $m[2]);
 | 
			
		||||
        }
 | 
			
		||||
        else if (preg_match('#^ssh\-[a-z]{3}\s(\S+)(?:\s(\S+))?$#', $this->content, $m)) {
 | 
			
		||||
        else if (preg_match('#^ssh\-(?:dss|rsa)\s(\S+)(?:\s(.*))?$#', $this->content, $m)) {
 | 
			
		||||
            if (!isset($m[2])) {
 | 
			
		||||
                $m[2] = "";
 | 
			
		||||
            }
 | 
			
		||||
            return array('ssh', $m[2], $m[1]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -85,8 +85,11 @@ class IDF_Middleware
 | 
			
		||||
                              'issuetext' => 'IDF_Template_IssueComment',
 | 
			
		||||
                              'timeline' => 'IDF_Template_TimelineFragment',
 | 
			
		||||
                              'markdown' => 'IDF_Template_Markdown',
 | 
			
		||||
                              'markdown_forge' => 'IDF_Template_MarkdownForge',
 | 
			
		||||
                              'showuser' => 'IDF_Template_ShowUser',
 | 
			
		||||
                              'ashowuser' => 'IDF_Template_AssignShowUser',
 | 
			
		||||
                              'appversion' => 'IDF_Template_AppVersion',
 | 
			
		||||
                              'upload' => 'IDF_Template_Tag_UploadUrl',
 | 
			
		||||
                                            ));
 | 
			
		||||
        $params['modifiers'] = array_merge($params['modifiers'],
 | 
			
		||||
                                           array(
 | 
			
		||||
@@ -100,6 +103,7 @@ class IDF_Middleware
 | 
			
		||||
 | 
			
		||||
function IDF_Middleware_ContextPreProcessor($request)
 | 
			
		||||
{
 | 
			
		||||
    $forge = IDF_Forge::instance();
 | 
			
		||||
    $c = array();
 | 
			
		||||
    $c['request'] = $request;
 | 
			
		||||
    $c['isAdmin'] = ($request->user->administrator or $request->user->staff);
 | 
			
		||||
@@ -113,6 +117,7 @@ function IDF_Middleware_ContextPreProcessor($request)
 | 
			
		||||
    }
 | 
			
		||||
    $c['usherConfigured'] = Pluf::f("mtn_usher_conf", null) !== null;
 | 
			
		||||
    $c['allProjects'] = IDF_Views::getProjects($request->user);
 | 
			
		||||
    $c['customForgePageEnabled'] = $forge->isCustomForgePageEnabled();
 | 
			
		||||
    return $c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										43
									
								
								src/IDF/Migrations/16AddUserMail.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/IDF/Migrations/16AddUserMail.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add the new IDF_Gconf model.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_16AddUserMail_up($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $schema = new Pluf_DB_Schema($db);
 | 
			
		||||
    $schema->model = new IDF_EmailAddress();
 | 
			
		||||
    $schema->createTables();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_16AddUserMail_down($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $schema = new Pluf_DB_Schema($db);
 | 
			
		||||
    $schema->model = new IDF_EmailAddress();
 | 
			
		||||
    $schema->dropTables();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										90
									
								
								src/IDF/Migrations/17AddIssueRelations.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/IDF/Migrations/17AddIssueRelations.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,90 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add the new IDF_IssueRelation model.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_17AddIssueRelations_up($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $schema = new Pluf_DB_Schema($db);
 | 
			
		||||
    $schema->model = new IDF_IssueRelation();
 | 
			
		||||
    $schema->createTables();
 | 
			
		||||
 | 
			
		||||
    // change the serialization format for added / removed labels in IDF_IssueComment
 | 
			
		||||
    $comments = Pluf::factory('IDF_IssueComment')->getList();
 | 
			
		||||
    foreach ($comments as $comment) {
 | 
			
		||||
        if (!isset($comment->changes['lb'])) continue;
 | 
			
		||||
        $changes = $comment->changes;
 | 
			
		||||
        $adds = $removals = array();
 | 
			
		||||
        foreach ($comment->changes['lb'] as $lb) {
 | 
			
		||||
            if (substr($lb, 0, 1) == '-')
 | 
			
		||||
                $removals[] = substr($lb, 1);
 | 
			
		||||
            else
 | 
			
		||||
                $adds[] = $lb;
 | 
			
		||||
        }
 | 
			
		||||
        $changes['lb'] = array();
 | 
			
		||||
        if (count($adds) > 0)
 | 
			
		||||
            $changes['lb']['add'] = $adds;
 | 
			
		||||
        if (count($removals) > 0)
 | 
			
		||||
            $changes['lb']['rem'] = $removals;
 | 
			
		||||
        $comment->changes = $changes;
 | 
			
		||||
        $comment->update();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_17AddIssueRelations_down($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $schema = new Pluf_DB_Schema($db);
 | 
			
		||||
    $schema->model = new IDF_IssueRelation();
 | 
			
		||||
    $schema->dropTables();
 | 
			
		||||
 | 
			
		||||
    // change the serialization format for added / removed labels in IDF_IssueComment
 | 
			
		||||
    $comments = Pluf::factory('IDF_IssueComment')->getList();
 | 
			
		||||
    foreach ($comments as $comment) {
 | 
			
		||||
        $changes = $comment->changes;
 | 
			
		||||
        if (empty($changes))
 | 
			
		||||
            continue;
 | 
			
		||||
        if (isset($changes['lb'])) {
 | 
			
		||||
            $labels = array();
 | 
			
		||||
            foreach ($changes['lb'] as $type => $lbs) {
 | 
			
		||||
                if (!is_array($lbs)) {
 | 
			
		||||
                    $labels[] = $lbs;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                foreach ($lbs as $lb) {
 | 
			
		||||
                    $labels[] = ($type == 'rem' ? '-' : '') . $lb;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            $changes['lb'] = $labels;
 | 
			
		||||
        }
 | 
			
		||||
        // while we're at it, remove any 'rel' changes
 | 
			
		||||
        unset($changes['rel']);
 | 
			
		||||
        $comment->changes = $changes;
 | 
			
		||||
        $comment->update();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										63
									
								
								src/IDF/Migrations/18DownloadMD5.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/IDF/Migrations/18DownloadMD5.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add the md5 column for the download model.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_18DownloadMD5_up($params=null)
 | 
			
		||||
{
 | 
			
		||||
    // Add the row
 | 
			
		||||
    $table = Pluf::factory('IDF_Upload')->getSqlTable();
 | 
			
		||||
    $sql = array();
 | 
			
		||||
    $sql['PostgreSQL'] = 'ALTER TABLE '.$table.' ADD COLUMN "md5" VARCHAR(32) DEFAULT \'\'';
 | 
			
		||||
    $sql['MySQL'] = 'ALTER TABLE '.$table.' ADD COLUMN `md5` VARCHAR(32) DEFAULT \'\'';
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $engine = Pluf::f('db_engine');
 | 
			
		||||
    if (!isset($sql[$engine])) {
 | 
			
		||||
        throw new Exception('SQLite complex migration not supported.');
 | 
			
		||||
    }
 | 
			
		||||
    $db->execute($sql[$engine]);
 | 
			
		||||
    
 | 
			
		||||
    // Process md5 of already uploaded file
 | 
			
		||||
    $files = Pluf::factory('IDF_Upload')->getList();
 | 
			
		||||
    foreach ($files as $f) {
 | 
			
		||||
        $f->md5 = md5_file (Pluf::f('upload_path') . '/' . $f->get_project()->shortname . '/files/' . $f->file);
 | 
			
		||||
        $f->update();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_18DownloadMD5_down($params=null)
 | 
			
		||||
{
 | 
			
		||||
    // Remove the row
 | 
			
		||||
    $table = Pluf::factory('IDF_Upload')->getSqlTable();
 | 
			
		||||
    $sql = array();
 | 
			
		||||
    $sql['PostgreSQL'] = 'ALTER TABLE '.$table.' DROP COLUMN "md5"';
 | 
			
		||||
    $sql['MySQL'] = 'ALTER TABLE '.$table.' DROP COLUMN `md5`';
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $engine = Pluf::f('db_engine');
 | 
			
		||||
    if (!isset($sql[$engine])) {
 | 
			
		||||
        throw new Exception('SQLite complex migration not supported.');
 | 
			
		||||
    }
 | 
			
		||||
    $db->execute($sql[$engine]);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										74
									
								
								src/IDF/Migrations/19WikiPageAssocs.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/IDF/Migrations/19WikiPageAssocs.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_19WikiPageAssocs_up($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $engine = Pluf::f('db_engine');
 | 
			
		||||
    if (!in_array($engine, array('MySQL', 'PostgreSQL'))) {
 | 
			
		||||
        throw new Exception('unsupported engine '.$engine);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $intro = new Pluf_DB_Introspect($db);
 | 
			
		||||
    if (in_array($db->pfx.'idf_tag_idf_wiki_page_assoc', $intro->listTables())) {
 | 
			
		||||
        echo '19 skipping up migration - relation table has correct name already'."\n";
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wikipage_assoc RENAME TO '.$db->pfx.'idf_tag_idf_wiki_page_assoc');
 | 
			
		||||
    $db->execute('ALTER TABLE '.$db->pfx.'idf_wikipage_pluf_user_assoc RENAME TO '.$db->pfx.'idf_wiki_page_pluf_user_assoc');
 | 
			
		||||
 | 
			
		||||
    if ($engine === 'PostgreSQL') {
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wiki_page_assoc RENAME COLUMN idf_wikipage_id TO idf_wiki_page_id');
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_wiki_page_pluf_user_assoc RENAME COLUMN idf_wikipage_id TO idf_wiki_page_id');
 | 
			
		||||
    } else if ($engine === 'MySQL') {
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wiki_page_assoc CHANGE idf_wikipage_id idf_wiki_page_id MEDIUMINT NOT NULL');
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_wiki_page_pluf_user_assoc CHANGE idf_wikipage_id idf_wiki_page_id MEDIUMINT NOT NULL');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_19WikiPageAssocs_down($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $engine = Pluf::f('db_engine');
 | 
			
		||||
    if (!in_array($engine, array('MySQL', 'PostgreSQL'))) {
 | 
			
		||||
        throw new Exception('unsupported engine '.$engine);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $intro = new Pluf_DB_Introspect($db);
 | 
			
		||||
    if (in_array($db->pfx.'idf_tag_idf_wikipage_assoc', $intro->listTables())) {
 | 
			
		||||
        echo '19 skipping down migration - relation table has correct name already'."\n";
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wiki_page_assoc RENAME TO '.$db->pfx.'idf_tag_idf_wikipage_assoc');
 | 
			
		||||
    $db->execute('ALTER TABLE '.$db->pfx.'idf_wiki_page_pluf_user_assoc RENAME TO '.$db->pfx.'idf_wikipage_pluf_user_assoc');
 | 
			
		||||
 | 
			
		||||
    if ($engine === 'PostgreSQL') {
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wikipage_assoc RENAME COLUMN idf_wiki_page_id TO idf_wikipage_id');
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_wikipage_pluf_user_assoc RENAME COLUMN idf_wiki_page_id TO idf_wikipage_id');
 | 
			
		||||
    } else if ($engine === 'MySQL') {
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wikipage_assoc CHANGE idf_wiki_page_id idf_wikipage_id MEDIUMINT NOT NULL');
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_wikipage_pluf_user_assoc CHANGE idf_wiki_page_id idf_wikipage_id MEDIUMINT NOT NULL');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										51
									
								
								src/IDF/Migrations/20AddWikiResources.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/IDF/Migrations/20AddWikiResources.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add the new IDF_Wiki_Resource and IDF_Wiki_ResourceRevision models.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_20AddWikiResources_up($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $schema = new Pluf_DB_Schema($db);
 | 
			
		||||
 | 
			
		||||
    $schema->model = new IDF_Wiki_Resource();
 | 
			
		||||
    $schema->createTables();
 | 
			
		||||
 | 
			
		||||
    $schema->model = new IDF_Wiki_ResourceRevision();
 | 
			
		||||
    $schema->createTables();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_20AddWikiResources_down($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $schema = new Pluf_DB_Schema($db);
 | 
			
		||||
 | 
			
		||||
    $schema->model = new IDF_Wiki_ResourceRevision();
 | 
			
		||||
    $schema->dropTables();
 | 
			
		||||
 | 
			
		||||
    $schema->model = new IDF_Wiki_Resource();
 | 
			
		||||
    $schema->dropTables();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										68
									
								
								src/IDF/Migrations/21WikiPageRevisionName.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/IDF/Migrations/21WikiPageRevisionName.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_21WikiPageRevisionName_up($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $engine = Pluf::f('db_engine');
 | 
			
		||||
    if (!in_array($engine, array('MySQL', 'PostgreSQL'))) {
 | 
			
		||||
        throw new Exception('unsupported engine '.$engine);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $intro = new Pluf_DB_Introspect($db);
 | 
			
		||||
    if (in_array($db->pfx.'idf_wikipagerevs', $intro->listTables())) {
 | 
			
		||||
        echo '21 skipping up migration - table has correct name already'."\n";
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $db->execute('ALTER TABLE '.$db->pfx.'idf_wikirevisions RENAME TO '.$db->pfx.'idf_wikipagerevs');
 | 
			
		||||
    $db->execute("UPDATE ".$db->pfx."idf_timeline SET model_class='IDF_Wiki_Page' WHERE model_class LIKE 'IDF_WikiPage'");
 | 
			
		||||
    $db->execute("UPDATE ".$db->pfx."idf_timeline SET model_class='IDF_Wiki_PageRevision' WHERE model_class LIKE 'IDF_WikiRevision'");
 | 
			
		||||
    $db->execute("UPDATE ".$db->pfx."idf_search_occs SET model_class='IDF_Wiki_Page' WHERE model_class LIKE 'IDF_WikiPage'");
 | 
			
		||||
    $db->execute("UPDATE ".$db->pfx."idf_search_occs SET model_class='IDF_Wiki_PageRevision' WHERE model_class LIKE 'IDF_WikiRevision'");
 | 
			
		||||
    $db->execute("UPDATE ".$db->pfx."pluf_search_stats SET model_class='IDF_Wiki_Page' WHERE model_class LIKE 'IDF_WikiPage'");
 | 
			
		||||
    $db->execute("UPDATE ".$db->pfx."pluf_search_stats SET model_class='IDF_Wiki_PageRevision' WHERE model_class LIKE 'IDF_WikiRevision'");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_21WikiPageRevisionName_down($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $engine = Pluf::f('db_engine');
 | 
			
		||||
    if (!in_array($engine, array('MySQL', 'PostgreSQL'))) {
 | 
			
		||||
        throw new Exception('unsupported engine '.$engine);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $intro = new Pluf_DB_Introspect($db);
 | 
			
		||||
    if (in_array($db->pfx.'idf_wikirevisions', $intro->listTables())) {
 | 
			
		||||
        echo '21 skipping down migration - table has correct name already'."\n";
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $db->execute('ALTER TABLE '.$db->pfx.'idf_wikipagerevs RENAME TO '.$db->pfx.'idf_wikirevisions');
 | 
			
		||||
    $db->execute("UPDATE ".$db->pfx."idf_timeline SET model_class='IDF_WikiPage' WHERE model_class LIKE 'IDF_Wiki_Page'");
 | 
			
		||||
    $db->execute("UPDATE ".$db->pfx."idf_timeline SET model_class='IDF_WikiRevision' WHERE model_class LIKE 'IDF_Wiki_PageRevision'");
 | 
			
		||||
    $db->execute("UPDATE ".$db->pfx."idf_search_occs SET model_class='IDF_WikiPage' WHERE model_class LIKE 'IDF_Wiki_Page'");
 | 
			
		||||
    $db->execute("UPDATE ".$db->pfx."idf_search_occs SET model_class='IDF_WikiRevision' WHERE model_class LIKE 'IDF_Wiki_PageRevision'");
 | 
			
		||||
    $db->execute("UPDATE ".$db->pfx."pluf_search_stats SET model_class='IDF_WikiPage' WHERE model_class LIKE 'IDF_Wiki_Page'");
 | 
			
		||||
    $db->execute("UPDATE ".$db->pfx."pluf_search_stats SET model_class='IDF_WikiRevision' WHERE model_class LIKE 'IDF_Wiki_PageRevision'");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										60
									
								
								src/IDF/Migrations/22ProjectTagRelationTable.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/IDF/Migrations/22ProjectTagRelationTable.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_22ProjectTagRelationTable_up($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $table = $db->pfx.'idf_project_idf_tag_assoc';
 | 
			
		||||
    if (!in_array($db->engine, array('MySQL', 'PostgreSQL'))) {
 | 
			
		||||
        throw new Exception('unsupported engine '.$engine);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $intro = new Pluf_DB_Introspect($db);
 | 
			
		||||
    if (in_array($table, $intro->listTables())) {
 | 
			
		||||
        echo '21 skipping up migration - table already exists'."\n";
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $schema = Pluf::factory('Pluf_DB_Schema_'.$db->engine, $db);
 | 
			
		||||
    $sql = $schema->getSqlCreate(new IDF_Project());
 | 
			
		||||
    $db->execute($sql[$table]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_22ProjectTagRelationTable_down($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $table = $db->pfx.'idf_project_idf_tag_assoc';
 | 
			
		||||
    if (!in_array($db->engine, array('MySQL', 'PostgreSQL'))) {
 | 
			
		||||
        throw new Exception('unsupported engine '.$engine);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $intro = new Pluf_DB_Introspect($db);
 | 
			
		||||
    if (!in_array($table, $intro->listTables())) {
 | 
			
		||||
        echo '22 skipping down migration - table does not exist'."\n";
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $schema = Pluf::factory('Pluf_DB_Schema_'.$db->engine, $db);
 | 
			
		||||
    $sql = $schema->getSqlDelete(new IDF_Project());
 | 
			
		||||
    $db->execute($sql[$table]);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								src/IDF/Migrations/23ProjectActivity.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/IDF/Migrations/23ProjectActivity.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add the new IDF_ProjectActivity model.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
function IDF_Migrations_23ProjectActivity_up($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $schema = new Pluf_DB_Schema($db);
 | 
			
		||||
    $schema->model = new IDF_ProjectActivity();
 | 
			
		||||
    $schema->createTables();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_23ProjectActivity_down($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $schema = new Pluf_DB_Schema($db);
 | 
			
		||||
    $schema->model = new IDF_ProjectActivity();
 | 
			
		||||
    $schema->dropTables();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								src/IDF/Migrations/24CurrentProjectActivity.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/IDF/Migrations/24CurrentProjectActivity.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_24CurrentProjectActivity_up($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $engine = Pluf::f('db_engine');
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
 | 
			
		||||
    if ($engine === 'PostgreSQL') {
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_projects ADD COLUMN current_activity INTEGER');
 | 
			
		||||
    } else if ($engine === 'MySQL') {
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_projects ADD COLUMN current_activity MEDIUMINT');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_24CurrentProjectActivity_down($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $db->execute('ALTER TABLE '.$db->pfx.'idf_projects DROP COLUMN current_activity');
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								src/IDF/Migrations/25NullableProjectInTag.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/IDF/Migrations/25NullableProjectInTag.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_25NullableProjectInTag_up($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $engine = Pluf::f('db_engine');
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
 | 
			
		||||
    if ($engine === 'PostgreSQL') {
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_tags ALTER COLUMN project DROP NOT NULL');
 | 
			
		||||
    } else if ($engine === 'MySQL') {
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_tags MODIFY project MEDIUMINT NULL');
 | 
			
		||||
        // this is only needed for non-transactional setups where MySQL set 0 as default value
 | 
			
		||||
        $db->execute('UPDATE '.$db->pfx.'idf_tags SET project=NULL WHERE project=0');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_25NullableProjectInTag_down($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $engine = Pluf::f('db_engine');
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    if ($engine === 'PostgreSQL') {
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_tags ALTER COLUMN project SET NOT NULL');
 | 
			
		||||
    } else if ($engine === 'MySQL') {
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_tags MODIFY project MEDIUMINT NOT NULL');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								src/IDF/Migrations/26NullableActivityInProject.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/IDF/Migrations/26NullableActivityInProject.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2012 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_26NullableActivityInProject_up($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $engine = Pluf::f('db_engine');
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    if ($engine === 'PostgreSQL') {
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_projects ALTER COLUMN current_activity DROP NOT NULL');
 | 
			
		||||
    } else if ($engine === 'MySQL') {
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_projects MODIFY current_activity MEDIUMINT NULL');
 | 
			
		||||
        // this is only needed for non-transactional setups where MySQL set 0 as default value
 | 
			
		||||
        $db->execute('UPDATE '.$db->pfx.'idf_projects SET current_activity=NULL WHERE current_activity=0');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_26NullableActivityInProject_down($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $engine = Pluf::f('db_engine');
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    if ($engine === 'PostgreSQL') {
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_projects ALTER COLUMN current_activity SET NOT NULL');
 | 
			
		||||
    } else if ($engine === 'MySQL') {
 | 
			
		||||
        $db->execute('ALTER TABLE '.$db->pfx.'idf_projects MODIFY current_activity MEDIUMINT NOT NULL');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										55
									
								
								src/IDF/Migrations/27IssueDueDate.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/IDF/Migrations/27IssueDueDate.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
<?php
 | 
			
		||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software
 | 
			
		||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
#
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add the private column for the project.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_27IssueDueDate_up($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $table = Pluf::factory('IDF_Issue')->getSqlTable();
 | 
			
		||||
    $sql = array();
 | 
			
		||||
    $sql['PostgreSQL'] = 'ALTER TABLE '.$table.' ADD COLUMN "due_dtime" TIMESTAMP';
 | 
			
		||||
    $sql['MySQL'] = 'ALTER TABLE '.$table.' ADD COLUMN `due_dtime` DATETIME';
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $engine = Pluf::f('db_engine');
 | 
			
		||||
    if (!isset($sql[$engine])) {
 | 
			
		||||
        throw new Exception('SQLite complex migration not supported.');
 | 
			
		||||
    }
 | 
			
		||||
    $db->execute($sql[$engine]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_27IssueDueDate_down($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $table = Pluf::factory('IDF_Issue')->getSqlTable();
 | 
			
		||||
    $sql = array();
 | 
			
		||||
    $sql['PostgreSQL'] = 'ALTER TABLE '.$table.' DROP COLUMN "due_dtime"';
 | 
			
		||||
    $sql['MySQL'] = 'ALTER TABLE '.$table.' DROP COLUMN `due_dtime`';
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $engine = Pluf::f('db_engine');
 | 
			
		||||
    if (!isset($sql[$engine])) {
 | 
			
		||||
        throw new Exception('SQLite complex migration not supported.');
 | 
			
		||||
    }
 | 
			
		||||
    $db->execute($sql[$engine]);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -22,14 +22,14 @@
 | 
			
		||||
# ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add the download of files.
 | 
			
		||||
 * Add wiki functionality.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
function IDF_Migrations_7Wiki_up($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $models = array(
 | 
			
		||||
                    'IDF_WikiPage',
 | 
			
		||||
                    'IDF_WikiRevision',
 | 
			
		||||
                    'IDF_Wiki_Page',
 | 
			
		||||
                    'IDF_Wiki_PageRevision',
 | 
			
		||||
                    );
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $schema = new Pluf_DB_Schema($db);
 | 
			
		||||
@@ -42,8 +42,8 @@ function IDF_Migrations_7Wiki_up($params=null)
 | 
			
		||||
function IDF_Migrations_7Wiki_down($params=null)
 | 
			
		||||
{
 | 
			
		||||
    $models = array(
 | 
			
		||||
                    'IDF_WikiRevision',
 | 
			
		||||
                    'IDF_WikiPage',
 | 
			
		||||
                    'IDF_Wiki_PageRevision',
 | 
			
		||||
                    'IDF_Wiki_Page',
 | 
			
		||||
                    );
 | 
			
		||||
    $db = Pluf::db();
 | 
			
		||||
    $schema = new Pluf_DB_Schema($db);
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
/*
 | 
			
		||||
# ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
# This file is part of InDefero, an open source project management application.
 | 
			
		||||
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
			
		||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
 | 
			
		||||
#
 | 
			
		||||
# InDefero is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user