JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
don't warn about me having to set the price again if they haven't approved it yet
[contractor-progress.git] / tasks.php
1 <?php
2
3 require_once('code/tasks.php');
4
5 $GLOBALS['tasks_form_recipient'] = "fixme@example.com";
6
7
8
9 require_once('code/wfpl/template.php');
10 require_once('code/wfpl/format.php');
11 require_once('code/wfpl/messages.php');
12 require_once('code/wfpl/email.php');
13 require_once('code/db_connect.php');
14
15 function description_has_fixmes($description) {
16         return (strpos($description, 'FIXME') !== false);
17 }
18
19 # replace every character in $str with "&nbsp;"
20 function tonbsp($matches) {
21         return str_repeat('&nbsp;', strlen($matches[0]) * 2);
22 }
23
24 # encode as html, make it display newlines and leading spaces
25 function enc_htmlbrtab($str) {
26         $str = enc_htmlbr($str);
27         $str = preg_replace_callback("|^ *|m", tonbsp, $str);
28         return $str;
29 }
30
31 function tasks_get_fields() {
32         $title = format_oneline($_REQUEST['title']);
33         $url = format_oneline($_REQUEST['url']);
34         $description = format_unix($_REQUEST['description']);
35         $price = format_decimal($_REQUEST['price']);
36
37         tasks_tem_sets($title, $url, $description, $price);
38
39         return array($title, $url, $description, $price);
40 }
41
42 function tasks_tem_sets($title, $url, $description, $price) {
43         tem_set('title', $title);
44         tem_set('url', $url);
45         tem_set('description', $description);
46         tem_set('price', $price);
47 }
48
49 function tasks_main() {
50         if(!logged_in()) {
51                 $GLOBALS['url'] = this_url();
52                 return 'login';
53         }
54
55         if(isset($_REQUEST['tasks_id'])) {
56                 $ret = tasks_display_main();
57                 if($ret) {
58                         return $ret;
59                 }
60                 tem_show('display_body');
61         } else {
62                 $ret = tasks_edit_main();
63                 if($ret) {
64                         return $ret;
65                 }
66                 tem_show('edit_body');
67         }
68
69         tem_show('main_body');
70 }
71
72 function tasks_display_main() {
73         $task_id = format_int($_REQUEST['tasks_id']);;
74         $client_id = logged_in();
75         if(logged_in_as_contractor()) {
76                 $row = db_get_row('tasks', 'title,url,description,state,price', 'where id=%i', $task_id);
77         } else {
78                 $row = db_get_row('tasks', 'title,url,description,state,price', 'where id=%i && client_id=%i', $task_id, $client_id);
79         }
80         if($row) {
81                 list($title, $url, $description, $state, $price) = $row;
82                 tem_set('task_id', $task_id);
83                 tem_set('title', $title);
84                 tem_set('url', $url);
85                 tem_set('description', $description);
86                 tem_set('state', task_state_pretty($state));
87                 tem_set('price', $price);
88                 if($state == TASK_BUG) {
89                         tem_show('bug_title');
90                 } else {
91                         tem_show('normal_title');
92                 }
93                 if(logged_in_as_contractor()) {
94                         switch($state) {
95                                 case TASK_DRAFT:
96                                 case TASK_NEEDS_CLARIFICATION:
97                                 case TASK_NEEDS_QUOTE:
98                                 case TASK_BUG:
99                                 case TASK_NEEDS_GO_AHEAD:
100                                         tem_show('normal_edit_link');
101                                         tem_show('price_row');
102                                 break;
103                                 case TASK_QUEUED:
104                                         tem_show('normal_edit_link');
105                                         tem_show('working_link');
106                                         tem_show('price_row');
107                                 case TASK_WORKING:
108                                         tem_show('price_row');
109                                         tem_show('needs_testing_link');
110                                 break;
111                                 case TASK_NEEDS_TESTING:
112                                 case TASK_FINISHED:
113                                         tem_show('price_row');
114                                 break;
115                         }
116                 } else {
117                         switch($state) {
118                                 case TASK_DRAFT:
119                                 case TASK_NEEDS_CLARIFICATION:
120                                 case TASK_NEEDS_QUOTE:
121                                 case TASK_BUG:
122                                         tem_show('normal_edit_link');
123                                 break;
124                                 case TASK_NEEDS_GO_AHEAD:
125                                         tem_show('price_row');
126                                         tem_show('approve_price_link');
127                                         tem_show('normal_edit_link');
128                                 break;
129                                 case TASK_QUEUED:
130                                         tem_show('price_row');
131                                         tem_show('warning_edit_link');
132                                 break;
133                                 case TASK_WORKING:
134                                         tem_show('price_row');
135                                 break;
136                                 case TASK_NEEDS_TESTING:
137                                         tem_show('price_row');
138                                         tem_show('finished_link');
139                                 break;
140                                 case TASK_FINISHED:
141                                         tem_show('price_row');
142                                 break;
143                         }
144                 }
145         } else {
146                 message("Task #$task_id not found");
147                 return './';
148         }
149 }
150
151 function tasks_edit_main() {
152         $state = TASK_DRAFT; # will be overwritten
153         $client_id = logged_in(); # fixed shortly if we're contractor
154         $edit_id = format_int($_REQUEST['tasks_edit_id']);
155         unset($_REQUEST['tasks_edit_id']);
156         if($edit_id) {
157                 $owner = db_get_value('tasks', 'client_id', 'where id=%i', $edit_id);
158                 if(logged_in_as_contractor()) {
159                         $client_id = $owner;
160                 } elseif($owner != $client_id) {
161                         message('Sorry, that task was entered by/for another client.');
162                         return './';
163                 }
164
165                 # add hidden field for database id of row we're editing
166                 tem_set('tasks_edit_id', $edit_id);
167                 tem_show('editing');
168
169                 $state = db_get_value('tasks', 'state', 'where id=%i', $edit_id);
170         }
171
172         if(isset($_REQUEST['tasks_new_bug'])) {
173                 $state = TASK_BUG;
174         }
175
176         if(isset($_REQUEST['tasks_approve_price_id'])) {
177                 $id = $_REQUEST['tasks_approve_price_id'];
178                 $owner = db_get_value('tasks', 'client_id', 'where id=%i', $id);;
179                 if(logged_in() != $owner) {
180                         message("Error: can't approve a task entered by/for another client.");
181                         return './';
182                 }
183                 db_update('tasks', 'state', TASK_QUEUED, 'where id=%i', $id);
184                 message('Price approved.');
185                 return './';
186         }
187
188         if(isset($_REQUEST['tasks_working_id'])) {
189                 $id = $_REQUEST['tasks_working_id'];
190                 if(!logged_in_as_contractor()) {
191                         message("Error: only Jason can say what he's working on.");
192                         return './';
193                 }
194                 db_update('tasks', 'state', TASK_WORKING, 'where id=%i', $id);
195                 message('OK, client locked out of modifying that one.');
196                 return './';
197         }
198
199         if(isset($_REQUEST['tasks_needs_testing_id'])) {
200                 $id = $_REQUEST['tasks_needs_testing_id'];
201                 if(!logged_in_as_contractor()) {
202                         message("Error: only Jason can say when he's done.");
203                         return './';
204                 }
205                 db_update('tasks', 'state', TASK_NEEDS_TESTING, 'where id=%i', $id);
206                 message('Task awaits testing.');
207                 return './';
208         }
209
210         if(isset($_REQUEST['tasks_finished_id'])) {
211                 $id = $_REQUEST['tasks_finished_id'];
212                 $owner = db_get_value('tasks', 'client_id', 'where id=%i', $id);;
213                 if(logged_in() != $owner) {
214                         message("Error: can't test a task entered by/for another client.");
215                         return './';
216                 }
217                 db_update('tasks', 'state', TASK_FINISHED, 'where id=%i', $id);
218                 message('Task marked as finished.');
219                 # FIXME also mark it as paid if client's balance can cover it
220                 return './';
221         }
222
223         $delete_id = format_int($_REQUEST['tasks_delete_id']);
224         unset($_REQUEST['tasks_delete_id']);
225         if($delete_id) {
226                 db_delete('tasks', 'where id=%i', $delete_id);
227                 message('Task deleted.');
228
229                 return './tasks.html';
230         }
231
232         if(isset($_REQUEST['title'])) {
233                 list($title, $url, $description, $price) = tasks_get_fields();
234
235                 # FIXME
236                 if(isset($_REQUEST['save_draft'])) {
237                         $state = TASK_DRAFT;
238                 } elseif(isset($_REQUEST['save_bug'])) {
239                         $state = TASK_BUG;
240                 } elseif(isset($_REQUEST['save_price']) && logged_in_as_contractor()) {
241                         $tiny_agreement = db_get_value('people', 'tiny_agreement', 'where id=%i', $client_id);
242                         if($price < $tiny_agreement) {
243                                 $state = TASK_QUEUED;
244                         } else {
245                                 $state = TASK_NEEDS_GO_AHEAD;
246                         }
247                 } elseif(isset($_REQUEST['needs_clarification'])) {
248                         $state = TASK_NEEDS_CLARIFICATION;
249                 } else { # better be "request_price"
250                         if(description_has_fixmes($description)) {
251                                 $state = TASK_NEEDS_CLARIFICATION;
252                                 message('The description is not ready to be priced yet because it still contains at least one "FIXME".');
253                         } else {
254                                 $state = TASK_NEEDS_QUOTE;
255                         }
256                 }
257
258                 if("you're happy with the POSTed values") {
259                         if($edit_id) {
260                                 if(isset($_REQUEST['price']) && logged_in_as_contractor()) {
261                                         db_update('tasks', 'title,url,description,state,price', $title, $url, $description, $state, $price, 'where id=%i', $edit_id);
262                                 } else {
263                                         db_update('tasks', 'title,url,description,state', $title, $url, $description, $state, 'where id=%i', $edit_id);
264                                 }
265                                 message('Task updated.');
266                         } else {
267                                 # new task
268                                 $paid = 0;
269                                 $client_id = logged_in();
270                                 db_insert('tasks', 'client_id,title,url,description,state,paid', $client_id, $title, $url, $description, $state, $paid);
271                                 message('Task saved.');
272                         }
273                         if($GLOBALS['tasks_form_recipient'] != "fixme@example.com") {
274                                 $to = $GLOBALS['tasks_form_recipient'];
275                                 $from = $to;
276                                 $reply_to = '';
277                                 if(isset($_REQUEST['email']) and valid_email($_REQUEST['email'])) {
278                                         $reply_to = $_REQUEST['email'];
279                                         if($_REQUEST['name'] and ereg('^[a-zA-Z0-9_\' -]*$', $_REQUEST['name']) !== false) {
280                                                 $reply_to = "$_REQUEST[name] <$reply_to>";
281                                         }
282                                 }
283                                 $subject = 'tasks form submitted';
284                                 $message = tem_run('tasks.email.txt');
285                                 $cc = '';
286                                 $bcc = '';
287                                 if(email($from, $to, $subject, $message, $reply_to, $cc, $bcc)) {
288                                         message('Due to an internal error, your message could not be sent. Please try again later.');
289                                         $error = true;
290                                 }
291                         }
292                         if($error !== true) {
293                                 return './';
294                         }
295                 }
296                 # otherwise, we display the form again. tasks_get_fields() has
297                 # already put the posted values back into the template engine, so they will
298                 # show up in the form fields. You should add some message asking people to
299                 # fix their entry in whatever way you require.
300         } elseif($edit_id) {
301                 # we've recieved an edit id, but no data. So we grab the values to be edited from the database
302                 list($title, $url, $description, $state, $paid) = db_get_row('tasks', 'title,url,description,state,price', 'where id=%i', $edit_id);
303                 tasks_tem_sets($title, $url, $description, $price);
304         } else {
305                 # form not submitted, you can set default values like so:
306                 #tem_set('client_id', 'Yes');
307         }
308
309         # display header
310         if($edit_id) {
311                 tem_show('edit_msg');
312         } elseif($state == TASK_BUG) {
313                 tem_show('bug_msg');
314         } else {
315                 tem_show('new_msg');
316         }
317
318         # display instructions
319         if($state == TASK_BUG) {
320                 tem_show('bug_instructions');
321                 if(logged_in_as_contractor()) {
322                         tem_show('price_field');
323                         tem_show('contractor_submits');
324                 } else {
325                         tem_show('bug_submit');
326                 }
327         } elseif($state == TASK_NEEDS_QUOTE && logged_in_as_contractor()) {
328                 tem_show('set_price_instructions');
329                 tem_show('price_field');
330                 tem_show('contractor_submits');
331         } else {
332                 if(description_has_fixmes($description)) {
333                         tem_show('fixme_instructions');
334                 } else {
335                         tem_show('normal_instructions');
336                 }
337                 tem_show('normal_submits');
338         }
339 }
340
341 ?>