Compare commits
650 Commits
dev
...
feature.do
Author | SHA1 | Date | |
---|---|---|---|
|
d7857c5126 | ||
|
06c57f7da6 | ||
|
4d5418a601 | ||
|
95cc7f627f | ||
|
b9407f6aee | ||
|
d079838818 | ||
|
81ce4688df | ||
|
ee33cc1832 | ||
|
82bb18fe10 | ||
|
8987ca7db6 | ||
|
8066fd8982 | ||
|
a96d8c05a7 | ||
|
4238a5dd50 | ||
|
94da55d15e | ||
|
09979b8551 | ||
|
5b82efa0be | ||
|
8502a36481 | ||
|
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 | ||
|
f8b49c805a | ||
|
7ac254169c | ||
|
f95ff57db9 | ||
|
c2207452bd | ||
|
a28604ae4f | ||
|
4e53b7d178 | ||
|
38e6e4f8d3 | ||
|
dfa223b39e | ||
|
0a8d771c11 | ||
|
5afd073ff3 | ||
|
46fda14e08 | ||
|
bbf9ef8b3d | ||
|
2b7de0b7a4 | ||
|
f590b1c5f8 | ||
|
bae73f266c | ||
|
b00dbfaeaa | ||
|
e2e1e50890 | ||
|
423548dc2c | ||
|
545117eeae | ||
|
0b0392a274 | ||
|
0c0236c766 | ||
|
067d88136e | ||
|
d0cd0bb9bf | ||
|
69ecb1a049 | ||
|
e50f2f2b5f | ||
|
905a81a715 | ||
|
4d0d41ef02 | ||
|
15e7adaefb | ||
|
fea67af4df | ||
|
86832e4a36 | ||
|
c6ffc47c24 | ||
|
40881bb4e5 | ||
|
7cedd4af7a | ||
|
6832e45b1f | ||
|
e31f10e648 | ||
|
336faa4503 | ||
|
fbd1ebc294 | ||
|
7bcfb806b0 | ||
|
2908e28999 | ||
|
a188e1b275 | ||
|
52d76cd146 | ||
|
4eb34044ff | ||
|
ccb1bd33d4 | ||
|
ba14aec7a3 | ||
|
41fb1bf13c | ||
|
ddb05e68a3 | ||
|
b544792f36 | ||
|
a069661b4a | ||
|
07c94b97f9 | ||
|
116a7e34db | ||
|
f4fc2342d5 | ||
|
f7228ef2ec | ||
|
207eb1322d | ||
|
390c9b5048 | ||
|
58804923ef | ||
|
296091e977 | ||
|
77ba17eb61 | ||
|
a489cb15b5 | ||
|
b0bebb44e6 | ||
|
74baebde96 | ||
|
caac979263 | ||
|
bbc9bd6ef4 | ||
|
d445a65788 | ||
|
cdebac0b13 | ||
|
651617b8bf | ||
|
0e6eb9059a | ||
|
22d6453d56 | ||
|
a7b62a30ff | ||
|
d5e6d355ab | ||
|
431e199c1c | ||
|
3884bcdd01 | ||
|
fa974eb8dd | ||
|
023a3ce879 | ||
|
c67e61cbaa | ||
|
cdeefb43a5 | ||
|
93af6a68bd | ||
|
146e956432 | ||
|
afa91188d8 | ||
|
c2a9a60aa7 | ||
|
d654c95689 | ||
|
439f1fefe2 | ||
|
4245617c6f | ||
|
5635cdcac7 | ||
|
dd05a58c8c | ||
|
a437da6a4c | ||
|
0334e88625 | ||
|
05b081e6d4 | ||
|
c7c39c6fa1 | ||
|
0a7c2bca85 | ||
|
fd7a53a854 | ||
|
9ccbcea743 | ||
|
4b75a55639 | ||
|
90b9279c3a | ||
|
80be99890a | ||
|
d4929622bf | ||
|
7059150ac8 | ||
|
777937b70c | ||
|
b4b53d3e22 | ||
|
97bc383bc0 | ||
|
dbd088458e | ||
|
0739b856e0 | ||
|
81acb276d8 | ||
|
80e965a904 | ||
|
39c29dbe10 | ||
|
51c42a65c5 | ||
|
784c9718eb | ||
|
874b5aa7e9 | ||
|
bf28a24b72 | ||
|
dffeb1f9d5 | ||
|
6d7d7ebbfa | ||
|
5b41fe3167 | ||
|
28f36dc7b0 | ||
|
dc2881ad02 | ||
|
653299f4d8 | ||
|
704850f5c6 | ||
|
1548d4184e | ||
|
abc8b8f4ab | ||
|
08ef485ca9 | ||
|
35e670a1ab | ||
|
deb1ea4d2b | ||
|
3aac4d528a | ||
|
70e8d12420 | ||
|
ad15b13f7e | ||
|
b4bc6abace | ||
|
e6f255bc56 | ||
|
470a961a80 | ||
|
d08fee129b | ||
|
8993d2988b | ||
|
e776fc0713 | ||
|
c0ccdc768a | ||
|
039ae01cfa | ||
|
612d00ade2 | ||
|
fe001abd26 | ||
|
b800ffcc1f | ||
|
8a55952204 | ||
|
8b2363fd6f | ||
|
e7a0d9d497 | ||
|
c807c4b734 | ||
|
0af51d90ba | ||
|
972df3b231 | ||
|
1887e9effd | ||
|
7e10524f92 | ||
|
c3ff90c4f8 | ||
|
2c4f2d3037 | ||
|
07aec736f5 | ||
|
b30bdc9833 | ||
|
d171a249c5 | ||
|
d994e0efb0 | ||
|
0379b862ec | ||
|
5af2ab4d97 | ||
|
b518385962 | ||
|
d25bc74d71 | ||
|
5641173a04 | ||
|
806e69b858 | ||
|
a29a2a0fa4 | ||
|
4951498c0b | ||
|
97ea828532 | ||
|
d539eaf64b | ||
|
90edbf0d8b | ||
|
0c575ccc74 | ||
|
eebdc5ad12 | ||
|
617589f41b | ||
|
50638c768f | ||
|
29b8bf8a4e | ||
|
42936cc51d | ||
|
b138548a10 | ||
|
7d5ba6248e | ||
|
36a58dcae2 | ||
|
2106a5fbdc | ||
|
0897c8608f | ||
|
a32d6d8265 | ||
|
0f9f337e66 | ||
|
bb13722a2f | ||
|
77cdbefe0c | ||
|
f68bba1292 | ||
|
37d0ccc728 | ||
|
7557a73014 | ||
|
f3f00dd182 | ||
|
a2297decfd | ||
|
07b2b2f305 | ||
|
85df9e5ab2 | ||
|
439014b0b1 | ||
|
f6fc5ae466 | ||
|
132c4f6c89 | ||
|
21cdf60c31 | ||
|
b4f8cf8c50 | ||
|
f4dbabe8de | ||
|
c5c7ebff04 | ||
|
5d263e78e0 | ||
|
5f4e1da0c8 | ||
|
187365db76 | ||
|
e26a5c8cdf | ||
|
a384c60937 | ||
|
6b4abac08e | ||
|
e789263068 | ||
|
82aaf43d5d | ||
|
adae73080c | ||
|
b648e6f7a7 | ||
|
194dcad0e3 | ||
|
af3df142d4 | ||
|
f2a9518b5c | ||
|
593240b420 | ||
|
8aae0f29d4 | ||
|
14d07a22e2 | ||
|
3eb0247b37 | ||
|
7f32a5679d | ||
|
a442fd588e | ||
|
e7ce32fc26 | ||
|
f0a606e5cf | ||
|
0c4846c986 | ||
|
31e81118dd | ||
|
e47d51d14c | ||
|
ce436cc6ec | ||
|
3d1ac97dc3 | ||
|
7a2065c687 | ||
|
9e6c7dad88 | ||
|
4f23ea4dd5 | ||
|
f25dbd8872 | ||
|
de036920a4 | ||
|
061c806588 | ||
|
780267978d | ||
|
0ad7f47885 | ||
|
d2f0bac907 | ||
|
e46a6fa171 | ||
|
7cbc690890 | ||
|
a46fd28dae | ||
|
8decc383aa | ||
|
f3268b3d37 | ||
|
4fdf248cb6 | ||
|
1fd1e63043 | ||
|
5ce324f35f | ||
|
7303e9dd58 | ||
|
e57fc18bcb | ||
|
9a8148079d | ||
|
24762adecc | ||
|
2ee665ac96 | ||
|
2e1a91622e | ||
|
4687355351 | ||
|
38dd610319 | ||
|
a4408de74d | ||
|
7a952215aa | ||
|
982b330739 | ||
|
598451f470 | ||
|
3e9229be5f | ||
|
ad6148cae7 | ||
|
2aebc0e099 | ||
|
06022bf378 | ||
|
430c9cb00e | ||
|
89780b0317 | ||
|
c534894995 | ||
|
a91ce1600f | ||
|
145f6d0d1d | ||
|
04e7d7c99b | ||
|
7ed69c7f4a | ||
|
8f914c44a1 | ||
|
28ce82c6f6 | ||
|
641a3b24a5 | ||
|
0d61866b89 | ||
|
c1a477e7d0 | ||
|
692d2e53b2 | ||
|
47acc73451 | ||
|
2f22d48dd0 | ||
|
e0b0a732b4 | ||
|
59ad0f5b11 | ||
|
3b53ceedcd | ||
|
15a2bd90b3 | ||
|
c49a8204e0 | ||
|
601e894935 | ||
|
445c90fefe | ||
|
b7ced5fa69 | ||
|
995f1a13c3 | ||
|
cf22909722 | ||
|
02603fd8fd | ||
|
af4f5aaeb0 | ||
|
f8012c37d1 | ||
|
5954cd0ad1 | ||
|
5ef6e6c08f | ||
|
94a5464155 | ||
|
18ba8d0ac5 | ||
|
9fd4334dec | ||
|
d7843a55bd | ||
|
b7833b5d23 | ||
|
0f617f8e09 | ||
|
fbc1fab68d | ||
|
68890c3c48 | ||
|
10f08386f7 | ||
|
45fa309c07 | ||
|
2ad13a96f9 | ||
|
73f95de843 | ||
|
c13d1aba30 | ||
|
42f561dc75 | ||
|
8280add935 | ||
|
bbc29c889f | ||
|
e5ee6d8fca | ||
|
738a8bdd60 | ||
|
119faf55cf | ||
|
7b0ece42f0 | ||
|
3c29e4e6ae | ||
|
a5f97c59d9 | ||
|
77c7f8ecfe | ||
|
dc34829afe | ||
|
10245113d5 | ||
|
349970cfaf | ||
|
0056e3f0b2 | ||
|
4e7d3618a7 | ||
|
548a427148 | ||
|
49e5aa783d | ||
|
b9d8eeea9e | ||
|
75777daf4b | ||
|
d3b76975cd | ||
|
64fb5b3bf0 | ||
|
51842c02f6 | ||
|
cc6f1c7cd8 | ||
|
5d24931d9b | ||
|
e2bce19526 | ||
|
9653f1a341 | ||
|
a5a5c7b2b6 | ||
|
c486ca928b | ||
|
3a28fe9d28 | ||
|
8da6fe7287 | ||
|
52be41186f | ||
|
96e8f4ae3c | ||
|
355f9ca05f | ||
|
ef40b0a34e | ||
|
73f6430a60 | ||
|
2b107c1610 | ||
|
93d379f293 | ||
|
6d415e9ec5 | ||
|
577aac2069 | ||
|
73641a03d5 | ||
|
0b580ba2ec | ||
|
a8a292a3c5 | ||
|
ec1d21a625 | ||
|
078c6feae8 | ||
|
63aedd6b42 | ||
|
1e3dfef438 | ||
|
c72e9f4eb0 | ||
|
857c11933a | ||
|
30a3515e94 | ||
|
ff4f8afde8 | ||
|
8050463a12 | ||
|
73dba2fa1a | ||
|
3c46b7734f | ||
|
48ff314487 | ||
|
4fa7a20fd3 | ||
|
75280d6892 | ||
|
6c5fde77b4 | ||
|
646cf6479b | ||
|
1d24432f8d | ||
|
37aa3d8b69 | ||
|
9437a19ee0 | ||
|
6c04fa80bd | ||
|
a667227943 | ||
|
8d32905913 | ||
|
58ab16432c | ||
|
aa383ffb1b | ||
|
f3cadfe013 | ||
|
c7aa91fc29 | ||
|
e5934e0a3a | ||
|
b6c5e803cb | ||
|
ec8ff4f76b | ||
|
06668db697 | ||
|
cab5d35771 | ||
|
a82b4b7b6b | ||
|
37e0604647 | ||
|
4765ca2232 | ||
|
6edaf03faa | ||
|
0dedee4429 | ||
|
078c75514e | ||
|
838645463d | ||
|
157819195b | ||
|
25d7a5a776 | ||
|
9d9541ee11 | ||
|
c1e23ae9e2 | ||
|
14e074b122 | ||
|
c3ae1970ca | ||
|
fbcdacdccf | ||
|
f473691479 | ||
|
f7a7ac39f3 | ||
|
ca5270a074 | ||
|
0e421c0b34 | ||
|
cb375dea26 | ||
|
6845f59150 | ||
|
021805f1e1 | ||
|
95881bd7f1 | ||
|
3c59c80bcc | ||
|
b3bacf25ff | ||
|
99992442f5 | ||
|
dd56d681b3 | ||
|
ba18f30c4f | ||
|
82e2684004 | ||
|
dc6f25cdef | ||
|
36c1f98438 | ||
|
ac7be1bde2 | ||
|
1a067ca107 | ||
|
c321e4828b | ||
|
68cc1ed5d3 | ||
|
69a7a58ce7 | ||
|
c0dfd6b5dc | ||
|
7d6cb22291 | ||
|
32507085b4 | ||
|
c488278ce1 | ||
|
ad17d797b2 | ||
|
2b1a741946 | ||
|
cbae598893 | ||
|
d153cd9049 | ||
|
2a15e2a350 | ||
|
1815aaa909 | ||
|
bdea6e4cbb | ||
|
75af09062f | ||
|
c366124917 | ||
|
16ce0da5f9 | ||
|
2ab52e7eaf | ||
|
fcefbe719f | ||
|
7d3f7e226c | ||
|
3848bd8d22 | ||
|
0873d44162 | ||
|
6cf4f00f92 | ||
|
d6c0b7a680 | ||
|
25e296fbb6 | ||
|
e235242ea6 | ||
|
9b39d63104 | ||
|
8915b45948 | ||
|
29e053bf6b | ||
|
a15107558c | ||
|
b320375d60 | ||
|
fb66e1e98f | ||
|
2f0156e63b | ||
|
e31d822d74 | ||
|
15cba014ba | ||
|
88a1bf9c94 | ||
|
d014b36ee2 | ||
|
cefdceba13 | ||
|
1c8490be6b | ||
|
1243a8f6ad | ||
|
d98dda645e | ||
|
44ea8f1817 | ||
|
6ef721d3a8 | ||
|
7d84da4d7c | ||
|
a53c6a1778 | ||
|
b75286375e | ||
|
ad8a6d3071 | ||
|
54b37ac5b6 | ||
|
bc434504b1 | ||
|
88ce10b8e6 | ||
|
0abb706ded | ||
|
54abd7bc7b | ||
|
c866d09e27 | ||
|
668b49df40 | ||
|
3476541bf4 | ||
|
2c9cf96245 | ||
|
39699ba723 | ||
|
0fd0c40e89 | ||
|
d31cd2aef4 | ||
|
c83e2e6f30 | ||
|
f55769a946 | ||
|
8345a02aaa | ||
|
1c51437569 | ||
|
63cdede854 | ||
|
d216e21858 | ||
|
358a774017 | ||
|
3c162486e4 | ||
|
a3f40447c0 | ||
|
96784b6e7c | ||
|
37cb05ff38 |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
src/IDF/version.php export-subst
|
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
*~
|
||||||
tmp
|
tmp
|
||||||
src/IDF/conf/idf.php
|
src/IDF/conf/idf.php
|
||||||
src/IDF/conf/idf.test.php
|
src/IDF/conf/idf.test.php
|
||||||
@@ -5,3 +6,9 @@ www/test.php
|
|||||||
www/media/upload
|
www/media/upload
|
||||||
src/IDF/gettexttemplates
|
src/IDF/gettexttemplates
|
||||||
indefero-*.zip
|
indefero-*.zip
|
||||||
|
src/IDF/conf/path.php
|
||||||
|
.tx/config
|
||||||
|
src/IDF/locale/idf.pot.bak
|
||||||
|
test/test.db
|
||||||
|
test/tmp
|
||||||
|
test/config.php
|
||||||
|
47
AUTHORS
47
AUTHORS
@@ -1,18 +1,43 @@
|
|||||||
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.
|
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
|
Adrien Bustany <madcat@mymadcat.com>
|
||||||
bohwaz <http://bohwaz.net/>
|
Andrew Nguyen <andrew-git-indefero@na-consulting.net>
|
||||||
Benjamin Jorand <benjamin.jorand@gmail.com> - Mercurial support
|
Baptiste Durand-Bret <bathizte@ozazar.org>
|
||||||
Baptiste Michaud <bactisme@gmail.com> - Subversion synchronization
|
Baptiste Michaud <bactisme@gmail.com> - Subversion sync
|
||||||
Julien Issler
|
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>
|
||||||
|
David Feeney <davidf>
|
||||||
|
Denis Kot <denis.kot@gmail.com> - Russian translation
|
||||||
|
Dmitry Dulepov <dmitryd>
|
||||||
|
Fernando Sayago Gil <mikados.mikados@gmail.com> - Spanish translation
|
||||||
|
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
|
||||||
|
Julien Issler <julien@issler.net>
|
||||||
|
Ludovic Bellière <xrogaan>
|
||||||
Manuel Eidenberger <eidenberger@gmail.com>
|
Manuel Eidenberger <eidenberger@gmail.com>
|
||||||
Ciaran Gultnieks
|
Matthew Dawson <mjd>
|
||||||
Mehdi Kabab
|
Matías Halles <matias@halles.cl>
|
||||||
Sindre R. Myren
|
Mehdi Kabab <http://pioupioum.fr/>
|
||||||
|
Nicolas Lassalle <nicolas@beroot.org> - Subversion support
|
||||||
Patrick Georgi <patrick.georgi@coresystems.de>
|
Patrick Georgi <patrick.georgi@coresystems.de>
|
||||||
|
Raphaël Emourgeon <raphael>
|
||||||
|
Samuel Suther <info@suther.de> - German translation
|
||||||
|
Sindre R. Myren <sindrero@stud.ntnu.no>
|
||||||
|
Stewart Platt <stew@futurete.ch>
|
||||||
|
Thomas Keller <me@thomaskeller.biz> - Monotone support
|
||||||
|
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
|
And all the nice users who spent time reporting issues and promoting
|
||||||
the project. The project could not live without them.
|
the project. The project could not live without them.
|
||||||
|
|
||||||
|
116
CONTRIBUTE.mdtext
Normal file
116
CONTRIBUTE.mdtext
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
[Indefero][idf] is not only a software you can use either hosted for
|
||||||
|
you or hosted by you, but also a free software you can contribute to.
|
||||||
|
|
||||||
|
Here you will get how to contribute and what to contribute.
|
||||||
|
|
||||||
|
[idf]: http://www.indefero.net
|
||||||
|
|
||||||
|
# Quick Way on How to Contribute
|
||||||
|
|
||||||
|
Simple contribution:
|
||||||
|
|
||||||
|
1. Open a ticket with your idea. You can directly propose a patch if
|
||||||
|
you have it.
|
||||||
|
|
||||||
|
2. Wait for it to be checked by the devs or meet us on the #indefero
|
||||||
|
channel on [FreeNode][freenode].
|
||||||
|
|
||||||
|
Bigger contribution:
|
||||||
|
|
||||||
|
1. Fork Indefero where you want (fork from the develop branch).
|
||||||
|
|
||||||
|
2. Code your change and document it.
|
||||||
|
|
||||||
|
3. Open a ticket with a pull request and talk about it on IRC.
|
||||||
|
|
||||||
|
# The General Contribution Workflow for Regular Contributors
|
||||||
|
|
||||||
|
1. Fork Indefero from the **develop** branch.
|
||||||
|
2. Request a pull request if you do not have write access on the repository.
|
||||||
|
3. Merge your changes without fast forward in develop. This keeps track of
|
||||||
|
the history of the changes and makes understanding what is going on easy.
|
||||||
|
4. Merge your changes with fast forward **only if a single commit**.
|
||||||
|
|
||||||
|
Indefero is composed of two main branches:
|
||||||
|
|
||||||
|
1. **master**: this is the shipped branch, only a select number of people
|
||||||
|
can push into it.
|
||||||
|
2. **develop**: this is the development branch, all the people having write
|
||||||
|
access to the repository are welcomed to push in.
|
||||||
|
|
||||||
|
**Note:** The branching model we use is [explained in details here][bmi]. You
|
||||||
|
**must** understand it to really contribute to the code base in an
|
||||||
|
efficient way.
|
||||||
|
|
||||||
|
[bmi]: http://nvie.com/git-model "A successful Git branching model"
|
||||||
|
|
||||||
|
# What to Contribute
|
||||||
|
|
||||||
|
Contribution is easy, you can contribute in a lot of different fields,
|
||||||
|
contributions small or big are always appreciated. Here is an example
|
||||||
|
list of what you can do:
|
||||||
|
|
||||||
|
- Install InDefero on your system and report the problem you had.
|
||||||
|
- Find the bad English and typos and propose corrections.
|
||||||
|
- Help with the translation effort.
|
||||||
|
- Find little bugs or usability problems and provide ideas on how to fix them.
|
||||||
|
- Register to the [discussion group][group] and help new users.
|
||||||
|
- Come and chat on IRC #indefero on the [FreeNode][freenode] servers.
|
||||||
|
- Find ways to improve the design while keeping it **beautifully simple**.
|
||||||
|
- Write a blog post about the project, what you think is good or bad.
|
||||||
|
- Translate InDefero for the sake of the community.
|
||||||
|
- Or maybe really hack into the code.
|
||||||
|
|
||||||
|
As you can see, the real hacking into the code is just a small part of the work, so even if you are not a coder you can do a lot.
|
||||||
|
|
||||||
|
[group]: http://groups.google.com/group/indefero-users
|
||||||
|
[freenode]: http://freenode.net/
|
||||||
|
|
||||||
|
## I am a simple user
|
||||||
|
|
||||||
|
Thanks a lot! Really! As a project leader, I consider **you** as
|
||||||
|
**the most important person in the success of the project**. So do not
|
||||||
|
worry, I will really listen to your needs and make you love this
|
||||||
|
project.
|
||||||
|
|
||||||
|
What you can do to help:
|
||||||
|
|
||||||
|
- Use the software and each time you find something a bit annoying in your daily use, report a bug. Usability issues are high priority issues.
|
||||||
|
- Find typos, grammar mistakes, etc. and report a bug.
|
||||||
|
- Write about InDefero on your blog/website.
|
||||||
|
- Read the issues submitted by the users and provide answers if you have them.
|
||||||
|
- ...
|
||||||
|
|
||||||
|
## I am a designer
|
||||||
|
|
||||||
|
A lot of things to do for you:
|
||||||
|
|
||||||
|
- Check the design and find the flaws in it. Is the space well used, does it look really nice and is it also functional for the first users?
|
||||||
|
- Do we have good support of all the major browsers?
|
||||||
|
- ...
|
||||||
|
|
||||||
|
## I am a coder
|
||||||
|
|
||||||
|
Checkout the code and have fun, but keep in mind that your results
|
||||||
|
must be simple to use. Do not worry about the beautiful part, the
|
||||||
|
designers can work on that.
|
||||||
|
|
||||||
|
## I am a security guy
|
||||||
|
|
||||||
|
Please, do try to break it, if you find a problem, come on IRC or
|
||||||
|
contact the developers to get the issue fixed as soon as
|
||||||
|
possible. Please, be nice, do not release the issue in the wild
|
||||||
|
without first talking to us.
|
||||||
|
|
||||||
|
## I am a translator
|
||||||
|
|
||||||
|
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 the maintainer pushs the
|
||||||
|
changes. In that way, try to do big changes with less submissions.
|
@@ -4,6 +4,12 @@ The installation of InDefero is composed of 2 parts, first the
|
|||||||
installation of the [Pluf framework](http://www.pluf.org) and second,
|
installation of the [Pluf framework](http://www.pluf.org) and second,
|
||||||
the installation of InDefero by itself.
|
the installation of InDefero by itself.
|
||||||
|
|
||||||
|
## PHP modules for indefero
|
||||||
|
|
||||||
|
Indefero need the GD module for PHP. It's named "php5-gd" in debian.
|
||||||
|
|
||||||
|
$ apt-get install php5-gd
|
||||||
|
|
||||||
## Recommended Layout of the Files
|
## Recommended Layout of the Files
|
||||||
|
|
||||||
If your server document root is in `/var/www` a good thing is to keep
|
If your server document root is in `/var/www` a good thing is to keep
|
||||||
@@ -37,6 +43,7 @@ docroot.
|
|||||||
$ sudo pear upgrade-all
|
$ sudo pear upgrade-all
|
||||||
$ sudo pear install --alldeps Mail
|
$ sudo pear install --alldeps Mail
|
||||||
$ sudo pear install --alldeps Mail_mime
|
$ sudo pear install --alldeps Mail_mime
|
||||||
|
$ sudo pear install --alldeps Console_Getopt
|
||||||
|
|
||||||
If you already have some of the PEAR packages installed with your
|
If you already have some of the PEAR packages installed with your
|
||||||
distribution, the `Mail` package is often not up-to-date,
|
distribution, the `Mail` package is often not up-to-date,
|
||||||
@@ -59,6 +66,8 @@ Here is the step-by-step installation procedure:
|
|||||||
* The InDefero installation folder is the folder containing this file INSTALL.mdtext.
|
* The InDefero installation folder is the folder containing this file INSTALL.mdtext.
|
||||||
* Make a copy of `src/IDF/conf/idf.php-dist` as `src/IDF/conf/idf.php`.
|
* Make a copy of `src/IDF/conf/idf.php-dist` as `src/IDF/conf/idf.php`.
|
||||||
* Update the idf.php file to match your system.
|
* Update the idf.php file to match your system.
|
||||||
|
* Make a copy of `src/IDF/conf/path.php-dist` as `src/IDF/conf/path.php`.
|
||||||
|
* Update the path.php file to match your installation paths. It should work out of the box if you followed the recommended file layout.
|
||||||
* Open a terminal/shell and go into the `src` folder in the InDefero installation folder.
|
* Open a terminal/shell and go into the `src` folder in the InDefero installation folder.
|
||||||
|
|
||||||
**Command:**
|
**Command:**
|
||||||
@@ -73,8 +82,7 @@ Here is the step-by-step installation procedure:
|
|||||||
**Bootstrap script:**
|
**Bootstrap script:**
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
set_include_path(get_include_path().PATH_SEPARATOR.'/home/www/indefero/src');
|
require '/home/www/indefero/src/IDF/conf/path.php';
|
||||||
set_include_path(get_include_path().PATH_SEPARATOR.'/home/www/pluf/src');
|
|
||||||
require 'Pluf.php';
|
require 'Pluf.php';
|
||||||
Pluf::start('/home/www/indefero/src/IDF/conf/idf.php');
|
Pluf::start('/home/www/indefero/src/IDF/conf/idf.php');
|
||||||
Pluf_Dispatcher::loadControllers(Pluf::f('idf_views'));
|
Pluf_Dispatcher::loadControllers(Pluf::f('idf_views'));
|
||||||
@@ -97,7 +105,7 @@ Here is the step-by-step installation procedure:
|
|||||||
* Open the `www/index.php` file and ensure that the path to Pluf and
|
* Open the `www/index.php` file and ensure that the path to Pluf and
|
||||||
Indefero are correctly set for your configuration.
|
Indefero are correctly set for your configuration.
|
||||||
* Now you can login with this user into the interface.
|
* Now you can login with this user into the interface.
|
||||||
* Click on the Administer link on top and create your first project.
|
* Click on the Forge Management link on top and create your first project.
|
||||||
|
|
||||||
## Upgrade InDefero
|
## Upgrade InDefero
|
||||||
|
|
||||||
@@ -112,11 +120,11 @@ To upgrade:
|
|||||||
|
|
||||||
**Upgrade commands:**
|
**Upgrade commands:**
|
||||||
|
|
||||||
|
$ cd /home/www/indefero/src
|
||||||
$ php /home/www/pluf/src/migrate.php --conf=IDF/conf/idf.php -a -d -u
|
$ php /home/www/pluf/src/migrate.php --conf=IDF/conf/idf.php -a -d -u
|
||||||
$ php /home/www/pluf/src/migrate.php --conf=IDF/conf/idf.php -a -d
|
$ php /home/www/pluf/src/migrate.php --conf=IDF/conf/idf.php -a -d
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Repository Synchronization
|
## Repository Synchronization
|
||||||
|
|
||||||
The documentation is available in the `doc` folder.
|
The documentation is available in the `doc` folder.
|
||||||
@@ -124,6 +132,7 @@ The documentation is available in the `doc` folder.
|
|||||||
* Subversion: `doc/syncsvn.mdtext`.
|
* Subversion: `doc/syncsvn.mdtext`.
|
||||||
* Mercurial: `doc/syncmercurial.mdtext`.
|
* Mercurial: `doc/syncmercurial.mdtext`.
|
||||||
* Git: `doc/syncgit.mdtext`.
|
* Git: `doc/syncgit.mdtext`.
|
||||||
|
* Monotone: `doc/syncmonotone.mdtext`
|
||||||
|
|
||||||
## For the Apache Webserver Users
|
## For the Apache Webserver Users
|
||||||
|
|
||||||
@@ -162,6 +171,11 @@ this in your configuration file:
|
|||||||
|
|
||||||
$cfg['idf_mimetypes_db'] = '/home/mime.types';
|
$cfg['idf_mimetypes_db'] = '/home/mime.types';
|
||||||
|
|
||||||
|
## FreeBSD Installation
|
||||||
|
|
||||||
|
You need to install `/usr/ports/lang/php5-extensions` which contains
|
||||||
|
the Standard PHP Library (SPL).
|
||||||
|
|
||||||
## Using a SMTP server with authentication
|
## Using a SMTP server with authentication
|
||||||
|
|
||||||
If your SMTP server requires authentication, for example,
|
If your SMTP server requires authentication, for example,
|
||||||
@@ -177,3 +191,43 @@ If your SMTP server requires authentication, for example,
|
|||||||
|
|
||||||
Check with your provider to get the right settings.
|
Check with your provider to get the right settings.
|
||||||
|
|
||||||
|
## Git Daemon on Ubuntu Karmic
|
||||||
|
|
||||||
|
If you have problems getting it to run, you can follow this procedure
|
||||||
|
proposed by Mathias in ticket 369.
|
||||||
|
|
||||||
|
1. Install git-daemon-run in addition to git-core
|
||||||
|
2. Edit /etc/sv/git-daemon/run to look as follows:
|
||||||
|
|
||||||
|
#!/bin/sh
|
||||||
|
exec 2>&1
|
||||||
|
echo 'git-daemon starting.'
|
||||||
|
exec chpst -ugit:git \
|
||||||
|
/usr/lib/git-core/git-daemon \
|
||||||
|
--reuseaddr \
|
||||||
|
--syslog \
|
||||||
|
--verbose \
|
||||||
|
--base-path=/home/git/repositories \
|
||||||
|
/home/git/repositories
|
||||||
|
|
||||||
|
3. Restart git-daemon-run
|
||||||
|
|
||||||
|
sv restart git-daemon
|
||||||
|
|
||||||
|
## If Subversion is not working
|
||||||
|
|
||||||
|
If you access a Subversion server with a self-signed certificate, you
|
||||||
|
may have problems as your certificate is not trusted, check the
|
||||||
|
[procedure provided here][svnfix] to solve the problem.
|
||||||
|
|
||||||
|
[svnfix]: http://projects.ceondo.com/p/indefero/issues/319/#ic1358
|
||||||
|
|
||||||
|
## If the registration links are not working
|
||||||
|
|
||||||
|
If You have standard instalaction of PHP ie in Debian, php.ini sets
|
||||||
|
mbstring.func_overload to value "2" for overloading str*
|
||||||
|
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/
|
||||||
|
141
Makefile
Normal file
141
Makefile
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
|
# This file is part of InDefero, an open source project management application.
|
||||||
|
# Copyright (C) 2010 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 ***** */
|
||||||
|
|
||||||
|
# Installation of external tools : transifex-client
|
||||||
|
# sudo apt-get install python-setuptools
|
||||||
|
# sudo easy_install -U transifex-client
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: help
|
||||||
|
help:
|
||||||
|
@printf "Rules for generating distributable files :\n"
|
||||||
|
@for b in `git branch | sed "s/^. //g"`; do \
|
||||||
|
printf "\t"$$b"-zipfile - Generate a zip archive of the "$$b" branch.\n"; \
|
||||||
|
done
|
||||||
|
@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"
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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: 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; for phpfile in `find . -iname "*.php"`; do \
|
||||||
|
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: pluf_path
|
||||||
|
@for pofile in `ls src/IDF/locale/*/idf.po`; do \
|
||||||
|
printf "Updating file : "$$pofile"\n"; \
|
||||||
|
msgmerge -v -U $$pofile src/IDF/locale/idf.pot; \
|
||||||
|
printf "\n"; \
|
||||||
|
done
|
||||||
|
|
||||||
|
#
|
||||||
|
# Transifex
|
||||||
|
#
|
||||||
|
.PHONY: check-tx-config
|
||||||
|
check-tx-config:
|
||||||
|
@if [ ! -e .tx/config ]; then \
|
||||||
|
mkdir -p .tx; \
|
||||||
|
touch .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 \
|
||||||
|
touch $(HOME)/.transifexrc; \
|
||||||
|
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
|
||||||
|
|
||||||
|
pot-push: check-tx-config
|
||||||
|
@tx push -s
|
||||||
|
|
||||||
|
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 zipfile of indefero for a specified branch
|
||||||
|
# ex: make master_zipfile
|
||||||
|
# make develop_zipfile
|
||||||
|
#
|
||||||
|
%-zipfile:
|
||||||
|
@git archive --format=zip --prefix="indefero/" $(@:-zipfile=) \
|
||||||
|
> indefero-$(@:-zipfile=)-`git log $(@:-zipfile=) -n 1 \
|
||||||
|
--pretty=format:%h`.zip
|
||||||
|
|
124
NEWS.mdtext
Normal file
124
NEWS.mdtext
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
# InDefero 1.2 - xxx xxx xx xx:xx 2011 UTC
|
||||||
|
|
||||||
|
## New Features
|
||||||
|
|
||||||
|
- Mercurial source views now show parent revisions (if any) and detailed change information
|
||||||
|
- File download URLs now contain the file name rather than the upload id; old links still work though (issue 686)
|
||||||
|
|
||||||
|
## Bugfixes
|
||||||
|
|
||||||
|
- monotone zip archive entries now all carry the revision date as mtime (issue 645)
|
||||||
|
- Timeline 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)
|
||||||
|
- Fix SSH public key parsing issues and improve the check for existing, uploaded keys (issue 679)
|
||||||
|
- Let the SVN command line client not store the login credentials we give him as arguments
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
## Translations
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
20
contrib/zipstream-php-0.2.2/COPYING
Normal file
20
contrib/zipstream-php-0.2.2/COPYING
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
Copyright (C) 2007-2009 Paul Duncan <pabs@pablotron.org>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
42
contrib/zipstream-php-0.2.2/README
Normal file
42
contrib/zipstream-php-0.2.2/README
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
ZipStream 0.2.2 README
|
||||||
|
======================
|
||||||
|
|
||||||
|
Please see the file COPYING for licensing and warranty information. The
|
||||||
|
latest version of this software is available at the following URL:
|
||||||
|
|
||||||
|
http://pablotron.org/software/zipstream-php/
|
||||||
|
|
||||||
|
Overview
|
||||||
|
========
|
||||||
|
A fast and simple streaming zip file downloader for PHP. Here's a
|
||||||
|
simple example:
|
||||||
|
|
||||||
|
# create a new zipstream object
|
||||||
|
$zip = new ZipStream('example.zip');
|
||||||
|
|
||||||
|
# create a file named 'hello.txt'
|
||||||
|
$zip->add_file('some_image.jpg', 'This is the contents of hello.txt');
|
||||||
|
|
||||||
|
# add a file named 'image.jpg' from a local file 'path/to/image.jpg'
|
||||||
|
$zip->add_file_from_path('some_image.jpg', 'path/to/image.jpg');
|
||||||
|
|
||||||
|
# finish the zip stream
|
||||||
|
$zip->finish();
|
||||||
|
|
||||||
|
You can also add comments, modify file timestamps, and customize (or
|
||||||
|
disable) the HTTP headers. See the class file for details. There are a
|
||||||
|
couple of additional examples in the initial release announcement at the
|
||||||
|
following URL:
|
||||||
|
|
||||||
|
http://pablotron.org/?cid=1535
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
============
|
||||||
|
|
||||||
|
* PHP version 5.1.2 or newer (specifically, the hash_init and
|
||||||
|
hash_file functions).
|
||||||
|
|
||||||
|
About the Author
|
||||||
|
================
|
||||||
|
Paul Duncan <pabs@pablotron.org>
|
||||||
|
http://pablotron.org/
|
2
contrib/zipstream-php-0.2.2/extras/README
Normal file
2
contrib/zipstream-php-0.2.2/extras/README
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Based on PKZIP appnotes, which are included here.
|
||||||
|
|
3071
contrib/zipstream-php-0.2.2/extras/zip-appnote-6.3.1-20070411.txt
Normal file
3071
contrib/zipstream-php-0.2.2/extras/zip-appnote-6.3.1-20070411.txt
Normal file
File diff suppressed because it is too large
Load Diff
52
contrib/zipstream-php-0.2.2/test/index.php
Normal file
52
contrib/zipstream-php-0.2.2/test/index.php
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
# load zipstream class
|
||||||
|
require '../zipstream.php';
|
||||||
|
|
||||||
|
# get path to current file
|
||||||
|
$pwd = dirname(__FILE__);
|
||||||
|
|
||||||
|
# add some random files
|
||||||
|
$files = array(
|
||||||
|
'../extras/zip-appnote-6.3.1-20070411.txt',
|
||||||
|
'../zipstream.php',
|
||||||
|
);
|
||||||
|
|
||||||
|
# create new zip stream object
|
||||||
|
$zip = new ZipStream('test.zip', array(
|
||||||
|
'comment' => 'this is a zip file comment. hello?'
|
||||||
|
));
|
||||||
|
|
||||||
|
# common file options
|
||||||
|
$file_opt = array(
|
||||||
|
# file creation time (2 hours ago)
|
||||||
|
'time' => time() - 2 * 3600,
|
||||||
|
|
||||||
|
# file comment
|
||||||
|
'comment' => 'this is a file comment. hi!',
|
||||||
|
);
|
||||||
|
|
||||||
|
# add files under folder 'asdf'
|
||||||
|
foreach ($files as $file) {
|
||||||
|
# build absolute path and get file data
|
||||||
|
$path = ($file[0] == '/') ? $file : "$pwd/$file";
|
||||||
|
$data = file_get_contents($path);
|
||||||
|
|
||||||
|
# add file to archive
|
||||||
|
$zip->add_file('asdf/' . basename($file), $data, $file_opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
# add same files again wihtout a folder
|
||||||
|
foreach ($files as $file) {
|
||||||
|
# build absolute path and get file data
|
||||||
|
$path = ($file[0] == '/') ? $file : "$pwd/$file";
|
||||||
|
$data = file_get_contents($path);
|
||||||
|
|
||||||
|
# add file to archive
|
||||||
|
$zip->add_file(basename($file), $data, $file_opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
# finish archive
|
||||||
|
$zip->finish();
|
||||||
|
|
||||||
|
?>
|
580
contrib/zipstream-php-0.2.2/zipstream.php
Normal file
580
contrib/zipstream-php-0.2.2/zipstream.php
Normal file
@@ -0,0 +1,580 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# ZipStream - Streamed, dynamically generated zip archives. #
|
||||||
|
# by Paul Duncan <pabs@pablotron.org> #
|
||||||
|
# #
|
||||||
|
# Copyright (C) 2007-2009 Paul Duncan <pabs@pablotron.org> #
|
||||||
|
# #
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining #
|
||||||
|
# a copy of this software and associated documentation files (the #
|
||||||
|
# "Software"), to deal in the Software without restriction, including #
|
||||||
|
# without limitation the rights to use, copy, modify, merge, publish, #
|
||||||
|
# distribute, sublicense, and/or sell copies of the Software, and to #
|
||||||
|
# permit persons to whom the Software is furnished to do so, subject to #
|
||||||
|
# the following conditions: #
|
||||||
|
# #
|
||||||
|
# The above copyright notice and this permission notice shall be #
|
||||||
|
# included in all copies or substantial portions of the of the Software. #
|
||||||
|
# #
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, #
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF #
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. #
|
||||||
|
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR #
|
||||||
|
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, #
|
||||||
|
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR #
|
||||||
|
# OTHER DEALINGS IN THE SOFTWARE. #
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
#
|
||||||
|
# ZipStream - Streamed, dynamically generated zip archives.
|
||||||
|
# by Paul Duncan <pabs@pablotron.org>
|
||||||
|
#
|
||||||
|
# Requirements:
|
||||||
|
#
|
||||||
|
# * PHP version 5.1.2 or newer.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# Streaming zip archives is a simple, three-step process:
|
||||||
|
#
|
||||||
|
# 1. Create the zip stream:
|
||||||
|
#
|
||||||
|
# $zip = new ZipStream('example.zip');
|
||||||
|
#
|
||||||
|
# 2. Add one or more files to the archive:
|
||||||
|
#
|
||||||
|
# # add first file
|
||||||
|
# $data = file_get_contents('some_file.gif');
|
||||||
|
# $zip->add_file('some_file.gif', $data);
|
||||||
|
#
|
||||||
|
# # add second file
|
||||||
|
# $data = file_get_contents('some_file.gif');
|
||||||
|
# $zip->add_file('another_file.png', $data);
|
||||||
|
#
|
||||||
|
# 3. Finish the zip stream:
|
||||||
|
#
|
||||||
|
# $zip->finish();
|
||||||
|
#
|
||||||
|
# You can also add an archive comment, add comments to individual files,
|
||||||
|
# and adjust the timestamp of files. See the API documentation for each
|
||||||
|
# method below for additional information.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# # create a new zip stream object
|
||||||
|
# $zip = new ZipStream('some_files.zip');
|
||||||
|
#
|
||||||
|
# # list of local files
|
||||||
|
# $files = array('foo.txt', 'bar.jpg');
|
||||||
|
#
|
||||||
|
# # read and add each file to the archive
|
||||||
|
# foreach ($files as $path)
|
||||||
|
# $zip->add_file($path, file_get_contents($path));
|
||||||
|
#
|
||||||
|
# # write archive footer to stream
|
||||||
|
# $zip->finish();
|
||||||
|
#
|
||||||
|
class ZipStream {
|
||||||
|
const VERSION = '0.2.2';
|
||||||
|
|
||||||
|
var $opt = array(),
|
||||||
|
$files = array(),
|
||||||
|
$cdr_ofs = 0,
|
||||||
|
$need_headers = false,
|
||||||
|
$ofs = 0;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Create a new ZipStream object.
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
#
|
||||||
|
# $name - Name of output file (optional).
|
||||||
|
# $opt - Hash of archive options (optional, see "Archive Options"
|
||||||
|
# below).
|
||||||
|
#
|
||||||
|
# Archive Options:
|
||||||
|
#
|
||||||
|
# comment - Comment for this archive.
|
||||||
|
# content_type - HTTP Content-Type. Defaults to 'application/x-zip'.
|
||||||
|
# content_disposition - HTTP Content-Disposition. Defaults to
|
||||||
|
# 'attachment; filename=\"FILENAME\"', where
|
||||||
|
# FILENAME is the specified filename.
|
||||||
|
# large_file_size - Size, in bytes, of the largest file to try
|
||||||
|
# and load into memory (used by
|
||||||
|
# add_file_from_path()). Large files may also
|
||||||
|
# be compressed differently; see the
|
||||||
|
# 'large_file_method' option.
|
||||||
|
# large_file_method - How to handle large files. Legal values are
|
||||||
|
# 'store' (the default), or 'deflate'. Store
|
||||||
|
# sends the file raw and is significantly
|
||||||
|
# faster, while 'deflate' compresses the file
|
||||||
|
# and is much, much slower. Note that deflate
|
||||||
|
# must compress the file twice and extremely
|
||||||
|
# slow.
|
||||||
|
# send_http_headers - Boolean indicating whether or not to send
|
||||||
|
# the HTTP headers for this file.
|
||||||
|
#
|
||||||
|
# Note that content_type and content_disposition do nothing if you are
|
||||||
|
# not sending HTTP headers.
|
||||||
|
#
|
||||||
|
# Large File Support:
|
||||||
|
#
|
||||||
|
# By default, the method add_file_from_path() will send send files
|
||||||
|
# larger than 20 megabytes along raw rather than attempting to
|
||||||
|
# compress them. You can change both the maximum size and the
|
||||||
|
# compression behavior using the large_file_* options above, with the
|
||||||
|
# following caveats:
|
||||||
|
#
|
||||||
|
# * For "small" files (e.g. files smaller than large_file_size), the
|
||||||
|
# memory use can be up to twice that of the actual file. In other
|
||||||
|
# words, adding a 10 megabyte file to the archive could potentially
|
||||||
|
# occupty 20 megabytes of memory.
|
||||||
|
#
|
||||||
|
# * Enabling compression on large files (e.g. files larger than
|
||||||
|
# large_file_size) is extremely slow, because ZipStream has to pass
|
||||||
|
# over the large file once to calculate header information, and then
|
||||||
|
# again to compress and send the actual data.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
#
|
||||||
|
# # create a new zip file named 'foo.zip'
|
||||||
|
# $zip = new ZipStream('foo.zip');
|
||||||
|
#
|
||||||
|
# # create a new zip file named 'bar.zip' with a comment
|
||||||
|
# $zip = new ZipStream('bar.zip', array(
|
||||||
|
# 'comment' => 'this is a comment for the zip file.',
|
||||||
|
# ));
|
||||||
|
#
|
||||||
|
# Notes:
|
||||||
|
#
|
||||||
|
# If you do not set a filename, then this library _DOES NOT_ send HTTP
|
||||||
|
# headers by default. This behavior is to allow software to send its
|
||||||
|
# own headers (including the filename), and still use this library.
|
||||||
|
#
|
||||||
|
function __construct($name = null, $opt = array()) {
|
||||||
|
# save options
|
||||||
|
$this->opt = $opt;
|
||||||
|
|
||||||
|
# set large file defaults: size = 20 megabytes, method = store
|
||||||
|
if (!isset($this->opt['large_file_size']))
|
||||||
|
$this->opt['large_file_size'] = 20 * 1024 * 1024;
|
||||||
|
if (!isset($this->opt['large_file_method']))
|
||||||
|
$this->opt['large_file_method'] = 'store';
|
||||||
|
|
||||||
|
$this->output_name = $name;
|
||||||
|
if ($name || (isset($opt['send_http_headers'])
|
||||||
|
&& $opt['send_http_headers']))
|
||||||
|
$this->need_headers = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# add_file - add a file to the archive
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
#
|
||||||
|
# $name - path of file in archive (including directory).
|
||||||
|
# $data - contents of file
|
||||||
|
# $opt - Hash of options for file (optional, see "File Options"
|
||||||
|
# below).
|
||||||
|
#
|
||||||
|
# File Options:
|
||||||
|
# time - Last-modified timestamp (seconds since the epoch) of
|
||||||
|
# this file. Defaults to the current time.
|
||||||
|
# comment - Comment related to this file.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
#
|
||||||
|
# # add a file named 'foo.txt'
|
||||||
|
# $data = file_get_contents('foo.txt');
|
||||||
|
# $zip->add_file('foo.txt', $data);
|
||||||
|
#
|
||||||
|
# # add a file named 'bar.jpg' with a comment and a last-modified
|
||||||
|
# # time of two hours ago
|
||||||
|
# $data = file_get_contents('bar.jpg');
|
||||||
|
# $zip->add_file('bar.jpg', $data, array(
|
||||||
|
# 'time' => time() - 2 * 3600,
|
||||||
|
# 'comment' => 'this is a comment about bar.jpg',
|
||||||
|
# ));
|
||||||
|
#
|
||||||
|
function add_file($name, $data, $opt = array()) {
|
||||||
|
# compress data
|
||||||
|
$zdata = gzdeflate($data);
|
||||||
|
|
||||||
|
# calculate header attributes
|
||||||
|
$crc = crc32($data);
|
||||||
|
$zlen = strlen($zdata);
|
||||||
|
$len = strlen($data);
|
||||||
|
$meth = 0x08;
|
||||||
|
|
||||||
|
# send file header
|
||||||
|
$this->add_file_header($name, $opt, $meth, $crc, $zlen, $len);
|
||||||
|
|
||||||
|
# print data
|
||||||
|
$this->send($zdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# add_file_from_path - add a file at path to the archive.
|
||||||
|
#
|
||||||
|
# Note that large files may be compresed differently than smaller
|
||||||
|
# files; see the "Large File Support" section above for more
|
||||||
|
# information.
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
#
|
||||||
|
# $name - name of file in archive (including directory path).
|
||||||
|
# $path - path to file on disk (note: paths should be encoded using
|
||||||
|
# UNIX-style forward slashes -- e.g '/path/to/some/file').
|
||||||
|
# $opt - Hash of options for file (optional, see "File Options"
|
||||||
|
# below).
|
||||||
|
#
|
||||||
|
# File Options:
|
||||||
|
# time - Last-modified timestamp (seconds since the epoch) of
|
||||||
|
# this file. Defaults to the current time.
|
||||||
|
# comment - Comment related to this file.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
#
|
||||||
|
# # add a file named 'foo.txt' from the local file '/tmp/foo.txt'
|
||||||
|
# $zip->add_file_from_path('foo.txt', '/tmp/foo.txt');
|
||||||
|
#
|
||||||
|
# # add a file named 'bigfile.rar' from the local file
|
||||||
|
# # '/usr/share/bigfile.rar' with a comment and a last-modified
|
||||||
|
# # time of two hours ago
|
||||||
|
# $path = '/usr/share/bigfile.rar';
|
||||||
|
# $zip->add_file_from_path('bigfile.rar', $path, array(
|
||||||
|
# 'time' => time() - 2 * 3600,
|
||||||
|
# 'comment' => 'this is a comment about bar.jpg',
|
||||||
|
# ));
|
||||||
|
#
|
||||||
|
function add_file_from_path($name, $path, $opt = array()) {
|
||||||
|
if ($this->is_large_file($path)) {
|
||||||
|
# file is too large to be read into memory; add progressively
|
||||||
|
$this->add_large_file($name, $path, $opt);
|
||||||
|
} else {
|
||||||
|
# file is small enough to read into memory; read file contents and
|
||||||
|
# handle with add_file()
|
||||||
|
$data = file_get_contents($path);
|
||||||
|
$this->add_file($name, $data, $opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# finish - Write zip footer to stream.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# # add a list of files to the archive
|
||||||
|
# $files = array('foo.txt', 'bar.jpg');
|
||||||
|
# foreach ($files as $path)
|
||||||
|
# $zip->add_file($path, file_get_contents($path));
|
||||||
|
#
|
||||||
|
# # write footer to stream
|
||||||
|
# $zip->finish();
|
||||||
|
#
|
||||||
|
function finish() {
|
||||||
|
# add trailing cdr record
|
||||||
|
$this->add_cdr($this->opt);
|
||||||
|
$this->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
###################
|
||||||
|
# PRIVATE METHODS #
|
||||||
|
###################
|
||||||
|
|
||||||
|
#
|
||||||
|
# Create and send zip header for this file.
|
||||||
|
#
|
||||||
|
private function add_file_header($name, $opt, $meth, $crc, $zlen, $len) {
|
||||||
|
# strip leading slashes from file name
|
||||||
|
# (fixes bug in windows archive viewer)
|
||||||
|
$name = preg_replace('/^\\/+/', '', $name);
|
||||||
|
|
||||||
|
# calculate name length
|
||||||
|
$nlen = strlen($name);
|
||||||
|
|
||||||
|
# create dos timestamp
|
||||||
|
$opt['time'] = isset($opt['time']) ? $opt['time'] : time();
|
||||||
|
$dts = $this->dostime($opt['time']);
|
||||||
|
|
||||||
|
# build file header
|
||||||
|
$fields = array( # (from V.A of APPNOTE.TXT)
|
||||||
|
array('V', 0x04034b50), # local file header signature
|
||||||
|
array('v', (6 << 8) + 3), # version needed to extract
|
||||||
|
array('v', 0x00), # general purpose bit flag
|
||||||
|
array('v', $meth), # compresion method (deflate or store)
|
||||||
|
array('V', $dts), # dos timestamp
|
||||||
|
array('V', $crc), # crc32 of data
|
||||||
|
array('V', $zlen), # compressed data length
|
||||||
|
array('V', $len), # uncompressed data length
|
||||||
|
array('v', $nlen), # filename length
|
||||||
|
array('v', 0), # extra data len
|
||||||
|
);
|
||||||
|
|
||||||
|
# pack fields and calculate "total" length
|
||||||
|
$ret = $this->pack_fields($fields);
|
||||||
|
$cdr_len = strlen($ret) + $nlen + $zlen;
|
||||||
|
|
||||||
|
# print header and filename
|
||||||
|
$this->send($ret . $name);
|
||||||
|
|
||||||
|
# add to central directory record and increment offset
|
||||||
|
$this->add_to_cdr($name, $opt, $meth, $crc, $zlen, $len, $cdr_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Add a large file from the given path.
|
||||||
|
#
|
||||||
|
private function add_large_file($name, $path, $opt = array()) {
|
||||||
|
$st = stat($path);
|
||||||
|
$block_size = 1048576; # process in 1 megabyte chunks
|
||||||
|
$algo = 'crc32b';
|
||||||
|
|
||||||
|
# calculate header attributes
|
||||||
|
$zlen = $len = $st['size'];
|
||||||
|
|
||||||
|
$meth_str = $this->opt['large_file_method'];
|
||||||
|
if ($meth_str == 'store') {
|
||||||
|
# store method
|
||||||
|
$meth = 0x00;
|
||||||
|
$crc = unpack('V', hash_file($algo, $path, true));
|
||||||
|
$crc = $crc[1];
|
||||||
|
} elseif ($meth_str == 'deflate') {
|
||||||
|
# deflate method
|
||||||
|
$meth = 0x08;
|
||||||
|
|
||||||
|
# open file, calculate crc and compressed file length
|
||||||
|
$fh = fopen($path, 'rb');
|
||||||
|
$hash_ctx = hash_init($algo);
|
||||||
|
$zlen = 0;
|
||||||
|
|
||||||
|
# read each block, update crc and zlen
|
||||||
|
while ($data = fgets($fh, $block_size)) {
|
||||||
|
hash_update($hash_ctx, $data);
|
||||||
|
$data = gzdeflate($data);
|
||||||
|
$zlen += strlen($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
# close file and finalize crc
|
||||||
|
fclose($fh);
|
||||||
|
$crc = unpack('V', hash_final($hash_ctx, true));
|
||||||
|
$crc = $crc[1];
|
||||||
|
} else {
|
||||||
|
die("unknown large_file_method: $meth_str");
|
||||||
|
}
|
||||||
|
|
||||||
|
# send file header
|
||||||
|
$this->add_file_header($name, $opt, $meth, $crc, $zlen, $len);
|
||||||
|
|
||||||
|
# open input file
|
||||||
|
$fh = fopen($path, 'rb');
|
||||||
|
|
||||||
|
# send file blocks
|
||||||
|
while ($data = fgets($fh, $block_size)) {
|
||||||
|
if ($meth_str == 'deflate')
|
||||||
|
$data = gzdeflate($data);
|
||||||
|
|
||||||
|
# send data
|
||||||
|
$this->send($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
# close input file
|
||||||
|
fclose($fh);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Is this file larger than large_file_size?
|
||||||
|
#
|
||||||
|
function is_large_file($path) {
|
||||||
|
$st = stat($path);
|
||||||
|
return ($this->opt['large_file_size'] > 0) &&
|
||||||
|
($st['size'] > $this->opt['large_file_size']);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Save file attributes for trailing CDR record.
|
||||||
|
#
|
||||||
|
private function add_to_cdr($name, $opt, $meth, $crc, $zlen, $len, $rec_len) {
|
||||||
|
$this->files[] = array($name, $opt, $meth, $crc, $zlen, $len, $this->ofs);
|
||||||
|
$this->ofs += $rec_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Send CDR record for specified file.
|
||||||
|
#
|
||||||
|
private function add_cdr_file($args) {
|
||||||
|
list ($name, $opt, $meth, $crc, $zlen, $len, $ofs) = $args;
|
||||||
|
|
||||||
|
# get attributes
|
||||||
|
$comment = isset($opt['comment']) ? $opt['comment'] : '';
|
||||||
|
|
||||||
|
# get dos timestamp
|
||||||
|
$dts = $this->dostime($opt['time']);
|
||||||
|
|
||||||
|
$fields = array( # (from V,F of APPNOTE.TXT)
|
||||||
|
array('V', 0x02014b50), # central file header signature
|
||||||
|
array('v', (6 << 8) + 3), # version made by
|
||||||
|
array('v', (6 << 8) + 3), # version needed to extract
|
||||||
|
array('v', 0x00), # general purpose bit flag
|
||||||
|
array('v', $meth), # compresion method (deflate or store)
|
||||||
|
array('V', $dts), # dos timestamp
|
||||||
|
array('V', $crc), # crc32 of data
|
||||||
|
array('V', $zlen), # compressed data length
|
||||||
|
array('V', $len), # uncompressed data length
|
||||||
|
array('v', strlen($name)), # filename length
|
||||||
|
array('v', 0), # extra data len
|
||||||
|
array('v', strlen($comment)), # file comment length
|
||||||
|
array('v', 0), # disk number start
|
||||||
|
array('v', 0), # internal file attributes
|
||||||
|
array('V', 32), # external file attributes
|
||||||
|
array('V', $ofs), # relative offset of local header
|
||||||
|
);
|
||||||
|
|
||||||
|
# pack fields, then append name and comment
|
||||||
|
$ret = $this->pack_fields($fields) . $name . $comment;
|
||||||
|
|
||||||
|
$this->send($ret);
|
||||||
|
|
||||||
|
# increment cdr offset
|
||||||
|
$this->cdr_ofs += strlen($ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Send CDR EOF (Central Directory Record End-of-File) record.
|
||||||
|
#
|
||||||
|
private function add_cdr_eof($opt = null) {
|
||||||
|
$num = count($this->files);
|
||||||
|
$cdr_len = $this->cdr_ofs;
|
||||||
|
$cdr_ofs = $this->ofs;
|
||||||
|
|
||||||
|
# grab comment (if specified)
|
||||||
|
$comment = '';
|
||||||
|
if ($opt && isset($opt['comment']))
|
||||||
|
$comment = $opt['comment'];
|
||||||
|
|
||||||
|
$fields = array( # (from V,F of APPNOTE.TXT)
|
||||||
|
array('V', 0x06054b50), # end of central file header signature
|
||||||
|
array('v', 0x00), # this disk number
|
||||||
|
array('v', 0x00), # number of disk with cdr
|
||||||
|
array('v', $num), # number of entries in the cdr on this disk
|
||||||
|
array('v', $num), # number of entries in the cdr
|
||||||
|
array('V', $cdr_len), # cdr size
|
||||||
|
array('V', $cdr_ofs), # cdr ofs
|
||||||
|
array('v', strlen($comment)), # zip file comment length
|
||||||
|
);
|
||||||
|
|
||||||
|
$ret = $this->pack_fields($fields) . $comment;
|
||||||
|
$this->send($ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Add CDR (Central Directory Record) footer.
|
||||||
|
#
|
||||||
|
private function add_cdr($opt = null) {
|
||||||
|
foreach ($this->files as $file)
|
||||||
|
$this->add_cdr_file($file);
|
||||||
|
$this->add_cdr_eof($opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Clear all internal variables. Note that the stream object is not
|
||||||
|
# usable after this.
|
||||||
|
#
|
||||||
|
function clear() {
|
||||||
|
$this->files = array();
|
||||||
|
$this->ofs = 0;
|
||||||
|
$this->cdr_ofs = 0;
|
||||||
|
$this->opt = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
###########################
|
||||||
|
# PRIVATE UTILITY METHODS #
|
||||||
|
###########################
|
||||||
|
|
||||||
|
#
|
||||||
|
# Send HTTP headers for this stream.
|
||||||
|
#
|
||||||
|
private function send_http_headers() {
|
||||||
|
# grab options
|
||||||
|
$opt = $this->opt;
|
||||||
|
|
||||||
|
# grab content type from options
|
||||||
|
$content_type = 'application/x-zip';
|
||||||
|
if (isset($opt['content_type']))
|
||||||
|
$content_type = $this->opt['content_type'];
|
||||||
|
|
||||||
|
# grab content disposition
|
||||||
|
$disposition = 'attachment';
|
||||||
|
if (isset($opt['content_disposition']))
|
||||||
|
$disposition = $opt['content_disposition'];
|
||||||
|
|
||||||
|
if ($this->output_name)
|
||||||
|
$disposition .= "; filename=\"{$this->output_name}\"";
|
||||||
|
|
||||||
|
$headers = array(
|
||||||
|
'Content-Type' => $content_type,
|
||||||
|
'Content-Disposition' => $disposition,
|
||||||
|
'Pragma' => 'public',
|
||||||
|
'Cache-Control' => 'public, must-revalidate',
|
||||||
|
'Content-Transfer-Encoding' => 'binary',
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($headers as $key => $val)
|
||||||
|
header("$key: $val");
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Send string, sending HTTP headers if necessary.
|
||||||
|
#
|
||||||
|
private function send($str) {
|
||||||
|
if ($this->need_headers)
|
||||||
|
$this->send_http_headers();
|
||||||
|
$this->need_headers = false;
|
||||||
|
|
||||||
|
echo $str;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Convert a UNIX timestamp to a DOS timestamp.
|
||||||
|
#
|
||||||
|
function dostime($when = 0) {
|
||||||
|
# get date array for timestamp
|
||||||
|
$d = getdate($when);
|
||||||
|
|
||||||
|
# set lower-bound on dates
|
||||||
|
if ($d['year'] < 1980) {
|
||||||
|
$d = array('year' => 1980, 'mon' => 1, 'mday' => 1,
|
||||||
|
'hours' => 0, 'minutes' => 0, 'seconds' => 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
# remove extra years from 1980
|
||||||
|
$d['year'] -= 1980;
|
||||||
|
|
||||||
|
# return date string
|
||||||
|
return ($d['year'] << 25) | ($d['mon'] << 21) | ($d['mday'] << 16) |
|
||||||
|
($d['hours'] << 11) | ($d['minutes'] << 5) | ($d['seconds'] >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Create a format string and argument list for pack(), then call
|
||||||
|
# pack() and return the result.
|
||||||
|
#
|
||||||
|
function pack_fields($fields) {
|
||||||
|
list ($fmt, $args) = array('', array());
|
||||||
|
|
||||||
|
# populate format string and argument list
|
||||||
|
foreach ($fields as $field) {
|
||||||
|
$fmt .= $field[0];
|
||||||
|
$args[] = $field[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
# prepend format string to argument list
|
||||||
|
array_unshift($args, $fmt);
|
||||||
|
|
||||||
|
# build output string from header and compressed data
|
||||||
|
return call_user_func_array('pack', $args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
?>
|
@@ -70,6 +70,13 @@ folder. Here is a configuration example:
|
|||||||
$cfg['idf_plugin_syncgit_path_gitserve'] = '/home/www/indefero/scripts/gitserve.py'; # yes .py
|
$cfg['idf_plugin_syncgit_path_gitserve'] = '/home/www/indefero/scripts/gitserve.py'; # yes .py
|
||||||
$cfg['idf_plugin_syncgit_path_authorized_keys'] = '/home/git/.ssh/authorized_keys';
|
$cfg['idf_plugin_syncgit_path_authorized_keys'] = '/home/git/.ssh/authorized_keys';
|
||||||
$cfg['idf_plugin_syncgit_sync_file'] = '/tmp/SYNC-GIT';
|
$cfg['idf_plugin_syncgit_sync_file'] = '/tmp/SYNC-GIT';
|
||||||
|
# Remove the git repositories which do not have a corresponding project
|
||||||
|
# This is run at cron time
|
||||||
|
$cfg['idf_plugin_syncgit_remove_orphans'] = false;
|
||||||
|
# git account home dir
|
||||||
|
$cfg['idf_plugin_syncgit_git_home_dir'] = '/home/git';
|
||||||
|
# where are going to be the git repositories
|
||||||
|
$cfg['idf_plugin_syncgit_base_repositories'] = '/home/git/repositories';
|
||||||
|
|
||||||
When someone will change his SSH key or add a new one, the
|
When someone will change his SSH key or add a new one, the
|
||||||
`/tmp/SYNC-GIT` file will be created. The cron job
|
`/tmp/SYNC-GIT` file will be created. The cron job
|
||||||
|
@@ -67,6 +67,14 @@ You also need to provide the base definition of the hgrc file. For example:
|
|||||||
'extensions' => array(),
|
'extensions' => array(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
If you are note using Apache but Nginx, you may need to create the
|
||||||
|
passwords as plain text passwords (see ticket 391). You can configure
|
||||||
|
the password storage with the format you want. The default is `sha`
|
||||||
|
you can set it to `plain` for nginx.
|
||||||
|
|
||||||
|
$cfg['idf_plugin_syncmercurial_passwd_mode'] = 'sha';
|
||||||
|
|
||||||
|
See the [`FILE_PASSWD_*` constants](http://euk1.php.net/package/File_Passwd/docs/latest/File_Passwd/_File_Passwd-1.1.7---Passwd.php.html) for more choices.
|
||||||
|
|
||||||
## Cron configuration
|
## Cron configuration
|
||||||
|
|
||||||
@@ -76,3 +84,13 @@ Each time this file is modified, a temporary file is created.
|
|||||||
*/5 * * * * /bin/sh /home/indefero/src/scripts/SyncMercurial.sh
|
*/5 * * * * /bin/sh /home/indefero/src/scripts/SyncMercurial.sh
|
||||||
|
|
||||||
Edit this script and add correct values to `private_notify` and `reload_cmd`.
|
Edit this script and add correct values to `private_notify` and `reload_cmd`.
|
||||||
|
|
||||||
|
## Hook configuratin
|
||||||
|
|
||||||
|
To get notifications sent directly when pushing in your repositories,
|
||||||
|
you need to add the following in your `.hgrc` file. The script will be
|
||||||
|
called onec per push and will automatically send the notifications and
|
||||||
|
sync the timeline.
|
||||||
|
|
||||||
|
[hooks]
|
||||||
|
changegroup = /home/indefero/src/scripts/hgchangegroup.php
|
||||||
|
272
doc/syncmonotone.mdtext
Normal file
272
doc/syncmonotone.mdtext
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
# Plugin SyncMonotone by Thomas Keller (me@thomaskeller.biz)
|
||||||
|
|
||||||
|
The SyncMonotone plugin allow the direct creation and synchronisation of
|
||||||
|
monotone repositories with the InDefero database. It has been built to
|
||||||
|
work together with monotone's "super server" usher, which is used to control
|
||||||
|
several repositories at once, acts as proxy and single entrance.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
* a unixoid operating system
|
||||||
|
* monotone >= 0.99.1
|
||||||
|
* for a proxy setup with usher:
|
||||||
|
* boost headers (for usher compilation)
|
||||||
|
* a current version of usher
|
||||||
|
* a daemonizer, like supervise
|
||||||
|
|
||||||
|
## Installation of monotone
|
||||||
|
|
||||||
|
If you install monotone from a distribution package, ensure you do not
|
||||||
|
install and / or activate the server component. We just need a plain
|
||||||
|
client installation which usually consists only of the `mtn` binary and
|
||||||
|
a few docs.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
The monotone plugin can be used in several different ways:
|
||||||
|
|
||||||
|
1. One database for everything. This is the easiest setup and of possible
|
||||||
|
use in case you do not want indefero to manage the access to your project.
|
||||||
|
Your `idf.php` should look like this:
|
||||||
|
|
||||||
|
$ cat idf.php
|
||||||
|
...
|
||||||
|
$cfg['mtn_path'] = 'mtn';
|
||||||
|
$cfg['mtn_opts'] = array('--no-workspace', '--no-standard-rcfiles');
|
||||||
|
$cfg['mtn_repositories'] = '/home/monotone/all_projects.mtn';
|
||||||
|
$cfg['mtn_remote_url'] = 'ssh://monotone@my.server.com:~all_projects.mtn';
|
||||||
|
$cfg['mtn_db_access'] = 'local';
|
||||||
|
...
|
||||||
|
|
||||||
|
Pro:
|
||||||
|
* easy to setup and to manage
|
||||||
|
|
||||||
|
Con:
|
||||||
|
* you need to give committers SSH access to your machine
|
||||||
|
* database lock problem: the database from which
|
||||||
|
indefero reads its data might be locked in case a user
|
||||||
|
syncs at the very moment via SSH
|
||||||
|
|
||||||
|
2. One database for every project. Similar to the above setup, but this
|
||||||
|
time you use the '%s' placeholder which is replaced with the short name
|
||||||
|
of the indefero project:
|
||||||
|
|
||||||
|
$ cat idf.php
|
||||||
|
...
|
||||||
|
$cfg['mtn_path'] = 'mtn';
|
||||||
|
$cfg['mtn_opts'] = array('--no-workspace', '--no-standard-rcfiles');
|
||||||
|
$cfg['mtn_repositories'] = '/home/monotone/%s.mtn';
|
||||||
|
$cfg['mtn_remote_url'] = 'ssh://monotone@my.server.com:~%s.mtn';
|
||||||
|
$cfg['mtn_db_access'] = 'local';
|
||||||
|
...
|
||||||
|
|
||||||
|
The same pro's and con's apply. Additionally you have to be careful about
|
||||||
|
not giving people physical read/write access of another project's database.
|
||||||
|
|
||||||
|
Furthermore, if you do not want to use `ssh`, but `netsync` transport,
|
||||||
|
each project's database must be served over a separate port.
|
||||||
|
|
||||||
|
3. One database for every project, all managed with usher. This is the
|
||||||
|
recommended setup for a mid-size forge setup. The remaining part of this
|
||||||
|
document will describe the process to set this up in detail.
|
||||||
|
|
||||||
|
Pro:
|
||||||
|
* access rights can be granted per project and are automatically
|
||||||
|
managed by indefero, just like the user's public monotone keys
|
||||||
|
* no database locking issues
|
||||||
|
* one public server running on the one well-known port
|
||||||
|
|
||||||
|
Con:
|
||||||
|
* harder to setup
|
||||||
|
|
||||||
|
## Installation and configuration of usher
|
||||||
|
|
||||||
|
1. Clone usher's monotone repository:
|
||||||
|
|
||||||
|
$ mtn clone "mtn://monotone.ca?net.venge.monotone.contrib.usher"
|
||||||
|
|
||||||
|
2. Compile usher:
|
||||||
|
|
||||||
|
$ autoreconf -i
|
||||||
|
$ ./configure && make
|
||||||
|
$ sudo make install
|
||||||
|
|
||||||
|
This installs the usher binary in $prefix/bin.
|
||||||
|
|
||||||
|
3. Create a new usher user:
|
||||||
|
|
||||||
|
$ adduser --system --disabled-login --home /var/lib/usher usher
|
||||||
|
|
||||||
|
4. Create the basic usher setup:
|
||||||
|
|
||||||
|
$ cd /var/lib/usher
|
||||||
|
$ mkdir projects logs
|
||||||
|
$ cat > usher.conf
|
||||||
|
userpass "admin" "<secret-password>"
|
||||||
|
adminaddr "127.0.0.1:12345"
|
||||||
|
logdir "log"
|
||||||
|
^D
|
||||||
|
$ chmod 600 usher.conf
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
$ setfacl -m u:www:rw usher.conf
|
||||||
|
$ setfacl -m d:u:www:rwx projects/
|
||||||
|
|
||||||
|
5. Wrap a daemonizer around usher, for example supervise from daemontools
|
||||||
|
(<http://cr.yp.to/damontools.html>):
|
||||||
|
|
||||||
|
$ cat > run
|
||||||
|
#!/bin/sh
|
||||||
|
cd /var/lib/usher
|
||||||
|
exec 2>&1
|
||||||
|
exec \
|
||||||
|
setuidgid usher \
|
||||||
|
usher usher.conf
|
||||||
|
^D
|
||||||
|
|
||||||
|
The service can now be started through supervise:
|
||||||
|
|
||||||
|
$ supervise /var/lib/usher
|
||||||
|
|
||||||
|
## Configuration of indefero
|
||||||
|
|
||||||
|
Based on the above setup, the configuration in `src/IDF/conf/idf.php` should
|
||||||
|
look like this:
|
||||||
|
|
||||||
|
$ cat idf.php
|
||||||
|
...
|
||||||
|
$cfg['mtn_path'] = 'mtn';
|
||||||
|
$cfg['mtn_opts'] = array('--no-workspace', '--no-standard-rcfiles');
|
||||||
|
$cfg['mtn_repositories'] = '/var/lib/usher/projects/%s/';
|
||||||
|
$cfg['mtn_remote_url'] = 'mtn://my.server.com/%s';
|
||||||
|
$cfg['mtn_db_access'] = 'remote';
|
||||||
|
$cfg['mtn_usher_conf'] = '/var/lib/usher/usher.conf';
|
||||||
|
...
|
||||||
|
|
||||||
|
The `%s` placeholders are automatically replaced by the name of the
|
||||||
|
indefero project. The plugin assumes that every project is separated
|
||||||
|
by a distinct server name in the monotone URL (hence the use of `/%s`),
|
||||||
|
so if a user calls
|
||||||
|
|
||||||
|
$ mtn sync mtn://my.server.com/project1
|
||||||
|
|
||||||
|
then the database / repository of the indefero `project1` is used.
|
||||||
|
Note that 'mtn_remote_url' is also used as internal URI to query the data
|
||||||
|
for indefero's source view, so it *must* be a valid host!
|
||||||
|
|
||||||
|
Usher also allows the identification of a project repository by hostname,
|
||||||
|
which would allow an URL template like `mtn://%s.my.server.com`, however
|
||||||
|
the plugin does not write out the configuration which is needed for this
|
||||||
|
yet.
|
||||||
|
|
||||||
|
For even more advanced setups, usher can also be used to forward sync
|
||||||
|
requests to other remote servers for load balancing, please consult the
|
||||||
|
README file for more information.
|
||||||
|
|
||||||
|
## Security and remote access
|
||||||
|
|
||||||
|
Indefero distinguishs between public and private projects and so does
|
||||||
|
the monotone plugin.
|
||||||
|
|
||||||
|
Public projects can be pulled by everybody and pushed by team members
|
||||||
|
or additional invited people. Remote command execution is enabled, but
|
||||||
|
only for read-only commands.
|
||||||
|
|
||||||
|
Remote commands can be helpful for a user or a 3rd party tool (like
|
||||||
|
[mtn-browse](http://mtn-browse.sourceforge.net) or
|
||||||
|
[guitone](http://guitone.thomaskeller.biz)) to browse the database
|
||||||
|
contents remotely without having to pull everything in first instance.
|
||||||
|
|
||||||
|
Private projects on the other hand can only be synced by team members
|
||||||
|
or additional invited people. Remote command execution is disabled
|
||||||
|
by default. If you want to enable that, simply put the keys of the users
|
||||||
|
you want to give access to in your project's `remote-automate-permissions`
|
||||||
|
file. In the future this plugin might handle this file just as it handles
|
||||||
|
`read-permissions` and `write-permissions`.
|
||||||
|
|
||||||
|
## Notifications
|
||||||
|
|
||||||
|
If you have successfully set up your monotone instance, you probably want
|
||||||
|
to notify 3rd party systems for incoming changes or simply mirror them
|
||||||
|
somewhere else for backup purposes. The monotone source tree already comes
|
||||||
|
with [many example scripts and hooks](http://code.monotone.ca/p/monotone/source/tree/h:net.venge.monotone/contrib)
|
||||||
|
which serve these purposes, after only little additional configuration.
|
||||||
|
|
||||||
|
The usher/indefero-controlled setup automatically looks for *.lua files
|
||||||
|
in a directory called `hooks.d` right under the project's base directory
|
||||||
|
(configured via $cfg['mtn_repositories']) and this is the ideal place to
|
||||||
|
put or link these additional lua sources.
|
||||||
|
|
||||||
|
## Custom project configurations and templates
|
||||||
|
|
||||||
|
If a new project is created in IDF, the SyncMonotone plugin creates a new
|
||||||
|
configuration tree for the project into the project's configuration directory,
|
||||||
|
determined by `$cfg['mtn_repositories']`. IDF ships with the minimum set of
|
||||||
|
files for this configuration tree and sets up everything automatically for you.
|
||||||
|
|
||||||
|
Even more, most of the configuration files from the newly created tree are only
|
||||||
|
symlinked to the original configuration directory which is configurable via
|
||||||
|
`$cfg['mtn_confdir']` and defaults to `src/IDF/Plugin/SyncMonotone/`. This has
|
||||||
|
the advantage that your standard IDF setup automatically receives updates to
|
||||||
|
existing (symlinked) configuration files as soon as you update to a newer
|
||||||
|
version.
|
||||||
|
|
||||||
|
You could, however, also choose to place the directory tree somewhere else
|
||||||
|
and adapt the contents of the individual files yourself, so these changes get
|
||||||
|
automatically applied to all new projects you create. You could even go so far
|
||||||
|
and add new files to the tree and let them be processed automatically just
|
||||||
|
as the basic files! All you need to do is to copy your files and / or directories
|
||||||
|
underknees your `$cfg['mtn_confdir']` and add their relative paths to
|
||||||
|
`$cfg['mtn_confdir_extra']`.
|
||||||
|
|
||||||
|
By convention, all entries which end with a slash are considered directories,
|
||||||
|
so mkdir(1) is issued for these entries, all files which do not end up with
|
||||||
|
".in" are considered to be static script files which are just symlinked from
|
||||||
|
the basic configuration dir and all entries ending on ".in" are considered
|
||||||
|
configuration files or templates, which are copied over to the project's
|
||||||
|
configuration tree and which get some basic project-specific values replaced.
|
||||||
|
|
||||||
|
The following placeholders are currently recognized and replaced for these files:
|
||||||
|
|
||||||
|
* %%PROJECT%% - the name of the created project
|
||||||
|
* %%MTNPOSTPUSH%% - the absolute path to the `mtn-post-push` script
|
||||||
|
* %%MTNCLIENTKEY%% - the public key hash of the key which is used by IDF
|
||||||
|
to authenticate remote stdio access
|
||||||
|
|
||||||
|
Thats it - I hope you find it useful :)
|
||||||
|
|
||||||
|
## Q&A
|
||||||
|
|
||||||
|
### After I created a new project, IDF throws an exception and tells me that it couldn't save the membership data with a cryptic error message. Whats wrong?
|
||||||
|
|
||||||
|
Multiple issues could cause that. If you've set up usher, make sure the usher
|
||||||
|
can fork your database at all and look out for specific errors in the log file
|
||||||
|
of your project. If you stumble upon permission issues, ensure that the user
|
||||||
|
who runs the usher can access all files in your project's configuration directory,
|
||||||
|
including symlinked files.
|
||||||
|
|
||||||
|
### I pushed a branch to my server, but it does not show up in IDF. Whats wrong?
|
||||||
|
|
||||||
|
Check if the heads of your branch are not suspended, i.e. do not carry a
|
||||||
|
`suspend` certificate. This usually hides the branch and all of its history
|
||||||
|
from monotone's eyes and therefor also from indefero. You can either choose
|
||||||
|
to "unsuspend" the branch simply by committing and pushing another head or
|
||||||
|
by letting monotone ignore all suspend certs. For the latter, its usually
|
||||||
|
enough to add `--ignore-suspend-certs` to the list of options in `$cfg['mtn_opts']`.
|
||||||
|
|
||||||
|
### I want to display another default branch when I click the "Source" tab. How can I do that?
|
||||||
|
|
||||||
|
Let the forge admin know the new master branch for your project. He is able
|
||||||
|
to change that quickly. Depending on the backend / server setup this might
|
||||||
|
also require some changes in the usher configuration, but only if usher
|
||||||
|
recognizes and proxies your database on a branch name level.
|
||||||
|
|
@@ -66,6 +66,8 @@ need to put the following in your configuration file:
|
|||||||
$cfg['idf_plugin_syncsvn_authz_file'] = '/home/svn/dav_svn.authz';
|
$cfg['idf_plugin_syncsvn_authz_file'] = '/home/svn/dav_svn.authz';
|
||||||
$cfg['idf_plugin_syncsvn_passwd_file'] = '/home/svn/dav_svn.passwd';
|
$cfg['idf_plugin_syncsvn_passwd_file'] = '/home/svn/dav_svn.passwd';
|
||||||
$cfg['idf_plugin_syncsvn_svn_path'] = '/home/svn/repositories';
|
$cfg['idf_plugin_syncsvn_svn_path'] = '/home/svn/repositories';
|
||||||
|
// Delete the corresponding repository when deleting the project
|
||||||
|
$cfg['idf_plugin_syncsvn_remove_orphans'] = false;
|
||||||
|
|
||||||
You can have more control over the permissions given to the owners,
|
You can have more control over the permissions given to the owners,
|
||||||
members, extra authorized users and anonymous users if you want with
|
members, extra authorized users and anonymous users if you want with
|
||||||
@@ -77,3 +79,12 @@ the following configuration variables:
|
|||||||
* **idf_plugin_syncsvn_access_public ('r')**: Anonymous access.
|
* **idf_plugin_syncsvn_access_public ('r')**: Anonymous access.
|
||||||
* **idf_plugin_syncsvn_access_private ('')**: Anonymous access in the case of a private project.
|
* **idf_plugin_syncsvn_access_private ('')**: Anonymous access in the case of a private project.
|
||||||
|
|
||||||
|
## svn: Can't open file '/root/.subversion/servers': Permission denied error
|
||||||
|
|
||||||
|
If you get the error:
|
||||||
|
|
||||||
|
svn: Can't open file '/root/.subversion/servers': Permission denied
|
||||||
|
|
||||||
|
Check the [fix available](http://projects.ceondo.com/p/indefero/issues/458/)
|
||||||
|
|
||||||
|
|
||||||
|
86
logo/indefero-logo-lite.svg
Normal file
86
logo/indefero-logo-lite.svg
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<?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="16"
|
||||||
|
height="16"
|
||||||
|
id="svg2"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.48.0 r9654"
|
||||||
|
version="1.0"
|
||||||
|
sodipodi:docname="indefero-logo-lite.svg"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||||
|
<defs
|
||||||
|
id="defs4">
|
||||||
|
<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" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
gridtolerance="10000"
|
||||||
|
guidetolerance="10"
|
||||||
|
objecttolerance="10"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="11.313708"
|
||||||
|
inkscape:cx="31.568929"
|
||||||
|
inkscape:cy="-0.35578703"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1280"
|
||||||
|
inkscape:window-height="723"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="24"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<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" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(0,-728.09451)">
|
||||||
|
<g
|
||||||
|
id="g2401"
|
||||||
|
transform="matrix(0.13580542,0,0,0.13580542,-47.580342,708.10521)"
|
||||||
|
style="fill:#8ae234;stroke:#4e9a06;stroke-width:2.4000001;stroke-miterlimit:4;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:#8ae234;fill-opacity:1;fill-rule:nonzero;stroke:#4e9a06;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:#8ae234;fill-opacity:1;fill-rule:nonzero;stroke:#4e9a06;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>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.1 KiB |
248
logo/indefero-logo5.svg
Normal file
248
logo/indefero-logo5.svg
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
<?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:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="2500.0901"
|
||||||
|
height="1052.3622"
|
||||||
|
id="svg2"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.46"
|
||||||
|
sodipodi:docname="indefero-logo5.svg"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||||
|
version="1.0">
|
||||||
|
<defs
|
||||||
|
id="defs4">
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="linearGradient3535">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#8ae234;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3537" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#8ae234;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3539" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="linearGradient3527">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#9f5e21;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3529" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#9f5e21;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3531" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3309">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#73d213;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3311" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4e9a06;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3313" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3300">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#a56223;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3302" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#492902;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3304" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3214">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#c17d11;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3216" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#c17d11;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3218" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3200">
|
||||||
|
<stop
|
||||||
|
id="stop3204"
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#feaf36;stop-opacity:1;" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3178">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#8f5902;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3180" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#8f5902;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3182" />
|
||||||
|
</linearGradient>
|
||||||
|
<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" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3300"
|
||||||
|
id="linearGradient3502"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="255.2104"
|
||||||
|
y1="743.95398"
|
||||||
|
x2="517.18134"
|
||||||
|
y2="334.32626" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3309"
|
||||||
|
id="linearGradient3505"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.90055,0,0,0.9256685,8.702072,50.919096)"
|
||||||
|
x1="314.81146"
|
||||||
|
y1="549.55981"
|
||||||
|
x2="603.79364"
|
||||||
|
y2="130.80347" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3527"
|
||||||
|
id="linearGradient3533"
|
||||||
|
x1="344.48004"
|
||||||
|
y1="526.93384"
|
||||||
|
x2="279.66428"
|
||||||
|
y2="343.77176"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3535"
|
||||||
|
id="linearGradient3541"
|
||||||
|
x1="189.38306"
|
||||||
|
y1="542.79291"
|
||||||
|
x2="213.16689"
|
||||||
|
y2="515.03833"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
gridtolerance="10000"
|
||||||
|
guidetolerance="10"
|
||||||
|
objecttolerance="10"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.26121807"
|
||||||
|
inkscape:cx="54.404882"
|
||||||
|
inkscape:cy="468.48648"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1279"
|
||||||
|
inkscape:window-height="951"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="25" />
|
||||||
|
<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" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#2e1c09;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:9.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect3479"
|
||||||
|
width="2327.0989"
|
||||||
|
height="738.08856"
|
||||||
|
x="28.861307"
|
||||||
|
y="47.247032"
|
||||||
|
ry="0"
|
||||||
|
inkscape:export-filename="/home/loa/Projects/indefero.net/media/idfn/img/indefero-logo.png"
|
||||||
|
inkscape:export-xdpi="10.974293"
|
||||||
|
inkscape:export-ydpi="10.974293" />
|
||||||
|
<path
|
||||||
|
style="fill:url(#linearGradient3505);fill-opacity:1;fill-rule:nonzero;stroke:#4e9a06;stroke-width:8.6737175;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
d="M 380.09452,80.164434 C 325.61878,80.164434 277.73831,109.63179 250.44346,154.01542 C 173.08362,161.38346 112.57489,224.77008 112.57489,301.77525 C 112.57489,328.86745 120.06848,354.27485 133.14683,376.14693 C 107.0966,405.29318 91.243109,443.82739 91.243109,486.07006 C 91.243109,576.90189 164.55915,650.60763 254.88993,650.60763 C 271.09473,650.60763 286.73713,648.22781 301.52154,643.80975 C 339.34139,666.58702 385.02955,679.88189 434.18381,679.88189 C 564.58392,679.88189 670.40931,586.17696 670.40933,470.70975 C 670.40933,424.81133 653.66603,382.36023 625.32555,347.85618 C 628.73221,333.4146 630.53185,318.20844 630.53185,302.49843 C 630.53185,212.12462 570.29216,138.17535 494.43623,133.1011 C 466.29611,100.61828 425.47491,80.164434 380.09452,80.164434 z"
|
||||||
|
id="path2397"
|
||||||
|
inkscape:export-filename="/home/loa/Projects/indefero.net/media/idfn/img/indefero-logo.png"
|
||||||
|
inkscape:export-xdpi="10.974293"
|
||||||
|
inkscape:export-ydpi="10.974293" />
|
||||||
|
<path
|
||||||
|
style="fill:url(#linearGradient3502);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.40000010000000019;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
d="M 480.78826,286.70465 C 471.74217,303.14801 466.59919,316.91871 462.21007,324.32034 C 458.4305,332.41806 437.64848,381.27668 422.04792,410.85567 C 411.43569,432.35724 400.69212,454.31445 384.28125,472.09375 C 378.04049,477.37818 367.78727,475.23418 363.26933,468.71428 C 353.17919,458.89555 343.45836,448.70244 333.24758,439.0075 C 317.77144,422.84753 305.56098,403.5827 297.62915,382.65768 C 289.88676,365.17614 282.06423,347.03016 268.29833,333.33399 C 266.87079,332.00892 257.87723,342.72971 251.17151,350.13535 C 257.91944,385.02379 261.45712,393.83832 272.16171,424.59112 C 277.97988,444.06591 287.52802,462.10601 295.01596,480.9416 C 301.95377,497.73482 307.73336,515.11749 310.44798,533.13227 C 316.97458,571.06863 313.78852,610.29702 303.54294,647.28446 C 295.53018,678.50408 283.87873,708.83248 268.40625,737.125 C 267.48586,741.82958 273.28765,745.0451 277.32903,743.60868 C 316.10441,740.6132 354.85515,736.72668 393.76368,736.01019 C 432.08809,735.62752 470.30781,739.07963 508.44819,742.41755 C 512.60098,742.7876 516.75356,743.16004 520.90625,743.53125 C 522.73666,738.32781 518.93119,733.37885 515.5,729.84375 C 505.37922,718.85052 495.85001,707.33025 486.04792,696.05659 C 472.12065,679.28224 459.49275,660.74518 453.48949,639.55179 C 445.74909,613.54378 446.01072,585.89039 449.3871,559.18722 C 454.13621,520.65521 457.70434,476.90793 468.12716,439.5747 C 475.03595,414.82825 499.26944,325.16045 505.28557,302.9463 C 506.6387,297.45482 507.70151,291.88947 508.4375,286.28125 C 508.3006,286.02979 501.31023,285.50092 480.78826,286.70465 z"
|
||||||
|
id="rect2383"
|
||||||
|
sodipodi:nodetypes="ccscscscccccccccccccccsccc"
|
||||||
|
inkscape:export-filename="/home/loa/Projects/indefero.net/media/idfn/img/indefero-logo.png"
|
||||||
|
inkscape:export-xdpi="10.974293"
|
||||||
|
inkscape:export-ydpi="10.974293" />
|
||||||
|
<path
|
||||||
|
style="fill:url(#linearGradient3533);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.25000000000000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 261.61445,343.77177 C 258.29796,347.16111 256.78029,348.5143 253.80525,350.94005 C 257.34812,367.72635 271.24491,410.33512 274.92704,420.91638 C 283.98781,446.95407 298.27703,470.44926 305.96388,496.81755 C 312.6285,519.6793 316.95796,541.99153 318.18734,565.63445 C 319.43684,589.66412 317.35056,617.16231 311.24725,640.25675 C 304.22544,666.82669 289.67219,709.81256 278.71119,735.38821 C 291.85032,736.74081 303.9092,734.30172 317.58611,733.28738 C 330.8032,732.91089 346.51711,728.41602 360.28427,728.58961 C 361.70248,692.98386 362.28914,639.87401 361.91883,606.08799 C 361.53577,571.13943 356.10739,550.49134 343.0934,518.4162 C 332.76842,492.96857 313.62977,457.39972 298.73254,430.34797 C 283.83531,403.29622 270.0195,371.02282 261.61445,343.77177 z"
|
||||||
|
id="path3450"
|
||||||
|
sodipodi:nodetypes="ccsssscccsssc"
|
||||||
|
inkscape:export-filename="/home/loa/Projects/indefero.net/media/idfn/img/indefero-logo.png"
|
||||||
|
inkscape:export-xdpi="10.974293"
|
||||||
|
inkscape:export-ydpi="10.974293" />
|
||||||
|
<path
|
||||||
|
style="fill:url(#linearGradient3541);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.25000000000000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 113.16529,429.39362 C 113.16529,429.39362 104.64326,454.1652 103.03794,468.69107 C 101.44344,483.11903 102.46825,506.23771 105.4804,520.43755 C 108.98801,536.97308 121.29761,558.93795 130.281,573.25668 C 138.61935,586.54728 158.09648,604.51753 171.10612,613.28778 C 185.25725,622.82754 205.57955,633.4095 222.19789,637.29436 C 239.00231,641.22271 255.43702,641.52676 272.63495,640.09436 C 278.21565,639.62955 302.26007,633.26385 302.26007,633.26385 L 308.87233,606.09973 L 113.16529,429.39362 z"
|
||||||
|
id="path3461"
|
||||||
|
sodipodi:nodetypes="cssssssccc"
|
||||||
|
inkscape:export-filename="/home/loa/Projects/indefero.net/media/idfn/img/indefero-logo.png"
|
||||||
|
inkscape:export-xdpi="10.974293"
|
||||||
|
inkscape:export-ydpi="10.974293" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:500px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;writing-mode:lr-tb;text-anchor:start;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FromageCondOblique;-inkscape-font-specification:FromageCondOblique"
|
||||||
|
x="739.95435"
|
||||||
|
y="534.80164"
|
||||||
|
id="text3481"
|
||||||
|
inkscape:export-filename="/home/loa/Projects/indefero.net/media/idfn/img/indefero-logo.png"
|
||||||
|
inkscape:export-xdpi="10.974293"
|
||||||
|
inkscape:export-ydpi="10.974293"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3483"
|
||||||
|
x="739.95435"
|
||||||
|
y="534.80164">indefero</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:150px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FromageCondOblique;-inkscape-font-specification:FromageCondOblique"
|
||||||
|
x="744.05432"
|
||||||
|
y="711.55402"
|
||||||
|
id="text3485"
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
inkscape:export-filename="/home/loa/Projects/indefero.net/media/idfn/img/indefero-logo.png"
|
||||||
|
inkscape:export-xdpi="10.974293"
|
||||||
|
inkscape:export-ydpi="10.974293"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3487"
|
||||||
|
x="744.05432"
|
||||||
|
y="711.55402"
|
||||||
|
style="letter-spacing:5.01085806">Better code management</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 12 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>
|
||||||
|
|
@@ -1,10 +1,13 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
last="$1"
|
last="$1"
|
||||||
new="$2"
|
new="$2"
|
||||||
|
PLUF_PATH=`php -r "require_once('./IDF/conf/path.php'); echo PLUF_PATH;"`
|
||||||
|
echo "php $PLUF_PATH/extracttemplates.php ./IDF/conf/idf.php ./IDF/gettexttemplates"
|
||||||
echo "xgettext -o idf.pot -p ./IDF/locale --force-po --from-code=UTF-8 --keyword --keyword=__ --keyword=_n:1,2 -L PHP ./IDF/*.php"
|
echo "xgettext -o idf.pot -p ./IDF/locale --force-po --from-code=UTF-8 --keyword --keyword=__ --keyword=_n:1,2 -L PHP ./IDF/*.php"
|
||||||
echo "find ./ -iname \"*.php\" -exec xgettext -o idf.pot -p ./IDF/locale/ --from-code=UTF-8 -j --keyword --keyword=__ --keyword=_n:1,2 -L PHP {} \;"
|
echo "find ./ -iname \"*.php\" -exec xgettext -o idf.pot -p ./IDF/locale/ --from-code=UTF-8 -j --keyword --keyword=__ --keyword=_n:1,2 -L PHP {} \;"
|
||||||
|
echo 'for pofile in `ls ./IDF/locale/*/idf.po`; do msgmerge -U $pofile ./IDF/locale/idf.pot; done'
|
||||||
echo "# git tag v$new"
|
echo "# git tag v$new"
|
||||||
echo "git archive --format=zip --prefix=indefero-$new/ v$new > indefero-$new.zip"
|
echo "git archive --format=zip --prefix=indefero-$new/ v$new > indefero-$new.zip"
|
||||||
echo "git log --no-merges v$new ^v$last > ChangeLog-$new"
|
echo "git log --no-merges v$new ^v$last > ChangeLog-$new"
|
||||||
echo "git shortlog --no-merges v$new ^v$last > ShortLog"
|
echo "git shortlog --no-merges v$new ^v$last > ShortLog"
|
||||||
echo "git diff --stat --summary -M v$last v$new > diffstat-$new"
|
echo "git diff --stat --summary -M v$last v$new > diffstat-$new"
|
||||||
|
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='.$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)
|
||||||
|
);
|
||||||
|
|
0
scripts/SyncMercurial.sh
Normal file → Executable file
0
scripts/SyncMercurial.sh
Normal file → Executable file
24
scripts/git-post-update
Executable file
24
scripts/git-post-update
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# This hook does only one thing:
|
||||||
|
#
|
||||||
|
# 1. It calls the gitpostupdate.php script with the current $GIT_DIR
|
||||||
|
# as argument. The gitpostupdate.php script will then trigger
|
||||||
|
# the 'gitpostupdate.php::run' event with the $GIT_DIR as argument
|
||||||
|
# together with merged $_ENV and $_SERVER array.
|
||||||
|
#
|
||||||
|
# This hook is normally installed automatically at the creation of your
|
||||||
|
# repository if you have everything configured correctly. If you want
|
||||||
|
# to enable it later, you need to symlink it as "post-update" in your
|
||||||
|
# $GIT_DIR/hooks folder.
|
||||||
|
#
|
||||||
|
# www$ chmod +x /home/www/indefero/scripts/git-post-update
|
||||||
|
# git$ cd /home/git/repositories/project.git/hooks
|
||||||
|
# git$ ln -s /home/www/indefero/scripts/git-post-update post-update
|
||||||
|
#
|
||||||
|
|
||||||
|
SCRIPTDIR=$(dirname $(readlink $0))
|
||||||
|
FULL_GIT_DIR=$(cd "$GIT_DIR" && /bin/pwd || "$GIT_DIR")
|
||||||
|
PHP_POST_UPDATE=$SCRIPTDIR/gitpostupdate.php
|
||||||
|
|
||||||
|
echo php $PHP_POST_UPDATE $FULL_GIT_DIR | at now > /dev/null 2>&1
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -22,18 +22,12 @@
|
|||||||
# ***** END LICENSE BLOCK ***** */
|
# ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This script is used to control the access to the git repositories
|
* This script is used to sync the SSH keys, mark the repositories for
|
||||||
* using a restricted shell access.
|
* export and prune the deleted repositories.
|
||||||
*
|
*
|
||||||
* The only argument must be the login of the user.
|
|
||||||
*/
|
*/
|
||||||
// Set the include path to have Pluf and IDF in it.
|
|
||||||
$indefero_path = dirname(__FILE__).'/../src';
|
require dirname(__FILE__).'/../src/IDF/conf/path.php';
|
||||||
//$pluf_path = '/path/to/pluf/src';
|
|
||||||
set_include_path(get_include_path()
|
|
||||||
.PATH_SEPARATOR.$indefero_path
|
|
||||||
// .PATH_SEPARATOR.$pluf_path
|
|
||||||
);
|
|
||||||
require 'Pluf.php';
|
require 'Pluf.php';
|
||||||
Pluf::start(dirname(__FILE__).'/../src/IDF/conf/idf.php');
|
Pluf::start(dirname(__FILE__).'/../src/IDF/conf/idf.php');
|
||||||
Pluf_Dispatcher::loadControllers(Pluf::f('idf_views'));
|
Pluf_Dispatcher::loadControllers(Pluf::f('idf_views'));
|
||||||
|
59
scripts/gitpostupdate.php
Normal file
59
scripts/gitpostupdate.php
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<?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 will send the notifications after a push in your
|
||||||
|
* repository.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require dirname(__FILE__).'/../src/IDF/conf/path.php';
|
||||||
|
require 'Pluf.php';
|
||||||
|
Pluf::start(dirname(__FILE__).'/../src/IDF/conf/idf.php');
|
||||||
|
Pluf_Dispatcher::loadControllers(Pluf::f('idf_views'));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [signal]
|
||||||
|
*
|
||||||
|
* gitpostupdate.php::run
|
||||||
|
*
|
||||||
|
* [sender]
|
||||||
|
*
|
||||||
|
* gitpostupdate.php
|
||||||
|
*
|
||||||
|
* [description]
|
||||||
|
*
|
||||||
|
* This signal allows an application to perform a set of tasks on a
|
||||||
|
* post update of a git repository.
|
||||||
|
*
|
||||||
|
* [parameters]
|
||||||
|
*
|
||||||
|
* array('git_dir' => '/path/to/git/repository.git',
|
||||||
|
* 'env' => array_merge($_ENV, $_SERVER));
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$params = array('git_dir' => $argv[1],
|
||||||
|
'env' => array_merge($_ENV, $_SERVER));
|
||||||
|
Pluf_Log::event(array('gitpostupdate.php', 'Send run signal.', $params));
|
||||||
|
Pluf_Signal::send('gitpostupdate.php::run', 'gitpostupdate.php', $params);
|
||||||
|
|
||||||
|
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -27,13 +27,8 @@
|
|||||||
*
|
*
|
||||||
* The only argument must be the login of the user.
|
* The only argument must be the login of the user.
|
||||||
*/
|
*/
|
||||||
// Set the include path to have Pluf and IDF in it.
|
|
||||||
$indefero_path = dirname(__FILE__).'/../src';
|
require dirname(__FILE__).'/../src/IDF/conf/path.php';
|
||||||
//$pluf_path = '/path/to/pluf/src';
|
|
||||||
set_include_path(get_include_path()
|
|
||||||
.PATH_SEPARATOR.$indefero_path
|
|
||||||
// .PATH_SEPARATOR.$pluf_path
|
|
||||||
);
|
|
||||||
require 'Pluf.php';
|
require 'Pluf.php';
|
||||||
Pluf::start(dirname(__FILE__).'/../src/IDF/conf/idf.php');
|
Pluf::start(dirname(__FILE__).'/../src/IDF/conf/idf.php');
|
||||||
Pluf_Dispatcher::loadControllers(Pluf::f('idf_views'));
|
Pluf_Dispatcher::loadControllers(Pluf::f('idf_views'));
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -23,14 +23,17 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import commands
|
import subprocess
|
||||||
import traceback
|
|
||||||
|
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:
|
if status == 0:
|
||||||
os.execvp('git', ['git', 'shell', '-c', output.strip()])
|
os.execvp('git', ['git', 'shell', '-c', output.strip()])
|
||||||
else:
|
else:
|
||||||
sys.stderr.write("%s\n" % output)
|
sys.stderr.write("%s\n" % output.strip())
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
61
scripts/hgchangegroup.php
Executable file
61
scripts/hgchangegroup.php
Executable file
@@ -0,0 +1,61 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?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 will send the notifications after a push in your
|
||||||
|
* repository.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require dirname(__FILE__).'/../src/IDF/conf/path.php';
|
||||||
|
require 'Pluf.php';
|
||||||
|
Pluf::start(dirname(__FILE__).'/../src/IDF/conf/idf.php');
|
||||||
|
Pluf_Dispatcher::loadControllers(Pluf::f('idf_views'));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [signal]
|
||||||
|
*
|
||||||
|
* hgchangegroup.php::run
|
||||||
|
*
|
||||||
|
* [sender]
|
||||||
|
*
|
||||||
|
* hgchangegroup.php
|
||||||
|
*
|
||||||
|
* [description]
|
||||||
|
*
|
||||||
|
* This signal allows an application to perform a set of tasks on a
|
||||||
|
* group change hook of a Mercurial repository. The rel_dir is a
|
||||||
|
* relative path to the root of your hg repositories but starting with
|
||||||
|
* a slash.
|
||||||
|
*
|
||||||
|
* [parameters]
|
||||||
|
*
|
||||||
|
* array('rel_dir' => '/relative/path/to/hg/repository',
|
||||||
|
* 'env' => array_merge($_ENV, $_SERVER));
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$params = array('rel_dir' => $_ENV['PATH_INFO'],
|
||||||
|
'env' => array_merge($_ENV, $_SERVER));
|
||||||
|
Pluf_Signal::send('hgchangegroup.php::run', 'hgchangegroup.php', $params);
|
||||||
|
|
||||||
|
|
22
scripts/mtn-post-push
Executable file
22
scripts/mtn-post-push
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# This hook informs IDF that new revisions arrived in the database
|
||||||
|
# of the specified project.
|
||||||
|
#
|
||||||
|
# This hook is normally installed automatically at the creation of your
|
||||||
|
# repository if you have everything configured correctly. If you want
|
||||||
|
# to enable it later, you need to call it into your monotonerc file
|
||||||
|
# from the hook "note_netsync_end". (See chapter "Event Notifications
|
||||||
|
# and Triggers" on <http://monotone.ca/docs/Hooks.html#Hooks>.)
|
||||||
|
#
|
||||||
|
|
||||||
|
dir=$(dirname "$0")
|
||||||
|
res=$(cd "$dir" && /bin/pwd || "$dir")
|
||||||
|
SCRIPTDIR="$res/$(readlink $0)"
|
||||||
|
PHP_POST_PUSH=$SCRIPTDIR/mtnpostpush.php
|
||||||
|
|
||||||
|
TMPFILE=$(mktemp /tmp/mtn-post-push.XXXXXX) || exit 1
|
||||||
|
while read rev; do echo $rev >> $TMPFILE; done
|
||||||
|
|
||||||
|
echo php $PHP_POST_PUSH "$1" \< $TMPFILE \&\& rm -f $TMPFILE |\
|
||||||
|
at now > /dev/null 2>&1
|
63
scripts/mtnpostpush.php
Normal file
63
scripts/mtnpostpush.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 ***** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This script will send the notifications after a push in your
|
||||||
|
* repository.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require dirname(__FILE__).'/../src/IDF/conf/path.php';
|
||||||
|
require 'Pluf.php';
|
||||||
|
Pluf::start(dirname(__FILE__).'/../src/IDF/conf/idf.php');
|
||||||
|
Pluf_Dispatcher::loadControllers(Pluf::f('idf_views'));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [signal]
|
||||||
|
*
|
||||||
|
* mtnpostpush.php::run
|
||||||
|
*
|
||||||
|
* [sender]
|
||||||
|
*
|
||||||
|
* mtnpostpush.php
|
||||||
|
*
|
||||||
|
* [description]
|
||||||
|
*
|
||||||
|
* This signal allows an application to perform a set of tasks
|
||||||
|
* after a push to a monotone repository.
|
||||||
|
*
|
||||||
|
* [parameters]
|
||||||
|
*
|
||||||
|
* array('project' => 'name-of-the-project',
|
||||||
|
* 'revisions' => array('123abc...', '456def...', ...));
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
fwrite(STDERR, "waiting for revisions on STDIN...\n");
|
||||||
|
$stdin = file_get_contents('php://stdin');
|
||||||
|
|
||||||
|
$params = array('project' => $argv[1],
|
||||||
|
'revisions' => explode("\n", chop($stdin)));
|
||||||
|
Pluf_Signal::send('mtnpostpush.php::run', 'mtnpostpush.php', $params);
|
||||||
|
|
||||||
|
|
||||||
|
|
69
scripts/queuecron.php
Normal file
69
scripts/queuecron.php
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<?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 process the queue of items.
|
||||||
|
*
|
||||||
|
* At the moment the queue is only used for the webhooks, but it would
|
||||||
|
* be good in the future to use it for indexing and email
|
||||||
|
* notifications.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
require dirname(__FILE__).'/../src/IDF/conf/path.php';
|
||||||
|
require 'Pluf.php';
|
||||||
|
Pluf::start(dirname(__FILE__).'/../src/IDF/conf/idf.php');
|
||||||
|
Pluf_Dispatcher::loadControllers(Pluf::f('idf_views'));
|
||||||
|
|
||||||
|
#;*/ ::
|
||||||
|
$lock_file = Pluf::f('idf_queuecron_lock',
|
||||||
|
Pluf::f('tmp_folder', '/tmp').'/queuecron.lock');
|
||||||
|
if (file_exists($lock_file)) {
|
||||||
|
Pluf_Log::event(array('queuecron.php', 'skip'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
file_put_contents($lock_file, time(), LOCK_EX);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [signal]
|
||||||
|
*
|
||||||
|
* queuecron.php::run
|
||||||
|
*
|
||||||
|
* [sender]
|
||||||
|
*
|
||||||
|
* queuecron.php
|
||||||
|
*
|
||||||
|
* [description]
|
||||||
|
*
|
||||||
|
* This signal allows an application to perform a set of tasks when
|
||||||
|
* the queue cron job is run. This is done usually every 5 minutes.
|
||||||
|
*
|
||||||
|
* [parameters]
|
||||||
|
*
|
||||||
|
* array()
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$params = array();
|
||||||
|
Pluf_Signal::send('queuecron.php::run', 'queuecron.php', $params);
|
||||||
|
|
||||||
|
unlink($lock_file);
|
24
scripts/svn-post-commit
Executable file
24
scripts/svn-post-commit
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# This hook does only one thing:
|
||||||
|
#
|
||||||
|
# 1. It calls the svnpostcommit.php script with the current repository
|
||||||
|
# and revision as argument. The svnpostcommit.php script will then
|
||||||
|
# trigger the 'svnpostcommit.php::run' event with the repository path
|
||||||
|
# and revision as arguments together with merged $_ENV and $_SERVER
|
||||||
|
# array.
|
||||||
|
#
|
||||||
|
# This hook is normally installed automatically at the creation of your
|
||||||
|
# repository if you have everything configured correctly. If you want
|
||||||
|
# to enable it later, you need to symlink it as "post-commit" in your
|
||||||
|
# $REPOSITORY/hooks folder.
|
||||||
|
#
|
||||||
|
# www$ chmod +x /home/www/indefero/scripts/svn-post-commit
|
||||||
|
# www$ cd /home/svn/repositories/project/hooks
|
||||||
|
# www$ ln -s /home/www/indefero/scripts/svn-post-commit post-commit
|
||||||
|
#
|
||||||
|
|
||||||
|
SCRIPTDIR=$(dirname $(readlink $0))
|
||||||
|
PHP_POST_COMMIT=$SCRIPTDIR/svnpostcommit.php
|
||||||
|
|
||||||
|
echo php $PHP_POST_COMMIT "$1" "$2" | at now > /dev/null 2>&1
|
29
scripts/svn-post-revprop-change
Executable file
29
scripts/svn-post-revprop-change
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# This hook does only one thing:
|
||||||
|
#
|
||||||
|
# 1. It calls the svnpostrevpropchange.php script with the current repository
|
||||||
|
# and revision as argument. The svnpostrevpropchange.php script will then
|
||||||
|
# trigger the 'svnpostrevpropchange.php::run' event with the repository
|
||||||
|
# path, revision, username, property name and action as arguments together
|
||||||
|
# with merged $_ENV and $_SERVER array.
|
||||||
|
#
|
||||||
|
# This hook is normally installed automatically at the creation of your
|
||||||
|
# repository if you have everything configured correctly. If you want
|
||||||
|
# to enable it later, you need to symlink it as "post-revprop-change" in your
|
||||||
|
# $REPOSITORY/hooks folder. It needs to be executable.
|
||||||
|
#
|
||||||
|
# www$ chmod +x /home/www/indefero/scripts/svn-post-revprop-change
|
||||||
|
# www$ cd /home/svn/repositories/project/hooks
|
||||||
|
# www$ ln -s /home/www/indefero/scripts/svn-post-revprop-change post-revprop-change
|
||||||
|
#
|
||||||
|
|
||||||
|
SCRIPTDIR=$(dirname $(readlink $0))
|
||||||
|
PHP_POST_REVPROP=$SCRIPTDIR/svnpostrevpropchange.php
|
||||||
|
|
||||||
|
echo php $PHP_POST_REVPROP "$1" "$2" "$3" "$4" "$5" | at now > /dev/null 2>&1
|
||||||
|
REPOS="$1"
|
||||||
|
REV="$2"
|
||||||
|
USER="$3"
|
||||||
|
PROPNAME="$4"
|
||||||
|
ACTION="$5"
|
62
scripts/svnpostcommit.php
Normal file
62
scripts/svnpostcommit.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 ***** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This script will send the notifications after a push in your
|
||||||
|
* repository.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require dirname(__FILE__).'/../src/IDF/conf/path.php';
|
||||||
|
require 'Pluf.php';
|
||||||
|
Pluf::start(dirname(__FILE__).'/../src/IDF/conf/idf.php');
|
||||||
|
Pluf_Dispatcher::loadControllers(Pluf::f('idf_views'));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [signal]
|
||||||
|
*
|
||||||
|
* svnpostcommit.php::run
|
||||||
|
*
|
||||||
|
* [sender]
|
||||||
|
*
|
||||||
|
* svnpostcommit.php
|
||||||
|
*
|
||||||
|
* [description]
|
||||||
|
*
|
||||||
|
* This signal allows an application to perform a set of tasks on a
|
||||||
|
* post commit of a subversion repository.
|
||||||
|
*
|
||||||
|
* [parameters]
|
||||||
|
*
|
||||||
|
* array('repo_dir' => '/path/to/subversion/repository',
|
||||||
|
* 'revision' => 1234,
|
||||||
|
* 'env' => array_merge($_ENV, $_SERVER));
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$params = array('repo_dir' => $argv[1],
|
||||||
|
'revision' => $argv[2],
|
||||||
|
'env' => array_merge($_ENV, $_SERVER));
|
||||||
|
Pluf_Log::event(array('svnpostcommit.php', 'Send run signal.', $params));
|
||||||
|
Pluf_Signal::send('svnpostcommit.php::run', 'svnpostcommit.php', $params);
|
||||||
|
|
||||||
|
|
||||||
|
|
70
scripts/svnpostrevpropchange.php
Normal file
70
scripts/svnpostrevpropchange.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 ***** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This script allows you to hook into the post-revprop-change action
|
||||||
|
* of your subversion repository. I am using it to perform near real
|
||||||
|
* time backup of the repositories on indefero.net.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require dirname(__FILE__).'/../src/IDF/conf/path.php';
|
||||||
|
require 'Pluf.php';
|
||||||
|
Pluf::start(dirname(__FILE__).'/../src/IDF/conf/idf.php');
|
||||||
|
Pluf_Dispatcher::loadControllers(Pluf::f('idf_views'));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [signal]
|
||||||
|
*
|
||||||
|
* svnpostrevpropchange.php::run
|
||||||
|
*
|
||||||
|
* [sender]
|
||||||
|
*
|
||||||
|
* svnpostrevpropchange.php
|
||||||
|
*
|
||||||
|
* [description]
|
||||||
|
*
|
||||||
|
* This signal allows an application to perform a set of tasks on a
|
||||||
|
* post property revision change of a subversion repository.
|
||||||
|
*
|
||||||
|
* [parameters]
|
||||||
|
*
|
||||||
|
* array('repo_dir' => '/path/to/subversion/repository',
|
||||||
|
* 'revision' => 1234,
|
||||||
|
* 'user' => 'username',
|
||||||
|
* 'propname' => 'changed-property',
|
||||||
|
* 'action' => 'the action M, A or D',
|
||||||
|
* 'env' => array_merge($_ENV, $_SERVER));
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
$params = array('repo_dir' => $argv[1],
|
||||||
|
'revision' => $argv[2],
|
||||||
|
'user' => $argv[3],
|
||||||
|
'propname' => $argv[4],
|
||||||
|
'action' => $argv[5],
|
||||||
|
'env' => array_merge($_ENV, $_SERVER));
|
||||||
|
Pluf_Signal::send('svnpostrevpropchange.php::run', 'svnpostrevpropchange.php',
|
||||||
|
$params);
|
||||||
|
|
||||||
|
|
||||||
|
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
# InDefero 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
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
n# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU 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
|
# along with this program; if not, write to the Free Software
|
||||||
@@ -34,6 +34,7 @@ Pluf::loadFunction('Pluf_Template_dateAgo');
|
|||||||
class IDF_Commit extends Pluf_Model
|
class IDF_Commit extends Pluf_Model
|
||||||
{
|
{
|
||||||
public $_model = __CLASS__;
|
public $_model = __CLASS__;
|
||||||
|
public $extra = null; /**< Extra data as IDF_Gconf object */
|
||||||
|
|
||||||
function init()
|
function init()
|
||||||
{
|
{
|
||||||
@@ -44,9 +45,9 @@ class IDF_Commit extends Pluf_Model
|
|||||||
'id' =>
|
'id' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Sequence',
|
'type' => 'Pluf_DB_Field_Sequence',
|
||||||
'blank' => true,
|
'blank' => true,
|
||||||
),
|
),
|
||||||
'project' =>
|
'project' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||||
'model' => 'IDF_Project',
|
'model' => 'IDF_Project',
|
||||||
@@ -54,7 +55,7 @@ class IDF_Commit extends Pluf_Model
|
|||||||
'verbose' => __('project'),
|
'verbose' => __('project'),
|
||||||
'relate_name' => 'commits',
|
'relate_name' => 'commits',
|
||||||
),
|
),
|
||||||
'author' =>
|
'author' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||||
'model' => 'Pluf_User',
|
'model' => 'Pluf_User',
|
||||||
@@ -118,7 +119,7 @@ class IDF_Commit extends Pluf_Model
|
|||||||
{
|
{
|
||||||
IDF_Search::index($this);
|
IDF_Search::index($this);
|
||||||
if ($create) {
|
if ($create) {
|
||||||
IDF_Timeline::insert($this, $this->get_project(),
|
IDF_Timeline::insert($this, $this->get_project(),
|
||||||
$this->get_author(), $this->creation_dtime);
|
$this->get_author(), $this->creation_dtime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,6 +128,7 @@ class IDF_Commit extends Pluf_Model
|
|||||||
{
|
{
|
||||||
IDF_Timeline::remove($this);
|
IDF_Timeline::remove($this);
|
||||||
IDF_Search::remove($this);
|
IDF_Search::remove($this);
|
||||||
|
IDF_Gconf::dropForModel($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,51 +144,82 @@ class IDF_Commit extends Pluf_Model
|
|||||||
array($project->id, $change->commit));
|
array($project->id, $change->commit));
|
||||||
$r = Pluf::factory('IDF_Commit')->getList(array('filter'=>$sql->gen()));
|
$r = Pluf::factory('IDF_Commit')->getList(array('filter'=>$sql->gen()));
|
||||||
if ($r->count() > 0) {
|
if ($r->count() > 0) {
|
||||||
|
$r[0]->extra = new IDF_Gconf();
|
||||||
|
$r[0]->extra->serialize = true;
|
||||||
|
$r[0]->extra->setModel($r[0]);
|
||||||
|
$r[0]->extra->initCache();
|
||||||
return $r[0];
|
return $r[0];
|
||||||
}
|
}
|
||||||
|
if (!isset($change->full_message)) {
|
||||||
|
$change->full_message = '';
|
||||||
|
}
|
||||||
$scm = IDF_Scm::get($project);
|
$scm = IDF_Scm::get($project);
|
||||||
$commit = new IDF_Commit();
|
$commit = new IDF_Commit();
|
||||||
$commit->project = $project;
|
$commit->project = $project;
|
||||||
$commit->scm_id = $change->commit;
|
$commit->scm_id = $change->commit;
|
||||||
$commit->summary = $change->title;
|
$commit->summary = self::toUTF8($change->title);
|
||||||
$commit->fullmessage = $change->full_message;
|
$commit->fullmessage = self::toUTF8($change->full_message);
|
||||||
$commit->author = $scm->findAuthor($change->author);
|
$commit->author = $scm->findAuthor($change->author);
|
||||||
$commit->origauthor = $change->author;
|
$commit->origauthor = self::toUTF8($change->author);
|
||||||
$commit->creation_dtime = $change->date;
|
$commit->creation_dtime = $change->date;
|
||||||
$commit->create();
|
$commit->create();
|
||||||
// We notify the creation of the commit
|
$extra = $scm->getExtraProperties($change);
|
||||||
if ('' != $project->getConf()->getVal('source_notification_email', '')) {
|
$commit->extra = new IDF_Gconf();
|
||||||
$context = new Pluf_Template_Context(
|
$commit->extra->serialize = true; // As we can store arrays
|
||||||
array(
|
$commit->extra->setModel($commit);
|
||||||
'c' => $commit,
|
foreach ($extra as $key => $val) {
|
||||||
'project' => $project,
|
$commit->extra->setVal($key, $val);
|
||||||
'url_base' => Pluf::f('url_base'),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$tmpl = new Pluf_Template('idf/source/commit-created-email.txt');
|
|
||||||
$text_email = $tmpl->render($context);
|
|
||||||
$email = new Pluf_Mail(Pluf::f('from_email'),
|
|
||||||
$project->getConf()->getVal('source_notification_email'),
|
|
||||||
sprintf(__('New Commit %s - %s (%s)'),
|
|
||||||
$commit->scm_id, $commit->summary, $project->shortname));
|
|
||||||
$email->addTextMessage($text_email);
|
|
||||||
$email->sendMail();
|
|
||||||
}
|
}
|
||||||
|
$commit->notify($project->getConf());
|
||||||
return $commit;
|
return $commit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert encoding to UTF8.
|
||||||
|
*
|
||||||
|
* If an array is given, the encoding is detected only on the
|
||||||
|
* first value and then used to convert all the strings.
|
||||||
|
*
|
||||||
|
* @param mixed String or array of string to be converted
|
||||||
|
* @param bool Returns the encoding together with the converted text (false)
|
||||||
|
* @return mixed String or array of string or array of res + encoding
|
||||||
|
*/
|
||||||
|
public static function toUTF8($text, $get_encoding=False)
|
||||||
|
{
|
||||||
|
$enc = 'ASCII, UTF-8, ISO-8859-1, JIS, EUC-JP, SJIS';
|
||||||
|
$ref = $text;
|
||||||
|
if (is_array($text)) {
|
||||||
|
$ref = $text[0];
|
||||||
|
}
|
||||||
|
if (Pluf_Text_UTF8::check($ref)) {
|
||||||
|
return (!$get_encoding) ? $text : array($text, 'UTF-8');
|
||||||
|
}
|
||||||
|
$encoding = mb_detect_encoding($ref, $enc, true);
|
||||||
|
if ($encoding == false) {
|
||||||
|
$encoding = Pluf_Text_UTF8::detect_cyr_charset($ref);
|
||||||
|
}
|
||||||
|
if (is_array($text)) {
|
||||||
|
foreach ($text as $t) {
|
||||||
|
$res[] = mb_convert_encoding($t, 'UTF-8', $encoding);
|
||||||
|
}
|
||||||
|
return (!$get_encoding) ? $res : array($res, $encoding);
|
||||||
|
} else {
|
||||||
|
$res = mb_convert_encoding($text, 'UTF-8', $encoding);
|
||||||
|
return (!$get_encoding) ? $res : array($res, $encoding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the timeline fragment for the commit.
|
* Returns the timeline fragment for the commit.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param Pluf_HTTP_Request
|
* @param Pluf_HTTP_Request
|
||||||
* @return Pluf_Template_SafeString
|
* @return Pluf_Template_SafeString
|
||||||
*/
|
*/
|
||||||
public function timelineFragment($request)
|
public function timelineFragment($request)
|
||||||
{
|
{
|
||||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::commit',
|
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::commit',
|
||||||
array($request->project->shortname,
|
array($request->project->shortname,
|
||||||
$this->scm_id));
|
$this->scm_id));
|
||||||
$out = '<tr class="log"><td><a href="'.$url.'">'.
|
$out = '<tr class="log"><td><a href="'.$url.'">'.
|
||||||
Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')).
|
Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')).
|
||||||
@@ -202,39 +235,103 @@ class IDF_Commit extends Pluf_Model
|
|||||||
</tr>
|
</tr>
|
||||||
<tr class="extra">
|
<tr class="extra">
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="helptext right">'.__('Commit').' <a href="'.$url.'" class="mono">'.$this->scm_id.'</a>, '.__('by').' '.$user.'</div></td></tr>';
|
<div class="helptext right">'.sprintf(__('Commit %s, by %s'), '<a href="'.$url.'" class="mono">'.$this->scm_id.'</a>', $user).'</div></td></tr>';
|
||||||
return Pluf_Template::markSafe($out);
|
return Pluf_Template::markSafe($out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the feed fragment for the commit.
|
* Returns the feed fragment for the commit.
|
||||||
*
|
*
|
||||||
* @param Pluf_HTTP_Request
|
* @param Pluf_HTTP_Request
|
||||||
* @return Pluf_Template_SafeString
|
* @return Pluf_Template_SafeString
|
||||||
*/
|
*/
|
||||||
public function feedFragment($request)
|
public function feedFragment($request)
|
||||||
{
|
{
|
||||||
$url = Pluf::f('url_base')
|
$url = Pluf::f('url_base')
|
||||||
.Pluf_HTTP_URL_urlForView('IDF_Views_Source::commit',
|
.Pluf_HTTP_URL_urlForView('IDF_Views_Source::commit',
|
||||||
array($request->project->shortname,
|
array($request->project->shortname,
|
||||||
$this->scm_id));
|
$this->scm_id));
|
||||||
$tag = new IDF_Template_IssueComment();
|
|
||||||
$summary = '<content type="xhtml">'."\n"
|
|
||||||
.'<div xmlns="http://www.w3.org/1999/xhtml">'
|
|
||||||
.$tag->start($this->summary, $request, false, false, false);
|
|
||||||
if ($this->fullmessage) {
|
|
||||||
$summary .= '<br /><br />'
|
|
||||||
.$tag->start($this->fullmessage, $request, false, false, false);
|
|
||||||
}
|
|
||||||
$date = Pluf_Date::gmDateToGmString($this->creation_dtime);
|
$date = Pluf_Date::gmDateToGmString($this->creation_dtime);
|
||||||
$summary .= '</div></content>';
|
$author = ($this->get_author()) ?
|
||||||
$out = '<entry>
|
$this->get_author() : $this->origauthor;
|
||||||
<title>'.Pluf_esc($request->project->name).': '.__('Commit').' '.$this->scm_id.'</title>
|
$cproject = $this->get_project();
|
||||||
<link href="'.$url.'"/>
|
$context = new Pluf_Template_Context_Request(
|
||||||
<id>'.$url.'</id>
|
$request,
|
||||||
<updated>'.$date.'</updated>'.$summary.'
|
array(
|
||||||
</entry>
|
'c' => $this,
|
||||||
';
|
'cproject' => $cproject,
|
||||||
return $out;
|
'url' => $url,
|
||||||
|
'date' => $date,
|
||||||
|
'author' => $author,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$tmpl = new Pluf_Template('idf/source/feedfragment.xml');
|
||||||
|
return $tmpl->render($context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification of change of the object.
|
||||||
|
*
|
||||||
|
* @param IDF_Conf Current configuration
|
||||||
|
* @param bool Creation (true)
|
||||||
|
*/
|
||||||
|
public function notify($conf, $create=true)
|
||||||
|
{
|
||||||
|
// Now we add to the queue, soon we will push everything in
|
||||||
|
// the queue, including email notifications and indexing.
|
||||||
|
// Even if the url is empty, we add to the queue as some
|
||||||
|
// plugins may want to do something with this information in
|
||||||
|
// an asynchronous way.
|
||||||
|
$project = $this->get_project();
|
||||||
|
$scm = $project->getConf()->getVal('scm', 'git');
|
||||||
|
$url = str_replace(array('%p', '%r'),
|
||||||
|
array($project->shortname, $this->scm_id),
|
||||||
|
$conf->getVal('webhook_url', ''));
|
||||||
|
$payload = array('to_send' => array(
|
||||||
|
'project' => $project->shortname,
|
||||||
|
'rev' => $this->scm_id,
|
||||||
|
'scm' => $scm,
|
||||||
|
'summary' => $this->summary,
|
||||||
|
'fullmessage' => $this->fullmessage,
|
||||||
|
'author' => $this->origauthor,
|
||||||
|
'creation_date' => $this->creation_dtime,
|
||||||
|
),
|
||||||
|
'project_id' => $project->id,
|
||||||
|
'authkey' => $project->getPostCommitHookKey(),
|
||||||
|
'url' => $url,
|
||||||
|
);
|
||||||
|
$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'),
|
||||||
|
$address,
|
||||||
|
sprintf(__('New Commit %s - %s (%s)'),
|
||||||
|
$this->scm_id, $this->summary,
|
||||||
|
$this->get_project()->shortname));
|
||||||
|
$email->addTextMessage($text_email);
|
||||||
|
$email->sendMail();
|
||||||
|
}
|
||||||
|
Pluf_Translation::loadSetLocale($current_locale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
199
src/IDF/Diff.php
199
src/IDF/Diff.php
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -27,17 +27,17 @@
|
|||||||
*/
|
*/
|
||||||
class IDF_Diff
|
class IDF_Diff
|
||||||
{
|
{
|
||||||
public $repo = '';
|
public $path_strip_level = 0;
|
||||||
public $diff = '';
|
|
||||||
protected $lines = array();
|
protected $lines = array();
|
||||||
|
|
||||||
public $files = array();
|
public $files = array();
|
||||||
|
|
||||||
public function __construct($diff, $repo='')
|
public function __construct($diff, $path_strip_level = 0)
|
||||||
{
|
{
|
||||||
$this->repo = $repo;
|
$this->path_strip_level = $path_strip_level;
|
||||||
$this->diff = $diff;
|
// this works because in unified diff format even empty lines are
|
||||||
$this->lines = preg_split("/\015\012|\015|\012/", $diff);
|
// either prefixed with a '+', '-' or ' '
|
||||||
|
$this->lines = preg_split("/\015\012|\015|\012/", $diff, -1, PREG_SPLIT_NO_EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function parse()
|
public function parse()
|
||||||
@@ -49,90 +49,95 @@ class IDF_Diff
|
|||||||
$files = array();
|
$files = array();
|
||||||
$indiff = false; // Used to skip the headers in the git patches
|
$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
|
$i = 0; // Used to skip the end of a git patch with --\nversion number
|
||||||
foreach ($this->lines as $line) {
|
$diffsize = count($this->lines);
|
||||||
$i++;
|
while ($i < $diffsize) {
|
||||||
if (0 === strpos($line, '--') and isset($this->lines[$i])
|
// look for the potential beginning of a diff
|
||||||
and preg_match('/^\d+\.\d+\.\d+\.\d+$/', $this->lines[$i])) {
|
if (substr($this->lines[$i], 0, 4) !== '--- ') {
|
||||||
break;
|
$i++;
|
||||||
}
|
|
||||||
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;
|
|
||||||
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 (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;
|
continue;
|
||||||
}
|
}
|
||||||
if (!$indiff) {
|
|
||||||
|
// 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;
|
continue;
|
||||||
}
|
}
|
||||||
if (0 === strpos($line, '@@ ')) {
|
|
||||||
$files[$current_file]['chunks_def'][] = self::getChunk($line);
|
// use new file name by default
|
||||||
|
preg_match("/^\+\+\+ ([^\t]+)/", $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]+)/", $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;
|
||||||
|
}
|
||||||
|
$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();
|
$files[$current_file]['chunks'][] = array();
|
||||||
|
|
||||||
|
while ($i < $diffsize && ($addlines >= 0 || $dellines >= 0)) {
|
||||||
|
$linetype = $this->lines[$i] != '' ? $this->lines[$i][0] : ' ';
|
||||||
|
switch ($linetype) {
|
||||||
|
case ' ':
|
||||||
|
$files[$current_file]['chunks'][$current_chunk][] =
|
||||||
|
array($delstart, $addstart, substr($this->lines[$i++], 1));
|
||||||
|
$dellines--;
|
||||||
|
$addlines--;
|
||||||
|
$delstart++;
|
||||||
|
$addstart++;
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
$files[$current_file]['chunks'][$current_chunk][] =
|
||||||
|
array('', $addstart, substr($this->lines[$i++], 1));
|
||||||
|
$addlines--;
|
||||||
|
$addstart++;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
$files[$current_file]['chunks'][$current_chunk][] =
|
||||||
|
array($delstart, '', substr($this->lines[$i++], 1));
|
||||||
|
$dellines--;
|
||||||
|
$delstart++;
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
// ignore newline handling for now, see issue 636
|
||||||
|
$i++;
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
$current_chunk++;
|
$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;
|
$this->files = $files;
|
||||||
return $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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the html version of a parsed diff.
|
* Return the html version of a parsed diff.
|
||||||
*/
|
*/
|
||||||
@@ -141,8 +146,8 @@ class IDF_Diff
|
|||||||
$out = '';
|
$out = '';
|
||||||
foreach ($this->files as $filename=>$file) {
|
foreach ($this->files as $filename=>$file) {
|
||||||
$pretty = '';
|
$pretty = '';
|
||||||
$fileinfo = IDF_Views_Source::getMimeType($filename);
|
$fileinfo = IDF_FileUtil::getMimeType($filename);
|
||||||
if (IDF_Views_Source::isSupportedExtension($fileinfo[2])) {
|
if (IDF_FileUtil::isSupportedExtension($fileinfo[2])) {
|
||||||
$pretty = ' prettyprint';
|
$pretty = ' prettyprint';
|
||||||
}
|
}
|
||||||
$out .= "\n".'<table class="diff" summary="">'."\n";
|
$out .= "\n".'<table class="diff" summary="">'."\n";
|
||||||
@@ -169,7 +174,6 @@ class IDF_Diff
|
|||||||
return Pluf_Template::markSafe($out);
|
return Pluf_Template::markSafe($out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static function padLine($line)
|
public static function padLine($line)
|
||||||
{
|
{
|
||||||
$line = str_replace("\t", ' ', $line);
|
$line = str_replace("\t", ' ', $line);
|
||||||
@@ -182,19 +186,6 @@ class IDF_Diff
|
|||||||
return str_repeat(' ', $i).substr($line, $i);
|
return str_repeat(' ', $i).substr($line, $i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array array(array(start, n), array(start, n))
|
|
||||||
*/
|
|
||||||
public static function getChunk($line)
|
|
||||||
{
|
|
||||||
$elts = split(' ', $line);
|
|
||||||
$res = array();
|
|
||||||
for ($i=1;$i<3;$i++) {
|
|
||||||
$res[] = split(',', trim(substr($elts[$i], 1)));
|
|
||||||
}
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Review patch.
|
* Review patch.
|
||||||
*
|
*
|
||||||
@@ -215,14 +206,14 @@ class IDF_Diff
|
|||||||
* @param int Number of lines before/after the chunk to be displayed (10)
|
* @param int Number of lines before/after the chunk to be displayed (10)
|
||||||
* @return Pluf_Template_SafeString The table body
|
* @return Pluf_Template_SafeString The table body
|
||||||
*/
|
*/
|
||||||
public function fileCompare($orig, $chunks, $filename, $context=10)
|
public function fileCompare($orig, $chunks, $filename, $context=10)
|
||||||
{
|
{
|
||||||
$orig_lines = preg_split("/\015\012|\015|\012/", $orig);
|
$orig_lines = preg_split("/\015\012|\015|\012/", $orig);
|
||||||
$new_chunks = $this->mergeChunks($orig_lines, $chunks, $context);
|
$new_chunks = $this->mergeChunks($orig_lines, $chunks, $context);
|
||||||
return $this->renderCompared($new_chunks, $filename);
|
return $this->renderCompared($new_chunks, $filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function mergeChunks($orig_lines, $chunks, $context=10)
|
public function mergeChunks($orig_lines, $chunks, $context=10)
|
||||||
{
|
{
|
||||||
$spans = array();
|
$spans = array();
|
||||||
$new_chunks = array();
|
$new_chunks = array();
|
||||||
@@ -250,7 +241,7 @@ class IDF_Diff
|
|||||||
for ($lc=$spans[$i][0];$lc<$chunk[0][0];$lc++) {
|
for ($lc=$spans[$i][0];$lc<$chunk[0][0];$lc++) {
|
||||||
$exists = false;
|
$exists = false;
|
||||||
foreach ($chunk_lines as $line) {
|
foreach ($chunk_lines as $line) {
|
||||||
if ($lc == $line[0]
|
if ($lc == $line[0]
|
||||||
or ($chunk[0][1]-$chunk[0][0]+$lc) == $line[1]) {
|
or ($chunk[0][1]-$chunk[0][0]+$lc) == $line[1]) {
|
||||||
$exists = true;
|
$exists = true;
|
||||||
break;
|
break;
|
||||||
@@ -259,7 +250,7 @@ class IDF_Diff
|
|||||||
if (!$exists) {
|
if (!$exists) {
|
||||||
$orig = isset($orig_lines[$lc-1]) ? $orig_lines[$lc-1] : '';
|
$orig = isset($orig_lines[$lc-1]) ? $orig_lines[$lc-1] : '';
|
||||||
$n_chunk[] = array(
|
$n_chunk[] = array(
|
||||||
$lc,
|
$lc,
|
||||||
$chunk[0][1]-$chunk[0][0]+$lc,
|
$chunk[0][1]-$chunk[0][0]+$lc,
|
||||||
$orig
|
$orig
|
||||||
);
|
);
|
||||||
@@ -283,7 +274,7 @@ class IDF_Diff
|
|||||||
}
|
}
|
||||||
if (!$exists) {
|
if (!$exists) {
|
||||||
$n_chunk[] = array(
|
$n_chunk[] = array(
|
||||||
$lc,
|
$lc,
|
||||||
$lline[1]-$lline[0]+$lc,
|
$lline[1]-$lline[0]+$lc,
|
||||||
$orig_lines[$lc-1]
|
$orig_lines[$lc-1]
|
||||||
);
|
);
|
||||||
@@ -305,7 +296,7 @@ class IDF_Diff
|
|||||||
foreach ($chunk as $line) {
|
foreach ($chunk as $line) {
|
||||||
if ($line[0] > $lline[0] or empty($line[0])) {
|
if ($line[0] > $lline[0] or empty($line[0])) {
|
||||||
$nnew_chunks[$i-1][] = $line;
|
$nnew_chunks[$i-1][] = $line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$nnew_chunks[] = $chunk;
|
$nnew_chunks[] = $chunk;
|
||||||
@@ -319,12 +310,11 @@ class IDF_Diff
|
|||||||
return $nnew_chunks;
|
return $nnew_chunks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function renderCompared($chunks, $filename)
|
public function renderCompared($chunks, $filename)
|
||||||
{
|
{
|
||||||
$fileinfo = IDF_Views_Source::getMimeType($filename);
|
$fileinfo = IDF_FileUtil::getMimeType($filename);
|
||||||
$pretty = '';
|
$pretty = '';
|
||||||
if (IDF_Views_Source::isSupportedExtension($fileinfo[2])) {
|
if (IDF_FileUtil::isSupportedExtension($fileinfo[2])) {
|
||||||
$pretty = ' prettyprint';
|
$pretty = ' prettyprint';
|
||||||
}
|
}
|
||||||
$out = '';
|
$out = '';
|
||||||
@@ -353,6 +343,5 @@ class IDF_Diff
|
|||||||
$i++;
|
$i++;
|
||||||
}
|
}
|
||||||
return Pluf_Template::markSafe($out);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
165
src/IDF/FileUtil.php
Normal file
165
src/IDF/FileUtil.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 ***** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File utilities.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class IDF_FileUtil
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Extension supported by the syntax highlighter.
|
||||||
|
*/
|
||||||
|
public static $supportedExtenstions = array(
|
||||||
|
'ascx', 'ashx', 'asmx', 'aspx', 'browser', 'bsh', 'c', 'cl', 'cc',
|
||||||
|
'config', 'cpp', 'cs', 'csh', 'csproj', 'css', 'cv', 'cyc', 'el', 'fs',
|
||||||
|
'h', 'hh', 'hpp', 'hs', 'html', 'html', 'java', 'js', 'lisp', 'master',
|
||||||
|
'pas', 'perl', 'php', 'pl', 'pm', 'py', 'rb', 'scm', 'sh', 'sitemap',
|
||||||
|
'skin', 'sln', 'svc', 'vala', 'vb', 'vbproj', 'vbs', 'wsdl', 'xhtml',
|
||||||
|
'xml', 'xsd', 'xsl', 'xslt');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if an extension is supported by the syntax highlighter.
|
||||||
|
*
|
||||||
|
* @param string The extension to test
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function isSupportedExtension($extension)
|
||||||
|
{
|
||||||
|
return in_array($extension, self::$supportedExtenstions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HTML snippet with a line-by-line pre-rendered table
|
||||||
|
* for the given source content
|
||||||
|
*
|
||||||
|
* @param array file information as returned by getMimeType or getMimeTypeFromContent
|
||||||
|
* @param string the content of the file
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function highLight($fileinfo, $content)
|
||||||
|
{
|
||||||
|
$pretty = '';
|
||||||
|
if (self::isSupportedExtension($fileinfo[2])) {
|
||||||
|
$pretty = ' prettyprint';
|
||||||
|
}
|
||||||
|
$table = array();
|
||||||
|
$i = 1;
|
||||||
|
foreach (preg_split("/\015\012|\015|\012/", $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>';
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
return Pluf_Template::markSafe(implode("\n", $table));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the mime type of a file.
|
||||||
|
*
|
||||||
|
* Use /etc/mime.types to find the type.
|
||||||
|
*
|
||||||
|
* @param string Filename/Filepath
|
||||||
|
* @param array Mime type found or 'application/octet-stream', basename, extension
|
||||||
|
*/
|
||||||
|
public static function getMimeType($file)
|
||||||
|
{
|
||||||
|
static $mimes = null;
|
||||||
|
if ($mimes == null) {
|
||||||
|
$mimes = array();
|
||||||
|
$src = Pluf::f('idf_mimetypes_db', '/etc/mime.types');
|
||||||
|
$filecontent = @file_get_contents($src);
|
||||||
|
if ($filecontent !== false) {
|
||||||
|
$mimes = preg_split("/\015\012|\015|\012/", $filecontent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$info = pathinfo($file);
|
||||||
|
if (isset($info['extension'])) {
|
||||||
|
foreach ($mimes as $mime) {
|
||||||
|
if ('#' != substr($mime, 0, 1)) {
|
||||||
|
$elts = preg_split('/ |\t/', $mime, -1, PREG_SPLIT_NO_EMPTY);
|
||||||
|
if (in_array($info['extension'], $elts)) {
|
||||||
|
return array($elts[0], $info['basename'], $info['extension']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// we consider that if no extension and base name is all
|
||||||
|
// uppercase, then we have a text file.
|
||||||
|
if ($info['basename'] == strtoupper($info['basename'])) {
|
||||||
|
return array('text/plain', $info['basename'], 'txt');
|
||||||
|
}
|
||||||
|
$info['extension'] = 'bin';
|
||||||
|
}
|
||||||
|
return array('application/octet-stream', $info['basename'], $info['extension']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the mime type of a file using the fileinfo class.
|
||||||
|
*
|
||||||
|
* @param string Filename/Filepath
|
||||||
|
* @param string File content
|
||||||
|
* @return array Mime type found or 'application/octet-stream', basename, extension
|
||||||
|
*/
|
||||||
|
public static function getMimeTypeFromContent($file, $filedata)
|
||||||
|
{
|
||||||
|
$info = pathinfo($file);
|
||||||
|
$res = array('application/octet-stream',
|
||||||
|
$info['basename'],
|
||||||
|
isset($info['extension']) ? $info['extension'] : 'bin');
|
||||||
|
if (function_exists('finfo_open')) {
|
||||||
|
$finfo = finfo_open(FILEINFO_MIME);
|
||||||
|
$mime = finfo_buffer($finfo, $filedata);
|
||||||
|
finfo_close($finfo);
|
||||||
|
if ($mime) {
|
||||||
|
$res[0] = $mime;
|
||||||
|
}
|
||||||
|
if (!isset($info['extension']) && $mime) {
|
||||||
|
$res[2] = (0 === strpos($mime, 'text/')) ? 'txt' : 'bin';
|
||||||
|
} elseif (!isset($info['extension'])) {
|
||||||
|
$res[2] = 'bin';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find if a given mime type is a text file.
|
||||||
|
* This uses the output of the self::getMimeType function.
|
||||||
|
*
|
||||||
|
* @param array (Mime type, file name, extension)
|
||||||
|
* @return bool Is text
|
||||||
|
*/
|
||||||
|
public static function isText($fileinfo)
|
||||||
|
{
|
||||||
|
if (0 === strpos($fileinfo[0], 'text/')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$ext = 'mdtext php-dist h gitignore diff patch';
|
||||||
|
$extra_ext = trim(Pluf::f('idf_extra_text_ext', ''));
|
||||||
|
if (!empty($extra_ext))
|
||||||
|
$ext .= ' ' . $extra_ext;
|
||||||
|
$ext = array_merge(self::$supportedExtenstions, explode(' ' , $ext));
|
||||||
|
return (in_array($fileinfo[2], $ext));
|
||||||
|
}
|
||||||
|
}
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -38,6 +38,7 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
|
|||||||
'git' => __('git'),
|
'git' => __('git'),
|
||||||
'svn' => __('Subversion'),
|
'svn' => __('Subversion'),
|
||||||
'mercurial' => __('mercurial'),
|
'mercurial' => __('mercurial'),
|
||||||
|
'mtn' => __('monotone'),
|
||||||
);
|
);
|
||||||
foreach (Pluf::f('allowed_scm', array()) as $key => $class) {
|
foreach (Pluf::f('allowed_scm', array()) as $key => $class) {
|
||||||
$choices[$options[$key]] = $key;
|
$choices[$options[$key]] = $key;
|
||||||
@@ -63,6 +64,14 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
|
|||||||
'help_text' => __('It must be unique for each project and composed only of letters, digits and dash (-) like "my-project".'),
|
'help_text' => __('It must be unique for each project and composed only of letters, digits and dash (-) like "my-project".'),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$this->fields['shortdesc'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => true,
|
||||||
|
'label' => __('Short description'),
|
||||||
|
'help_text' => __('A one line description of the project.'),
|
||||||
|
'initial' => '',
|
||||||
|
'widget_attrs' => array('size' => '35'),
|
||||||
|
));
|
||||||
|
|
||||||
$this->fields['scm'] = new Pluf_Form_Field_Varchar(
|
$this->fields['scm'] = new Pluf_Form_Field_Varchar(
|
||||||
array('required' => true,
|
array('required' => true,
|
||||||
'label' => __('Repository type'),
|
'label' => __('Repository type'),
|
||||||
@@ -92,6 +101,14 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
|
|||||||
'widget' => 'Pluf_Form_Widget_PasswordInput',
|
'widget' => 'Pluf_Form_Widget_PasswordInput',
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$this->fields['mtn_master_branch'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Master branch'),
|
||||||
|
'initial' => '',
|
||||||
|
'widget_attrs' => array('size' => '35'),
|
||||||
|
'help_text' => __('This should be a world-wide unique identifier for your project. A reverse DNS notation like "com.my-domain.my-project" is a good idea.'),
|
||||||
|
));
|
||||||
|
|
||||||
$this->fields['owners'] = new Pluf_Form_Field_Varchar(
|
$this->fields['owners'] = new Pluf_Form_Field_Varchar(
|
||||||
array('required' => false,
|
array('required' => false,
|
||||||
'label' => __('Project owners'),
|
'label' => __('Project owners'),
|
||||||
@@ -109,6 +126,20 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
|
|||||||
'cols' => 40),
|
'cols' => 40),
|
||||||
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$projects = array('--' => '--');
|
||||||
|
foreach (Pluf::factory('IDF_Project')->getList(array('order' => 'name ASC')) as $proj) {
|
||||||
|
$projects[$proj->name] = $proj->shortname;
|
||||||
|
}
|
||||||
|
$this->fields['template'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Project template'),
|
||||||
|
'initial' => '--',
|
||||||
|
'help_text' => __('Use the given project to initialize the new project. Access rights and general configuration will be taken from the template project.'),
|
||||||
|
'widget' => 'Pluf_Form_Widget_SelectInput',
|
||||||
|
'widget_attrs' => array('choices' => $projects),
|
||||||
|
));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [signal]
|
* [signal]
|
||||||
*
|
*
|
||||||
@@ -133,6 +164,16 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
|
|||||||
'IDF_Form_Admin_ProjectCreate', $params);
|
'IDF_Form_Admin_ProjectCreate', $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function clean_owners()
|
||||||
|
{
|
||||||
|
return IDF_Form_MembersConf::checkBadLogins($this->cleaned_data['owners']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clean_members()
|
||||||
|
{
|
||||||
|
return IDF_Form_MembersConf::checkBadLogins($this->cleaned_data['members']);
|
||||||
|
}
|
||||||
|
|
||||||
public function clean_svn_remote_url()
|
public function clean_svn_remote_url()
|
||||||
{
|
{
|
||||||
$this->cleaned_data['svn_remote_url'] = (!empty($this->cleaned_data['svn_remote_url'])) ? $this->cleaned_data['svn_remote_url'] : '';
|
$this->cleaned_data['svn_remote_url'] = (!empty($this->cleaned_data['svn_remote_url'])) ? $this->cleaned_data['svn_remote_url'] : '';
|
||||||
@@ -141,14 +182,42 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
|
|||||||
// we accept only starting with http(s):// to avoid people
|
// we accept only starting with http(s):// to avoid people
|
||||||
// trying to access the local filesystem.
|
// trying to access the local filesystem.
|
||||||
if (!preg_match('#^(http|https)://#', $url)) {
|
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;
|
return $url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function clean_mtn_master_branch()
|
||||||
|
{
|
||||||
|
// do not validate, but empty the field if a different
|
||||||
|
// SCM should be used
|
||||||
|
if ($this->cleaned_data['scm'] != 'mtn')
|
||||||
|
return '';
|
||||||
|
|
||||||
|
$mtn_master_branch = mb_strtolower($this->cleaned_data['mtn_master_branch']);
|
||||||
|
if (!preg_match('/^([\w\d]+([-][\w\d]+)*)(\.[\w\d]+([-][\w\d]+)*)*$/',
|
||||||
|
$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.'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = new Pluf_SQL('vkey=%s AND vdesc=%s',
|
||||||
|
array('mtn_master_branch', $mtn_master_branch));
|
||||||
|
$l = Pluf::factory('IDF_Conf')->getList(array('filter'=>$sql->gen()));
|
||||||
|
if ($l->count() > 0) {
|
||||||
|
throw new Pluf_Form_Invalid(__(
|
||||||
|
'This master branch is already used. Please select another one.'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $mtn_master_branch;
|
||||||
|
}
|
||||||
|
|
||||||
public function clean_shortname()
|
public function clean_shortname()
|
||||||
{
|
{
|
||||||
$shortname = $this->cleaned_data['shortname'];
|
$shortname = mb_strtolower($this->cleaned_data['shortname']);
|
||||||
if (preg_match('/[^\-A-Za-z0-9]/', $shortname)) {
|
if (preg_match('/[^\-A-Za-z0-9]/', $shortname)) {
|
||||||
throw new Pluf_Form_Invalid(__('This shortname contains illegal characters, please use only letters, digits and dash (-).'));
|
throw new Pluf_Form_Invalid(__('This shortname contains illegal characters, please use only letters, digits and dash (-).'));
|
||||||
}
|
}
|
||||||
@@ -174,6 +243,11 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
|
|||||||
$this->cleaned_data[$key] = '';
|
$this->cleaned_data[$key] = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->cleaned_data['scm'] != 'mtn') {
|
||||||
|
$this->cleaned_data['mtn_master_branch'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [signal]
|
* [signal]
|
||||||
*
|
*
|
||||||
@@ -207,24 +281,88 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
|
|||||||
$project = new IDF_Project();
|
$project = new IDF_Project();
|
||||||
$project->name = $this->cleaned_data['name'];
|
$project->name = $this->cleaned_data['name'];
|
||||||
$project->shortname = $this->cleaned_data['shortname'];
|
$project->shortname = $this->cleaned_data['shortname'];
|
||||||
$project->private = $this->cleaned_data['private_project'];
|
$project->shortdesc = $this->cleaned_data['shortdesc'];
|
||||||
$project->description = __('Click on the Administer tab to set the description of your project.');
|
|
||||||
|
if ($this->cleaned_data['template'] != '--') {
|
||||||
|
// Find the template project
|
||||||
|
$sql = new Pluf_SQL('shortname=%s',
|
||||||
|
array($this->cleaned_data['template']));
|
||||||
|
$tmpl = Pluf::factory('IDF_Project')->getOne(array('filter' => $sql->gen()));
|
||||||
|
$project->private = $tmpl->private;
|
||||||
|
$project->description = $tmpl->description;
|
||||||
|
} else {
|
||||||
|
$project->private = $this->cleaned_data['private_project'];
|
||||||
|
$project->description = __('Click on the Project Management tab to set the description of your project.');
|
||||||
|
}
|
||||||
$project->create();
|
$project->create();
|
||||||
$conf = new IDF_Conf();
|
$conf = new IDF_Conf();
|
||||||
$conf->setProject($project);
|
$conf->setProject($project);
|
||||||
$keys = array('scm', 'svn_remote_url',
|
$keys = array('scm', 'svn_remote_url', 'svn_username',
|
||||||
'svn_username', 'svn_password');
|
'svn_password', 'mtn_master_branch');
|
||||||
foreach ($keys as $key) {
|
foreach ($keys as $key) {
|
||||||
$this->cleaned_data[$key] = (!empty($this->cleaned_data[$key])) ?
|
$this->cleaned_data[$key] = (!empty($this->cleaned_data[$key])) ?
|
||||||
$this->cleaned_data[$key] : '';
|
$this->cleaned_data[$key] : '';
|
||||||
$conf->setVal($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));
|
||||||
|
}
|
||||||
|
}
|
||||||
$project->created();
|
$project->created();
|
||||||
IDF_Form_MembersConf::updateMemberships($project,
|
|
||||||
$this->cleaned_data);
|
if ($this->cleaned_data['template'] == '--') {
|
||||||
|
IDF_Form_MembersConf::updateMemberships($project,
|
||||||
|
$this->cleaned_data);
|
||||||
|
} else {
|
||||||
|
// Get the membership of the template $tmpl
|
||||||
|
IDF_Form_MembersConf::updateMemberships($project,
|
||||||
|
$tmpl->getMembershipData('string'));
|
||||||
|
}
|
||||||
$project->membershipsUpdated();
|
$project->membershipsUpdated();
|
||||||
return $project;
|
return $project;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that the template project exists.
|
||||||
|
*/
|
||||||
|
public function clean_template()
|
||||||
|
{
|
||||||
|
if ($this->cleaned_data['template'] == '--') {
|
||||||
|
return $this->cleaned_data['template'];
|
||||||
|
}
|
||||||
|
$sql = new Pluf_SQL('shortname=%s', array($this->cleaned_data['template']));
|
||||||
|
if (Pluf::factory('IDF_Project')->getOne(array('filter' => $sql->gen())) == null) {
|
||||||
|
throw new Pluf_Form_Invalid(__('This project is not available.'));
|
||||||
|
}
|
||||||
|
return $this->cleaned_data['template'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -37,12 +37,32 @@ class IDF_Form_Admin_ProjectUpdate extends Pluf_Form
|
|||||||
{
|
{
|
||||||
$this->project = $extra['project'];
|
$this->project = $extra['project'];
|
||||||
$members = $this->project->getMembershipData('string');
|
$members = $this->project->getMembershipData('string');
|
||||||
|
$conf = $this->project->getConf();
|
||||||
|
|
||||||
$this->fields['name'] = new Pluf_Form_Field_Varchar(
|
$this->fields['name'] = new Pluf_Form_Field_Varchar(
|
||||||
array('required' => true,
|
array('required' => true,
|
||||||
'label' => __('Name'),
|
'label' => __('Name'),
|
||||||
'initial' => $this->project->name,
|
'initial' => $this->project->name,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$this->fields['shortdesc'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => true,
|
||||||
|
'label' => __('Short description'),
|
||||||
|
'help_text' => __('A one line description of the project.'),
|
||||||
|
'initial' => $this->project->shortdesc,
|
||||||
|
'widget_attrs' => array('size' => '35'),
|
||||||
|
));
|
||||||
|
|
||||||
|
if ($this->project->getConf()->getVal('scm') == 'mtn') {
|
||||||
|
$this->fields['mtn_master_branch'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Master branch'),
|
||||||
|
'initial' => $conf->getVal('mtn_master_branch'),
|
||||||
|
'widget_attrs' => array('size' => '35'),
|
||||||
|
'help_text' => __('This should be a world-wide unique identifier for your project. A reverse DNS notation like "com.my-domain.my-project" is a good idea.'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
$this->fields['owners'] = new Pluf_Form_Field_Varchar(
|
$this->fields['owners'] = new Pluf_Form_Field_Varchar(
|
||||||
array('required' => false,
|
array('required' => false,
|
||||||
'label' => __('Project owners'),
|
'label' => __('Project owners'),
|
||||||
@@ -61,16 +81,58 @@ class IDF_Form_Admin_ProjectUpdate extends Pluf_Form
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function clean_mtn_master_branch()
|
||||||
|
{
|
||||||
|
$mtn_master_branch = mb_strtolower($this->cleaned_data['mtn_master_branch']);
|
||||||
|
if (!preg_match('/^([\w\d]+([-][\w\d]+)*)(\.[\w\d]+([-][\w\d]+)*)*$/',
|
||||||
|
$mtn_master_branch)) {
|
||||||
|
throw new Pluf_Form_Invalid(__(
|
||||||
|
'The master branch is empty or contains illegal characters, '.
|
||||||
|
'please use only letters, digits, dashes and dots as separators.'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = new Pluf_SQL('vkey=%s AND vdesc=%s AND project!=%s',
|
||||||
|
array('mtn_master_branch', $mtn_master_branch,
|
||||||
|
(string)$this->project->id));
|
||||||
|
$l = Pluf::factory('IDF_Conf')->getList(array('filter'=>$sql->gen()));
|
||||||
|
if ($l->count() > 0) {
|
||||||
|
throw new Pluf_Form_Invalid(__(
|
||||||
|
'This master branch is already used. Please select another one.'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $mtn_master_branch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clean_owners()
|
||||||
|
{
|
||||||
|
return IDF_Form_MembersConf::checkBadLogins($this->cleaned_data['owners']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clean_members()
|
||||||
|
{
|
||||||
|
return IDF_Form_MembersConf::checkBadLogins($this->cleaned_data['members']);
|
||||||
|
}
|
||||||
|
|
||||||
public function save($commit=true)
|
public function save($commit=true)
|
||||||
{
|
{
|
||||||
if (!$this->isValid()) {
|
if (!$this->isValid()) {
|
||||||
throw new Exception(__('Cannot save the model from an invalid form.'));
|
throw new Exception(__('Cannot save the model from an invalid form.'));
|
||||||
}
|
}
|
||||||
IDF_Form_MembersConf::updateMemberships($this->project,
|
IDF_Form_MembersConf::updateMemberships($this->project,
|
||||||
$this->cleaned_data);
|
$this->cleaned_data);
|
||||||
$this->project->membershipsUpdated();
|
$this->project->membershipsUpdated();
|
||||||
$this->project->name = $this->cleaned_data['name'];
|
$this->project->name = $this->cleaned_data['name'];
|
||||||
|
$this->project->shortdesc = $this->cleaned_data['shortdesc'];
|
||||||
$this->project->update();
|
$this->project->update();
|
||||||
|
|
||||||
|
$keys = array('mtn_master_branch');
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
if (!empty($this->cleaned_data[$key])) {
|
||||||
|
$this->project->getConf()->setVal($key, $this->cleaned_data[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
215
src/IDF/Form/Admin/UserCreate.php
Normal file
215
src/IDF/Form/Admin/UserCreate.php
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
<?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 ***** */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow an admin to create a user.
|
||||||
|
*/
|
||||||
|
class IDF_Form_Admin_UserCreate extends Pluf_Form
|
||||||
|
{
|
||||||
|
public $request = null;
|
||||||
|
|
||||||
|
public function initFields($extra=array())
|
||||||
|
{
|
||||||
|
$this->request = $extra['request'];
|
||||||
|
$this->fields['first_name'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('First name'),
|
||||||
|
'initial' => '',
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 50,
|
||||||
|
'size' => 15,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
$this->fields['last_name'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => true,
|
||||||
|
'label' => __('Last name'),
|
||||||
|
'initial' => '',
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 50,
|
||||||
|
'size' => 20,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['login'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => true,
|
||||||
|
'label' => __('Login'),
|
||||||
|
'max_length' => 15,
|
||||||
|
'min_length' => 3,
|
||||||
|
'initial' => '',
|
||||||
|
'help_text' => __('The login must be between 3 and 15 characters long and contains only letters and digits.'),
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 15,
|
||||||
|
'size' => 10,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['email'] = new Pluf_Form_Field_Email(
|
||||||
|
array('required' => true,
|
||||||
|
'label' => __('Email'),
|
||||||
|
'initial' => '',
|
||||||
|
'help_text' => __('Double check the email address as the password is sent directly to the user.'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['language'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => true,
|
||||||
|
'label' => __('Language'),
|
||||||
|
'initial' => '',
|
||||||
|
'widget' => 'Pluf_Form_Widget_SelectInput',
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'choices' =>
|
||||||
|
Pluf_L10n::getInstalledLanguages()
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['public_key'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Add a public key'),
|
||||||
|
'initial' => '',
|
||||||
|
'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!')
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.'));
|
||||||
|
}
|
||||||
|
$password = Pluf_Utils::getPassword();
|
||||||
|
$user = new Pluf_User();
|
||||||
|
$user->setFromFormData($this->cleaned_data);
|
||||||
|
$user->active = true;
|
||||||
|
$user->staff = false;
|
||||||
|
$user->administrator = false;
|
||||||
|
$user->setPassword($password);
|
||||||
|
$user->create();
|
||||||
|
/**
|
||||||
|
* [signal]
|
||||||
|
*
|
||||||
|
* Pluf_User::passwordUpdated
|
||||||
|
*
|
||||||
|
* [sender]
|
||||||
|
*
|
||||||
|
* IDF_Form_Admin_UserCreate
|
||||||
|
*
|
||||||
|
* [description]
|
||||||
|
*
|
||||||
|
* This signal is sent when a user is created
|
||||||
|
* by the staff.
|
||||||
|
*
|
||||||
|
* [parameters]
|
||||||
|
*
|
||||||
|
* array('user' => $user)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$params = array('user' => $user);
|
||||||
|
Pluf_Signal::send('Pluf_User::passwordUpdated',
|
||||||
|
'IDF_Form_Admin_UserCreate', $params);
|
||||||
|
// Create the public key as needed
|
||||||
|
if ('' !== $this->cleaned_data['public_key']) {
|
||||||
|
$key = new IDF_Key();
|
||||||
|
$key->user = $user;
|
||||||
|
$key->content = $this->cleaned_data['public_key'];
|
||||||
|
$key->create();
|
||||||
|
}
|
||||||
|
// Send an email to the user with the password
|
||||||
|
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
|
||||||
|
$url = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views::login', array(), array(), false);
|
||||||
|
$context = new Pluf_Template_Context(
|
||||||
|
array('password' => Pluf_Template::markSafe($password),
|
||||||
|
'user' => $user,
|
||||||
|
'url' => Pluf_Template::markSafe($url),
|
||||||
|
'admin' => $this->request->user,
|
||||||
|
));
|
||||||
|
$tmpl = new Pluf_Template('idf/gadmin/users/createuser-email.txt');
|
||||||
|
$text_email = $tmpl->render($context);
|
||||||
|
$email = new Pluf_Mail(Pluf::f('from_email'), $user->email,
|
||||||
|
__('Your details to access your forge.'));
|
||||||
|
$email->addTextMessage($text_email);
|
||||||
|
$email->sendMail();
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clean_last_name()
|
||||||
|
{
|
||||||
|
$last_name = trim($this->cleaned_data['last_name']);
|
||||||
|
if ($last_name == mb_strtoupper($last_name)) {
|
||||||
|
return mb_convert_case(mb_strtolower($last_name),
|
||||||
|
MB_CASE_TITLE, 'UTF-8');
|
||||||
|
}
|
||||||
|
return $last_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clean_first_name()
|
||||||
|
{
|
||||||
|
$first_name = trim($this->cleaned_data['first_name']);
|
||||||
|
if ($first_name == mb_strtoupper($first_name)) {
|
||||||
|
return mb_convert_case(mb_strtolower($first_name),
|
||||||
|
MB_CASE_TITLE, 'UTF-8');
|
||||||
|
}
|
||||||
|
return $first_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clean_email()
|
||||||
|
{
|
||||||
|
$this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email']));
|
||||||
|
$guser = new Pluf_User();
|
||||||
|
$sql = new Pluf_SQL('email=%s', array($this->cleaned_data['email']));
|
||||||
|
if ($guser->getCount(array('filter' => $sql->gen())) > 0) {
|
||||||
|
throw new Pluf_Form_Invalid(sprintf(__('The email "%s" is already used.'), $this->cleaned_data['email']));
|
||||||
|
}
|
||||||
|
return $this->cleaned_data['email'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clean_login()
|
||||||
|
{
|
||||||
|
$this->cleaned_data['login'] = mb_strtolower(trim($this->cleaned_data['login']));
|
||||||
|
if (preg_match('/[^a-z0-9]/', $this->cleaned_data['login'])) {
|
||||||
|
throw new Pluf_Form_Invalid(sprintf(__('The login "%s" can only contain letters and digits.'), $this->cleaned_data['login']));
|
||||||
|
}
|
||||||
|
$guser = new Pluf_User();
|
||||||
|
$sql = new Pluf_SQL('login=%s', $this->cleaned_data['login']);
|
||||||
|
if ($guser->getCount(array('filter' => $sql->gen())) > 0) {
|
||||||
|
throw new Pluf_Form_Invalid(sprintf(__('The login "%s" is already used, please find another one.'), $this->cleaned_data['login']));
|
||||||
|
}
|
||||||
|
return $this->cleaned_data['login'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clean_public_key()
|
||||||
|
{
|
||||||
|
$this->cleaned_data['public_key'] =
|
||||||
|
IDF_Form_UserAccount::checkPublicKey($this->cleaned_data['public_key']);
|
||||||
|
|
||||||
|
return $this->cleaned_data['public_key'];
|
||||||
|
}
|
||||||
|
}
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -24,13 +24,15 @@
|
|||||||
/**
|
/**
|
||||||
* Update user's details.
|
* Update user's details.
|
||||||
*/
|
*/
|
||||||
class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
||||||
{
|
{
|
||||||
public $user = null;
|
public $user = null;
|
||||||
|
|
||||||
public function initFields($extra=array())
|
public function initFields($extra=array())
|
||||||
{
|
{
|
||||||
$this->user = $extra['user'];
|
$this->user = $extra['user'];
|
||||||
|
$user_data = IDF_UserData::factory($this->user);
|
||||||
|
|
||||||
$this->fields['first_name'] = new Pluf_Form_Field_Varchar(
|
$this->fields['first_name'] = new Pluf_Form_Field_Varchar(
|
||||||
array('required' => false,
|
array('required' => false,
|
||||||
'label' => __('First name'),
|
'label' => __('First name'),
|
||||||
@@ -66,7 +68,7 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
|||||||
'initial' => $this->user->language,
|
'initial' => $this->user->language,
|
||||||
'widget' => 'Pluf_Form_Widget_SelectInput',
|
'widget' => 'Pluf_Form_Widget_SelectInput',
|
||||||
'widget_attrs' => array(
|
'widget_attrs' => array(
|
||||||
'choices' =>
|
'choices' =>
|
||||||
Pluf_L10n::getInstalledLanguages()
|
Pluf_L10n::getInstalledLanguages()
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
@@ -76,7 +78,7 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
|||||||
'label' => __('Password'),
|
'label' => __('Password'),
|
||||||
'initial' => '',
|
'initial' => '',
|
||||||
'widget' => 'Pluf_Form_Widget_PasswordInput',
|
'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(
|
'widget_attrs' => array(
|
||||||
'maxlength' => 50,
|
'maxlength' => 50,
|
||||||
'size' => 15,
|
'size' => 15,
|
||||||
@@ -93,13 +95,73 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
|||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$this->fields['description'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Description'),
|
||||||
|
'initial' => $user_data->description,
|
||||||
|
'widget_attrs' => array('rows' => 3,
|
||||||
|
'cols' => 40),
|
||||||
|
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['twitter'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Twitter username'),
|
||||||
|
'initial' => $user_data->twitter,
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 50,
|
||||||
|
'size' => 15,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['public_email'] = new Pluf_Form_Field_Email(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Public email address'),
|
||||||
|
'initial' => $user_data->public_email,
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 50,
|
||||||
|
'size' => 15,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['website'] = new Pluf_Form_Field_Url(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Website URL'),
|
||||||
|
'initial' => $user_data->website,
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 50,
|
||||||
|
'size' => 15,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['custom_avatar'] = new Pluf_Form_Field_File(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Upload custom avatar'),
|
||||||
|
'initial' => '',
|
||||||
|
'max_size' => Pluf::f('max_upload_size', 2097152),
|
||||||
|
'move_function_params' => array('upload_path' => Pluf::f('upload_path').'/avatars',
|
||||||
|
'upload_path_create' => true,
|
||||||
|
'upload_overwrite' => true,
|
||||||
|
'file_name' => 'user_'.$this->user->id.'_%s'),
|
||||||
|
'help_text' => __('An image file with a width and height not larger than 60 pixels (bigger images are scaled down).'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['remove_custom_avatar'] = new Pluf_Form_Field_Boolean(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Remove custom avatar'),
|
||||||
|
'initial' => false,
|
||||||
|
'widget' => 'Pluf_Form_Widget_CheckboxInput',
|
||||||
|
'widget_attrs' => array(),
|
||||||
|
'help_text' => __('Tick this to delete the custom avatar.'),
|
||||||
|
));
|
||||||
|
|
||||||
if ($extra['request']->user->administrator) {
|
if ($extra['request']->user->administrator) {
|
||||||
$this->fields['staff'] = new Pluf_Form_Field_Boolean(
|
$this->fields['staff'] = new Pluf_Form_Field_Boolean(
|
||||||
array('required' => false,
|
array('required' => false,
|
||||||
'label' => __('Staff'),
|
'label' => __('Staff'),
|
||||||
'initial' => $this->user->staff,
|
'initial' => $this->user->staff,
|
||||||
'widget' => 'Pluf_Form_Widget_CheckboxInput',
|
'widget' => 'Pluf_Form_Widget_CheckboxInput',
|
||||||
'help_text' => __('If you give staff rights to a user, you really need to trust him.'),
|
'help_text' => __('If you give staff rights to a user, you really need to trust them.'),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +173,7 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
|||||||
'initial' => $this->user->active,
|
'initial' => $this->user->active,
|
||||||
'widget' => 'Pluf_Form_Widget_CheckboxInput',
|
'widget' => 'Pluf_Form_Widget_CheckboxInput',
|
||||||
'widget_attrs' => $attrs,
|
'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.'),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,8 +198,37 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
|||||||
$update_pass = true;
|
$update_pass = true;
|
||||||
}
|
}
|
||||||
$this->user->setFromFormData($this->cleaned_data);
|
$this->user->setFromFormData($this->cleaned_data);
|
||||||
|
|
||||||
if ($commit) {
|
if ($commit) {
|
||||||
$this->user->update();
|
$this->user->update();
|
||||||
|
|
||||||
|
// FIXME: go the extra mile and check the input lengths for
|
||||||
|
// all fields here!
|
||||||
|
// FIXME: this is all doubled in UserAccount!
|
||||||
|
|
||||||
|
$user_data = IDF_UserData::factory($this->user);
|
||||||
|
|
||||||
|
// Add or remove avatar - we need to do this here because every
|
||||||
|
// single setter directly leads to a save in the database
|
||||||
|
if ($user_data->avatar != '' &&
|
||||||
|
($this->cleaned_data['remove_custom_avatar'] == 1 ||
|
||||||
|
$this->cleaned_data['custom_avatar'] != '')) {
|
||||||
|
$avatar_path = Pluf::f('upload_path').'/avatars/'.basename($user_data->avatar);
|
||||||
|
if (basename($avatar_path) != '' && is_file($avatar_path)) {
|
||||||
|
unlink($avatar_path);
|
||||||
|
}
|
||||||
|
$user_data->avatar = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->cleaned_data['custom_avatar'] != '') {
|
||||||
|
$user_data->avatar = $this->cleaned_data['custom_avatar'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_data->description = $this->cleaned_data['description'];
|
||||||
|
$user_data->twitter = $this->cleaned_data['twitter'];
|
||||||
|
$user_data->public_email = $this->cleaned_data['public_email'];
|
||||||
|
$user_data->website = $this->cleaned_data['website'];
|
||||||
|
|
||||||
if ($update_pass) {
|
if ($update_pass) {
|
||||||
/**
|
/**
|
||||||
* [signal]
|
* [signal]
|
||||||
@@ -170,7 +261,7 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
|||||||
{
|
{
|
||||||
$last_name = trim($this->cleaned_data['last_name']);
|
$last_name = trim($this->cleaned_data['last_name']);
|
||||||
if ($last_name == mb_strtoupper($last_name)) {
|
if ($last_name == mb_strtoupper($last_name)) {
|
||||||
return mb_convert_case(mb_strtolower($last_name),
|
return mb_convert_case(mb_strtolower($last_name),
|
||||||
MB_CASE_TITLE, 'UTF-8');
|
MB_CASE_TITLE, 'UTF-8');
|
||||||
}
|
}
|
||||||
return $last_name;
|
return $last_name;
|
||||||
@@ -179,9 +270,12 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
|||||||
function clean_first_name()
|
function clean_first_name()
|
||||||
{
|
{
|
||||||
$first_name = trim($this->cleaned_data['first_name']);
|
$first_name = trim($this->cleaned_data['first_name']);
|
||||||
|
if ($first_name == '---') {
|
||||||
|
throw new Pluf_Form_Invalid(__('--- is not a valid first name.'));
|
||||||
|
}
|
||||||
if ($first_name == mb_strtoupper($first_name)) {
|
if ($first_name == mb_strtoupper($first_name)) {
|
||||||
return mb_convert_case(mb_strtolower($first_name),
|
$first_name = mb_convert_case(mb_strtolower($first_name),
|
||||||
MB_CASE_TITLE, 'UTF-8');
|
MB_CASE_TITLE, 'UTF-8');
|
||||||
}
|
}
|
||||||
return $first_name;
|
return $first_name;
|
||||||
}
|
}
|
||||||
@@ -198,12 +292,23 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
|||||||
return $email;
|
return $email;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clean_custom_avatar()
|
||||||
|
{
|
||||||
|
// Just png, jpeg/jpg or gif
|
||||||
|
if (!preg_match('/\.(png|jpg|jpeg|gif)$/i', $this->cleaned_data['custom_avatar']) &&
|
||||||
|
$this->cleaned_data['custom_avatar'] != '') {
|
||||||
|
@unlink(Pluf::f('upload_path').'/avatars/'.$this->cleaned_data['custom_avatar']);
|
||||||
|
throw new Pluf_Form_Invalid(__('For security reason, you cannot upload a file with this extension.'));
|
||||||
|
}
|
||||||
|
return $this->cleaned_data['custom_avatar'];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if the 2 passwords are the same.
|
* Check to see if the two passwords are the same.
|
||||||
*/
|
*/
|
||||||
public function clean()
|
public function clean()
|
||||||
{
|
{
|
||||||
if (!isset($this->errors['password'])
|
if (!isset($this->errors['password'])
|
||||||
&& !isset($this->errors['password2'])) {
|
&& !isset($this->errors['password2'])) {
|
||||||
$password1 = $this->cleaned_data['password'];
|
$password1 = $this->cleaned_data['password'];
|
||||||
$password2 = $this->cleaned_data['password2'];
|
$password2 = $this->cleaned_data['password2'];
|
||||||
|
51
src/IDF/Form/Field/EmailList.php
Normal file
51
src/IDF/Form/Field/EmailList.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 ***** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to Pluf_Form_Field_Email, this form field validates one or more
|
||||||
|
* email addresses separated by a comma
|
||||||
|
*/
|
||||||
|
class IDF_Form_Field_EmailList extends Pluf_Form_Field
|
||||||
|
{
|
||||||
|
public $widget = 'Pluf_Form_Widget_TextInput';
|
||||||
|
|
||||||
|
public function clean($value)
|
||||||
|
{
|
||||||
|
parent::clean($value);
|
||||||
|
if (in_array($value, $this->empty_values)) {
|
||||||
|
$value = '';
|
||||||
|
}
|
||||||
|
if ($value == '') {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
$emails = preg_split('/\s*,\s*/', $value, -1, PREG_SPLIT_NO_EMPTY);
|
||||||
|
foreach ($emails as $email) {
|
||||||
|
if (!Pluf_Utils::isValidEmail($email)) {
|
||||||
|
throw new Pluf_Form_Invalid(__(
|
||||||
|
'Please enter one or more valid email addresses.'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return implode(',', $emails);
|
||||||
|
}
|
||||||
|
}
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -45,6 +45,9 @@ class IDF_Form_IssueCreate extends Pluf_Form
|
|||||||
or $this->user->hasPerm('IDF.project-member', $this->project)) {
|
or $this->user->hasPerm('IDF.project-member', $this->project)) {
|
||||||
$this->show_full = true;
|
$this->show_full = true;
|
||||||
}
|
}
|
||||||
|
$contentTemplate = $this->project->getConf()->getVal(
|
||||||
|
'labels_issue_template', IDF_Form_IssueTrackingConf::init_template
|
||||||
|
);
|
||||||
$this->fields['summary'] = new Pluf_Form_Field_Varchar(
|
$this->fields['summary'] = new Pluf_Form_Field_Varchar(
|
||||||
array('required' => true,
|
array('required' => true,
|
||||||
'label' => __('Summary'),
|
'label' => __('Summary'),
|
||||||
@@ -57,7 +60,7 @@ class IDF_Form_IssueCreate extends Pluf_Form
|
|||||||
$this->fields['content'] = new Pluf_Form_Field_Varchar(
|
$this->fields['content'] = new Pluf_Form_Field_Varchar(
|
||||||
array('required' => true,
|
array('required' => true,
|
||||||
'label' => __('Description'),
|
'label' => __('Description'),
|
||||||
'initial' => '',
|
'initial' => $contentTemplate,
|
||||||
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
||||||
'widget_attrs' => array(
|
'widget_attrs' => array(
|
||||||
'cols' => 58,
|
'cols' => 58,
|
||||||
@@ -105,14 +108,41 @@ class IDF_Form_IssueCreate extends Pluf_Form
|
|||||||
'size' => 15,
|
'size' => 15,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get predefined tags for issues from current project
|
||||||
|
*
|
||||||
|
* first Type:<...> and Priority:<...> will be used
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$predefined = preg_split("/[\r\n]+/", $extra['project']->getConf()->getVal(
|
||||||
|
'labels_issue_predefined'
|
||||||
|
));
|
||||||
|
$predefined_type = 'Type:Defect';
|
||||||
|
foreach ($predefined as $tag) {
|
||||||
|
if (strpos($tag, 'Type:') === 0) {
|
||||||
|
$predefined_type = explode('=', $tag, 2);
|
||||||
|
$predefined_type = trim($predefined_type[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$predefined_priority = 'Priority:Medium';
|
||||||
|
foreach ($predefined as $tag) {
|
||||||
|
if (strpos($tag, 'Priority:') === 0) {
|
||||||
|
$predefined_priority = explode('=', $tag, 2);
|
||||||
|
$predefined_priority = trim($predefined_priority[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for ($i=1;$i<7;$i++) {
|
for ($i=1;$i<7;$i++) {
|
||||||
$initial = '';
|
$initial = '';
|
||||||
switch ($i) {
|
switch ($i) {
|
||||||
case 1:
|
case 1:
|
||||||
$initial = 'Type:Defect';
|
$initial = $predefined_type;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
$initial = 'Priority:Medium';
|
$initial = $predefined_priority;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$this->fields['label'.$i] = new Pluf_Form_Field_Varchar(
|
$this->fields['label'.$i] = new Pluf_Form_Field_Varchar(
|
||||||
@@ -141,7 +171,7 @@ class IDF_Form_IssueCreate extends Pluf_Form
|
|||||||
$conf = new IDF_Conf();
|
$conf = new IDF_Conf();
|
||||||
$conf->setProject($this->project);
|
$conf->setProject($this->project);
|
||||||
$onemax = array();
|
$onemax = array();
|
||||||
foreach (split(',', $conf->getVal('labels_issue_one_max', IDF_Form_IssueTrackingConf::init_one_max)) as $class) {
|
foreach (explode(',', $conf->getVal('labels_issue_one_max', IDF_Form_IssueTrackingConf::init_one_max)) as $class) {
|
||||||
if (trim($class) != '') {
|
if (trim($class) != '') {
|
||||||
$onemax[] = mb_strtolower(trim($class));
|
$onemax[] = mb_strtolower(trim($class));
|
||||||
}
|
}
|
||||||
@@ -276,6 +306,7 @@ class IDF_Form_IssueCreate extends Pluf_Form
|
|||||||
$comment->create();
|
$comment->create();
|
||||||
// If we have a file, create the IDF_IssueFile and attach
|
// If we have a file, create the IDF_IssueFile and attach
|
||||||
// it to the comment.
|
// it to the comment.
|
||||||
|
$created_files = array();
|
||||||
for ($i=1;$i<4;$i++) {
|
for ($i=1;$i<4;$i++) {
|
||||||
if ($this->cleaned_data['attachment'.$i]) {
|
if ($this->cleaned_data['attachment'.$i]) {
|
||||||
$file = new IDF_IssueFile();
|
$file = new IDF_IssueFile();
|
||||||
@@ -283,8 +314,36 @@ class IDF_Form_IssueCreate extends Pluf_Form
|
|||||||
$file->submitter = $this->user;
|
$file->submitter = $this->user;
|
||||||
$file->comment = $comment;
|
$file->comment = $comment;
|
||||||
$file->create();
|
$file->create();
|
||||||
|
$created_files[] = $file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* [signal]
|
||||||
|
*
|
||||||
|
* IDF_Issue::create
|
||||||
|
*
|
||||||
|
* [sender]
|
||||||
|
*
|
||||||
|
* IDF_Form_IssueCreate
|
||||||
|
*
|
||||||
|
* [description]
|
||||||
|
*
|
||||||
|
* This signal allows an application to perform a set of tasks
|
||||||
|
* just after the creation of an issue. The comment contains
|
||||||
|
* the description of the issue.
|
||||||
|
*
|
||||||
|
* [parameters]
|
||||||
|
*
|
||||||
|
* array('issue' => $issue,
|
||||||
|
* 'comment' => $comment,
|
||||||
|
* 'files' => $attached_files);
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$params = array('issue' => $issue,
|
||||||
|
'comment' => $comment,
|
||||||
|
'files' => $created_files);
|
||||||
|
Pluf_Signal::send('IDF_Issue::create', 'IDF_Form_IssueCreate',
|
||||||
|
$params);
|
||||||
return $issue;
|
return $issue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -31,6 +31,15 @@ class IDF_Form_IssueTrackingConf extends Pluf_Form
|
|||||||
* Defined as constants to easily access the value in the
|
* Defined as constants to easily access the value in the
|
||||||
* IssueUpdate/Create form in the case nothing is in the db yet.
|
* IssueUpdate/Create form in the case nothing is in the db yet.
|
||||||
*/
|
*/
|
||||||
|
const init_template = 'Steps to reproduce the problem:
|
||||||
|
1.
|
||||||
|
2.
|
||||||
|
3.
|
||||||
|
|
||||||
|
Expected result:
|
||||||
|
|
||||||
|
Actual result:
|
||||||
|
';
|
||||||
const init_open = 'New = Issue has not had initial review yet
|
const init_open = 'New = Issue has not had initial review yet
|
||||||
Accepted = Problem reproduced / Need acknowledged
|
Accepted = Problem reproduced / Need acknowledged
|
||||||
Started = Work on this issue has begun';
|
Started = Work on this issue has begun';
|
||||||
@@ -66,6 +75,15 @@ Maintainability = Hinders future changes';
|
|||||||
|
|
||||||
public function initFields($extra=array())
|
public function initFields($extra=array())
|
||||||
{
|
{
|
||||||
|
$this->fields['labels_issue_template'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Define an issue template to hint to the reporter to provide certain information'),
|
||||||
|
'initial' => self::init_template,
|
||||||
|
'widget_attrs' => array('rows' => 7,
|
||||||
|
'cols' => 75),
|
||||||
|
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
||||||
|
));
|
||||||
|
|
||||||
$this->fields['labels_issue_open'] = new Pluf_Form_Field_Varchar(
|
$this->fields['labels_issue_open'] = new Pluf_Form_Field_Varchar(
|
||||||
array('required' => true,
|
array('required' => true,
|
||||||
'label' => __('Open issue status values'),
|
'label' => __('Open issue status values'),
|
||||||
@@ -87,6 +105,7 @@ Maintainability = Hinders future changes';
|
|||||||
array('required' => true,
|
array('required' => true,
|
||||||
'label' => __('Predefined issue labels'),
|
'label' => __('Predefined issue labels'),
|
||||||
'initial' => self::init_predefined,
|
'initial' => self::init_predefined,
|
||||||
|
'help_text' => __('The first "Type:" and "Priority:" entries found in this list are automatically chosen as defaults for new issues.'),
|
||||||
'widget_attrs' => array('rows' => 7,
|
'widget_attrs' => array('rows' => 7,
|
||||||
'cols' => 75),
|
'cols' => 75),
|
||||||
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
||||||
@@ -99,8 +118,6 @@ Maintainability = Hinders future changes';
|
|||||||
'widget_attrs' => array('size' => 60),
|
'widget_attrs' => array('size' => 60),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -305,6 +305,7 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
|
|||||||
$this->issue->submitter != $this->user->id) {
|
$this->issue->submitter != $this->user->id) {
|
||||||
$this->issue->setAssoc($this->user); // interested user.
|
$this->issue->setAssoc($this->user); // interested user.
|
||||||
}
|
}
|
||||||
|
$attached_files = array();
|
||||||
for ($i=1;$i<4;$i++) {
|
for ($i=1;$i<4;$i++) {
|
||||||
if ($this->cleaned_data['attachment'.$i]) {
|
if ($this->cleaned_data['attachment'.$i]) {
|
||||||
$file = new IDF_IssueFile();
|
$file = new IDF_IssueFile();
|
||||||
@@ -312,8 +313,36 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
|
|||||||
$file->submitter = $this->user;
|
$file->submitter = $this->user;
|
||||||
$file->comment = $comment;
|
$file->comment = $comment;
|
||||||
$file->create();
|
$file->create();
|
||||||
|
$attached_files[] = $file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* [signal]
|
||||||
|
*
|
||||||
|
* IDF_Issue::update
|
||||||
|
*
|
||||||
|
* [sender]
|
||||||
|
*
|
||||||
|
* IDF_Form_IssueUpdate
|
||||||
|
*
|
||||||
|
* [description]
|
||||||
|
*
|
||||||
|
* This signal allows an application to perform a set of tasks
|
||||||
|
* just after the update of an issue.
|
||||||
|
*
|
||||||
|
* [parameters]
|
||||||
|
*
|
||||||
|
* array('issue' => $issue,
|
||||||
|
* 'comment' => $comment,
|
||||||
|
* 'files' => $attached_files);
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$params = array('issue' => $this->issue,
|
||||||
|
'comment' => $comment,
|
||||||
|
'files' => $attached_files);
|
||||||
|
Pluf_Signal::send('IDF_Issue::update', 'IDF_Form_IssueUpdate',
|
||||||
|
$params);
|
||||||
|
|
||||||
return $this->issue;
|
return $this->issue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -67,6 +67,45 @@ class IDF_Form_MembersConf extends Pluf_Form
|
|||||||
$this->project->membershipsUpdated();
|
$this->project->membershipsUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function clean_owners()
|
||||||
|
{
|
||||||
|
return self::checkBadLogins($this->cleaned_data['owners']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clean_members()
|
||||||
|
{
|
||||||
|
return self::checkBadLogins($this->cleaned_data['members']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From the input, find the bad logins.
|
||||||
|
*
|
||||||
|
* @throws Pluf_Form_Invalid exception when bad logins are found
|
||||||
|
* @param string Comma, new line delimited list of logins
|
||||||
|
* @return string Comma, new line delimited list of logins
|
||||||
|
*/
|
||||||
|
public static function checkBadLogins($logins)
|
||||||
|
{
|
||||||
|
$bad = array();
|
||||||
|
foreach (preg_split("/\015\012|\015|\012|\,/", $logins, -1, PREG_SPLIT_NO_EMPTY) as $login) {
|
||||||
|
$sql = new Pluf_SQL('login=%s', array(trim($login)));
|
||||||
|
try {
|
||||||
|
$user = Pluf::factory('Pluf_User')->getOne(array('filter'=>$sql->gen()));
|
||||||
|
if (null == $user) {
|
||||||
|
$bad[] = $login;
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$bad[] = $login;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$n = count($bad);
|
||||||
|
if ($n) {
|
||||||
|
$badlogins = Pluf_esc(implode(', ', $bad));
|
||||||
|
throw new Pluf_Form_Invalid(sprintf(_n('The following login is invalid: %s.', 'The following logins are invalid: %s.', $n), $badlogins));
|
||||||
|
}
|
||||||
|
return $logins;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The update of the memberships is done in different places. This
|
* The update of the memberships is done in different places. This
|
||||||
* avoids duplicating code.
|
* avoids duplicating code.
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -48,6 +48,21 @@ class IDF_Form_Password extends Pluf_Form
|
|||||||
if ($users->count() == 0) {
|
if ($users->count() == 0) {
|
||||||
throw new Pluf_Form_Invalid(__('Sorry, we cannot find a user with this email address or login. Feel free to try again.'));
|
throw new Pluf_Form_Invalid(__('Sorry, we cannot find a user with this email address or login. Feel free to try again.'));
|
||||||
}
|
}
|
||||||
|
$ok = false;
|
||||||
|
foreach ($users as $user) {
|
||||||
|
if ($user->active) {
|
||||||
|
$ok = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!$user->active and $user->first_name == '---') {
|
||||||
|
$ok = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$ok = false; // This ensures an all or nothing ok.
|
||||||
|
}
|
||||||
|
if (!$ok) {
|
||||||
|
throw new Pluf_Form_Invalid(__('Sorry, we cannot find a user with this email address or login. Feel free to try again.'));
|
||||||
|
}
|
||||||
return $account;
|
return $account;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,23 +79,34 @@ class IDF_Form_Password extends Pluf_Form
|
|||||||
$sql = new Pluf_SQL('email=%s OR login=%s',
|
$sql = new Pluf_SQL('email=%s OR login=%s',
|
||||||
array($account, $account));
|
array($account, $account));
|
||||||
$users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen()));
|
$users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen()));
|
||||||
|
|
||||||
|
$return_url = '';
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
$tmpl = new Pluf_Template('idf/user/passrecovery-email.txt');
|
if ($user->active) {
|
||||||
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
|
$return_url = Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecoveryInputCode');
|
||||||
$code = trim($cr->encrypt($user->email.':'.$user->id.':'.time()),
|
$tmpl = new Pluf_Template('idf/user/passrecovery-email.txt');
|
||||||
'~');
|
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
|
||||||
$code = substr(md5(Pluf::f('secret_key').$code), 0, 2).$code;
|
$code = trim($cr->encrypt($user->email.':'.$user->id.':'.time().':primary'),
|
||||||
$url = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecovery', array($code), array(), false);
|
'~');
|
||||||
$urlic = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecoveryInputCode', array(), array(), false);
|
$code = substr(md5(Pluf::f('secret_key').$code), 0, 2).$code;
|
||||||
$context = new Pluf_Template_Context(array('url' => Pluf_Template::markSafe($url),
|
$url = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecovery', array($code), array(), false);
|
||||||
'urlik' => Pluf_Template::markSafe($urlic),
|
$urlic = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecoveryInputCode', array(), array(), false);
|
||||||
'user' => Pluf_Template::markSafe($user),
|
$context = new Pluf_Template_Context(
|
||||||
'key' => Pluf_Template::markSafe($code)));
|
array('url' => Pluf_Template::markSafe($url),
|
||||||
$email = new Pluf_Mail(Pluf::f('from_email'), $user->email,
|
'urlik' => Pluf_Template::markSafe($urlic),
|
||||||
__('Password Recovery - InDefero'));
|
'user' => Pluf_Template::markSafe($user),
|
||||||
$email->setReturnPath(Pluf::f('bounce_email', Pluf::f('from_email')));
|
'key' => Pluf_Template::markSafe($code)));
|
||||||
$email->addTextMessage($tmpl->render($context));
|
$email = new Pluf_Mail(Pluf::f('from_email'), $user->email,
|
||||||
$email->sendMail();
|
__('Password Recovery - InDefero'));
|
||||||
|
$email->setReturnPath(Pluf::f('bounce_email', Pluf::f('from_email')));
|
||||||
|
$email->addTextMessage($tmpl->render($context));
|
||||||
|
$email->sendMail();
|
||||||
|
}
|
||||||
|
if (!$user->active and $user->first_name == '---') {
|
||||||
|
$return_url = Pluf_HTTP_URL_urlForView('IDF_Views::registerInputKey');
|
||||||
|
IDF_Form_Register::sendVerificationEmail($user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return $return_url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -95,6 +95,10 @@ class IDF_Form_PasswordInputKey extends Pluf_Form
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
|
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
|
||||||
return split(':', $cr->decrypt($encrypted), 3);
|
$f = explode(':', $cr->decrypt($encrypted), 3);
|
||||||
|
if (count($f) != 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -73,6 +73,9 @@ class IDF_Form_PasswordReset extends Pluf_Form
|
|||||||
if ($this->cleaned_data['password'] != $this->cleaned_data['password2']) {
|
if ($this->cleaned_data['password'] != $this->cleaned_data['password2']) {
|
||||||
throw new Pluf_Form_Invalid(__('The two passwords must be the same.'));
|
throw new Pluf_Form_Invalid(__('The two passwords must be the same.'));
|
||||||
}
|
}
|
||||||
|
if (!$this->user->active) {
|
||||||
|
throw new Pluf_Form_Invalid(__('This account is not active. Please contact the forge administrator to activate it.'));
|
||||||
|
}
|
||||||
return $this->cleaned_data;
|
return $this->cleaned_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
140
src/IDF/Form/ProjectConf.php
Normal file
140
src/IDF/Form/ProjectConf.php
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
<?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'];
|
||||||
|
|
||||||
|
// 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',
|
||||||
|
));
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
'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 save($commit=true)
|
||||||
|
{
|
||||||
|
$conf = $this->project->getConf();
|
||||||
|
|
||||||
|
// 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->update();
|
||||||
|
|
||||||
|
// Logo part
|
||||||
|
if ($this->cleaned_data['logo'] !== "") {
|
||||||
|
$conf->setVal('logo', $this->cleaned_data['logo']);
|
||||||
|
}
|
||||||
|
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 *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# 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,
|
'max_length' => 15,
|
||||||
'min_length' => 3,
|
'min_length' => 3,
|
||||||
'initial' => $login,
|
'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(
|
'widget_attrs' => array(
|
||||||
'maxlength' => 15,
|
'maxlength' => 15,
|
||||||
'size' => 10,
|
'size' => 10,
|
||||||
@@ -52,7 +52,7 @@ class IDF_Form_Register extends Pluf_Form
|
|||||||
array('required' => true,
|
array('required' => true,
|
||||||
'label' => __('Your email'),
|
'label' => __('Your email'),
|
||||||
'initial' => '',
|
'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(
|
$this->fields['terms'] = new Pluf_Form_Field_Boolean(
|
||||||
@@ -93,10 +93,8 @@ class IDF_Form_Register extends Pluf_Form
|
|||||||
function clean_email()
|
function clean_email()
|
||||||
{
|
{
|
||||||
$this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email']));
|
$this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email']));
|
||||||
$guser = new Pluf_User();
|
if (Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($this->cleaned_data['email']) != null) {
|
||||||
$sql = new Pluf_SQL('email=%s', $this->cleaned_data['email']);
|
throw new Pluf_Form_Invalid(sprintf(__('The email "%s" is already used. If you need to, click on the help link to recover your password.'), $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']));
|
|
||||||
}
|
}
|
||||||
return $this->cleaned_data['email'];
|
return $this->cleaned_data['email'];
|
||||||
}
|
}
|
||||||
@@ -124,8 +122,14 @@ class IDF_Form_Register extends Pluf_Form
|
|||||||
$user->language = $this->request->language_code;
|
$user->language = $this->request->language_code;
|
||||||
$user->active = false;
|
$user->active = false;
|
||||||
$user->create();
|
$user->create();
|
||||||
$from_email = Pluf::f('from_email');
|
self::sendVerificationEmail($user);
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function sendVerificationEmail($user)
|
||||||
|
{
|
||||||
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
|
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
|
||||||
|
$from_email = Pluf::f('from_email');
|
||||||
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
|
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
|
||||||
$encrypted = trim($cr->encrypt($user->email.':'.$user->id), '~');
|
$encrypted = trim($cr->encrypt($user->email.':'.$user->id), '~');
|
||||||
$key = substr(md5(Pluf::f('secret_key').$encrypted), 0, 2).$encrypted;
|
$key = substr(md5(Pluf::f('secret_key').$encrypted), 0, 2).$encrypted;
|
||||||
@@ -144,6 +148,5 @@ class IDF_Form_Register extends Pluf_Form
|
|||||||
__('Confirm the creation of your account.'));
|
__('Confirm the creation of your account.'));
|
||||||
$email->addTextMessage($text_email);
|
$email->addTextMessage($text_email);
|
||||||
$email->sendMail();
|
$email->sendMail();
|
||||||
return $user;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# 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'),
|
'label' => __('Your password'),
|
||||||
'initial' => '',
|
'initial' => '',
|
||||||
'widget' => 'Pluf_Form_Widget_PasswordInput',
|
'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(
|
'widget_attrs' => array(
|
||||||
'maxlength' => 50,
|
'maxlength' => 50,
|
||||||
'size' => 15,
|
'size' => 15,
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -91,6 +91,6 @@ class IDF_Form_RegisterInputKey extends Pluf_Form
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
|
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
|
||||||
return split(':', $cr->decrypt($encrypted), 2);
|
return explode(':', $cr->decrypt($encrypted), 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,203 +0,0 @@
|
|||||||
<?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 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 documentation page.
|
|
||||||
*
|
|
||||||
* This create a new page and the corresponding revision.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class IDF_Form_WikiCreate extends Pluf_Form
|
|
||||||
{
|
|
||||||
public $user = null;
|
|
||||||
public $project = null;
|
|
||||||
public $show_full = false;
|
|
||||||
|
|
||||||
public function initFields($extra=array())
|
|
||||||
{
|
|
||||||
$initial = __('# Introduction
|
|
||||||
|
|
||||||
Add your content here.
|
|
||||||
|
|
||||||
|
|
||||||
# Details
|
|
||||||
|
|
||||||
Add your content here. Format your content with:
|
|
||||||
|
|
||||||
* Text in **bold** or *italic*.
|
|
||||||
* Headings, paragraphs, and lists.
|
|
||||||
* Links to other [[WikiPage]].
|
|
||||||
');
|
|
||||||
$this->user = $extra['user'];
|
|
||||||
$this->project = $extra['project'];
|
|
||||||
if ($this->user->hasPerm('IDF.project-owner', $this->project)
|
|
||||||
or $this->user->hasPerm('IDF.project-member', $this->project)) {
|
|
||||||
$this->show_full = true;
|
|
||||||
}
|
|
||||||
$this->fields['title'] = new Pluf_Form_Field_Varchar(
|
|
||||||
array('required' => true,
|
|
||||||
'label' => __('Page title'),
|
|
||||||
'initial' => __('PageName'),
|
|
||||||
'widget_attrs' => array(
|
|
||||||
'maxlength' => 200,
|
|
||||||
'size' => 67,
|
|
||||||
),
|
|
||||||
'help_text' => __('The page 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 pages.'),
|
|
||||||
'initial' => '',
|
|
||||||
'widget_attrs' => array(
|
|
||||||
'maxlength' => 200,
|
|
||||||
'size' => 67,
|
|
||||||
),
|
|
||||||
));
|
|
||||||
$this->fields['content'] = new Pluf_Form_Field_Varchar(
|
|
||||||
array('required' => true,
|
|
||||||
'label' => __('Content'),
|
|
||||||
'initial' => $initial,
|
|
||||||
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
|
||||||
'widget_attrs' => array(
|
|
||||||
'cols' => 58,
|
|
||||||
'rows' => 26,
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
if ($this->show_full) {
|
|
||||||
for ($i=1;$i<4;$i++) {
|
|
||||||
$this->fields['label'.$i] = new Pluf_Form_Field_Varchar(
|
|
||||||
array('required' => false,
|
|
||||||
'label' => __('Labels'),
|
|
||||||
'initial' => '',
|
|
||||||
'widget_attrs' => array(
|
|
||||||
'maxlength' => 50,
|
|
||||||
'size' => 20,
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
$pages = Pluf::factory('IDF_WikiPage')->getList(array('filter'=>$sql->gen()));
|
|
||||||
if ($pages->count() > 0) {
|
|
||||||
throw new Pluf_Form_Invalid(__('A page with this title already exists.'));
|
|
||||||
}
|
|
||||||
return $title;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate the interconnection in the form.
|
|
||||||
*/
|
|
||||||
public function clean()
|
|
||||||
{
|
|
||||||
if (!$this->show_full) {
|
|
||||||
return $this->cleaned_data;
|
|
||||||
}
|
|
||||||
$conf = new IDF_Conf();
|
|
||||||
$conf->setProject($this->project);
|
|
||||||
$onemax = array();
|
|
||||||
foreach (split(',', $conf->getVal('labels_wiki_one_max', IDF_Form_WikiConf::init_one_max)) as $class) {
|
|
||||||
if (trim($class) != '') {
|
|
||||||
$onemax[] = mb_strtolower(trim($class));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$count = array();
|
|
||||||
for ($i=1;$i<4;$i++) {
|
|
||||||
$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)),
|
|
||||||
trim($name));
|
|
||||||
} else {
|
|
||||||
$class = 'other';
|
|
||||||
$name = $this->cleaned_data['label'.$i];
|
|
||||||
}
|
|
||||||
if (!isset($count[$class])) $count[$class] = 1;
|
|
||||||
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);
|
|
||||||
throw new Pluf_Form_Invalid(__('You provided an invalid label.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $this->cleaned_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.'));
|
|
||||||
}
|
|
||||||
// Add a tag for each label
|
|
||||||
$tags = array();
|
|
||||||
if ($this->show_full) {
|
|
||||||
for ($i=1;$i<4;$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]);
|
|
||||||
}
|
|
||||||
$tags[] = IDF_Tag::add($name, $this->project, $class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Create the page
|
|
||||||
$page = new IDF_WikiPage();
|
|
||||||
$page->project = $this->project;
|
|
||||||
$page->submitter = $this->user;
|
|
||||||
$page->summary = trim($this->cleaned_data['summary']);
|
|
||||||
$page->title = trim($this->cleaned_data['title']);
|
|
||||||
$page->create();
|
|
||||||
foreach ($tags as $tag) {
|
|
||||||
$page->setAssoc($tag);
|
|
||||||
}
|
|
||||||
// add the first revision
|
|
||||||
$rev = new IDF_WikiRevision();
|
|
||||||
$rev->wikipage = $page;
|
|
||||||
$rev->content = $this->cleaned_data['content'];
|
|
||||||
$rev->submitter = $this->user;
|
|
||||||
$rev->summary = __('Initial page creation');
|
|
||||||
$rev->create();
|
|
||||||
return $page;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -204,26 +204,31 @@ class IDF_Form_ReviewCreate extends Pluf_Form
|
|||||||
$patch->commit = self::findCommit($this->cleaned_data['commit']);
|
$patch->commit = self::findCommit($this->cleaned_data['commit']);
|
||||||
$patch->patch = $this->cleaned_data['patch'];
|
$patch->patch = $this->cleaned_data['patch'];
|
||||||
$patch->create();
|
$patch->create();
|
||||||
// Send create notification
|
$patch->notify($this->project->getConf());
|
||||||
if ('' != $this->project->getConf()->getVal('review_notification_email', '')) {
|
/**
|
||||||
$context = new Pluf_Template_Context(
|
* [signal]
|
||||||
array(
|
*
|
||||||
'review' => $review,
|
* IDF_Review::create
|
||||||
'patch' => $patch,
|
*
|
||||||
'comments' => array(),
|
* [sender]
|
||||||
'project' => $this->project,
|
*
|
||||||
'url_base' => Pluf::f('url_base'),
|
* IDF_Form_ReviewCreate
|
||||||
)
|
*
|
||||||
);
|
* [description]
|
||||||
$tmpl = new Pluf_Template('idf/review/review-created-email.txt');
|
*
|
||||||
$text_email = $tmpl->render($context);
|
* This signal allows an application to perform a set of tasks
|
||||||
$email = new Pluf_Mail(Pluf::f('from_email'),
|
* just after the creation of a review and the notification.
|
||||||
$this->project->getConf()->getVal('review_notification_email'),
|
*
|
||||||
sprintf(__('New Code Review %s - %s (%s)'),
|
* [parameters]
|
||||||
$review->id, $review->summary, $this->project->shortname));
|
*
|
||||||
$email->addTextMessage($text_email);
|
* array('review' => $review,
|
||||||
$email->sendMail();
|
* 'patch' => $patch);
|
||||||
}
|
*
|
||||||
|
*/
|
||||||
|
$params = array('review' => $review,
|
||||||
|
'patch' => $patch);
|
||||||
|
Pluf_Signal::send('IDF_Review::create', 'IDF_Form_ReviewCreate',
|
||||||
|
$params);
|
||||||
return $review;
|
return $review;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -30,12 +30,15 @@ class IDF_Form_ReviewFileComment extends Pluf_Form
|
|||||||
public $files = null;
|
public $files = null;
|
||||||
public $patch = null;
|
public $patch = null;
|
||||||
public $user = null;
|
public $user = null;
|
||||||
|
public $project = null;
|
||||||
|
|
||||||
public function initFields($extra=array())
|
public function initFields($extra=array())
|
||||||
{
|
{
|
||||||
$this->files = $extra['files'];
|
$this->files = $extra['files'];
|
||||||
$this->patch = $extra['patch'];
|
$this->patch = $extra['patch'];
|
||||||
$this->user = $extra['user'];
|
$this->user = $extra['user'];
|
||||||
|
$this->project = $extra['project'];
|
||||||
|
|
||||||
foreach ($this->files as $filename => $def) {
|
foreach ($this->files as $filename => $def) {
|
||||||
$this->fields[md5($filename)] = new Pluf_Form_Field_Varchar(
|
$this->fields[md5($filename)] = new Pluf_Form_Field_Varchar(
|
||||||
array('required' => false,
|
array('required' => false,
|
||||||
@@ -48,6 +51,43 @@ class IDF_Form_ReviewFileComment extends Pluf_Form
|
|||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
$this->fields['content'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('General comment'),
|
||||||
|
'initial' => '',
|
||||||
|
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'cols' => 58,
|
||||||
|
'rows' => 9,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
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(
|
||||||
|
array('required' => true,
|
||||||
|
'label' => __('Summary'),
|
||||||
|
'initial' => $this->patch->get_review()->summary,
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 200,
|
||||||
|
'size' => 67,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['status'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => true,
|
||||||
|
'label' => __('Status'),
|
||||||
|
'initial' => $this->patch->get_review()->get_status()->name,
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 20,
|
||||||
|
'size' => 15,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -56,12 +96,38 @@ class IDF_Form_ReviewFileComment extends Pluf_Form
|
|||||||
*/
|
*/
|
||||||
public function clean()
|
public function clean()
|
||||||
{
|
{
|
||||||
foreach ($this->files as $filename => $def) {
|
$isOk = false;
|
||||||
if (!empty($this->cleaned_data[md5($filename)])) {
|
|
||||||
return $this->cleaned_data;
|
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(empty($content)) {
|
||||||
|
if ($this->fields['status']->initial != $this->fields['status']->value) {
|
||||||
|
return __('The status have been updated.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Pluf_Form_Invalid(__('This field is required.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,19 +142,40 @@ class IDF_Form_ReviewFileComment extends Pluf_Form
|
|||||||
if (!$this->isValid()) {
|
if (!$this->isValid()) {
|
||||||
throw new Exception(__('Cannot save the model from an invalid form.'));
|
throw new Exception(__('Cannot save the model from an invalid form.'));
|
||||||
}
|
}
|
||||||
|
// create a base comment
|
||||||
|
$bc = new IDF_Review_Comment();
|
||||||
|
$bc->patch = $this->patch;
|
||||||
|
$bc->submitter = $this->user;
|
||||||
|
$bc->content = $this->cleaned_data['content'];
|
||||||
|
$review = $this->patch->get_review();
|
||||||
|
if ($this->show_full) {
|
||||||
|
// Compare between the old and the new data
|
||||||
|
// Status, summary
|
||||||
|
$changes = array();
|
||||||
|
$status = IDF_Tag::add(trim($this->cleaned_data['status']), $this->project, 'Status');
|
||||||
|
if ($status->id != $this->patch->get_review()->status) {
|
||||||
|
$changes['st'] = $status->name;
|
||||||
|
}
|
||||||
|
if (trim($this->patch->get_review()->summary) != trim($this->cleaned_data['summary'])) {
|
||||||
|
$changes['su'] = trim($this->cleaned_data['summary']);
|
||||||
|
}
|
||||||
|
// Update the review
|
||||||
|
$review->summary = trim($this->cleaned_data['summary']);
|
||||||
|
$review->status = $status;
|
||||||
|
$bc->changes = $changes;
|
||||||
|
}
|
||||||
|
$bc->create();
|
||||||
foreach ($this->files as $filename => $def) {
|
foreach ($this->files as $filename => $def) {
|
||||||
if (!empty($this->cleaned_data[md5($filename)])) {
|
if (!empty($this->cleaned_data[md5($filename)])) {
|
||||||
// Add a comment.
|
// Add a comment.
|
||||||
$c = new IDF_Review_FileComment();
|
$c = new IDF_Review_FileComment();
|
||||||
$c->patch = $this->patch;
|
$c->comment = $bc;
|
||||||
$c->cfile = $filename;
|
$c->cfile = $filename;
|
||||||
$c->submitter = $this->user;
|
|
||||||
$c->content = $this->cleaned_data[md5($filename)];
|
$c->content = $this->cleaned_data[md5($filename)];
|
||||||
$c->create();
|
$c->create();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->patch->get_review()->update(); // reindex and put up in
|
$review->update(); // reindex and put up in the list.
|
||||||
// the list.
|
return $bc;
|
||||||
return $this->patch;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -34,7 +34,7 @@ class IDF_Form_SourceConf extends Pluf_Form
|
|||||||
public function initFields($extra=array())
|
public function initFields($extra=array())
|
||||||
{
|
{
|
||||||
$this->conf = $extra['conf'];
|
$this->conf = $extra['conf'];
|
||||||
if ($this->conf->getVal('scm', 'git') == 'svn') {
|
if ($extra['remote_svn']) {
|
||||||
$this->fields['svn_username'] = new Pluf_Form_Field_Varchar(
|
$this->fields['svn_username'] = new Pluf_Form_Field_Varchar(
|
||||||
array('required' => false,
|
array('required' => false,
|
||||||
'label' => __('Repository username'),
|
'label' => __('Repository username'),
|
||||||
@@ -49,6 +49,16 @@ class IDF_Form_SourceConf extends Pluf_Form
|
|||||||
'widget' => 'Pluf_Form_Widget_PasswordInput',
|
'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 *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -45,7 +45,7 @@ class IDF_Form_TabsConf extends Pluf_Form
|
|||||||
array('required' => true,
|
array('required' => true,
|
||||||
'label' => $label,
|
'label' => $label,
|
||||||
'initial' => $this->conf->getVal($key, 'all'),
|
'initial' => $this->conf->getVal($key, 'all'),
|
||||||
'widget_attrs' => array('choices' =>
|
'widget_attrs' => array('choices' =>
|
||||||
array(
|
array(
|
||||||
__('Open to all') => 'all',
|
__('Open to all') => 'all',
|
||||||
__('Signed in users') => 'login',
|
__('Signed in users') => 'login',
|
||||||
@@ -63,10 +63,11 @@ class IDF_Form_TabsConf extends Pluf_Form
|
|||||||
'source_notification_email',
|
'source_notification_email',
|
||||||
'issues_notification_email',);
|
'issues_notification_email',);
|
||||||
foreach ($ak as $key) {
|
foreach ($ak as $key) {
|
||||||
$this->fields[$key] = new Pluf_Form_Field_Email(
|
$this->fields[$key] = new IDF_Form_Field_EmailList(
|
||||||
array('required' => false,
|
array('required' => false,
|
||||||
'label' => $key,
|
'label' => $key,
|
||||||
'initial' => $this->conf->getVal($key, ''),
|
'initial' => $this->conf->getVal($key, ''),
|
||||||
|
'widget_attrs' => array('size' => 40),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +87,11 @@ class IDF_Form_TabsConf extends Pluf_Form
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function clean_authorized_users()
|
||||||
|
{
|
||||||
|
return IDF_Form_MembersConf::checkBadLogins($this->cleaned_data['authorized_users']);
|
||||||
|
}
|
||||||
|
|
||||||
public function save($commit=true)
|
public function save($commit=true)
|
||||||
{
|
{
|
||||||
if (!$this->isValid()) {
|
if (!$this->isValid()) {
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -46,6 +46,16 @@ class IDF_Form_UpdateUpload extends Pluf_Form
|
|||||||
'size' => 67,
|
'size' => 67,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
$this->fields['changelog'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Description'),
|
||||||
|
'initial' => $this->upload->changelog,
|
||||||
|
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'cols' => 58,
|
||||||
|
'rows' => 13,
|
||||||
|
),
|
||||||
|
));
|
||||||
$tags = $this->upload->get_tags_list();
|
$tags = $this->upload->get_tags_list();
|
||||||
for ($i=1;$i<7;$i++) {
|
for ($i=1;$i<7;$i++) {
|
||||||
$initial = '';
|
$initial = '';
|
||||||
@@ -76,7 +86,7 @@ class IDF_Form_UpdateUpload extends Pluf_Form
|
|||||||
$conf = new IDF_Conf();
|
$conf = new IDF_Conf();
|
||||||
$conf->setProject($this->project);
|
$conf->setProject($this->project);
|
||||||
$onemax = array();
|
$onemax = array();
|
||||||
foreach (split(',', $conf->getVal('labels_download_one_max', IDF_Form_UploadConf::init_one_max)) as $class) {
|
foreach (explode(',', $conf->getVal('labels_download_one_max', IDF_Form_UploadConf::init_one_max)) as $class) {
|
||||||
if (trim($class) != '') {
|
if (trim($class) != '') {
|
||||||
$onemax[] = mb_strtolower(trim($class));
|
$onemax[] = mb_strtolower(trim($class));
|
||||||
}
|
}
|
||||||
@@ -132,9 +142,32 @@ class IDF_Form_UpdateUpload extends Pluf_Form
|
|||||||
}
|
}
|
||||||
// Create the upload
|
// Create the upload
|
||||||
$this->upload->summary = trim($this->cleaned_data['summary']);
|
$this->upload->summary = trim($this->cleaned_data['summary']);
|
||||||
|
$this->upload->changelog = trim($this->cleaned_data['changelog']);
|
||||||
$this->upload->modif_dtime = gmdate('Y-m-d H:i:s');
|
$this->upload->modif_dtime = gmdate('Y-m-d H:i:s');
|
||||||
$this->upload->update();
|
$this->upload->update();
|
||||||
$this->upload->batchAssoc('IDF_Tag', $tags);
|
$this->upload->batchAssoc('IDF_Tag', $tags);
|
||||||
|
/**
|
||||||
|
* [signal]
|
||||||
|
*
|
||||||
|
* IDF_Upload::update
|
||||||
|
*
|
||||||
|
* [sender]
|
||||||
|
*
|
||||||
|
* IDF_Form_UpdateUpload
|
||||||
|
*
|
||||||
|
* [description]
|
||||||
|
*
|
||||||
|
* This signal allows an application to perform a set of tasks
|
||||||
|
* just after the update of an uploaded file.
|
||||||
|
*
|
||||||
|
* [parameters]
|
||||||
|
*
|
||||||
|
* array('upload' => $upload);
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$params = array('upload' => $this->upload);
|
||||||
|
Pluf_Signal::send('IDF_Upload::update',
|
||||||
|
'IDF_Form_UpdateUpload', $params);
|
||||||
return $this->upload;
|
return $this->upload;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -44,6 +44,16 @@ class IDF_Form_Upload extends Pluf_Form
|
|||||||
'size' => 67,
|
'size' => 67,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
$this->fields['changelog'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Description'),
|
||||||
|
'initial' => '',
|
||||||
|
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'cols' => 58,
|
||||||
|
'rows' => 13,
|
||||||
|
),
|
||||||
|
));
|
||||||
$this->fields['file'] = new Pluf_Form_Field_File(
|
$this->fields['file'] = new Pluf_Form_Field_File(
|
||||||
array('required' => true,
|
array('required' => true,
|
||||||
'label' => __('File'),
|
'label' => __('File'),
|
||||||
@@ -71,8 +81,9 @@ class IDF_Form_Upload extends Pluf_Form
|
|||||||
{
|
{
|
||||||
$extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext'))));
|
$extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext'))));
|
||||||
if (strlen($extra)) $extra .= '|';
|
if (strlen($extra)) $extra .= '|';
|
||||||
if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|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|wmv|zip)$/i', $this->cleaned_data['file'])) {
|
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'])) {
|
||||||
throw new Pluf_Form_Invalid(__('For security reason, you cannot upload a file with this extension.'));
|
@unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$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'];
|
return $this->cleaned_data['file'];
|
||||||
}
|
}
|
||||||
@@ -85,7 +96,7 @@ class IDF_Form_Upload extends Pluf_Form
|
|||||||
$conf = new IDF_Conf();
|
$conf = new IDF_Conf();
|
||||||
$conf->setProject($this->project);
|
$conf->setProject($this->project);
|
||||||
$onemax = array();
|
$onemax = array();
|
||||||
foreach (split(',', $conf->getVal('labels_download_one_max', IDF_Form_UploadConf::init_one_max)) as $class) {
|
foreach (explode(',', $conf->getVal('labels_download_one_max', IDF_Form_UploadConf::init_one_max)) as $class) {
|
||||||
if (trim($class) != '') {
|
if (trim($class) != '') {
|
||||||
$onemax[] = mb_strtolower(trim($class));
|
$onemax[] = mb_strtolower(trim($class));
|
||||||
}
|
}
|
||||||
@@ -155,6 +166,7 @@ class IDF_Form_Upload extends Pluf_Form
|
|||||||
$upload->project = $this->project;
|
$upload->project = $this->project;
|
||||||
$upload->submitter = $this->user;
|
$upload->submitter = $this->user;
|
||||||
$upload->summary = trim($this->cleaned_data['summary']);
|
$upload->summary = trim($this->cleaned_data['summary']);
|
||||||
|
$upload->changelog = trim($this->cleaned_data['changelog']);
|
||||||
$upload->file = $this->cleaned_data['file'];
|
$upload->file = $this->cleaned_data['file'];
|
||||||
$upload->filesize = filesize(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file']);
|
$upload->filesize = filesize(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file']);
|
||||||
$upload->downloads = 0;
|
$upload->downloads = 0;
|
||||||
@@ -163,21 +175,29 @@ class IDF_Form_Upload extends Pluf_Form
|
|||||||
$upload->setAssoc($tag);
|
$upload->setAssoc($tag);
|
||||||
}
|
}
|
||||||
// Send the notification
|
// Send the notification
|
||||||
if ('' != $this->project->getConf()->getVal('downloads_notification_email', '')) {
|
$upload->notify($this->project->getConf());
|
||||||
$context = new Pluf_Template_Context(
|
/**
|
||||||
array('file' => $upload,
|
* [signal]
|
||||||
'urlfile' => $upload->getAbsoluteUrl($this->project),
|
*
|
||||||
'project' => $this->project,
|
* IDF_Upload::create
|
||||||
'tags' => $upload->get_tags_list(),
|
*
|
||||||
));
|
* [sender]
|
||||||
$tmpl = new Pluf_Template('idf/downloads/download-created-email.txt');
|
*
|
||||||
$text_email = $tmpl->render($context);
|
* IDF_Form_Upload
|
||||||
$email = new Pluf_Mail(Pluf::f('from_email'), $this->project->getConf()->getVal('downloads_notification_email'),
|
*
|
||||||
sprintf(__('New download - %s (%s)'),
|
* [description]
|
||||||
$upload->summary, $this->project->shortname));
|
*
|
||||||
$email->addTextMessage($text_email);
|
* This signal allows an application to perform a set of tasks
|
||||||
$email->sendMail();
|
* 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);
|
||||||
return $upload;
|
return $upload;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -33,6 +33,8 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
public function initFields($extra=array())
|
public function initFields($extra=array())
|
||||||
{
|
{
|
||||||
$this->user = $extra['user'];
|
$this->user = $extra['user'];
|
||||||
|
$user_data = IDF_UserData::factory($this->user);
|
||||||
|
|
||||||
$this->fields['first_name'] = new Pluf_Form_Field_Varchar(
|
$this->fields['first_name'] = new Pluf_Form_Field_Varchar(
|
||||||
array('required' => false,
|
array('required' => false,
|
||||||
'label' => __('First name'),
|
'label' => __('First name'),
|
||||||
@@ -65,7 +67,7 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
'initial' => $this->user->language,
|
'initial' => $this->user->language,
|
||||||
'widget' => 'Pluf_Form_Widget_SelectInput',
|
'widget' => 'Pluf_Form_Widget_SelectInput',
|
||||||
'widget_attrs' => array(
|
'widget_attrs' => array(
|
||||||
'choices' =>
|
'choices' =>
|
||||||
Pluf_L10n::getInstalledLanguages()
|
Pluf_L10n::getInstalledLanguages()
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
@@ -77,6 +79,7 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
'widget' => 'Pluf_Form_Widget_PasswordInput',
|
'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.')),
|
'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(
|
'widget_attrs' => array(
|
||||||
|
'autocomplete' => 'off',
|
||||||
'maxlength' => 50,
|
'maxlength' => 50,
|
||||||
'size' => 15,
|
'size' => 15,
|
||||||
),
|
),
|
||||||
@@ -87,24 +90,118 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
'initial' => '',
|
'initial' => '',
|
||||||
'widget' => 'Pluf_Form_Widget_PasswordInput',
|
'widget' => 'Pluf_Form_Widget_PasswordInput',
|
||||||
'widget_attrs' => array(
|
'widget_attrs' => array(
|
||||||
|
'autocomplete' => 'off',
|
||||||
'maxlength' => 50,
|
'maxlength' => 50,
|
||||||
'size' => 15,
|
'size' => 15,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->fields['ssh_key'] = new Pluf_Form_Field_Varchar(
|
$this->fields['description'] = new Pluf_Form_Field_Varchar(
|
||||||
array('required' => false,
|
array('required' => false,
|
||||||
'label' => __('Your public SSH key'),
|
'label' => __('Description'),
|
||||||
|
'initial' => $user_data->description,
|
||||||
|
'widget_attrs' => array('rows' => 3,
|
||||||
|
'cols' => 40),
|
||||||
|
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['twitter'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Twitter username'),
|
||||||
|
'initial' => $user_data->twitter,
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 50,
|
||||||
|
'size' => 15,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['public_email'] = new Pluf_Form_Field_Email(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Public email address'),
|
||||||
|
'initial' => $user_data->public_email,
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 50,
|
||||||
|
'size' => 15,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['website'] = new Pluf_Form_Field_Url(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Website URL'),
|
||||||
|
'initial' => $user_data->website,
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 50,
|
||||||
|
'size' => 15,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['custom_avatar'] = new Pluf_Form_Field_File(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Upload custom avatar'),
|
||||||
|
'initial' => '',
|
||||||
|
'max_size' => Pluf::f('max_upload_size', 2097152),
|
||||||
|
'move_function_params' => array('upload_path' => Pluf::f('upload_path').'/avatars',
|
||||||
|
'upload_path_create' => true,
|
||||||
|
'upload_overwrite' => true,
|
||||||
|
'file_name' => 'user_'.$this->user->id.'_%s'),
|
||||||
|
'help_text' => __('An image file with a width and height not larger than 60 pixels (bigger images are scaled down).'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['remove_custom_avatar'] = new Pluf_Form_Field_Boolean(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Remove custom avatar'),
|
||||||
|
'initial' => false,
|
||||||
|
'widget' => 'Pluf_Form_Widget_CheckboxInput',
|
||||||
|
'widget_attrs' => array(),
|
||||||
|
'help_text' => __('Tick this to delete the custom avatar.'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['public_key'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Add a public key'),
|
||||||
'initial' => '',
|
'initial' => '',
|
||||||
'widget_attrs' => array('rows' => 3,
|
'widget_attrs' => array('rows' => 3,
|
||||||
'cols' => 40),
|
'cols' => 40),
|
||||||
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
||||||
'help_text' => __('Be careful to provide your public key and not your private key!')
|
'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 mail address'),
|
||||||
|
'initial' => '',
|
||||||
|
'help_text' => __('You will get a mail 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)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save the model in the database.
|
* Save the model in the database.
|
||||||
@@ -129,44 +226,52 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
$new_email = $this->cleaned_data['email'];
|
$new_email = $this->cleaned_data['email'];
|
||||||
unset($this->cleaned_data['email']);
|
unset($this->cleaned_data['email']);
|
||||||
if ($old_email != $new_email) {
|
if ($old_email != $new_email) {
|
||||||
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
|
$this->send_validation_mail($new_email);
|
||||||
$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->user->setFromFormData($this->cleaned_data);
|
$this->user->setFromFormData($this->cleaned_data);
|
||||||
// Get keys
|
// Add key as needed.
|
||||||
$keys = $this->user->get_idf_key_list();
|
if ('' !== $this->cleaned_data['public_key']) {
|
||||||
if ($keys->count() > 0) {
|
|
||||||
$key = $keys[0];
|
|
||||||
} else {
|
|
||||||
$key = new IDF_Key();
|
$key = new IDF_Key();
|
||||||
$key->user = $this->user;
|
$key->user = $this->user;
|
||||||
}
|
$key->content = $this->cleaned_data['public_key'];
|
||||||
$key->content = $this->cleaned_data['ssh_key'];
|
if ($commit) {
|
||||||
if ($commit) {
|
|
||||||
$this->user->update();
|
|
||||||
if ($key->id != '') {
|
|
||||||
$key->update();
|
|
||||||
} else {
|
|
||||||
$key->create();
|
$key->create();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if ('' !== $this->cleaned_data['secondary_mail']) {
|
||||||
|
$this->send_validation_mail($this->cleaned_data['secondary_mail'], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($commit) {
|
||||||
|
$this->user->update();
|
||||||
|
|
||||||
|
// FIXME: go the extra mile and check the input lengths for
|
||||||
|
// all fields here!
|
||||||
|
// FIXME: this is all doubled in admin/UserUpdate!
|
||||||
|
|
||||||
|
$user_data = IDF_UserData::factory($this->user);
|
||||||
|
|
||||||
|
// Add or remove avatar - we need to do this here because every
|
||||||
|
// single setter directly leads to a save in the database
|
||||||
|
if ($user_data->avatar != '' &&
|
||||||
|
($this->cleaned_data['remove_custom_avatar'] == 1 ||
|
||||||
|
$this->cleaned_data['custom_avatar'] != '')) {
|
||||||
|
$avatar_path = Pluf::f('upload_path').'/avatars/'.basename($user_data->avatar);
|
||||||
|
if (basename($avatar_path) != '' && is_file($avatar_path)) {
|
||||||
|
unlink($avatar_path);
|
||||||
|
}
|
||||||
|
$user_data->avatar = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->cleaned_data['custom_avatar'] != '') {
|
||||||
|
$user_data->avatar = $this->cleaned_data['custom_avatar'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_data->description = $this->cleaned_data['description'];
|
||||||
|
$user_data->twitter = $this->cleaned_data['twitter'];
|
||||||
|
$user_data->public_email = $this->cleaned_data['public_email'];
|
||||||
|
$user_data->website = $this->cleaned_data['website'];
|
||||||
|
|
||||||
if ($update_pass) {
|
if ($update_pass) {
|
||||||
/**
|
/**
|
||||||
* [signal]
|
* [signal]
|
||||||
@@ -195,11 +300,112 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
return $this->user;
|
return $this->user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check arbitrary public keys.
|
||||||
|
*
|
||||||
|
* It will throw a Pluf_Form_Invalid exception if it cannot
|
||||||
|
* validate the key.
|
||||||
|
*
|
||||||
|
* @param $key string The key
|
||||||
|
* @param $user int The user id of the user of the key (0)
|
||||||
|
* @return string The clean key
|
||||||
|
*/
|
||||||
|
public static function checkPublicKey($key, $user=0)
|
||||||
|
{
|
||||||
|
$key = trim($key);
|
||||||
|
if (strlen($key) == 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$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)) {
|
||||||
|
|
||||||
|
$tmpfile = Pluf::f('tmp_folder', '/tmp').'/'.$user.'-key';
|
||||||
|
file_put_contents($tmpfile, $key, LOCK_EX);
|
||||||
|
$cmd = Pluf::f('idf_exec_cmd_prefix', '').
|
||||||
|
'ssh-keygen -l -f '.escapeshellarg($tmpfile).' > /dev/null 2>&1';
|
||||||
|
exec($cmd, $out, $return);
|
||||||
|
unlink($tmpfile);
|
||||||
|
|
||||||
|
if ($return != 0) {
|
||||||
|
throw new Pluf_Form_Invalid(
|
||||||
|
__('Please check the key as it does not appear '.
|
||||||
|
'to be a valid SSH public 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
|
||||||
|
$mtn_opts = implode(' ', Pluf::f('mtn_opts', array()));
|
||||||
|
$cmd = Pluf::f('idf_exec_cmd_prefix', '').
|
||||||
|
sprintf('%s %s -d :memory: read >/tmp/php-out 2>&1',
|
||||||
|
Pluf::f('mtn_path', 'mtn'), $mtn_opts);
|
||||||
|
$fp = popen($cmd, 'w');
|
||||||
|
fwrite($fp, $key);
|
||||||
|
$return = pclose($fp);
|
||||||
|
|
||||||
|
if ($return != 0) {
|
||||||
|
throw new Pluf_Form_Invalid(
|
||||||
|
__('Please check the key as it does not appear '.
|
||||||
|
'to be a valid monotone public key.')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Pluf_Form_Invalid(
|
||||||
|
__('Public key looks like neither an SSH '.
|
||||||
|
'nor monotone public key.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If $user, then check if not the same key stored
|
||||||
|
if ($user) {
|
||||||
|
$ruser = Pluf::factory('Pluf_User', $user);
|
||||||
|
if ($ruser->id > 0) {
|
||||||
|
$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(
|
||||||
|
__('You already have uploaded this key.')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function clean_custom_avatar()
|
||||||
|
{
|
||||||
|
// Just png, jpeg/jpg or gif
|
||||||
|
if (!preg_match('/\.(png|jpg|jpeg|gif)$/i', $this->cleaned_data['custom_avatar']) &&
|
||||||
|
$this->cleaned_data['custom_avatar'] != '') {
|
||||||
|
@unlink(Pluf::f('upload_path').'/avatars/'.$this->cleaned_data['custom_avatar']);
|
||||||
|
throw new Pluf_Form_Invalid(__('For security reason, you cannot upload a file with this extension.'));
|
||||||
|
}
|
||||||
|
return $this->cleaned_data['custom_avatar'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function clean_last_name()
|
function clean_last_name()
|
||||||
{
|
{
|
||||||
$last_name = trim($this->cleaned_data['last_name']);
|
$last_name = trim($this->cleaned_data['last_name']);
|
||||||
if ($last_name == mb_strtoupper($last_name)) {
|
if ($last_name == mb_strtoupper($last_name)) {
|
||||||
return mb_convert_case(mb_strtolower($last_name),
|
return mb_convert_case(mb_strtolower($last_name),
|
||||||
MB_CASE_TITLE, 'UTF-8');
|
MB_CASE_TITLE, 'UTF-8');
|
||||||
}
|
}
|
||||||
return $last_name;
|
return $last_name;
|
||||||
@@ -209,7 +415,7 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
{
|
{
|
||||||
$first_name = trim($this->cleaned_data['first_name']);
|
$first_name = trim($this->cleaned_data['first_name']);
|
||||||
if ($first_name == mb_strtoupper($first_name)) {
|
if ($first_name == mb_strtoupper($first_name)) {
|
||||||
return mb_convert_case(mb_strtolower($first_name),
|
return mb_convert_case(mb_strtolower($first_name),
|
||||||
MB_CASE_TITLE, 'UTF-8');
|
MB_CASE_TITLE, 'UTF-8');
|
||||||
}
|
}
|
||||||
return $first_name;
|
return $first_name;
|
||||||
@@ -218,21 +424,36 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
function clean_email()
|
function clean_email()
|
||||||
{
|
{
|
||||||
$this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email']));
|
$this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email']));
|
||||||
$guser = new Pluf_User();
|
$user = Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($this->cleaned_data['email']);
|
||||||
$sql = new Pluf_SQL('email=%s AND id!=%s',
|
if ($user != null and $user->id != $this->user->id) {
|
||||||
array($this->cleaned_data['email'], $this->user->id));
|
|
||||||
if ($guser->getCount(array('filter' => $sql->gen())) > 0) {
|
|
||||||
throw new Pluf_Form_Invalid(sprintf(__('The email "%s" is already used.'), $this->cleaned_data['email']));
|
throw new Pluf_Form_Invalid(sprintf(__('The email "%s" is already used.'), $this->cleaned_data['email']));
|
||||||
}
|
}
|
||||||
return $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'] =
|
||||||
|
self::checkPublicKey($this->cleaned_data['public_key'],
|
||||||
|
$this->user->id);
|
||||||
|
return $this->cleaned_data['public_key'];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if the 2 passwords are the same.
|
* Check to see if the 2 passwords are the same
|
||||||
*/
|
*/
|
||||||
public function clean()
|
public function clean()
|
||||||
{
|
{
|
||||||
if (!isset($this->errors['password'])
|
if (!isset($this->errors['password'])
|
||||||
&& !isset($this->errors['password2'])) {
|
&& !isset($this->errors['password2'])) {
|
||||||
$password1 = $this->cleaned_data['password'];
|
$password1 = $this->cleaned_data['password'];
|
||||||
$password2 = $this->cleaned_data['password2'];
|
$password2 = $this->cleaned_data['password2'];
|
||||||
@@ -240,6 +461,9 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
throw new Pluf_Form_Invalid(__('The passwords do not match. Please give them again.'));
|
throw new Pluf_Form_Invalid(__('The passwords do not match. Please give them again.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->cleaned_data;
|
return $this->cleaned_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# 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.
|
* Throw a Pluf_Form_Invalid exception if the key is not valid.
|
||||||
*
|
*
|
||||||
* @param string Key
|
* @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)
|
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.'));
|
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')));
|
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
|
||||||
return split(':', $cr->decrypt($encrypted), 3);
|
return explode(':', $cr->decrypt($encrypted), 4);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -127,7 +127,7 @@ Add your content here. Format your content with:
|
|||||||
$conf = new IDF_Conf();
|
$conf = new IDF_Conf();
|
||||||
$conf->setProject($this->project);
|
$conf->setProject($this->project);
|
||||||
$onemax = array();
|
$onemax = array();
|
||||||
foreach (split(',', $conf->getVal('labels_wiki_one_max', IDF_Form_WikiConf::init_one_max)) as $class) {
|
foreach (explode(',', $conf->getVal('labels_wiki_one_max', IDF_Form_WikiConf::init_one_max)) as $class) {
|
||||||
if (trim($class) != '') {
|
if (trim($class) != '') {
|
||||||
$onemax[] = mb_strtolower(trim($class));
|
$onemax[] = mb_strtolower(trim($class));
|
||||||
}
|
}
|
||||||
@@ -199,25 +199,7 @@ Add your content here. Format your content with:
|
|||||||
$rev->submitter = $this->user;
|
$rev->submitter = $this->user;
|
||||||
$rev->summary = __('Initial page creation');
|
$rev->summary = __('Initial page creation');
|
||||||
$rev->create();
|
$rev->create();
|
||||||
// send the notification
|
$rev->notify($this->project->getConf());
|
||||||
if ('' != $this->project->getConf()->getVal('wiki_notification_email', '')) {
|
|
||||||
$context = new Pluf_Template_Context(
|
|
||||||
array(
|
|
||||||
'page' => $page,
|
|
||||||
'rev' => $rev,
|
|
||||||
'project' => $this->project,
|
|
||||||
'url_base' => Pluf::f('url_base'),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$tmpl = new Pluf_Template('idf/wiki/wiki-created-email.txt');
|
|
||||||
$text_email = $tmpl->render($context);
|
|
||||||
$email = new Pluf_Mail(Pluf::f('from_email'),
|
|
||||||
$this->project->getConf()->getVal('wiki_notification_email'),
|
|
||||||
sprintf(__('New Documentation Page %s - %s (%s)'),
|
|
||||||
$page->title, $page->summary, $this->project->shortname));
|
|
||||||
$email->addTextMessage($text_email);
|
|
||||||
$email->sendMail();
|
|
||||||
}
|
|
||||||
return $page;
|
return $page;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
64
src/IDF/Form/WikiDelete.php
Normal file
64
src/IDF/Form/WikiDelete.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_WikiDelete extends Pluf_Form
|
||||||
|
{
|
||||||
|
protected $page = null;
|
||||||
|
|
||||||
|
public function initFields($extra=array())
|
||||||
|
{
|
||||||
|
$this->page = $extra['page'];
|
||||||
|
$this->fields['confirm'] = new Pluf_Form_Field_Boolean(
|
||||||
|
array('required' => true,
|
||||||
|
'label' => __('Yes, I understand that the page 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->page->delete();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -138,7 +138,7 @@ class IDF_Form_WikiUpdate extends Pluf_Form
|
|||||||
$conf = new IDF_Conf();
|
$conf = new IDF_Conf();
|
||||||
$conf->setProject($this->project);
|
$conf->setProject($this->project);
|
||||||
$onemax = array();
|
$onemax = array();
|
||||||
foreach (split(',', $conf->getVal('labels_wiki_one_max', IDF_Form_WikiConf::init_one_max)) as $class) {
|
foreach (explode(',', $conf->getVal('labels_wiki_one_max', IDF_Form_WikiConf::init_one_max)) as $class) {
|
||||||
if (trim($class) != '') {
|
if (trim($class) != '') {
|
||||||
$onemax[] = mb_strtolower(trim($class));
|
$onemax[] = mb_strtolower(trim($class));
|
||||||
}
|
}
|
||||||
@@ -236,25 +236,7 @@ class IDF_Form_WikiUpdate extends Pluf_Form
|
|||||||
$rev->summary = $this->cleaned_data['comment'];
|
$rev->summary = $this->cleaned_data['comment'];
|
||||||
$rev->changes = $changes;
|
$rev->changes = $changes;
|
||||||
$rev->create();
|
$rev->create();
|
||||||
// send the notification
|
$rev->notify($this->project->getConf(), false);
|
||||||
if ('' != $this->project->getConf()->getVal('wiki_notification_email', '')) {
|
|
||||||
$context = new Pluf_Template_Context(
|
|
||||||
array(
|
|
||||||
'page' => $this->page,
|
|
||||||
'rev' => $rev,
|
|
||||||
'project' => $this->project,
|
|
||||||
'url_base' => Pluf::f('url_base'),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$tmpl = new Pluf_Template('idf/wiki/wiki-updated-email.txt');
|
|
||||||
$text_email = $tmpl->render($context);
|
|
||||||
$email = new Pluf_Mail(Pluf::f('from_email'),
|
|
||||||
$this->project->getConf()->getVal('wiki_notification_email'),
|
|
||||||
sprintf(__('Documentation Page Changed %s - %s (%s)'),
|
|
||||||
$this->page->title, $this->page->summary, $this->project->shortname));
|
|
||||||
$email->addTextMessage($text_email);
|
|
||||||
$email->sendMail();
|
|
||||||
}
|
|
||||||
return $this->page;
|
return $this->page;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
210
src/IDF/Gconf.php
Normal file
210
src/IDF/Gconf.php
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
<?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 objects.
|
||||||
|
*
|
||||||
|
* It is just storing a list of key/value pairs associated to
|
||||||
|
* different objects. If you use this table for your model, do not
|
||||||
|
* forget to drop the corresponding keys in your preDelete call.
|
||||||
|
*/
|
||||||
|
class IDF_Gconf extends Pluf_Model
|
||||||
|
{
|
||||||
|
public $_model = __CLASS__;
|
||||||
|
public $datacache = null;
|
||||||
|
public $dirty = array();
|
||||||
|
public $f = null;
|
||||||
|
protected $_mod = null;
|
||||||
|
/**
|
||||||
|
* Do we (un)serialize the data when getting/setting them.
|
||||||
|
*/
|
||||||
|
public $serialize = false;
|
||||||
|
|
||||||
|
function init()
|
||||||
|
{
|
||||||
|
$this->_a['table'] = 'idf_gconf';
|
||||||
|
$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,
|
||||||
|
),
|
||||||
|
'model_class' =>
|
||||||
|
array(
|
||||||
|
'type' => 'Pluf_DB_Field_Varchar',
|
||||||
|
'blank' => false,
|
||||||
|
'size' => 150,
|
||||||
|
'verbose' => __('model class'),
|
||||||
|
),
|
||||||
|
'model_id' =>
|
||||||
|
array(
|
||||||
|
'type' => 'Pluf_DB_Field_Integer',
|
||||||
|
'blank' => false,
|
||||||
|
'verbose' => __('model id'),
|
||||||
|
),
|
||||||
|
'vkey' =>
|
||||||
|
array(
|
||||||
|
'type' => 'Pluf_DB_Field_Varchar',
|
||||||
|
'blank' => false,
|
||||||
|
'size' => 50,
|
||||||
|
'verbose' => __('key'),
|
||||||
|
),
|
||||||
|
'vdesc' =>
|
||||||
|
array(
|
||||||
|
'type' => 'Pluf_DB_Field_Text',
|
||||||
|
'blank' => false,
|
||||||
|
'verbose' => __('value'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->_a['idx'] = array('model_vkey_idx' =>
|
||||||
|
array(
|
||||||
|
'col' => 'model_class, model_id, vkey',
|
||||||
|
'type' => 'unique',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->f = new IDF_Config_DataProxy($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setModel($model)
|
||||||
|
{
|
||||||
|
$this->datacache = null;
|
||||||
|
$this->_mod = $model;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initCache()
|
||||||
|
{
|
||||||
|
$this->datacache = array();
|
||||||
|
$this->dirty = array();
|
||||||
|
$sql = new Pluf_SQL('model_class=%s AND model_id=%s',
|
||||||
|
array($this->_mod->_model, $this->_mod->id));
|
||||||
|
foreach ($this->getList(array('filter' => $sql->gen())) as $val) {
|
||||||
|
$this->datacache[$val->vkey] = ($this->serialize) ? unserialize($val->vdesc) : $val->vdesc;
|
||||||
|
$this->dirty[$val->vkey] = $val->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FIXME: This is not efficient when setting a large number of
|
||||||
|
* values in a loop.
|
||||||
|
*/
|
||||||
|
function setVal($key, $value)
|
||||||
|
{
|
||||||
|
if (!is_null($this->getVal($key, null))
|
||||||
|
and $value == $this->getVal($key)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$svalue = ($this->serialize) ? serialize($value) : $value;
|
||||||
|
if (isset($this->dirty[$key])) {
|
||||||
|
// we get to check if deleted by other process + update
|
||||||
|
$conf = new IDF_Gconf($this->dirty[$key]);
|
||||||
|
if ($conf->id == $this->dirty[$key]) {
|
||||||
|
$conf->vdesc = $svalue;
|
||||||
|
$conf->update();
|
||||||
|
$this->datacache[$key] = $value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// we insert
|
||||||
|
$conf = new IDF_Gconf();
|
||||||
|
$conf->model_class = $this->_mod->_model;
|
||||||
|
$conf->model_id = $this->_mod->id;
|
||||||
|
$conf->vkey = $key;
|
||||||
|
$conf->vdesc = $svalue;
|
||||||
|
$conf->create();
|
||||||
|
$this->datacache[$key] = $value;
|
||||||
|
$this->dirty[$key] = $conf->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVal($key, $default='')
|
||||||
|
{
|
||||||
|
if ($this->datacache === null) {
|
||||||
|
$this->initCache();
|
||||||
|
}
|
||||||
|
return (isset($this->datacache[$key])) ? $this->datacache[$key] : $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
function delVal($key, $initcache=true)
|
||||||
|
{
|
||||||
|
$gconf = new IDF_Gconf();
|
||||||
|
$sql = new Pluf_SQL('vkey=%s AND model_class=%s AND model_id=%s', array($key, $this->_mod->_model, $this->_mod->id));
|
||||||
|
foreach ($gconf->getList(array('filter' => $sql->gen())) as $c) {
|
||||||
|
$c->delete();
|
||||||
|
}
|
||||||
|
if ($initcache) {
|
||||||
|
$this->initCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection selection.
|
||||||
|
*
|
||||||
|
* Suppose you have 5 objects with associated meta data in the
|
||||||
|
* Gconf storage, if you load the data independently for each
|
||||||
|
* object, you end up with 5 SELECT queries. With 25 objects, 25
|
||||||
|
* SELECT. You can select with one query all the data and merge in
|
||||||
|
* the code. It is faster. The collection selection get a
|
||||||
|
* model_class and a list of ids and returns an id indexed array
|
||||||
|
* of associative array data. This is for read only access as you
|
||||||
|
* do not get a series of Gconf objects.
|
||||||
|
*/
|
||||||
|
public static function collect($class, $ids)
|
||||||
|
{
|
||||||
|
$gconf = new IDF_Gconf();
|
||||||
|
$stmpl = sprintf('model_class=%%s AND model_id IN (%s)',
|
||||||
|
implode(',' , $ids));
|
||||||
|
$sql = new Pluf_SQL($stmpl, array($class));
|
||||||
|
$out = array_fill_keys($ids, array());
|
||||||
|
foreach ($gconf->getList(array('filter' => $sql->gen())) as $c) {
|
||||||
|
$out[$c->model_id][$c->vkey] = $c->vdesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop the conf of a model.
|
||||||
|
*
|
||||||
|
* If your model is using this table, just add the following line
|
||||||
|
* in your preDelete() method:
|
||||||
|
*
|
||||||
|
* IDF_Gconf::dropForModel($this)
|
||||||
|
*
|
||||||
|
* It will take care of the cleaning.
|
||||||
|
*/
|
||||||
|
static public function dropForModel($model)
|
||||||
|
{
|
||||||
|
$table = Pluf::factory(__CLASS__)->getSqlTable();
|
||||||
|
$sql = new Pluf_SQL('model_class=%s AND model_id=%s',
|
||||||
|
array($model->_model, $model->id));
|
||||||
|
$db = &Pluf::db();
|
||||||
|
$db->execute('DELETE FROM '.$table.' WHERE '.$sql->gen());
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function dropUser($signal, &$params)
|
||||||
|
{
|
||||||
|
self::dropForModel($params['user']);
|
||||||
|
}
|
||||||
|
}
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -42,9 +42,9 @@ class IDF_Issue extends Pluf_Model
|
|||||||
'id' =>
|
'id' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Sequence',
|
'type' => 'Pluf_DB_Field_Sequence',
|
||||||
'blank' => true,
|
'blank' => true,
|
||||||
),
|
),
|
||||||
'project' =>
|
'project' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||||
'model' => 'IDF_Project',
|
'model' => 'IDF_Project',
|
||||||
@@ -59,7 +59,7 @@ class IDF_Issue extends Pluf_Model
|
|||||||
'size' => 250,
|
'size' => 250,
|
||||||
'verbose' => __('summary'),
|
'verbose' => __('summary'),
|
||||||
),
|
),
|
||||||
'submitter' =>
|
'submitter' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||||
'model' => 'Pluf_User',
|
'model' => 'Pluf_User',
|
||||||
@@ -67,7 +67,7 @@ class IDF_Issue extends Pluf_Model
|
|||||||
'verbose' => __('submitter'),
|
'verbose' => __('submitter'),
|
||||||
'relate_name' => 'submitted_issue',
|
'relate_name' => 'submitted_issue',
|
||||||
),
|
),
|
||||||
'owner' =>
|
'owner' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||||
'model' => 'Pluf_User',
|
'model' => 'Pluf_User',
|
||||||
@@ -76,7 +76,7 @@ class IDF_Issue extends Pluf_Model
|
|||||||
'verbose' => __('owner'),
|
'verbose' => __('owner'),
|
||||||
'relate_name' => 'owned_issue',
|
'relate_name' => 'owned_issue',
|
||||||
),
|
),
|
||||||
'interested' =>
|
'interested' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Manytomany',
|
'type' => 'Pluf_DB_Field_Manytomany',
|
||||||
'model' => 'Pluf_User',
|
'model' => 'Pluf_User',
|
||||||
@@ -86,14 +86,14 @@ class IDF_Issue extends Pluf_Model
|
|||||||
),
|
),
|
||||||
'tags' =>
|
'tags' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Manytomany',
|
'type' => 'Pluf_DB_Field_Manytomany',
|
||||||
'blank' => true,
|
'blank' => true,
|
||||||
'model' => 'IDF_Tag',
|
'model' => 'IDF_Tag',
|
||||||
'verbose' => __('labels'),
|
'verbose' => __('labels'),
|
||||||
),
|
),
|
||||||
'status' =>
|
'status' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||||
'blank' => false,
|
'blank' => false,
|
||||||
'model' => 'IDF_Tag',
|
'model' => 'IDF_Tag',
|
||||||
'verbose' => __('status'),
|
'verbose' => __('status'),
|
||||||
@@ -111,7 +111,7 @@ class IDF_Issue extends Pluf_Model
|
|||||||
'verbose' => __('modification date'),
|
'verbose' => __('modification date'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
$this->_a['idx'] = array(
|
$this->_a['idx'] = array(
|
||||||
'modif_dtime_idx' =>
|
'modif_dtime_idx' =>
|
||||||
array(
|
array(
|
||||||
'col' => 'modif_dtime',
|
'col' => 'modif_dtime',
|
||||||
@@ -120,7 +120,7 @@ class IDF_Issue extends Pluf_Model
|
|||||||
);
|
);
|
||||||
$table = $this->_con->pfx.'idf_issue_idf_tag_assoc';
|
$table = $this->_con->pfx.'idf_issue_idf_tag_assoc';
|
||||||
$this->_a['views'] = array(
|
$this->_a['views'] = array(
|
||||||
'join_tags' =>
|
'join_tags' =>
|
||||||
array(
|
array(
|
||||||
'join' => 'LEFT JOIN '.$table
|
'join' => 'LEFT JOIN '.$table
|
||||||
.' ON idf_issue_id=id',
|
.' ON idf_issue_id=id',
|
||||||
@@ -164,7 +164,7 @@ class IDF_Issue extends Pluf_Model
|
|||||||
// that the issue as at least one comment in the database when
|
// that the issue as at least one comment in the database when
|
||||||
// doing the indexing.
|
// doing the indexing.
|
||||||
if ($create) {
|
if ($create) {
|
||||||
IDF_Timeline::insert($this, $this->get_project(),
|
IDF_Timeline::insert($this, $this->get_project(),
|
||||||
$this->get_submitter());
|
$this->get_submitter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,12 +177,12 @@ class IDF_Issue extends Pluf_Model
|
|||||||
* as such create links to other items etc. You can consider that
|
* as such create links to other items etc. You can consider that
|
||||||
* if displayed, you can create a link to it.
|
* if displayed, you can create a link to it.
|
||||||
*
|
*
|
||||||
* @param Pluf_HTTP_Request
|
* @param Pluf_HTTP_Request
|
||||||
* @return Pluf_Template_SafeString
|
* @return Pluf_Template_SafeString
|
||||||
*/
|
*/
|
||||||
public function timelineFragment($request)
|
public function timelineFragment($request)
|
||||||
{
|
{
|
||||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
|
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
|
||||||
array($request->project->shortname,
|
array($request->project->shortname,
|
||||||
$this->id));
|
$this->id));
|
||||||
$out = '<tr class="log"><td><a href="'.$url.'">'.
|
$out = '<tr class="log"><td><a href="'.$url.'">'.
|
||||||
@@ -193,38 +193,136 @@ class IDF_Issue extends Pluf_Model
|
|||||||
$ic = (in_array($this->status, $request->project->getTagIdsByStatus('closed'))) ? 'issue-c' : 'issue-o';
|
$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 .= 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">
|
$out .= "\n".'<tr class="extra"><td colspan="2">
|
||||||
<div class="helptext right">'.sprintf(__('Creation of <a href="%s" class="%s">issue %d</a>'), $url, $ic, $this->id).', '.__('by').' '.$user.'</div></td></tr>';
|
<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>';
|
||||||
return Pluf_Template::markSafe($out);
|
return Pluf_Template::markSafe($out);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function feedFragment($request)
|
public function feedFragment($request)
|
||||||
{
|
{
|
||||||
$base = '<entry>
|
|
||||||
<title>%%title%%</title>
|
|
||||||
<link href="%%url%%"/>
|
|
||||||
<id>%%url%%</id>
|
|
||||||
<updated>%%date%%</updated>
|
|
||||||
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<pre>%%content%%</pre>
|
|
||||||
</div></content>
|
|
||||||
</entry>';
|
|
||||||
$url = Pluf::f('url_base')
|
$url = Pluf::f('url_base')
|
||||||
.Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
|
.Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
|
||||||
array($request->project->shortname,
|
array($request->project->shortname,
|
||||||
$this->id));
|
$this->id));
|
||||||
$title = sprintf(__('%s: Issue %d created - %s'),
|
$title = sprintf(__('%s: Issue %d created - %s'),
|
||||||
Pluf_esc($request->project->name),
|
$request->project->name,
|
||||||
$this->id, Pluf_esc($this->summary));
|
$this->id, $this->summary);
|
||||||
// Get the first comment of this issue.
|
|
||||||
$cts = $this->get_comments_list(array('order' => 'id ASC',
|
$cts = $this->get_comments_list(array('order' => 'id ASC',
|
||||||
'nb' => 1));
|
'nb' => 1));
|
||||||
$tag = new IDF_Template_IssueComment();
|
|
||||||
$content = $tag->start($cts[0]->content, $request, false);
|
|
||||||
$date = Pluf_Date::gmDateToGmString($this->creation_dtime);
|
$date = Pluf_Date::gmDateToGmString($this->creation_dtime);
|
||||||
return Pluf_Translation::sprintf($base,
|
$context = new Pluf_Template_Context_Request(
|
||||||
array('url' => $url,
|
$request,
|
||||||
'title' => $title,
|
array('url' => $url,
|
||||||
'content' => $content,
|
'author' => $this->get_submitter(),
|
||||||
'date' => $date));
|
'title' => $title,
|
||||||
|
'c' => $cts[0],
|
||||||
|
'issue' => $this,
|
||||||
|
'date' => $date)
|
||||||
|
);
|
||||||
|
$tmpl = new Pluf_Template('idf/issues/feedfragment.xml');
|
||||||
|
return $tmpl->render($context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification of change of the object.
|
||||||
|
*
|
||||||
|
* For the moment, only email, but one can add webhooks later.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* <pre>
|
||||||
|
* $this->notify($conf); // Notify the creation
|
||||||
|
* $this->notify($conf, false); // Notify the update of the object
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param IDF_Conf Current configuration
|
||||||
|
* @param bool Creation (true)
|
||||||
|
*/
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Pluf_Translation::loadSetLocale($current_locale);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -41,9 +41,9 @@ class IDF_IssueComment extends Pluf_Model
|
|||||||
'id' =>
|
'id' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Sequence',
|
'type' => 'Pluf_DB_Field_Sequence',
|
||||||
'blank' => true,
|
'blank' => true,
|
||||||
),
|
),
|
||||||
'issue' =>
|
'issue' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||||
'model' => 'IDF_Issue',
|
'model' => 'IDF_Issue',
|
||||||
@@ -57,7 +57,7 @@ class IDF_IssueComment extends Pluf_Model
|
|||||||
'blank' => false,
|
'blank' => false,
|
||||||
'verbose' => __('comment'),
|
'verbose' => __('comment'),
|
||||||
),
|
),
|
||||||
'submitter' =>
|
'submitter' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||||
'model' => 'Pluf_User',
|
'model' => 'Pluf_User',
|
||||||
@@ -79,7 +79,7 @@ class IDF_IssueComment extends Pluf_Model
|
|||||||
'verbose' => __('creation date'),
|
'verbose' => __('creation date'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
$this->_a['idx'] = array(
|
$this->_a['idx'] = array(
|
||||||
'creation_dtime_idx' =>
|
'creation_dtime_idx' =>
|
||||||
array(
|
array(
|
||||||
'col' => 'creation_dtime',
|
'col' => 'creation_dtime',
|
||||||
@@ -119,7 +119,7 @@ class IDF_IssueComment extends Pluf_Model
|
|||||||
$sql = new Pluf_SQL('issue=%s', array($this->issue));
|
$sql = new Pluf_SQL('issue=%s', array($this->issue));
|
||||||
$co = Pluf::factory('IDF_IssueComment')->getList(array('filter'=>$sql->gen()));
|
$co = Pluf::factory('IDF_IssueComment')->getList(array('filter'=>$sql->gen()));
|
||||||
if ($co->count() > 1) {
|
if ($co->count() > 1) {
|
||||||
IDF_Timeline::insert($this, $this->get_issue()->get_project(),
|
IDF_Timeline::insert($this, $this->get_issue()->get_project(),
|
||||||
$this->get_submitter());
|
$this->get_submitter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,7 +129,7 @@ class IDF_IssueComment extends Pluf_Model
|
|||||||
public function timelineFragment($request)
|
public function timelineFragment($request)
|
||||||
{
|
{
|
||||||
$issue = $this->get_issue();
|
$issue = $this->get_issue();
|
||||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
|
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
|
||||||
array($request->project->shortname,
|
array($request->project->shortname,
|
||||||
$issue->id));
|
$issue->id));
|
||||||
$url .= '#ic'.$this->id;
|
$url .= '#ic'.$this->id;
|
||||||
@@ -167,66 +167,38 @@ class IDF_IssueComment extends Pluf_Model
|
|||||||
$out .= '</div>';
|
$out .= '</div>';
|
||||||
}
|
}
|
||||||
$out .= '</td></tr>';
|
$out .= '</td></tr>';
|
||||||
|
|
||||||
|
|
||||||
$out .= "\n".'<tr class="extra"><td colspan="2">
|
$out .= "\n".'<tr class="extra"><td colspan="2">
|
||||||
<div class="helptext right">'.sprintf(__('Comment on <a href="%s" class="%s">issue %d</a>'), $url, $ic, $issue->id).', '.__('by').' '.$user.'</div></td></tr>';
|
<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>';
|
||||||
|
|
||||||
return Pluf_Template::markSafe($out);
|
return Pluf_Template::markSafe($out);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function feedFragment($request)
|
public function feedFragment($request)
|
||||||
{
|
{
|
||||||
$base = '<entry>
|
|
||||||
<title>%%title%%</title>
|
|
||||||
<link href="%%url%%"/>
|
|
||||||
<id>%%url%%</id>
|
|
||||||
<updated>%%date%%</updated>
|
|
||||||
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
%%content%%
|
|
||||||
</div></content>
|
|
||||||
</entry>';
|
|
||||||
$issue = $this->get_issue();
|
$issue = $this->get_issue();
|
||||||
$url = Pluf::f('url_base')
|
$url = Pluf::f('url_base')
|
||||||
.Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
|
.Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
|
||||||
array($request->project->shortname,
|
array($request->project->shortname,
|
||||||
$issue->id));
|
$issue->id));
|
||||||
$url .= '#ic'.$this->id;
|
|
||||||
$title = sprintf(__('%s: Comment on issue %d - %s'),
|
$title = sprintf(__('%s: Comment on issue %d - %s'),
|
||||||
Pluf_esc($request->project->name),
|
Pluf_esc($request->project->name),
|
||||||
$issue->id, Pluf_esc($issue->summary));
|
$issue->id, Pluf_esc($issue->summary));
|
||||||
$submitter = $this->get_submitter();
|
$url .= '#ic'.$this->id;
|
||||||
$tag = new IDF_Template_IssueComment();
|
|
||||||
$content = '<p><pre>'.$tag->start($this->content, $request, false).'</pre></p>';
|
|
||||||
if ($this->changedIssue()) {
|
|
||||||
$content .= '<p>';
|
|
||||||
foreach ($this->changes as $w => $v) {
|
|
||||||
$content .= '<strong>';
|
|
||||||
switch ($w) {
|
|
||||||
case 'su':
|
|
||||||
$content .= __('Summary:'); break;
|
|
||||||
case 'st':
|
|
||||||
$content .= __('Status:'); break;
|
|
||||||
case 'ow':
|
|
||||||
$content .= __('Owner:'); break;
|
|
||||||
case 'lb':
|
|
||||||
$content .= __('Labels:'); break;
|
|
||||||
}
|
|
||||||
$content .= '</strong> ';
|
|
||||||
if ($w == 'lb') {
|
|
||||||
$content .= Pluf_esc(implode(', ', $v));
|
|
||||||
} else {
|
|
||||||
$content .= Pluf_esc($v);
|
|
||||||
}
|
|
||||||
$content .= ' ';
|
|
||||||
}
|
|
||||||
$content .= '</p>';
|
|
||||||
}
|
|
||||||
$date = Pluf_Date::gmDateToGmString($this->creation_dtime);
|
$date = Pluf_Date::gmDateToGmString($this->creation_dtime);
|
||||||
return Pluf_Translation::sprintf($base,
|
$context = new Pluf_Template_Context_Request(
|
||||||
array('url' => $url,
|
$request,
|
||||||
'title' => $title,
|
array('url' => $url,
|
||||||
'content' => $content,
|
'author' => $issue->get_submitter(),
|
||||||
'date' => $date));
|
'title' => $title,
|
||||||
|
'c' => $this,
|
||||||
|
'issue' => $issue,
|
||||||
|
'date' => $date)
|
||||||
|
);
|
||||||
|
$tmpl = new Pluf_Template('idf/issues/feedfragment.xml');
|
||||||
|
return $tmpl->render($context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_submitter_data()
|
||||||
|
{
|
||||||
|
return IDF_UserData::factory($this->get_submitter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -39,9 +39,9 @@ class IDF_IssueFile extends Pluf_Model
|
|||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Sequence',
|
'type' => 'Pluf_DB_Field_Sequence',
|
||||||
//It is automatically added.
|
//It is automatically added.
|
||||||
'blank' => true,
|
'blank' => true,
|
||||||
),
|
),
|
||||||
'comment' =>
|
'comment' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||||
'model' => 'IDF_IssueComment',
|
'model' => 'IDF_IssueComment',
|
||||||
@@ -49,7 +49,7 @@ class IDF_IssueFile extends Pluf_Model
|
|||||||
'verbose' => __('comment'),
|
'verbose' => __('comment'),
|
||||||
'relate_name' => 'attachment',
|
'relate_name' => 'attachment',
|
||||||
),
|
),
|
||||||
'submitter' =>
|
'submitter' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||||
'model' => 'Pluf_User',
|
'model' => 'Pluf_User',
|
||||||
@@ -63,7 +63,7 @@ class IDF_IssueFile extends Pluf_Model
|
|||||||
'size' => 100,
|
'size' => 100,
|
||||||
'verbose' => __('file name'),
|
'verbose' => __('file name'),
|
||||||
),
|
),
|
||||||
'attachment' =>
|
'attachment' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_File',
|
'type' => 'Pluf_DB_Field_File',
|
||||||
'blank' => false,
|
'blank' => false,
|
||||||
@@ -76,7 +76,7 @@ class IDF_IssueFile extends Pluf_Model
|
|||||||
'verbose' => __('file size'),
|
'verbose' => __('file size'),
|
||||||
'help_text' => 'Size in bytes.',
|
'help_text' => 'Size in bytes.',
|
||||||
),
|
),
|
||||||
'type' =>
|
'type' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Varchar',
|
'type' => 'Pluf_DB_Field_Varchar',
|
||||||
'blank' => false,
|
'blank' => false,
|
||||||
@@ -111,7 +111,7 @@ class IDF_IssueFile extends Pluf_Model
|
|||||||
$file = Pluf::f('upload_issue_path').'/'.$this->attachment;
|
$file = Pluf::f('upload_issue_path').'/'.$this->attachment;
|
||||||
$this->filesize = filesize($file);
|
$this->filesize = filesize($file);
|
||||||
// remove .dummy
|
// remove .dummy
|
||||||
$this->filename = substr(basename($file), 0, -6);
|
$this->filename = substr(basename($file), 0, -6);
|
||||||
$img_extensions = array('jpeg', 'jpg', 'png', 'gif');
|
$img_extensions = array('jpeg', 'jpg', 'png', 'gif');
|
||||||
$info = pathinfo($this->filename);
|
$info = pathinfo($this->filename);
|
||||||
if (!isset($info['extension'])) $info['extension'] = '';
|
if (!isset($info['extension'])) $info['extension'] = '';
|
||||||
@@ -128,4 +128,10 @@ class IDF_IssueFile extends Pluf_Model
|
|||||||
{
|
{
|
||||||
@unlink(Pluf::f('upload_issue_path').'/'.$this->attachment);
|
@unlink(Pluf::f('upload_issue_path').'/'.$this->attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isText()
|
||||||
|
{
|
||||||
|
$info = IDF_FileUtil::getMimeType($this->filename);
|
||||||
|
return IDF_FileUtil::isText($info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
101
src/IDF/Key.php
101
src/IDF/Key.php
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
# ***** END LICENSE BLOCK ***** */
|
# ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Storage of the SSH keys.
|
* Storage of the public keys (ssh or monotone).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class IDF_Key extends Pluf_Model
|
class IDF_Key extends Pluf_Model
|
||||||
@@ -39,9 +39,9 @@ class IDF_Key extends Pluf_Model
|
|||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Sequence',
|
'type' => 'Pluf_DB_Field_Sequence',
|
||||||
//It is automatically added.
|
//It is automatically added.
|
||||||
'blank' => true,
|
'blank' => true,
|
||||||
),
|
),
|
||||||
'user' =>
|
'user' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||||
'model' => 'Pluf_User',
|
'model' => 'Pluf_User',
|
||||||
@@ -52,14 +52,14 @@ class IDF_Key extends Pluf_Model
|
|||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Text',
|
'type' => 'Pluf_DB_Field_Text',
|
||||||
'blank' => false,
|
'blank' => false,
|
||||||
'verbose' => __('ssh key'),
|
'verbose' => __('public key'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// WARNING: Not using getSqlTable on the Pluf_User object to
|
// WARNING: Not using getSqlTable on the Pluf_User object to
|
||||||
// avoid recursion.
|
// avoid recursion.
|
||||||
$t_users = $this->_con->pfx.'users';
|
$t_users = $this->_con->pfx.'users';
|
||||||
$this->_a['views'] = array(
|
$this->_a['views'] = array(
|
||||||
'join_user' =>
|
'join_user' =>
|
||||||
array(
|
array(
|
||||||
'join' => 'LEFT JOIN '.$t_users
|
'join' => 'LEFT JOIN '.$t_users
|
||||||
.' ON '.$t_users.'.id='.$this->_con->qn('user'),
|
.' ON '.$t_users.'.id='.$this->_con->qn('user'),
|
||||||
@@ -70,6 +70,66 @@ class IDF_Key extends Pluf_Model
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showCompact()
|
||||||
|
{
|
||||||
|
return Pluf_Template::markSafe(Pluf_esc(substr($this->content, 0, 25)).' [...] '.Pluf_esc(substr($this->content, -55)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseContent()
|
||||||
|
{
|
||||||
|
if (preg_match('#^\[pubkey ([^\]]+)\]\s*(\S+)\s*\[end\]$#', $this->content, $m)) {
|
||||||
|
return array('mtn', $m[1], $m[2]);
|
||||||
|
}
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception(__('Invalid or unknown key data detected.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type of the public key
|
||||||
|
*
|
||||||
|
* @return string 'ssh' or 'mtn'
|
||||||
|
*/
|
||||||
|
function getType()
|
||||||
|
{
|
||||||
|
list($type, , ) = $this->parseContent();
|
||||||
|
return $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the key name of the key
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getName()
|
||||||
|
{
|
||||||
|
list(, $keyName, ) = $this->parseContent();
|
||||||
|
return $keyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function should be used to calculate the key id from the
|
||||||
|
* public key hash for authentication purposes. This avoids clashes
|
||||||
|
* in case the key name is not unique across the project
|
||||||
|
*
|
||||||
|
* And yes, this is actually how monotone itself calculates the key
|
||||||
|
* id...
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getMtnId()
|
||||||
|
{
|
||||||
|
list($type, $keyName, $keyData) = $this->parseContent();
|
||||||
|
if ($type != 'mtn')
|
||||||
|
throw new Exception('key is not a monotone public key');
|
||||||
|
return sha1($keyName.":".$keyData);
|
||||||
|
}
|
||||||
|
|
||||||
function postSave($create=false)
|
function postSave($create=false)
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@@ -84,7 +144,7 @@ class IDF_Key extends Pluf_Model
|
|||||||
* [description]
|
* [description]
|
||||||
*
|
*
|
||||||
* This signal allows an application to perform special
|
* This signal allows an application to perform special
|
||||||
* operations after the saving of a SSH Key.
|
* operations after the saving of a public Key.
|
||||||
*
|
*
|
||||||
* [parameters]
|
* [parameters]
|
||||||
*
|
*
|
||||||
@@ -97,4 +157,29 @@ class IDF_Key extends Pluf_Model
|
|||||||
'IDF_Key', $params);
|
'IDF_Key', $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function preDelete()
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* [signal]
|
||||||
|
*
|
||||||
|
* IDF_Key::preDelete
|
||||||
|
*
|
||||||
|
* [sender]
|
||||||
|
*
|
||||||
|
* IDF_Key
|
||||||
|
*
|
||||||
|
* [description]
|
||||||
|
*
|
||||||
|
* This signal allows an application to perform special
|
||||||
|
* operations before a key is deleted.
|
||||||
|
*
|
||||||
|
* [parameters]
|
||||||
|
*
|
||||||
|
* array('key' => $key)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$params = array('key' => $this);
|
||||||
|
Pluf_Signal::send('IDF_Key::preDelete',
|
||||||
|
'IDF_Key', $params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -87,11 +87,13 @@ class IDF_Middleware
|
|||||||
'markdown' => 'IDF_Template_Markdown',
|
'markdown' => 'IDF_Template_Markdown',
|
||||||
'showuser' => 'IDF_Template_ShowUser',
|
'showuser' => 'IDF_Template_ShowUser',
|
||||||
'ashowuser' => 'IDF_Template_AssignShowUser',
|
'ashowuser' => 'IDF_Template_AssignShowUser',
|
||||||
|
'appversion' => 'IDF_Template_AppVersion',
|
||||||
));
|
));
|
||||||
$params['modifiers'] = array_merge($params['modifiers'],
|
$params['modifiers'] = array_merge($params['modifiers'],
|
||||||
array(
|
array(
|
||||||
'size' => 'IDF_Views_Source_PrettySize',
|
'size' => 'IDF_Views_Source_PrettySize',
|
||||||
'ssize' => 'IDF_Views_Source_PrettySizeSimple',
|
'ssize' => 'IDF_Views_Source_PrettySizeSimple',
|
||||||
|
'shorten' => 'IDF_Views_Source_ShortenString',
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,12 +106,14 @@ function IDF_Middleware_ContextPreProcessor($request)
|
|||||||
$c['isAdmin'] = ($request->user->administrator or $request->user->staff);
|
$c['isAdmin'] = ($request->user->administrator or $request->user->staff);
|
||||||
if (isset($request->project)) {
|
if (isset($request->project)) {
|
||||||
$c['project'] = $request->project;
|
$c['project'] = $request->project;
|
||||||
$c['isOwner'] = $request->user->hasPerm('IDF.project-owner',
|
$c['isOwner'] = $request->user->hasPerm('IDF.project-owner',
|
||||||
$request->project);
|
$request->project);
|
||||||
$c['isMember'] = $request->user->hasPerm('IDF.project-member',
|
$c['isMember'] = $request->user->hasPerm('IDF.project-member',
|
||||||
$request->project);
|
$request->project);
|
||||||
$c = array_merge($c, $request->rights);
|
$c = array_merge($c, $request->rights);
|
||||||
}
|
}
|
||||||
|
$c['usherConfigured'] = Pluf::f("mtn_usher_conf", null) !== null;
|
||||||
|
$c['allProjects'] = IDF_Views::getProjects($request->user);
|
||||||
return $c;
|
return $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
55
src/IDF/Migrations/12DownloadDesc.php
Normal file
55
src/IDF/Migrations/12DownloadDesc.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_12DownloadDesc_up($params=null)
|
||||||
|
{
|
||||||
|
$table = Pluf::factory('IDF_Upload')->getSqlTable();
|
||||||
|
$sql = array();
|
||||||
|
$sql['PostgreSQL'] = 'ALTER TABLE '.$table.' ADD COLUMN "changelog" TEXT DEFAULT \'\'';
|
||||||
|
$sql['MySQL'] = 'ALTER TABLE '.$table.' ADD COLUMN `changelog` LONGTEXT 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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function IDF_Migrations_12DownloadDesc_down($params=null)
|
||||||
|
{
|
||||||
|
$table = Pluf::factory('IDF_Upload')->getSqlTable();
|
||||||
|
$sql = array();
|
||||||
|
$sql['PostgreSQL'] = 'ALTER TABLE '.$table.' DROP COLUMN "changelog"';
|
||||||
|
$sql['MySQL'] = 'ALTER TABLE '.$table.' DROP COLUMN `changelog`';
|
||||||
|
$db = Pluf::db();
|
||||||
|
$engine = Pluf::f('db_engine');
|
||||||
|
if (!isset($sql[$engine])) {
|
||||||
|
throw new Exception('SQLite complex migration not supported.');
|
||||||
|
}
|
||||||
|
$db->execute($sql[$engine]);
|
||||||
|
|
||||||
|
}
|
60
src/IDF/Migrations/13NewReview.php
Normal file
60
src/IDF/Migrations/13NewReview.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 ***** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the old review and add the new one.
|
||||||
|
*
|
||||||
|
* This is a destructive operation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function IDF_Migrations_13NewReview_up($params=null)
|
||||||
|
{
|
||||||
|
$extra = (Pluf::f('db_engine') == 'PostgreSQL') ? ' CASCADE' : '';
|
||||||
|
$pfx = Pluf::f('db_table_prefix');
|
||||||
|
$tables = array('idf_review_filecomments',
|
||||||
|
'idf_review_patches',
|
||||||
|
'idf_review_pluf_user_assoc',
|
||||||
|
'idf_review_idf_tag_assoc',
|
||||||
|
'idf_reviews');
|
||||||
|
$db = Pluf::db();
|
||||||
|
foreach ($tables as $table) {
|
||||||
|
$db->execute('DROP TABLE IF EXISTS '.$pfx.$table.$extra);
|
||||||
|
}
|
||||||
|
$models = array(
|
||||||
|
'IDF_Review',
|
||||||
|
'IDF_Review_Patch',
|
||||||
|
'IDF_Review_Comment',
|
||||||
|
'IDF_Review_FileComment',
|
||||||
|
);
|
||||||
|
$db = Pluf::db();
|
||||||
|
$schema = new Pluf_DB_Schema($db);
|
||||||
|
foreach ($models as $model) {
|
||||||
|
$schema->model = new $model();
|
||||||
|
$schema->createTables();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function IDF_Migrations_13NewReview_down($params=null)
|
||||||
|
{
|
||||||
|
// We do nothing as we cannot go back to the old reviews
|
||||||
|
}
|
53
src/IDF/Migrations/14Queue.php
Normal file
53
src/IDF/Migrations/14Queue.php
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?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_Queue model.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
function IDF_Migrations_14Queue_up($params=null)
|
||||||
|
{
|
||||||
|
$models = array(
|
||||||
|
'IDF_Queue',
|
||||||
|
);
|
||||||
|
$db = Pluf::db();
|
||||||
|
$schema = new Pluf_DB_Schema($db);
|
||||||
|
foreach ($models as $model) {
|
||||||
|
$schema->model = new $model();
|
||||||
|
$schema->createTables();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function IDF_Migrations_14Queue_down($params=null)
|
||||||
|
{
|
||||||
|
$models = array(
|
||||||
|
'IDF_Queue',
|
||||||
|
);
|
||||||
|
$db = Pluf::db();
|
||||||
|
$schema = new Pluf_DB_Schema($db);
|
||||||
|
foreach ($models as $model) {
|
||||||
|
$schema->model = new $model();
|
||||||
|
$schema->dropTables();
|
||||||
|
}
|
||||||
|
}
|
53
src/IDF/Migrations/15AddGconf.php
Normal file
53
src/IDF/Migrations/15AddGconf.php
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?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_15AddGconf_up($params=null)
|
||||||
|
{
|
||||||
|
$models = array(
|
||||||
|
'IDF_Gconf',
|
||||||
|
);
|
||||||
|
$db = Pluf::db();
|
||||||
|
$schema = new Pluf_DB_Schema($db);
|
||||||
|
foreach ($models as $model) {
|
||||||
|
$schema->model = new $model();
|
||||||
|
$schema->createTables();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function IDF_Migrations_15AddGconf_down($params=null)
|
||||||
|
{
|
||||||
|
$models = array(
|
||||||
|
'IDF_Gconf',
|
||||||
|
);
|
||||||
|
$db = Pluf::db();
|
||||||
|
$schema = new Pluf_DB_Schema($db);
|
||||||
|
foreach ($models as $model) {
|
||||||
|
$schema->model = new $model();
|
||||||
|
$schema->dropTables();
|
||||||
|
}
|
||||||
|
}
|
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();
|
||||||
|
}
|
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]);
|
||||||
|
}
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
115
src/IDF/Migrations/Backup.php
Normal file
115
src/IDF/Migrations/Backup.php
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
<?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 ***** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Backup of InDefero.
|
||||||
|
*
|
||||||
|
* !! You need also to backup Pluf if you want the full backup. !!
|
||||||
|
*
|
||||||
|
* @param string Path to the folder where to store the backup
|
||||||
|
* @param string Name of the backup (null)
|
||||||
|
* @return int The backup was correctly written
|
||||||
|
*/
|
||||||
|
function IDF_Migrations_Backup_run($folder, $name=null)
|
||||||
|
{
|
||||||
|
$models = array(
|
||||||
|
'IDF_Project',
|
||||||
|
'IDF_Tag',
|
||||||
|
'IDF_Issue',
|
||||||
|
'IDF_IssueComment',
|
||||||
|
'IDF_Conf',
|
||||||
|
'IDF_Upload',
|
||||||
|
'IDF_Search_Occ',
|
||||||
|
'IDF_IssueFile',
|
||||||
|
'IDF_Commit',
|
||||||
|
'IDF_Timeline',
|
||||||
|
'IDF_WikiPage',
|
||||||
|
'IDF_WikiRevision',
|
||||||
|
'IDF_Review',
|
||||||
|
'IDF_Review_Patch',
|
||||||
|
'IDF_Review_Comment',
|
||||||
|
'IDF_Review_FileComment',
|
||||||
|
'IDF_Key',
|
||||||
|
'IDF_Scm_Cache_Git',
|
||||||
|
'IDF_Queue',
|
||||||
|
'IDF_Gconf',
|
||||||
|
'IDF_EmailAddress',
|
||||||
|
);
|
||||||
|
$db = Pluf::db();
|
||||||
|
// Now, for each table, we dump the content in json, this is a
|
||||||
|
// memory intensive operation
|
||||||
|
$to_json = array();
|
||||||
|
foreach ($models as $model) {
|
||||||
|
$to_json[$model] = Pluf_Test_Fixture::dump($model, false);
|
||||||
|
}
|
||||||
|
if (null == $name) {
|
||||||
|
$name = date('Y-m-d');
|
||||||
|
}
|
||||||
|
return file_put_contents(sprintf('%s/%s-IDF.json', $folder, $name),
|
||||||
|
json_encode($to_json), LOCK_EX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore IDF from a backup.
|
||||||
|
*
|
||||||
|
* @param string Path to the backup folder
|
||||||
|
* @param string Backup name
|
||||||
|
* @return bool Success
|
||||||
|
*/
|
||||||
|
function IDF_Migrations_Backup_restore($folder, $name)
|
||||||
|
{
|
||||||
|
$models = array(
|
||||||
|
'IDF_Project',
|
||||||
|
'IDF_Tag',
|
||||||
|
'IDF_Issue',
|
||||||
|
'IDF_IssueComment',
|
||||||
|
'IDF_Conf',
|
||||||
|
'IDF_Upload',
|
||||||
|
'IDF_Search_Occ',
|
||||||
|
'IDF_IssueFile',
|
||||||
|
'IDF_Commit',
|
||||||
|
'IDF_Timeline',
|
||||||
|
'IDF_WikiPage',
|
||||||
|
'IDF_WikiRevision',
|
||||||
|
'IDF_Review',
|
||||||
|
'IDF_Review_Patch',
|
||||||
|
'IDF_Review_Comment',
|
||||||
|
'IDF_Review_FileComment',
|
||||||
|
'IDF_Key',
|
||||||
|
'IDF_Scm_Cache_Git',
|
||||||
|
'IDF_Queue',
|
||||||
|
'IDF_Gconf',
|
||||||
|
'IDF_EmailAddress',
|
||||||
|
);
|
||||||
|
$db = Pluf::db();
|
||||||
|
$schema = new Pluf_DB_Schema($db);
|
||||||
|
foreach ($models as $model) {
|
||||||
|
$schema->model = new $model();
|
||||||
|
$schema->createTables();
|
||||||
|
}
|
||||||
|
$full_data = json_decode(file_get_contents(sprintf('%s/%s-IDF.json', $folder, $name)), true);
|
||||||
|
foreach ($full_data as $model => $data) {
|
||||||
|
Pluf_Test_Fixture::load($data, false);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -44,8 +44,13 @@ function IDF_Migrations_Install_setup($params=null)
|
|||||||
'IDF_WikiRevision',
|
'IDF_WikiRevision',
|
||||||
'IDF_Review',
|
'IDF_Review',
|
||||||
'IDF_Review_Patch',
|
'IDF_Review_Patch',
|
||||||
|
'IDF_Review_Comment',
|
||||||
'IDF_Review_FileComment',
|
'IDF_Review_FileComment',
|
||||||
'IDF_Key',
|
'IDF_Key',
|
||||||
|
'IDF_Scm_Cache_Git',
|
||||||
|
'IDF_Queue',
|
||||||
|
'IDF_Gconf',
|
||||||
|
'IDF_EmailAddress',
|
||||||
);
|
);
|
||||||
$db = Pluf::db();
|
$db = Pluf::db();
|
||||||
$schema = new Pluf_DB_Schema($db);
|
$schema = new Pluf_DB_Schema($db);
|
||||||
@@ -83,8 +88,12 @@ function IDF_Migrations_Install_teardown($params=null)
|
|||||||
$perm = Pluf_Permission::getFromString('IDF.project-authorized-user');
|
$perm = Pluf_Permission::getFromString('IDF.project-authorized-user');
|
||||||
if ($perm) $perm->delete();
|
if ($perm) $perm->delete();
|
||||||
$models = array(
|
$models = array(
|
||||||
|
'IDF_Gconf',
|
||||||
|
'IDF_Queue',
|
||||||
|
'IDF_Scm_Cache_Git',
|
||||||
'IDF_Key',
|
'IDF_Key',
|
||||||
'IDF_Review_FileComment',
|
'IDF_Review_FileComment',
|
||||||
|
'IDF_Review_Comment',
|
||||||
'IDF_Review_Patch',
|
'IDF_Review_Patch',
|
||||||
'IDF_Review',
|
'IDF_Review',
|
||||||
'IDF_WikiRevision',
|
'IDF_WikiRevision',
|
||||||
@@ -99,6 +108,7 @@ function IDF_Migrations_Install_teardown($params=null)
|
|||||||
'IDF_Tag',
|
'IDF_Tag',
|
||||||
'IDF_Commit',
|
'IDF_Commit',
|
||||||
'IDF_Project',
|
'IDF_Project',
|
||||||
|
'IDF_EmailAddress',
|
||||||
);
|
);
|
||||||
$db = Pluf::db();
|
$db = Pluf::db();
|
||||||
$schema = new Pluf_DB_Schema($db);
|
$schema = new Pluf_DB_Schema($db);
|
||||||
@@ -106,4 +116,4 @@ function IDF_Migrations_Install_teardown($params=null)
|
|||||||
$schema->model = new $model();
|
$schema->model = new $model();
|
||||||
$schema->dropTables();
|
$schema->dropTables();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# This file is part of InDefero, an open source project management application.
|
# 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
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -44,9 +44,38 @@ class IDF_Plugin_SyncGit
|
|||||||
{
|
{
|
||||||
// First check for the single mandatory config variable.
|
// First check for the single mandatory config variable.
|
||||||
if (!Pluf::f('idf_plugin_syncgit_sync_file', false)) {
|
if (!Pluf::f('idf_plugin_syncgit_sync_file', false)) {
|
||||||
|
Pluf_Log::debug('IDF_Plugin_SyncGit plugin not configured.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@touch(Pluf::f('idf_plugin_syncgit_sync_file'));
|
if ($signal != 'gitpostupdate.php::run') {
|
||||||
@chmod(Pluf::f('idf_plugin_syncgit_sync_file'), 0666);
|
Pluf_Log::event('IDF_Plugin_SyncGit', 'create',
|
||||||
|
Pluf::f('idf_plugin_syncgit_sync_file'));
|
||||||
|
@touch(Pluf::f('idf_plugin_syncgit_sync_file'));
|
||||||
|
@chmod(Pluf::f('idf_plugin_syncgit_sync_file'), 0777);
|
||||||
|
} else {
|
||||||
|
self::postUpdate($signal, $params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry point for the post-update signal.
|
||||||
|
*
|
||||||
|
* It tries to find the name of the project, when found it runs an
|
||||||
|
* update of the timeline.
|
||||||
|
*/
|
||||||
|
static public function postUpdate($signal, &$params)
|
||||||
|
{
|
||||||
|
// Chop the ".git" and get what is left
|
||||||
|
$pname = basename($params['git_dir'], '.git');
|
||||||
|
try {
|
||||||
|
$project = IDF_Project::getOr404($pname);
|
||||||
|
} catch (Pluf_HTTP_Error404 $e) {
|
||||||
|
Pluf_Log::event(array('IDF_Plugin_SyncGit::postUpdate', 'Project not found.', array($pname, $params)));
|
||||||
|
return false; // Project not found
|
||||||
|
}
|
||||||
|
// Now we have the project and can update the timeline
|
||||||
|
Pluf_Log::debug(array('IDF_Plugin_SyncGit::postUpdate', 'Project found', $pname, $project->id));
|
||||||
|
IDF_Scm::syncTimeline($project, true);
|
||||||
|
Pluf_Log::event(array('IDF_Plugin_SyncGit::postUpdate', 'sync', array($pname, $project->id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user