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