Merge branch 'master' into uat
[readifood.git] / lib / contact.php
1 <?php
2
3   if (isset($_POST['show_add_contact'])) {
4     set_last_selected("city_id", $_POST['city_id']);
5     $city_id = $_POST['city_id'];
6     show_new_contact_form($city_id);
7   }
8   else if (isset($_POST['add_contact'])) {
9     set_last_selected("area_id", $_POST['area_id']);
10     $id = add_contact($displayname);
11     if ($id !== false) {
12       echo "<p>Added contact.</p>\n";
13       $parameters = array($displayname, $id);
14     }
15   }
16   else if (isset($_POST['update_contact'])) {
17     list($name, $id, $args) = parse_parameters($parameters);
18     $q = new ContactQuery;
19     $contact = $q->findOneById($id);
20     if ($contact) {
21       $area = get_contact_area($contact);
22       if ($area) $area_id = $area->getId();
23       if (update_contact($contact, $area_id) !== false) {
24         echo "<p>Updated contact.</p>\n";
25         $parameters = array($contact->getDisplayname(), $contact->getId());
26       }
27     }
28     else {
29       echo "<p>No such contact!</p>\n";
30     }
31   }
32   else if ($_POST['search_contact']) {
33     header(sprintf("Location: http%s://%s/%s/search/%s", ($_SERVER['HTTPS']) ? "s" : "", $_SERVER['HTTP_HOST'], $module, urlencode($_POST['search_contact'])));
34     exit;
35   }
36   else if ($_POST['show_in_area']) {
37     set_last_selected("area_id", $_POST['area_id']);
38     $q = new AreaQuery;
39     $area = $q->findOneById($_POST['area_id']);
40     header(sprintf("Location: http%s://%s/%s/in/area/%s/%d", ($_SERVER['HTTPS']) ? "s" : "", $_SERVER['HTTP_HOST'], $module, urlencode($area->getName()), $_POST['area_id']));
41     exit;
42   }
43   else if ($_POST['show_in_city']) {
44     set_last_selected("city_id", $_POST['city_id']);
45     $q = new CityQuery;
46     $city = $q->findOneById($_POST['city_id']);
47     header(sprintf("Location: http%s://%s/%s/in/city/%s/%d", ($_SERVER['HTTPS']) ? "s" : "", $_SERVER['HTTP_HOST'], $module, urlencode($city->getName()), $_POST['city_id']));
48     exit;
49   }
50
51   function show_contact_summary(&$contact, $editing = false) {
52     if ($editing) echo "<p>Contact: <span class=\"strong\">" . htmlspecialchars($contact->getDisplayname()) . "</span>";
53     else echo "<br>\nContact " . $contact->getStrongLink();
54     $role = $contact->getRole();
55     $role_string = get_contact_role_string($contact);
56     if ($role_string) echo " $role_string";
57     $d = urlencode($contact->getDisplayname());
58     $i = $contact->getId();
59     if ($role & $GLOBALS['ROLE_DONOR']) echo " " . get_small_link("Donations", "/donation/from/contact/%s/%d", $d, $i);
60     if ($role & $GLOBALS['ROLE_REQUESTER']) echo " " . get_small_link("Referred", "/order/from/referrer/%s/%d", $d, $i);
61     if ($role & $GLOBALS['ROLE_BENEFICIARY']) {
62       echo " " . get_small_link("Orders", "/order/to/beneficiary/%s/%d", $d, $contact->getId());
63       if (get_contact_area($contact)) echo " " . get_small_link("Place", "/order/place/for/beneficiary/%s/%d", $d, $i);
64     }
65     if (check_admin(1)) {
66       echo " " . $contact->getDeleteLink();
67     }
68     $area = get_contact_area($contact);
69     echo " in " . $area->getLink();
70     $city = get_contact_city($contact);
71     echo ", " . $city->getLink(get_city_displayname($city));
72   }
73
74   function show_contacts($address_ids) {
75     list($first_page, $per_page) = pagination();
76     $q = new ContactQuery;
77     $contacts = $q->filterByAddressId($address_ids)->orderByForename()->orderBySurname()->orderById('desc')->paginate($first_page, $per_page);
78     if (count($contacts)) {
79       foreach ($contacts as $contact) show_contact_summary($contact);
80       show_pagination($contacts);
81     }
82     else echo " none";
83   }
84
85   function search_contacts($search) {
86     list($first_page, $per_page) = pagination();
87     $q = new ContactQuery;
88     $contacts = $q->filterByDisplayname("%$search%")->orderByForename()->orderBySurname()->orderById('desc')->paginate($first_page, $per_page);
89     echo "<p>Contacts matching '" . htmlspecialchars($search) . "':";
90     if (count($contacts)) {
91       foreach ($contacts as $contact) show_contact_summary($contact);
92       show_pagination($contacts);
93     }
94     else echo "none";
95     echo "</p>\n";
96
97     $address_ids = array();
98     $q = new AddressQuery;
99     $addresses = $q->filterByLine("%$search%")->find();
100     foreach ($addresses as $address) $address_ids[] = $address->getId();
101     $q = new AddressQuery;
102     $addresses = $q->filterByPostcode("%$search%")->find();
103     foreach ($addresses as $address) $address_ids[] = $address->getId();
104
105     $q = new ContactQuery;
106     $contacts = $q->filterByAddressId($address_ids)->orderByForename()->orderBySurname()->orderById('desc')->paginate($first_page, $per_page);
107     echo "<p>Contacts in address '" . htmlspecialchars($search) . "':";
108     if (count($contacts)) {
109       foreach ($contacts as $contact) show_contact_summary($contact);
110       show_pagination($contacts);
111     }
112     else echo "none";
113     echo "</p>\n";
114   }
115
116   function show_city_contacts($city_name, $city_id = null) {
117     if (isset($city_id)) $city = get_city_by_id($city_id);
118     else if ($city_name) $city = get_city_by_name($city_name);
119     if ($city) {
120       $q = new AreaQuery;
121       $areas = $q->filterByCityId($city->getId())->find();
122       $area_ids = array();
123       foreach ($areas as $area) $area_ids[] = $area->getId();
124
125       $q = new AddressQuery;
126       $addresses = $q->filterByAreaId($area_ids)->find();
127       $address_ids = array();
128       foreach ($addresses as $address) $address_ids[] = $address->getId();
129
130       echo "<p>Contacts in city " . $city->getLink(get_city_displayname($city)) . ":";
131       return show_contacts($address_ids);
132     }
133     else echo "<p>No such city!</p>\n";
134   }
135
136   function show_area_contacts($area_name, $area_id = null) {
137     if (isset($area_id)) $area = get_area_by_id($area_id);
138     else if ($area_name) $area = get_area_by_name($area_name);
139     if ($area) {
140       $q = new AddressQuery;
141       $addresses = $q->filterByAreaId($area->getId())->find();
142       $address_ids = array();
143       foreach ($addresses as $address) $address_ids[] = $address->getId();
144
145       echo "<p>Contacts in area " . $area->getLink() . ":";
146       return show_contacts($address_ids);
147     }
148     else echo "<p>No such area!</p>\n";
149   }
150
151   function show_contact_areas_form($city_id = null) {
152     $areas = get_city_areas($city_id);
153     if (! count($areas)) {
154       echo "<p>No <a href=\"/area\">areas</a>!</p>\n";
155       return;
156     }
157
158     $candidates = array();
159     foreach ($areas as $area) {
160       if (! count(get_area_contacts($area->getId()))) continue;
161       $candidates[] = $area;
162     }
163     if (! count($candidates)) return;
164
165     echo "<p>Show contacts in area\n";
166     echo "<select name=\"area_id\">\n";
167     foreach ($candidates as $area) {
168       option("area_id", $area->getId(), get_area_displayname($area));
169     }
170     echo "</select>\n";
171     submit("show_in_area", "Show");
172   }
173
174   function show_contact_cities_form($city_id = null) {
175     $q = new CityQuery;
176     $cities = $q->orderByName()->find();
177
178     if (! count($cities)) {
179       echo "<p>No <a href=\"/city\">cities</a>!</p>\n";
180       return;
181     }
182
183     $candidates = array();
184     foreach ($cities as $city) {
185       if (! count(get_city_contacts($city->getId()))) continue;
186       $candidates[] = $city;
187     }
188     if (! count($candidates)) return;
189
190     echo "<p>Show contacts in city\n";
191     echo "<select name=\"city_id\">\n";
192     foreach ($candidates as $city) {
193       option("city_id", $city->getId(), get_city_displayname($city), $city_id);
194     }
195     echo "</select>\n";
196     submit("show_in_city", "Show");
197   }
198
199   function show_contact_search_form() {
200     echo "<p>Search for contacts:";
201     input("search_contact");
202     echo "<input type=\"submit\" value=\"Search\">\n";
203   }
204
205   function show_contact_forms($city_id) {
206     form("noprint standout");
207     show_contact_areas_form($city_id);
208     show_contact_cities_form($city_id);
209     show_contact_search_form();
210     end_form();
211   }
212
213   function show_contact_role_form($role) {
214     return show_role_form($role, $GLOBALS['contact_roles']);
215   }
216
217   function show_contact_form($contact = null, $new = false) {
218     global $contact_roles, $parcel_sizes, $parcel_contents;
219
220     if (! $contact) $contact = new Contact;
221     else if ($contact->getRole() & ($GLOBALS['ROLE_BENEFICIARY'] | $GLOBALS['ROLE_REQUESTER'])) {
222       $state_mask = $GLOBALS['STATE_ANY'];
223       $state_mask &= ~$GLOBALS['STATE_DELIVERED'];
224       $state_mask &= ~$GLOBALS['STATE_CANCELLED'];
225
226       $orders = get_contact_orders($contact, $state_mask);
227
228       if (count($orders)) {
229         echo "<tr>\n";
230         echo "  <td colspan=2><strong>Outstanding orders:</strong></td>\n";
231         echo "</tr>\n";
232
233         echo "<tr>\n";
234         echo "  <td colspan=2 class=\"history\">\n";
235         foreach ($orders as $order) {
236           echo "    " . get_order_summary($order) . "<br>\n";
237         }
238         echo "  </td>\n";
239         echo "</tr>\n";
240       }
241     }
242
243     /* Role. */
244     echo "<tr>\n";
245     echo "  <td>Role</td>\n";
246     echo "  <td>"; show_contact_role_form($contact->getRole()); echo "</td>\n";
247     echo "</tr>\n";
248
249     /* Date added. */
250     if (! $new) {
251       echo "<tr>\n";
252       echo "  <td>Registered</td>\n";
253       echo "  <td>" . $contact->getAdded() . "</td>\n";
254       echo "</tr>\n";
255     }
256
257     /* Forename. */
258     echo "<tr>\n";
259     echo "  <td>Forename</td>\n";
260     echo "  <td>"; input("forename", $contact->getForename()); echo "</td>\n";
261     echo "</tr>\n";
262
263     /* Middle names. */
264     echo "<tr>\n";
265     echo "  <td>Middle name(s)</td>\n";
266     echo "  <td>"; input("middle", $contact->getMiddle()); echo "</td>\n";
267     echo "</tr>\n";
268
269     /* Surname. */
270     echo "<tr>\n";
271     echo "  <td>Surname</td>\n";
272     echo "  <td>"; input("surname", $contact->getSurname()); echo "</td>\n";
273     echo "</tr>\n";
274
275     /* Display name. */
276     echo "<tr>\n";
277     echo "  <td>Display name (if not concatenation of above)</td>\n";
278     echo "  <td>"; input("displayname", $contact->getDisplayname()); echo "</td>\n";
279     echo "</tr>\n";
280
281     /* Address. */
282     $address = get_contact_address($contact);
283     if (! $address) $address = new Address;
284     echo "<tr>\n";
285     echo "  <td>Address</td>\n";
286     echo "  <td>"; textarea("address", $address->getLine()); echo "</td>\n";
287     echo "</tr>\n";
288
289     /* Postcode. */
290     echo "<tr>\n";
291     echo "  <td>Postcode</td>\n";
292     $postcode = $address->getPostcode();
293     if (validate_postcode($postcode)) {
294       echo "  <td>"; input("postcode", $postcode); echo get_address_map_link($address); echo "</td>\n";
295     }
296     else {
297       echo "  <td>"; input("postcode", $address->getPostcode()); echo " (invalid)</td>\n";
298     }
299     echo "</tr>\n";
300
301     /* Telephone. */
302     echo "<tr>\n";
303     echo "  <td>Telephone</td>\n";
304     echo "  <td>"; input("telephone1", $contact->getTelephone1()); echo "</td>\n";
305     echo "</tr>\n";
306     echo "<tr>\n";
307     echo "  <td>Alternative telephone</td>\n";
308     echo "  <td>"; input("telephone2", $contact->getTelephone2()); echo "</td>\n";
309     echo "</tr>\n";
310
311     /* Email. */
312     echo "<tr>\n";
313     echo "  <td>Email</td>\n";
314     echo "  <td>"; input("email", $contact->getEmail()); echo "</td>\n";
315     echo "</tr>\n";
316
317     /* Area. */
318     $area = get_contact_area($contact);
319     if ($area) $area_id = $area->getId();
320     echo "<tr>\n";
321     echo "  <td>Area</td>\n";
322     echo "  <td><select name=\"area_id\">\n";
323     $areas = get_city_areas();
324     foreach ($areas as $area) {
325       option("area_id", $area->getId(), get_area_displayname($area), $area_id);
326     }
327     echo "  </select></td>\n";
328     echo "</tr>\n";
329
330     /* Parcel type. */
331     echo "<tr>\n";
332     echo "  <td>Family unit</td>\n";
333     echo "  <td><select name=\"parcel_size\">\n";
334     $mask = 1 << count($parcel_sizes);
335     for ($i = 0; $i < count($parcel_sizes); $i++) {
336       option("parcel_size", 1 << $i, $parcel_sizes[$i], $contact->getParcel() % $mask);
337     }
338     echo "</select></td>\n";
339     echo "</tr>\n";
340
341     /* Parcel contents. */
342     echo "<tr>\n";
343     echo "  <td>Dietary requirements</td>\n";
344     echo "  <td>";
345     for ($i = count($parcel_sizes); $i < count($parcel_contents); $i++) {
346       if (1 << $i == $GLOBALS['PARCEL_TOILETRY']) continue;
347       echo "  <input type=\"checkbox\" id=\"parcel_$i\" name=\"parcel_$i\"";
348       if ($contact->getParcel() & (1 << $i)) echo " checked";
349       echo "><label for=\"parcel_$i\">$parcel_contents[$i]</label>\n";
350     }
351     echo "</td>\n";
352     echo "</tr>\n";
353
354     /* Notes. */
355     echo "<tr>\n";
356     echo "  <td>Notes</td>\n";
357     echo "  <td>"; textarea("notes", $contact->getNotes()); echo "</td>\n";
358     echo "</tr>\n";
359   }
360
361   function show_new_contact_form($city_id = null) {
362     if (! check_admin(1)) return;
363
364     $areas = get_city_areas($city_id);
365     if (! count($areas)) {
366       echo "<p>No <a href=\"/area\">areas</a>!</p>\n";
367       return;
368     }
369
370     form("noprint");
371     echo "<p>Add a new contact:</p>\n";
372
373     echo "<table>\n";
374     show_contact_form($contact, true);
375
376     echo "<tr>\n";
377     echo "  <td colspan=2>"; submit("add_contact", "Add"); echo "</td></tr>\n";
378     echo "</tr>\n";
379     echo "</table>\n";
380     end_form();
381   }
382
383   function show_add_new_contact_form() {
384     if (! check_admin(1)) return;
385
386     $q = new CityQuery;
387     $cities = $q->find();
388     if (! count($cities)) {
389       echo "<p>No <a href=\"/city\">cities</a>!</p>\n";
390       return;
391     }
392
393     form("noprint standout");
394     echo "<p>Add a new contact in <select name=\"city_id\">\n";
395     foreach ($cities as $city) {
396       option("city_id", $city->getId(), get_city_displayname($city));
397     }
398     echo "</select>";
399     submit("show_add_contact", "Proceed");
400     echo "</p>\n";
401     end_form();
402   }
403
404   function update_contact(&$contact, $area_id, $new = false) {
405     global $contact_roles, $parcel_sizes, $parcel_contents;
406
407     $role = 0;
408     for ($i = 0; $i < count($contact_roles); $i++) {
409       if ($_POST['role_' . $i] == "on") $role |= (1 << $i);
410     }
411
412     /* Staff can place orders. */
413     if ($role & (1 << 0)) $role |= (1 << 2);
414
415     $forename = $_POST['forename'];
416     $middle = $_POST['middle'];
417     $surname = $_POST['surname'];
418     $displayname = $_POST['displayname'];
419
420     if (! $forename && ! $surname) {
421       echo "<p>Must have either a forename or surname!</p>\n";
422       return false;
423     }
424     if ($middle && ! ($forename && $surname)) {
425       echo "<p>Must have both a forename or surname for middle name(s) to make sense!</p>\n";
426       return false;
427     }
428
429     if (! $displayname) {
430       $displayname = $forename;
431       if ($middle) $displayname .= " $middle";
432       if ($forename) $displayname .= " ";
433       $displayname .= $surname;
434       echo "<p>Display name will be $displayname.</p>\n";
435     }
436
437     /* Get address. */
438     $area_id = $_POST['area_id'];
439     $line = $_POST['address'];
440     $postcode = trim($_POST['postcode']);
441     if ($postcode) {
442       $postcode = format_postcode($_POST['postcode'], true);
443       if (! $postcode) return false;
444     }
445     $q = new AddressQuery;
446     /* XXX: Finding by area properly? */
447     $address = $q->filterByAreaId($area_id)->filterByLine($line)->filterByPostcode($postcode)->findOneOrCreate();
448     if ($address->isNew()) {
449       /* Changing address. */
450       //if (! $new)
451       /*
452         XXX: Check for other contacts at the old address.
453         Make this a new address if there are others, but
454         provide a link to update other contacts.
455       */
456       try {
457         $address->save();
458       }
459       catch (Exception $e) {
460         echo "<p>Error adding $line.</p>\n";
461         return false;
462       }
463     }
464
465     $telephone1 = $_POST['telephone1'];
466     $telephone2 = $_POST['telephone2'];
467     $email = $_POST['email'];
468     $parcel = $_POST['parcel_size'];
469     for ($i = count($parcel_sizes); $i < count($parcel_contents); $i++) {
470       if ($_POST['parcel_' . $i] == "on") $parcel |= (1 << $i);
471     }
472     $notes = $_POST['notes'];
473
474     $contact->setRole($role);
475     $contact->setForename($forename);
476     $contact->setMiddle($middle);
477     $contact->setSurname($surname);
478     $contact->setDisplayname($displayname);
479     $contact->setTelephone1($telephone1);
480     $contact->setTelephone2($telephone2);
481     $contact->setEmail($email);
482     $contact->setParcel($parcel);
483     $contact->setNotes($notes);
484     $contact->setAddressId($address->getId());
485
486     try {
487       $contact->save();
488     }
489     catch (Exception $e) {
490       if ($new) echo "<p>Error adding $displayname.</p>\n";
491       else echo "<p>Error updating $displayname.</p>\n";
492       return false;
493     }
494
495     return true;
496   }
497
498   function add_contact(&$name) {
499     if (! check_admin(1, "add a contact")) return;
500
501     $area_id = $_POST['area_id'];
502     if (! is_numeric($area_id)) {
503       echo "<p>Invalid area!</p>\n";
504       return false;
505     }
506
507     $area = get_area_by_id($area_id);
508     if (! $area) {
509       echo "<p>No such area!</p>\n";
510       return false;
511     }
512
513     $contact = new Contact;
514     if (! update_contact($contact, $area_id, true)) return false;
515     $name = $contact->getDisplayname();
516     return $contact->getId();
517   }
518
519   function confirm_delete_contact($name, $id = null, &$city_id = null) {
520     if (! check_admin(1, "delete a contact")) return;
521
522     if (isset($id)) $contact = get_contact_by_id($id);
523     else $contact = get_contact_by_name($name);
524     if (! $contact) return false;
525
526     echo "<h3>Confirm deletion</h3>\n";
527     echo "<p>You must confirm deletion of contact " . $contact->getDisplayname() . ": " . $contact->getDeleteLink(true) . "</p>\n";
528   }
529
530   function delete_contact($name, $id = null, &$city_id = null) {
531     if (! check_admin(1, "delete a contact")) return;
532
533     if (isset($id)) $contact = get_contact_by_id($id);
534     else $contact = get_contact_by_name($name);
535     if (! $contact) return false;
536
537     ///* Remember city ID for dropdown. */
538     //$city_id = $area->getCityId();
539
540     try {
541       $contact->delete();
542       echo "<p>Deleted contact.</p>\n";
543     }
544     catch (Exception $e) {
545       echo "<p>Error deleting $name!</p>\n";
546       return false;
547     }
548
549     return true;
550   }
551
552   function show_contact($name, &$id = null) {
553     if (isset($id)) $contact = get_contact_by_id($id);
554     else $contact = get_contact_by_name($name);
555     if (! $contact) return;
556
557     form();
558     show_contact_summary($contact, true);
559     echo ": ";
560     echo "\n</p>";
561
562     echo "<table>\n";
563     show_contact_form($contact);
564
565     if (check_admin(1)) {
566       echo "<tr>\n";
567       echo "  <td colspan=2>";
568       submit("update_contact", "Update");
569       echo "</td>\n";
570       echo "</tr>\n";
571     }
572
573     echo "</table>\n";
574     end_form();
575   }
576
577   /* /contact/in/area/Cambridge/1 */
578   if (count($parameters)) {
579     if ($parameters[0] == "in") {
580       switch ($parameters[1]) {
581         case "area":
582           $area_id = $parameters[3];
583           $_POST['area_id'] = $area_id;
584           $q = new AreaQuery;
585           $area = $q->findOneById($area_id);
586           $city = get_area_city($area);
587           if ($city) $city_id = $city->getId();
588           show_area_contacts($parameters[2], $area_id);
589         break;
590
591         case "city":
592           $city_id = $parameters[3];
593           $_POST['city_id'] = $city_id;
594           $q = new CityQuery;
595           $city = $q->findOneById($city_id);
596           show_city_contacts($parameters[2], $city_id);
597         break;
598       }
599     }
600     else if ($parameters[0] == "search") {
601       search_contacts(urldecode($parameters[1]));
602     }
603   }
604   list($name, $id, $args) = parse_parameters($parameters);
605   //echo "<p>$name($id) " . print_r($args, true) . "</p>\n";
606   if (count($args)) {
607     switch ($args[0]) {
608       case "delete":
609         confirm_delete_contact($name, $id);
610       break;
611
612       case "confirmdelete":
613         delete_contact($name, $id);
614       break;
615     }
616   }
617   else if (isset($name)) show_contact($name, $id);
618
619   show_contact_forms($city_id);
620   show_add_new_contact_form($city_id);
621
622 ?>