/[drupal]/contributions/modules/volunteer/volunteer.module
ViewVC logotype

Contents of /contributions/modules/volunteer/volunteer.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.58 - (show annotations) (download) (as text)
Tue May 16 20:22:37 2006 UTC (3 years, 6 months ago) by killes
Branch: MAIN
CVS Tags: HEAD
Changes since 1.57: +143 -117 lines
File MIME type: text/x-php
more 4.7 updates by Angie
1 <?php
2 // $Id: volunteer.module,v 1.57 2006/05/12 22:22:26 killes Exp $
3
4
5 /**
6 * Provides help information for the volunteer module.
7 */
8 function volunteer_help($section) {
9 switch($section) {
10 case 'admin/help#volunteer':
11 $output = '<p>'. t('Volunteer module helps you organize people for events. There is a managed email correspondence with the volunteer, as well as the ability to rate their volunteer performance at the end. It allows admins to further designate users as <em>volunteer coordinators</em> who can be designated as the contact person for volunteers for an event.') .'</p>';
12 $output .= '<p>'. t('This module now relies on the CiviCRM module to handle contact information for volunteers. The volunteer module is frequently used with the RSVP module to invite community members. The module allows for default settings, contact settings, message settings, and email settings.') .'</p>';
13 $output .= t('<p>You can</p>
14 <ul>
15 <li>administer default, contact, message and email settings at <a href="%admin-settings-volunteer">administer &gt;&gt; settings &gt;&gt; volunteer.</a></li>
16 <li>create an event at <a href="%node-add">create content &gt;&gt; event</a>.</li>
17 <li>volunteer for an event by clicking on the volunteer link below an event.</li>
18 <li>enable the calendar block for browsing events at <a href="%admin-block">administer >> block >> calendar for browing events</a>.</li>
19 <li>give user roles volunteer coordinate and volunteer maintain permissions at <a href="%admin-access">administer >> access control</a>.</li>
20 <li>see events that may allow volunteering at <a href="%event">events</a>.</li>
21 <li>rate volunteers for an event at events &gt;&gt; select an event &gt;&gt; volunteer admin &gt;&gt;<br />
22 Volunteer Status &gt;&gt; select a volunteer &gt;&gt; Avg. rating.</li>
23 <li>create a CiviCRM group for volunteers to be added to (when volunteering for an event) at <a href="%civicrm-group-add">CiviCRM &gt;&gt; Manage Groups &gt;&gt; New Group</a>.</li>
24 <li>create a CiviCRM profile&nbsp;for volunteers to register to (when volunteering for an event) at <a href="%civicrm-admin-uf-group">CiviCRM &gt;&gt; Administer CiviCRM &gt;&gt; CiviCRM Profile &gt;&gt; New CiviCRM Profile</a>.</li>
25 <li>select a CiviCRM group for volunteers to be added to (when volunteering for an event) at <a href="%admin-settings-volunteer">administer &gt;&gt; settings &gt;&gt; volunteer &gt;&gt; Contact Settings</a>.</li>
26 <li>select a CiviCRM profile form for volunteers to register to (when volunteering for an event) at <a href="%admin-settings-volunteer">administer &gt;&gt; settings &gt;&gt; volunteer &gt;&gt; Contact Settings</a>.</li>
27 <li>see a list of all contacts who have volunteered for events at CiviCRM &gt;&gt; Manage Groups &gt;&gt; select a group of volunteers &gt;&gt; Show Group Members.</li>
28 ', array('%admin-settings-volunteer' => url('admin/settings/volunteer'), '%node-add' => url('node/add'), '%admin-block' => url('admin/block'), '%admin-access' => url('admin/access'), '%event' => url('event'), '%civicrm-group-add' => url('civicrm/group/add?reset=1'), '%civicrm-admin-uf-group' => url('civicrm/admin/uf/group?action=add&amp;reset=1'))) .'</ul>';
29 $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%volunteer">Volunteer page</a>.', array('%volunteer' => 'http://www.drupal.org/handbook/modules/volunteer/')) .'</p>';
30 return $output;
31 case 'admin/modules#description':
32 return t('Provides volunteer functionality for events.');
33 case 'volunteer/overview':
34 return t('This page shows you all volunteers together with the events for which they volunteered and when they signed up.');
35 }
36 }
37
38 /**
39 * Allows the admin to set different defaults & settings for the module on the module config page
40 */
41 function volunteer_settings() {
42 $all_volunteer_coordinators = _volunteer_get_volunteer_coordinators();
43 $variables = _volunteer_message_vars();
44 $wildcards = implode(', ',array_keys($variables));
45
46 $form['default_settings'] = array(
47 '#type' => 'fieldset',
48 '#title' => t('Default Settings'),
49 );
50 $form['default_settings']['volunteer_event_default'] = array(
51 '#type' => 'radios',
52 '#title' => t('Events volunteer-enabled by default'),
53 '#default_value' => variable_get('volunteer_event_default',1),
54 '#options' => array('no','yes'),
55 '#description' => t('Should events be volunteer-enabled (with these settings) by default?'),
56 );
57 $form['default_settings']['volunteer_wanted'] = array(
58 '#type' => 'textfield',
59 '#title' => t('Default number of volunteers wanted'),
60 '#default_value' => variable_get('volunteer_wanted', '2'),
61 '#size' => 3,
62 '#maxlength' => 6,
63 '#description' => t('This will be the default number of volunteers entered into new events.'),
64 );
65 $form['default_settings']['volunteer_coordinator'] = array(
66 '#type' => 'select',
67 '#title' => t('Default volunteer coordinator'),
68 '#default_value' => variable_get('volunteer_coordinator', ''),
69 '#options' => $all_volunteer_coordinators,
70 '#description' => t('Select the default volunteer to coordinate events'),
71 '#extra' => 0,
72 '#multiple' => FALSE,
73 '#required' => TRUE,
74 );
75
76 if (module_exist('civicrm')) {
77 civicrm_initialize(TRUE);
78 $contact_groups = array();
79 db_set_active('civicrm');
80 $groups = crm_get_groups(array('is_active' => 1));
81 db_set_active();
82 $group_form = '';
83 if (is_array($groups) && count($groups)) {
84 foreach ($groups as $group) {
85 $contact_sources[$group->id] = $group->title;
86 }
87 $form['contact_settings'] = array(
88 '#type' => 'fieldset',
89 '#title' => t('Contact Settings'),
90 );
91 $form['contact_settings']['volunteer_contact_source'] = array(
92 '#type' => 'select',
93 '#title' => t('Add/Update contacts to CiviCRM group when volunteering'),
94 '#default_value' => variable_get('volunteer_contact_source',''),
95 '#options' => $contact_sources,
96 '#description' => t('Select a CiviCRM group for users to be added or updated to as contacts when volunteering for an event. You can <a href="%url">add</a> a volunteer specific group. You can later see a list of all users that volunteered by selecting the chosen group from <a href="%search">this page</a> and clicking Show Group Members.', array('%url' => url('civicrm/group/add'), '%search' => url('civicrm/group'))),
97 '#extra' => 0,
98 '#multiple' => FALSE,
99 '#required' => TRUE,
100 );
101 }
102 else {
103 drupal_set_message(t('You need to <a href="%url">define</a> a CiviCRM group for use with volunteer module.', array('%url' => url('civicrm/group/add'))), 'error');
104 }
105 // CiviCRM: Get all allowed fields for 'individual' type contact.
106 $forms = array();
107 db_set_active('civicrm');
108 $ufGroups = crm_uf_get_profile_groups();
109 db_set_active();
110 if (is_array($ufGroups) && count($ufGroups)) {
111 $correct_email_exists = FALSE;
112 $email_exists = FALSE;
113 db_set_active('civicrm');
114 foreach ($ufGroups as $id => $title) {
115 $profile = crm_uf_get_profile_fields($id, TRUE);
116 $has_correct_email = FALSE;
117 foreach ($profile as $field) {
118 if (strpos($field['name'], 'email') === 0) {
119 $email_exists = TRUE;
120 if ($field['is_required'] == 1) {
121 $has_correct_email = TRUE;
122 $correct_email_exists = TRUE;
123 }
124 }
125 }
126 if ($has_correct_email) {
127 $forms[$id] = $title;
128 }
129 }
130 db_set_active();
131 if ($email_exists) {
132 if ($correct_email_exists) {
133 $form['contact_settings']['volunteer_form'] = array(
134 '#type' => 'select',
135 '#title' => t('CiviCRM profile form for volunteers'),
136 '#default_value' => variable_get('volunteer_form', ''),
137 '#options' => $forms,
138 '#description' => t('Select a CiviCRM Profile form for volunteers. Users will fill out required fields in this form when volunteering for an event. You can <a href="%url">add</a> a volunteer specific profile. The profile needs at least an email field and it needs to be set to "Required" and "Active".', array('%url' => url('civicrm/admin/uf/group'))),
139 '#extra' => 0,
140 '#multiple' => FALSE,
141 '#required' => TRUE,
142 );
143 }
144 else {
145 drupal_set_message(t('You need to <a href="%url">define</a> a CiviCRM profile for use with the volunteer module. The profile needs at least an email field and it needs to be set to "Required" and "Active". A profile with an email field could be found, but it does not have the correct settings. ', array('%url' => url('civicrm/admin/uf/group'))), 'error');
146 }
147 }
148 else {
149 drupal_set_message(t('You need to <a href="%url">define</a> a CiviCRM profile for use with the volunteer module. The profile needs at least an email field and it needs to be set to "Required" and "Active". No profile with an email field could be found.', array('%url' => url('civicrm/admin/uf/group'))), 'error');
150 }
151 }
152 else {
153 drupal_set_message(t('You need to <a href="%url">define</a> a CiviCRM profile for use with the volunteer module. The profile needs at least an email field and it needs to be set to "Required" and "Active".', array('%url' => url('civicrm/admin/uf/group'))), 'error');
154 }
155 }
156 else {
157 drupal_set_message(t('You need to enable the CiviCRM module in order to use the volunteer module.'), 'error');
158 }
159 $form['message_settings'] = array(
160 '#type' => 'fieldset',
161 '#title' => t('Message Settings'),
162 );
163 $form['message_settings']['volunteer_message_sign_up'] = array(
164 '#type' => 'textarea',
165 '#title' => t('Volunteer message'),
166 '#default_value' => variable_get('volunteer_message_sign_up', t('Fill out this quick form to volunteer for this event.')),
167 '#cols' => 75,
168 '#rows' => 5,
169 '#description' => t('Message to display when volunteers are signing up'),
170 );
171 $form['message_settings']['volunteer_message_thanks'] = array(
172 '#type' => 'textarea',
173 '#title' => t('Volunteer thank you message'),
174 '#default_value' => variable_get('volunteer_message_thanks', t('Thank you for offering to volunteer! Someone will be in touch with you shortly with details.')),
175 '#cols' => 75,
176 '#rows' => 5,
177 '#description' => t('Message to display to user after they have signed up to volunteer for an event.'),
178 );
179 $form['message_settings']['wildcards'] = array(
180 '#value' => '<p>'. t("NOTE - wildcards are <b>inactive</b> for these messages.") .'</p>',
181 );
182
183 $form['email_settings'] = array(
184 '#type' => 'fieldset',
185 '#title' => t('Email Settings'),
186 );
187 $form['email_settings']['volunteer_default_from'] = array(
188 '#type' => 'textfield',
189 '#title' => t('Default email from address for automailer'),
190 '#default_value' => variable_get('volunteer_default_from', 'VOLUNTEER_AUTO_MAILER'),
191 '#size' => 30,
192 '#maxlength' => 75,
193 '#description' => t("This is the from address that the coordinator's will see when they get automated messages from the module"),
194 );
195 $form['email_settings']['volunteer_message_approve'] = array(
196 '#type' => 'textarea',
197 '#title' => t('Default message for approval'),
198 '#default_value' => variable_get('volunteer_message_approve', t(_volunteer_default_messages('approve'))),
199 '#cols' => 75,
200 '#rows' => 5,
201 '#description' => t('Default message sent to users when they have been approved to volunteer for an event'),
202 );
203 $form['email_settings']['volunteer_message_denial'] = array(
204 '#type' => 'textarea',
205 '#title' => t('Default message for denial'),
206 '#default_value' => variable_get('volunteer_message_deny', t(_volunteer_default_messages('deny'))),
207 '#cols' => 75,
208 '#rows' => 5,
209 '#description' => t('Default message sent to users when they have been denied to volunteer for an event'),
210 );
211 $form['email_settings']['volunteer_message_wait'] = array(
212 '#type' => 'textarea',
213 '#title' => t('Default message for waiting list'),
214 '#default_value' => variable_get('volunteer_message_wait', t(_volunteer_default_messages('wait'))),
215 '#cols' => 75,
216 '#rows' => 5,
217 '#description' => t('Default message sent to users to notify them that they have been put on the wait list for an event'),
218 );
219 $form['email_settings']['volunteer_message_reminder'] = array(
220 '#type' => 'textarea',
221 '#title' => t('Default message for reminder'),
222 '#default_value' => variable_get('volunteer_message_reminder', t(_volunteer_default_messages('reminder'))),
223 '#cols' => 75,
224 '#rows' => 5,
225 '#description' => t('Default message sent to users to remind them of event 24 hours before hand'),
226 );
227 $form['email_settings']['volunteer_message_follow_up'] = array(
228 '#type' => 'textarea',
229 '#title' => t('Default message for follow-up'),
230 '#default_value' => variable_get('volunteer_message_follow_up', t(_volunteer_default_messages('follow_up'))),
231 '#cols' => 75,
232 '#rows' => 5,
233 '#description' => t('Default message sent to users 24 hours after the event'),
234 );
235 $form['email_settings']['wildcards'] = array(
236 '#value' => '<p>'. t("FYI - The following 'Wildcards' can be used in messages to insert live data about the volunteer event: $wildcards") .'</p>',
237 );
238
239 return $form;
240 }
241
242 /**
243 * Provides the volunteer permission information for the drupal system.
244 *
245 * @ingroup volunteer_core
246 */
247 function volunteer_perm() {
248 return array('volunteer coordinate');
249 }
250
251 /**
252 * Provides the volunteer link information for the drupal system.
253 *
254 * @ingroup volunteer_core
255 */
256 function volunteer_link($type, $node = 0, $main = 0) {
257 switch ($type) {
258 case 'node' :
259 if (module_invoke('event', 'is_enabled', $node->type)) {
260 if (volunteer_event_is_volunteer($node)) {
261 if (volunteer_count($node->nid) >= $node->volunteer['wanted']) {
262 $links[] = l(t('volunteer (full)'), "volunteer/volunteer/$node->nid/wait_list", array("title" => t('you can volunteer for this event, but the event is already full.')) );
263 }
264 else {
265 $links[] = l(t('volunteer'), "volunteer/volunteer/$node->nid",
266 array("title" => t('volunteer for this event')) );
267 }
268 }
269 }
270 break;
271 case 'event_node_table' :
272 case 'event_node_day' :
273 case 'event_node_week' :
274 case 'event_node_month' :
275 if (volunteer_event_is_volunteer($node)) {
276 if (volunteer_count($node->nid) >= $node->volunteer['wanted']) {
277 $links[] = theme('volunteer_calendar_link', 'waitlist', $node->nid);
278 }
279 else {
280 $links[] = theme('volunteer_calendar_link', 'volunteer', $node->nid);
281 }
282 }
283 break;
284 }
285 return $links ? $links : array();
286 }
287
288
289 /**
290 * Implementation of hook_menu().
291 *
292 * @ingroup volunteer_core
293 */
294 function volunteer_menu($may_cache) {
295 $items = array();
296
297 if (function_exists('civicrm_initialize')) {
298 if ($may_cache) {
299 $items[] = array('path' => 'volunteer/question_coordinator', 'title' => t('volunteer approve'),
300 'callback' => 'volunteer_question_coordinator',
301 'type' => MENU_CALLBACK,
302 'access' => user_access('volunteer coordinate'));
303 $items[] = array('path' => 'volunteer/volunteer', 'title' => t('volunteer'),
304 'callback' => 'volunteer_volunteer',
305 'type' => MENU_CALLBACK,
306 'access' => user_access('access content'));
307
308 $items[] = array('path' => 'volunteer/rating', 'title' => t('volunteer rate'),
309 'callback' => 'volunteer_rate',
310 'type' => MENU_CALLBACK,
311 'access' => user_access('volunteer coordinate'));
312 $items[] = array('path' => 'volunteer', 'title' => t('volunteer overview'),
313 'callback' => 'volunteer_overview',
314 'access' => user_access('volunteer coordinate'));
315 }
316 elseif (arg(0)=='node' && is_numeric(arg(1))) {
317 $node = node_load(arg(1));
318 if (function_exists('event_is_enabled') && event_is_enabled($node->type)) {
319 $items[] = array('path' => 'node/'. arg(1) .'/volunteer', 'title' => t('volunteer admin'),
320 'callback' => 'volunteer_form', 'access' => user_access('volunteer coordinate'),
321 'type' => MENU_LOCAL_TASK, 'weight' => 10);
322 }
323 }
324 }
325
326 return $items;
327 }
328
329 /**
330 * Implementation of hook_civicrm_post
331 * Delete contacts from volunteer dataset that get deleted in CiviCRM
332 */
333 function volunteer_civicrm_post( $op, $objectName, $objectId, $objectRef ) {
334 if ($objectName == 'Individual') {
335 switch ($op) {
336 case 'delete':
337 db_query('DELETE FROM {volunteer_contact_event} WHERE cid = %d', $objectId);
338 default:
339 break;
340 }
341 }
342 }
343
344 /**
345 * Menu callback,
346 */
347 function volunteer_overview() {
348 $sql = 'SELECT v.cid, v.nid, v.timestamp, v.stage, n.title FROM {volunteer_contact_event} v INNER JOIN {node} n ON n.nid = v.nid ';
349 $header = array(
350 array('data' => t('Name')),
351 array('data' => t('Event'), 'field' => 'n.title'),
352 array('data' => t('Date'), 'field' => 'v.timestamp', 'sort' => 'desc'),
353 array('data' => t('Stage'), 'field' => 'v.stage')
354 );
355 $sql .= tablesort_sql($header);
356 $result = pager_query($sql, 50);
357
358 $rows = array();
359 while ($data = db_fetch_object($result)) {
360 switch ($data->stage) {
361 case '1':
362 $stage = l(t('Wait List'), "volunteer/question_coordinator/$data->cid/$data->nid");
363 break;
364 case '2':
365 $stage = l(t('Waiting Approval'), "volunteer/question_coordinator/$data->cid/$data->nid");
366 break;
367 case '3':
368 $stage = l(t('Approved'), "volunteer/question_coordinator/$data->cid/$data->nid");
369 break;
370 case '4':
371 $stage = l(t('Reminded'), "volunteer/question_coordinator/$data->cid/$data->nid");
372 break;
373 case '5':
374 $stage = l(t('Follow Up'), "volunteer/question_coordinator/$data->cid/$data->nid");
375 }
376 $rows[] = array($data->cid,
377 l($data->title, "node/$data->nid", array('title' => t('view this event'))),
378 format_date($data->timestamp, 'medium'),
379 $stage
380 );
381 }
382
383 $new_rows = array();
384 civicrm_initialize(TRUE);
385 foreach ($rows as $row) {
386 db_set_active('civicrm');
387 $contact = crm_get_contact(array('contact_id' => $row[0]));
388 db_set_active();
389 $row[0] = (isset($contact->display_name) && strlen($contact->display_name)) ? $contact->display_name : $contact->location[1]->email[1]->email;
390 $new_rows[] = $row;
391 }
392
393 if ($pager = theme('pager', NULL, 50, 0)) {
394 $new_rows[] = array(array('data' => $pager, 'colspan' => '3'));
395 }
396
397 if (!$new_rows) {
398 $new_rows[] = array(array('data' => t('Nobody volunteered yet.'), 'colspan' => '3'));
399 }
400
401 drupal_set_title(t('Volunteer Overview'));
402 print theme('page', theme('table', $header, $new_rows));
403 }
404
405 function volunteer_question_coordinator($cid, $nid) {
406 civicrm_initialize(TRUE);
407
408 if(isset($_POST['op'])) {
409 switch ($_POST['op']) {
410 case t('Approve'):
411 $form = volunteer_approve_volunteer($cid, $nid);
412 break;
413 case t('Deny'):
414 volunteer_deny_volunteer($cid, $nid);
415 drupal_set_message(t('Volunteer denied'));
416 break;
417 case t('Wait List'):
418 volunteer_wait_volunteer($cid, $nid);
419 drupal_set_message(t('Volunteer set to wait list'));
420 break;
421 case t('Overload'):
422 volunteer_approve_volunteer($cid, $nid);
423 break;
424 }
425 if(!isset($form)) {
426 drupal_goto('node/'.$nid.'/volunteer');
427 }
428 }
429 else {
430 $rating = volunteer_get_rating($cid);
431 $form['average'] = array(
432 '#type' => 'item',
433 '#title' => t('Avg. Rating'),
434 '#default_value' => l($rating['average'], "volunteer/rating/$cid/$nid"),
435 );
436 $form_title = variable_get('volunteer_form', '');
437 db_set_active('civicrm');
438 $title = crm_uf_get_profile_title($form_title);
439 $form['profile'] = array(
440 '#value' => crm_uf_get_profile_html( $cid, $title, CRM_CORE_ACTION_VIEW, false, true ),
441 );
442 db_set_active();
443 $form['approve'] = array(
444 '#type' => 'submit',
445 '#value' => t('Approve'),
446 );
447 $form['wait_list'] = array(
448 '#type' => 'submit',
449 '#value' => t('Wait List'),
450 );
451 $form['deny'] = array(
452 '#type' => 'submit',
453 '#value' => t('Deny'),
454 );
455 $form['cancel'] = array(
456 '#type' => 'submit',
457 '#value' => t('Cancel'),
458 );
459 }
460 drupal_set_title(t('Volunteer Status'));
461 return drupal_get_form('volunteer_question_coordinator', $form);
462 }
463
464 /********************************/
465
466 /**
467 * Check to see if a user is already signed up
468 * for the event in question
469 *
470 * @param int $nid node_id for the event
471 * @param int $contact_id CiviCRM contact_id for the user
472 */
473
474 function volunteer_has_user_volunteered($nid, $contact_id){
475 $sql = 'SELECT cid FROM {volunteer_contact_event} WHERE cid = %d AND nid = %d';
476 return db_num_rows(db_query($sql, $contact_id, $nid)) > 0;
477 }
478
479 function volunteer_volunteer($nid, $wait_list = NULL) {
480 global $user;
481 // TODO: convert to validate/submit model for better readability
482 // webchick: I tried to convert this, but because the entire form, including the submit button,
483 // is generated from civicrm, I can't seem to get any Drupalish FAPI stuff to work with it...
484 $edit = isset($_POST['edit']) ? $_POST['edit'] : array();
485 $op = isset($_POST['op']) ? $_POST['op'] : array();
486
487 civicrm_initialize(TRUE);
488 // Not a Drupal form, so we need to let CRM have a crack
489 //at it before we do
490 $crm_params = array(); //user data if any
491 $crm_form = volunteer_volunteer_form($nid, $crm_params);
492 // check if the user has already signed up
493 $contact_id = NULL;
494 if ($crm_params['contact_id']) {
495 //CRM knows about this user. Is he/she signed up?
496 $contact_id = $crm_params['contact_id'];
497 // NOTE: I would put this into a #pre_render function, but we're not allowed
498 // to pass in additional arguments ($contact_id) so I can't.
499 if (volunteer_has_user_volunteered($nid, $contact_id)) {
500 drupal_set_message(t('You have already signed up for this event.'), 'error');
501 drupal_goto('node/'. $nid);
502 }
503 }
504 // the form has been submitted
505 if (count($edit) && $contact_id && !form_get_errors()) {
506 // Go ahead and save/update and proceed
507 //insert into volunteer_contact_event
508 db_set_active('civicrm');
509 $contact = crm_get_contact(array('contact_id' => $contact_id));
510 db_set_active();
511 $group_id = variable_get('volunteer_contact_source', 1);
512 db_set_active('civicrm');
513 $group = crm_get_groups(array('id' => $group_id));
514 db_set_active();
515 $group = $group[0];
516 db_set_active('civicrm');
517 $contact_array = array($contact);
518 crm_add_group_contacts($group, $contact_array);
519 db_set_active();
520 $stage = $wait_list ? 1 : 2;
521 db_query('INSERT INTO {volunteer_contact_event} (cid, nid, timestamp, stage) VALUES (%d, %d, %d, %d)', $contact_id, $nid, time(), $stage);
522 volunteer_mail($contact_id, $nid, 'new_volunteer');
523 drupal_set_message(variable_get('volunteer_message_thanks', t('Thank you for offering to volunteer! Someone will be in touch with you shortly with details.')));
524 drupal_goto('node/'. $nid);
525 }
526 else {
527 // display form
528 $event = node_load($nid);
529 $form['#prefix'] = '<p>'. variable_get('volunteer_message_sign_up', t('Fill out this quick form to volunteer for this event.')) .'</p>';
530 $form['crm_form'] = array(
531 '#value' => $crm_form,
532 );
533 $form['placeholder'] = array(
534 '#value' => theme('box', t('Volunteer for %event', array('%event' => theme('placeholder', $event->title))), $output),
535 );
536 }
537 drupal_set_title('Volunteering');
538 return drupal_get_form('volunteer_volunteer', $form);
539 }
540
541 /********************************/
542
543
544 /**
545 * Utility function to extract CRM email data from POST
546 * This should probably move into civicrm.module...
547 */
548 function _volunteer_get_email(){
549 // TODO: Check if this still works/ is needed with 4.7.
550 if(isset($_POST['op'])){
551 foreach($_POST as $key => $val){
552 if(strncmp($key, 'email', 5) == 0){
553 //We only need 1 email
554 return $val;
555 }
556 }
557 }
558 return '';
559 }
560
561
562 function volunteer_volunteer_form($nid, &$edit) {
563 // TODO: convert to validate/submit model for better radability
564 global $user;
565 //why factor this? Because the HTML 1.0 designers did not
566 //care about I18n...
567 $submit_value = t('Volunteer');
568 //Preliminaries for getting CRM parameters
569 $op = $_POST['op'];
570 $form_title = variable_get('volunteer_form', '');
571 db_set_active('civicrm');
572 $title = crm_uf_get_profile_title($form_title);
573 $reset = $op ? FALSE : TRUE;
574 $register = FALSE; //always FALSE in 1.3 and later
575 $userID = $user->uid ? crm_uf_get_match_id( $user->uid ) : NULL;
576 $action = $userID ? CRM_CORE_ACTION_UPDATE : CRM_CORE_ACTION_ADD;
577
578 //The following call not only generates HTML, it also
579 //interacts with the CRM data store:
580 $crm_form = crm_uf_get_profile_html( $userID, $title, $action, $register, $reset );
581 db_set_active();
582 if ( !$userID && $op) {
583 //if everything went well, we have one now
584 $email = $user->mail ? $user->mail : _volunteer_get_email();
585 $params = array('email' => $email);
586 //$contact = crm_get_contact($params);
587 db_set_active('civicrm');
588 list($values, $options) = crm_contact_search($params);
589 db_set_active();
590 }
591 elseif ($userID) {
592 //Fix for 51833
593 $params = array('id' => $userID);
594 db_set_active('civicrm');
595 list($values, $options) = crm_contact_search($params);
596 db_set_active();
597 }
598
599 if ($values && $op == $submit_value) {
600 //We've already done what was needed with CRM
601 //(?? what if there was an error), so do our business
602 //with the Drupal side code:
603 $param_list = array_values($values);
604 $edit = $param_list[0];
605 //Do we need HTML in this case?
606 //I think not.
607 //Redirects should go here, most likely
608 return '';
609 }
610 else {
611 //Either an error occurred, or we haven't
612 //done anything yet.
613 $form['#action'] = url("volunteer/volunteer/$nid");
614 $form['#method'] = 'post';
615 $form['crm_form'] = array(
616 '#value' => $crm_form,
617 );
618 $form['submit'] = array(
619 '#type' => 'submit',
620 '#value' => t('Volunteer'),
621 );
622
623 return drupal_get_form('volunteer_form_form', $form);
624
625 /* // We do not use Forms API here, because CiviCRM
626 // ouputs HTML for the form
627 $output .= '<form action="'. $url. '" method="post">';
628 $output .= ;
629 $output .= '<input type="submit" value="'. t('Volunteer') .'"/>';
630 $output .= '</form>';
631
632 return $output;
633 */
634
635 }
636 }
637
638
639 /********************************/
640
641 function volunteer_rate($cid, $nid = 0) {
642 civicrm_initialize(TRUE);
643
644 db_set_active('civicrm');
645 $contact = crm_get_contact(array('contact_id' => $cid));
646 db_set_active();
647 $mail = $contact->location[1]->email[1]->email;
648 if ($nid) {
649 // rate a specific event
650 $form['#method'] = 'post';
651 $form['#action'] = url("volunteer/rating/$cid/$nid");
652 $form['#submit']['volunteer_rate_submit'] = array($cid, $nid);
653
654 $event = db_fetch_object(db_query('SELECT title FROM {node} WHERE nid = %d', $nid));
655 $volunteer_contact_event = db_fetch_object(db_query('SELECT * FROM {volunteer_contact_event} WHERE cid = %d AND nid = %d', $cid, $nid));
656 $rating_list = array(1 => 1,
657 2 => 2,
658 3 => 3,
659 4 => 4,
660 5 => 5);
661 $form['rate'] = array(
662 '#value' => t('Rate') .' '. "<a href=\"mailto:$mail\">$mail</a>". '\'s performance at: <b>' . $event->title . '</b>.',
663 );
664 $form[$event->title] = array(
665 '#type' => 'fieldset',
666 '#title' => $event->title,
667 );
668 $form[$event->title]['rating'] = array(
669 '#type' => 'select',
670 '#title' => t('Rating'),
671 '#default_value' => $volunteer_contact_event->rating,
672 '#options' => $rating_list,
673 '#description' => '1 being the worst and 5 being the best.',
674 );
675 $form[$event->title]['comments'] = array(
676 '#type' => 'textarea',
677 '#title' => t('Comments'),
678 '#default_value' => $volunteer_contact_event->comments,
679 '#cols' => 70,
680 '#rows' => 5,
681 '#description' => 'Leave comment specific to this event here',
682 );
683 $form[$event->title]['submit'] = array(
684 '#type' => 'submit',
685 '#value' => t('Submit'),
686 );
687 }
688 // output view of past ratings
689 $data = volunteer_get_rating($cid);
690 if (count($data['events'])) {
691 $header = array('Event', 'Rating', 'Coordinator', 'Comments');
692 $form['other_events'] = array(
693 '#type' => 'fieldset',
694 '#title' => t('Other Events which %name has volunteered for:', array('%name'=>$mail)),
695 );
696 $form['other_events']['events'] = array(
697 '#value' => theme('table', $header, $data['events']),
698 );
699 }
700
701 return drupal_get_form('volunteer_rate', $form);
702 }
703
704 function volunteer_rate_submit($form_id, $form_values, $cid, $nid) {
705 db_query("UPDATE {volunteer_contact_event} SET comments = '%s', rating = %d WHERE cid = %d AND nid = %d", $form_values['comments'], $form_values['rating'], $cid, $nid);
706 drupal_set_message(t('Volunteer rating updated'));
707 drupal_goto("node/$nid/volunteer");
708 }
709
710
711 /**********************************/
712 // Needs to be rewritten to use the CiviCRM activity history.
713 function volunteer_get_rating($cid) {
714 $result = db_query("SELECT v.*, n.title FROM {volunteer_contact_event} v LEFT JOIN {node} n ON v.nid = n.nid WHERE v.cid = %d and v.rating is NOT NULL", $cid); //data for all other events
715 $count = 0;
716 $rating_total = 0;
717
718 $data['events'] = array();
719 while($rating = db_fetch_object($result)) {
720 $ratings = array();
721 $coordinator = db_fetch_object(db_query('SELECT u.name, u.uid FROM {volunteer} v INNER JOIN {users} u ON v.uid = u.uid WHERE nid = %d', $rating->nid));
722 $rating_total = $rating_total + $rating->rating;
723 $ratings[] = l(t($rating->title), "node/$rating->nid");
724 $ratings[] = l(t($rating->rating ), "volunteer/rating/$cid/$rating->nid");
725 $ratings[] = l(t($coordinator->name), "node/$coordinator->uid");
726 if (strlen($rating->comments) > 25) {
727 $comments = l(t(substr($rating->comments, 0, 25) ."..."), "volunteer/rating/$cid/$rating->nid");
728 }
729 else{
730 $comments = l(t($rating->comments), "volunteer/rating/$cid/$rating->nid");
731 }
732 $ratings[] = $comments;
733 $data['events'][] = $ratings;
734 $count++;
735 }
736 if($count) {
737 $data['average'] = t('%ratio over %total events.', array('%ratio' => ($rating_total/$count), '%total' => $count));
738 }
739 else {
740 $data['average'] = t('Not Yet Rated');
741 }
742
743 return $data;
744 }
745
746 /***************************/
747
748 function volunteer_cron() {
749 //send reminder and set stage
750 $time = time();
751 $twodays = $time + (60*60*48);
752
753 $result = db_query('SELECT c.nid, c.cid FROM {volunteer_contact_event} c INNER JOIN {event} e ON e.nid = c.nid WHERE e.event_start > %d AND e.event_start < %d AND c.stage = %d', $time, $twodays, 3);
754 while($pairs = db_fetch_object($result)) {
755 volunteer_mail($pairs->cid, $pairs->nid, 'reminder');
756 db_query('UPDATE {volunteer_contact_event} set stage = 4 WHERE cid = %d AND nid = %d', $pairs->cid, $pairs->nid);
757 }
758
759 //send follow-up and set stage
760 $result = db_query('SELECT c.nid, c.cid FROM {volunteer_contact_event} c INNER JOIN {event} e ON e.nid = c.nid WHERE e.event_end < %d AND c.stage = %d', $time, 4);
761 while($pairs = db_fetch_object($result)) {
762 volunteer_mail($pairs->cid, $pairs->nid, 'follow_up');
763 db_query('UPDATE {volunteer_contact_event} set stage = 5 WHERE cid = %d AND nid = %d', $pairs->cid, $pairs->nid);
764 }
765 }
766
767 /*************************/
768
769 function volunteer_mail($cid, $nid, $message) {
770 global $base_url;
771
772 $default_from = variable_get('volunteer_default_from', 'VOLUNTEER_AUTO_MAILER');
773
774 $vcid = db_fetch_object(db_query('SELECT uid FROM {volunteer} v WHERE nid = %d', $nid));
775 $coordinator = user_load(array('uid'=>$vcid->uid));
776
777 $event = node_load($nid);
778
779 db_set_active('civicrm');
780 $volunteer = crm_get_contact(array('contact_id' => $cid));
781 db_set_active();
782 $volunteer_data = volunteer_get_volunteers($nid, TRUE, $cid);
783 foreach($volunteer_data['data'][0] as $key => $field) {
784 $volstats .= $volunteer_data['header'][$key] . ': ' . $field ."\n";
785 }
786 $event_link = $base_url .'/'. url("node/$nid");
787
788 $variables = _volunteer_message_vars($event, $coordinator, $volunteer);
789 $variables['%volstats'] = $volstats;
790 switch ($message) {
791 case 'new_volunteer':
792 $subject = $subject = t("New volunteer for %event_title!", $variables);
793 $recipient = $coordinator->mail;
794 $message = t("%coordinator,\n\n%volunteer_mail has offered to work at %event_title. You can check the status of that event, see all available volunteers, and approve, deny or waitlist this one by clicking here:\n\n%event_link/volunteer\n\n%volstats", $variables);
795 $header = "From: $default_from\nX-Mailer: Drupal\nErrors-to: $coordinator->mail";
796 break;
797 case 'approve':
798 $subject = $subject = t("You've beeen approved for %event_title!", $variables);
799 $recipient = $volunteer->location[1]->email[1]->email;
800 $text = $event->volunteer['message_approve'] ? $event->volunteer['message_approve'] : variable_get('volunteer_message_approve',_volunteer_default_messages('approve'));
801 $message = t($text, $variables);
802 $header = 'From: '.t('%coordinator <%coordinator_mail>',$variables)."\nX-Mailer: Drupal\nErrors-to: $coordinator->mail";
803 break;
804 case 'deny':
805 $subject = $subject = t("%event_title was full. Sorry!", $variables);
806 $recipient = $volunteer->location[1]->email[1]->email;
807 $text = $event->volunteer['message_deny'] ? $event->volunteer['message_deny'] : variable_get('volunteer_message_deny',_volunteer_default_messages('deny'));
808 $message = t($text, $variables);
809 $header = 'From: '.t('%coordinator <%coordinator_mail>',$variables)."\nX-Mailer: Drupal\nErrors-to: $coordinator->mail";
810 break;
811 case 'wait':
812 $subject = $subject = t("You've been placed on the waiting list for %event_title", $variables);
813 $recipient = $volunteer->location[1]->email[1]->email;
814 $text = $event->volunteer['message_wait'] ? $event->volunteer['message_wait'] : variable_get('volunteer_message_wait',_volunteer_default_messages('wait'));
815 $message = t($text, $variables);
816 $header = 'From: '.t('%coordinator <%coordinator_mail>',$variables)."\nX-Mailer: Drupal\nErrors-to: $coordinator->mail";
817 break;
818 case 'reminder':
819 $subject = $subject = t("Reminder about volunteering for %event_title", $variables);
820 $recipient = $volunteer->location[1]->email[1]->email;
821 $text = $event->volunteer['message_reminder'] ? $event->volunteer['message_reminder'] : variable_get('volunteer_message_reminder',_volunteer_default_messages('reminder'));
822 $message = t($text, $variables);
823 $header = 'From: '.t('%coordinator <%coordinator_mail>',$variables)."\nX-Mailer: Drupal\nErrors-to: $coordinator->mail";
824 break;
825 case 'follow_up':
826 $subject = $subject = t("How was %event_title?", $variables);
827 $recipient = $volunteer->location[1]->email[1]->email;
828 $text = $event->volunteer['message_follow_up'] ? $event->volunteer['message_follow_up'] : variable_get('volunteer_message_follow_up',_volunteer_default_messages('follow_up'));
829 $message = t($text, $variables);
830 $header = 'From: '.t('%coordinator <%coordinator_mail>',$variables)."\nX-Mailer: Drupal\nErrors-to: $coordinator->mail";
831 break;
832 case 'created':
833 $message = "A new event has been added by $user->name, and you're the coordinator!\n\n%event_link";
834 $message .= "\n\nGood luck!\n-Mgmt";
835 $recipient = $coordinator->mail;
836 $subject = "New Event For You (from website)";
837 $header = "From: $default_from\nReply-to: $coordinator->mail\nX-Mailer: Drupal\nReturn-path: $coordinator->mail\nErrors-to: $coordinator->mail";
838 }
839
840 return user_mail($recipient, $subject, $message, $header);
841 }
842
843
844 /*
845 * @param $nid -> the relevant event node's nid
846 * @param $single if true get a specific contact whose contact ID is $cid
847 * $param $cid
848 * @return -> an array of arrays contact fields for each volunteer assocaited with the event and the header.
849 */
850 function volunteer_get_volunteers($nid, $single = TRUE, $cid = NULL) {
851 $data = array();
852
853 if ($single) {
854 $result = db_query('SELECT * FROM {volunteer_contact_event} WHERE nid = %d AND cid = %d', $nid, $cid);
855 }
856 else{
857 $result = db_query('SELECT * FROM {volunteer_contact_event} WHERE nid = %d ORDER BY stage DESC', $nid);
858 }
859 $form_title = variable_get('volunteer_form', '');
860 db_set_active('civicrm');
861 $header_fields = crm_uf_get_profile_fields($form_title);
862 db_set_active();
863 if (is_array($header_fields)) {
864 foreach($header_fields as $field) {
865 $header[$field['name']] = $field['title'];
866 }
867 }
868 else {
869 drupal_set_message(t('You need to <a href="%url">assign</a> a CiviCRM profile form for volunteer data collection.', array('%url' => url('admin/settings/volunteer'))), 'error');
870 }
871 if (!$single) {
872 $header['stage'] = t('Stage');
873 $header['rating'] = t('Avg. rating');
874 }
875 $data['header'] = $header;
876 while ($volunteer = db_fetch_object($result)) {
877 $contact_data = array();
878 db_set_active('civicrm');
879 $contact = crm_get_contact(array('contact_id' => $volunteer->cid));
880 db_set_active();
881 if (strtolower(get_class($contact)) != 'crm_contact_bao_contact') {
882 continue;
883 }
884 // TODO @ killes: This does not populate 'first name', 'last name', etc. properly.
885 // Can I refer to $contact['contact_type_object'] directly?
886 $contact_data = volunteer_get_properties($contact, $header);
887 if (!$single) {
888 switch ($volunteer->stage) {
889 case '1':
890 $contact_data['stage'] = l(t('Wait List'), "volunteer/question_coordinator/$volunteer->cid/$nid");
891 break;
892 case '2':
893 $contact_data['stage'] = l(t('Waiting Approval'), "volunteer/question_coordinator/$volunteer->cid/$nid");
894 break;
895 case '3':
896 $contact_data['stage'] = l(t('Approved'), "volunteer/question_coordinator/$volunteer->cid/$nid");
897 break;
898 case '4':
899 $contact_data['stage'] = l(t('Reminded'), "volunteer/question_coordinator/$volunteer->cid/$nid");
900 break;
901 case '5':
902 $contact_data['stage'] = t('Follow Up');
903 break;
904 }
905 $rating = volunteer_get_rating($volunteer->cid);
906 $contact_data['rating'] = l($rating['average'], "volunteer/rating/$volunteer->cid/$nid");
907 }
908 $data['data'][] = $contact_data;
909 }
910 return $data;
911 }
912
913 function volunteer_count ($nid) {
914 $result = db_fetch_object(db_query('SELECT count(cid) AS approved FROM {volunteer_contact_event} WHERE nid = %d AND stage > %d', $nid, 2));
915 return $result->approved;
916 }
917
918 function volunteer_check_overload($nid) {
919 $wanted = db_fetch_object(db_query('SELECT wanted FROM {volunteer} WHERE nid = %d', $nid));
920 return ($wanted->wanted <= volunteer_count($nid)?true:false);
921 }
922
923 function volunteer_wait_volunteer($cid, $nid) {
924 $result = db_fetch_object(db_query('SELECT stage FROM {volunteer_contact_event} WHERE cid = %d AND nid = %d', $cid, $nid));
925 if ($result->stage != 1) {
926 volunteer_mail($cid, $nid, 'wait');
927 }
928 db_query('UPDATE {volunteer_contact_event} SET stage = 1 WHERE cid = %d AND nid = %d', $cid, $nid);
929 }
930
931 function volunteer_approve_volunteer($cid, $nid) {
932 // TODO: convert to validate/submit model for better radability
933 if (!volunteer_check_overload($nid) || $_POST['op'] == 'Overload') {
934 db_query('UPDATE {volunteer_contact_event} SET stage = %d WHERE cid = %d AND nid = %d', 3, $cid, $nid);
935 volunteer_mail($cid, $nid,'approve');
936 drupal_set_message(t('Volunteer status approved'));
937 return NULL;
938 }
939 else {
940 drupal_set_message(t('Event overloaded'));
941 $form['overload'] = array(
942 '#type' => 'fieldset',
943 '#title' => t('Would you like to overload the event?'),
944 );
945 $form['cancel'] = array(
946 '#type' => 'submit',
947 '#value' => t('Cancel'),
948 );
949 $form['overload'] = array(
950 '#type' => 'submit',
951 '#value' => t('Overload'),
952 );
953 return drupal_get_form('overload_event', $form);
954 }
955 }
956
957 function volunteer_deny_volunteer($uid, $nid) {
958 volunteer_mail($uid, $nid, 'deny');
959 db_query('DELETE FROM {volunteer_contact_event} WHERE nid = %d AND cid = %d', $nid, $uid);
960 }
961
962 function volunteer_view_volunteers($node) {
963 $data = volunteer_get_volunteers($node->nid, FALSE);
964 if(count($data['data'])) {
965 $output = theme('table', $data['header'], $data['data']);
966 }
967
968 return $output;
969 }
970
971 function volunteer_initial_user_view($node) {
972 $output = '<h2>'. t('volunteers wanted: ') . $node->volunteer['wanted'] .'<br />'. t('volunteers found: ') . volunteer_count($node->nid) .'</h2>';
973
974 return $output;
975 }
976
977 function volunteer_event_is_volunteer($node) {
978 return ($node->volunteer['wanted'] >= 1);
979 }
980
981 function volunteer_nodeapi(&$node, $op, $arg1 = 0, $arg2 = 0) {
982 if (event_is_enabled($node->type)) {
983 switch ($op) {
984 case 'load':
985 $result = db_query('SELECT wanted, uid, message_approve, message_deny, message_wait, message_reminder, message_follow_up FROM {volunteer} WHERE nid = %d', $node->nid);
986 if (db_num_rows($result) > 0) {
987 $result = db_fetch_object($result);
988 $node->volunteer['wanted'] = $result->wanted;
989 $node->volunteer['coordinator'] = $result->uid;
990 $node->volunteer['message_approve'] = $result->message_approve;
991 $node->volunteer['message_deny'] = $result->message_deny;
992 $node->volunteer['message_wait'] = $result->message_wait;
993 $node->volunteer['message_reminder'] = $result->message_reminder;
994 $node->volunteer['message_follow_up'] = $result->message_follow_up;
995 }
996 break;
997 case 'insert':
998 if (variable_get('volunteer_event_default', 1)) {
999 $author = user_load(array('uid' => $node->uid));
1000 $coordinator = user_access('volunteer coordinate', $author) ? $node->uid : variable_get('volunteer_coordinator', 1);
1001 $result = db_query("INSERT INTO {volunteer} (nid, wanted, uid) VALUES (%d, %d, %d)", $node->nid, variable_get('volunteer_wanted',2), $coordinator);
1002 }
1003 break;
1004 case 'view':
1005 if (!$arg1 && (!$node->volunteer['wanted']) && user_access('volunteer coordinate')) {
1006 drupal_set_message('No volunteer options have been set for this event. Site visitors and users cannot volunteer. Click the "volunteer admin" tab to set up volunteering', 'error');
1007 }
1008 break;
1009 case 'delete':
1010 db_query('DELETE FROM {volunteer} WHERE nid = %d', $node->nid);
1011 db_query('DELETE FROM {volunteer_contact_event} WHERE nid = %d',