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

Contents of /contributions/modules/volunteer_timeslots/volunteer_timeslots.module

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


Revision 1.19 - (show annotations) (download) (as text)
Sat Feb 17 02:55:23 2007 UTC (2 years, 9 months ago) by pwolanin
Branch: MAIN
CVS Tags: DRUPAL-5--1-0, HEAD
Branch point for: DRUPAL-5
Changes since 1.18: +9 -3 lines
File MIME type: text/x-php
#106536 update hook_link for 5.x
1 <?php
2 // $Id: volunteer_timeslots.module,v 1.18 2007/02/17 02:13:50 pwolanin Exp $
3
4 /**
5 * @file
6 * Enables creation of an event where volunteers can sign up for particular time slots
7 */
8
9 /**
10 * Implementation of hook_help().
11 */
12 function volunteer_timeslots_help($section) {
13 switch ($section) {
14 case 'admin/settings/volunteer_timeslots':
15 return t('A node type representing an event with timeslots where users can sign up to volunteer');
16 }
17 }
18
19 /**
20 * Implementation of hook_node_info().
21 */
22 function volunteer_timeslots_node_info() {
23 return array('volunteer_timeslots' => array(
24 'name' => t('Event with volunteer timeslots'),
25 'module' => 'volunteer_timeslots',
26 'description' => t("A content type for signing up volunteers for an event.")));
27 }
28
29 /**
30 * Implementation of hook_perm().
31 */
32 function volunteer_timeslots_perm() {
33 return array('create volunteer events', 'edit own volunteer events', 'administer volunteer events');
34 }
35
36 /**
37 * menu callback to settings page.
38 */
39 function volunteer_timeslots_settings() {
40
41 $form['volunteer_timeslots_organizer_updates'] = array(
42 '#type' => 'checkbox',
43 '#title' => t("Allow each event's organizer(s) to edit the event"),
44 '#default_value' => variable_get('volunteer_timeslots_organizer_updates', TRUE),
45 '#description' => t('If set, every user designated as an organizer of a volunteer event can edit that node.'),
46 );
47
48 $form['volunteer_timeslots_author_manages'] = array(
49 '#type' => 'checkbox',
50 '#title' => t("Allow each event's author to manage (add and remove) volunteers for the event"),
51 '#default_value' => variable_get('volunteer_timeslots_author_manages', TRUE),
52 '#description' => t("If set, the node author has the same ability as the event's organizer(s) to add or remove volunteers on the schedule."),
53 );
54
55 $hours = array(
56 -100 => t('never'),
57 6*60 => t('!s hours', array('!s' => '6')),
58 12*60 => t('!s hours', array('!s' => '12')),
59 18*60 => t('!s hours', array('!s' => '18')),
60 24*60 => t('!s hours', array('!s' => '24')),
61 36*60 => t('!s hours', array('!s' => '36')),
62 48*60 => t('!s hours', array('!s' => '48')),
63 72*60 => t('!s hours', array('!s' => '72')),
64 );
65 $form['volunteer_timeslots_remind_time'] = array(
66 '#type' => 'select',
67 '#title' => t('Number of hours in advance to send event reminder e-mails'),
68 '#default_value' => variable_get('volunteer_timeslots_remind_time', 36*60),
69 '#options' => $hours,
70 '#description' => t('This sets the maximum possible time before an event that the reminder e-mail will be sent. The actual time the e-mail is set depnds upon when and how often cron.php is executed on your system. Choose %s to disable automatic e-mail reminders', array('%s' => t('never'))),
71 );
72 if (module_exists('profile')) {
73 $result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d ORDER BY category, weight', PROFILE_HIDDEN);
74 while ($field = db_fetch_object($result)) {
75 $options[$field->name] = $field->title;
76 }
77 $form['volunteer_timeslots_profile_fields'] = array (
78 '#type' => 'checkboxes',
79 '#title' => t('User profile fields to include in the volunteer list for organizers'),
80 '#default_value' => variable_get('volunteer_timeslots_profile_fields', array()),
81 '#options' => $options,
82 );
83 $form['array_filter'] = array('#type' => 'value', '#value' => TRUE);
84 }
85 else {
86 $form['volunteer_timeslots_profile_note'] = array (
87 '#value' => '<p>'. t('Note: if you enable the profile module, you will be able to select profile fields to show in the volunteer roster.').'</p>',);
88 }
89 return system_settings_form($form);
90 }
91
92
93
94 /**
95 * Implementation of hook_access().
96 */
97 function volunteer_timeslots_access($op, $node) {
98 global $user;
99
100 if ($op == 'create') {
101 return user_access('create volunteer events');
102 }
103 $delete_perm = (user_access('administer volunteer events') ||
104 (user_access('edit own volunteer events') && ($user->uid == $node->uid)));
105 if ($op == 'delete') {
106 if ($delete_perm) {
107 return TRUE;
108 }
109 }
110 if ($op == 'update') { //note- check against $node->validated work-around allows organizers to remove themselves from the list of organizers
111 if ($delete_perm ||
112 (variable_get('volunteer_timeslots_organizer_updates', TRUE) && (in_array($user->uid, $node->timeslots_organizers) || $node->validated))) {
113 return TRUE;
114 }
115 }
116 }
117
118 /**
119 * Implementation of hook_menu().
120 */
121 function volunteer_timeslots_menu($may_cache) {
122 $items = array();
123
124 if ($may_cache) {
125 $items[] = array(
126 'path' => 'admin/settings/volunteer_timeslots',
127 'title' => t('Event with volunteer timeslots'),
128 'description' => t('Configure the volunteer timeslots.'),
129 'callback' => 'drupal_get_form',
130 'callback arguments' => 'volunteer_timeslots_settings',
131 'access' => user_access('administer site configuration'),
132 );
133 $items[] = array(
134 'path' => 'multiuser/autocomplete',
135 'title' => t('multiuser autocomplete'),
136 'callback' => 'multiuser_autocomplete',
137 'access' => user_access('access user profiles'),
138 'type' => MENU_CALLBACK,
139 );
140 }
141 else {
142 drupal_add_css(drupal_get_path('module', 'volunteer_timeslots') .'/volunteer_timeslots.css', 'module');
143 }
144
145 return $items;
146 }
147
148 function multiuser_autocomplete($string) {
149 // The user enters a comma-separated list of usernames. We only autocomplete the last one.
150 $array = explode(',',$string);
151 // Fetch last username
152 $last = trim(array_pop($array));
153 if ($last != '') {
154 $prefix = count($array) ? implode(',', $array) .', ' : '';
155 $matches = array();
156 $result = db_query_range("SELECT name FROM {users} WHERE status = 1 AND LOWER(name) LIKE LOWER('%s%%')", $last, 0, 10);
157
158 while ($user = db_fetch_object($result)) {
159 $matches[$prefix. $user->name] = check_plain($user->name);
160 }
161 print drupal_to_js($matches);
162 exit();
163 }
164 }
165
166 function timeslots_node_form_validate($form_id, $form_values, $form) {
167 $names = explode(',', $form_values['timeslots_organizers']);
168 foreach($names as $n) { // username validation
169 $n = trim($n);
170 if (!user_load(array('name' => $n, 'status' => 1))) {
171 form_set_error('timeslots_organizers', t('The username %name does not exist or is blocked.', array ('%name' => $n)));
172 }
173 }
174 }
175
176 /**
177 * Implementation of hook_form().
178 */
179 function volunteer_timeslots_form(&$node) {
180 global $user;
181 $form['title'] = array(
182 '#type' => 'textfield',
183 '#title' => t('Title'),
184 '#required' => TRUE,
185 '#default_value' => $node->title,
186 '#weight' => -25,
187 '#description' => t('A brief title for your event for the calendar listing.'),
188 );
189 if (variable_get('event_nodeapi_volunteer_timeslots', 'never') == 'never') {
190 $form['message'] = array(
191 '#value' => t("You must have the event module enabled and make sure the type '%type' to selected to appear in the events calendar.", array( '%type' => t('Event with volunteer timeslots'))),
192 );
193 }
194 else {
195 $form['#validate']['timeslots_node_form_validate'] = array();
196 $form['timeslots'] = array(
197 '#type' => 'fieldset',
198 '#title' => t('Set up the timeslots for volunteers and the organizer for this event'),
199 '#collapsible' => TRUE,
200 '#collapsed' => FALSE,
201 '#weight' => -10,
202 );
203 if (!isset($node->timeslot_data)) {
204 $node->timeslot_data = array();
205 }
206
207 if (!empty($node->timeslots_organizers)) {
208 $names = array();
209 foreach ($node->timeslots_organizers as $uid) {
210 $account = user_load(array('uid' => $uid));
211 $names[] = $account->name;
212 }
213 $org_names = implode(', ',$names);
214 }
215 else {
216 $org_names = '';
217 }
218
219 $form['timeslots']['timeslots_organizers'] = array(
220 '#type' => 'textfield',
221 '#maxlength' => 255,
222 '#autocomplete_path' => 'multiuser/autocomplete',
223 '#title' => t('@s username of the event organizer', array('@s' => variable_get('site_name', 'local'))),
224 '#default_value' => $org_names,
225 '#description' => t("For example: %name. To specify multiple organizers, separate each username with a comma.", array('%name' => $user->name)),
226 '#required' => TRUE,
227 );
228 $period = drupal_map_assoc(array(60*15, 60*30, 60*45, 60*60, 60*90, 60*120, 60*150, 60*180, 60*180, 60*240, 60*300, 60*360, 60*420, 60*480), 'format_interval');
229 $form['timeslots']['timeslot_length'] = array(
230 '#type' => 'select',
231 '#title' => t('Length of each time slot'),
232 '#default_value' => isset($node->timeslot_length) ? $node->timeslot_length : 60*60,
233 '#options' => $period,
234 );
235 $numbers = drupal_map_assoc(array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,20));
236 $form['timeslots']['num_volunteers'] = array(
237 '#type' => 'select',
238 '#title' => t('Number of volunteers in each time slot'),
239 '#default_value' => isset($node->num_volunteers) ? $node->num_volunteers : 1,
240 '#options' => $numbers,
241 '#description' => t('The volunteer form will have this number of volunteer spots in each time slot.'),
242 );
243 $form['timeslot_data'] = array(
244 '#type' => 'value',
245 '#value' => $node->timeslot_data,
246 );
247 if (user_access('administer volunteer events')) {
248 $form['administer'] = array(
249 '#type' => 'fieldset',
250 '#title' => t('Administer volunteers'),
251 '#collapsible' => TRUE,
252 '#collapsed' => TRUE,
253 '#weight' => -9,
254 );
255 $form['administer']['clear_volunteers'] = array(
256 '#type' => 'checkbox',
257 '#title' => t('Clear all volunteers'),
258 );
259 }
260 }
261 $form['body_filter']['body'] = array(
262 '#type' => 'textarea',
263 '#title' => t('volunteer event description'),
264 '#default_value' => $node->body,
265 '#rows' => 10,
266 '#required' => TRUE
267 );
268 $form['body_filter']['format'] = filter_form($node->format);
269 return $form;
270 }
271
272 /**
273 * Implementation of hook_load().
274 */
275 function volunteer_timeslots_load($node) {
276 $values = db_fetch_array(db_query("SELECT * FROM {volunteer_timeslots} WHERE vid = %d", $node->vid));
277 $values['timeslot_data'] = unserialize($values['timeslot_data']);
278 $values['timeslots_organizers'] = explode(',', $values['timeslots_organizers']);
279 return $values;
280 }
281
282
283 /**
284 * Implementation of hook_view().
285 *
286 */
287 function volunteer_timeslots_view(&$node, $teaser = FALSE, $page = FALSE) {
288 global $user;
289
290 $node = node_prepare($node, $teaser);
291
292 if (!$teaser) {
293 $admin = (user_access('administer volunteer events') ||
294 (($user->uid == $node->uid) && variable_get('volunteer_timeslots_author_manages', TRUE)) ||
295 in_array($user->uid, $node->timeslots_organizers)); //user is allowed to remove/add volunteers
296 $node->content['timeslots_signup_form'] = array(
297 '#value' => drupal_get_form('_timeslots_signup_form', $node, $admin),
298 '#weight' => 10,);
299
300 if ($admin) {
301 $node->content['timeslots_roster_form'] = array(
302 '#value' => drupal_get_form('_timeslots_roster_form', $node),
303 '#weight' => 20,);
304 }
305
306 }
307
308 return $node;
309 }
310
311 /**
312 * Generates each event's volunteer roster including textfields to record notes
313 *
314 */
315 function _timeslots_roster_form($node) {
316
317 if (!count($node->timeslot_data[0]['all_volunteers'])) {
318 return array();
319 }
320
321 $form = array(
322 '#theme' => 'timeslots_roster_form',
323 '#tree' => TRUE,
324 );
325
326 $form['nid'] = array('#type' => 'value', '#value' => $node->nid);
327
328 $header = array("Username");
329 if ($profile = module_exists('profile')) {
330 $fields = variable_get('volunteer_timeslots_profile_fields', array());
331 }
332 foreach ($node->timeslot_data[0]['all_volunteers'] as $uid) {
333 if ($account = user_load(array('uid' => $uid))) {
334 $form['info'][$uid]['username'] = array('#value' => $account->name);
335 if ($profile) {
336 foreach ($fields as $profile_field) {
337 $form['info'][$uid][$profile_field] = array('#value' => $account->$profile_field);
338 }
339 }
340 $form['notes'][$uid] = array(
341 '#type' => 'textfield',
342 '#size' => 30,
343 '#default_value' => (isset($node->timeslot_data[0]['notes'][$uid])) ? $node->timeslot_data[0]['notes'][$uid] : '',
344 );
345 }
346 }
347 if ($profile) {
348 $result = db_query("SELECT * FROM {profile_fields} p WHERE p.name in ('". implode("','", $fields). "') ORDER BY p.category, p.weight");
349
350 while ($pf = db_fetch_object($result)) {
351 $header[] = $pf->title;
352 }
353 }
354 $header[] = t('Notes');
355
356 $form['header'] = array(
357 '#type' => 'value',
358 '#value' => $header,
359 );
360 $form['submit'] = array(
361 '#type' => 'submit',
362 '#value' => t('Update notes'),
363 '#attributes' => array('class' => 'volunteer-timeslots'),
364 );
365 return $form;
366 }
367
368 function theme_timeslots_roster_form($form) {
369
370 foreach (element_children($form['info']) as $uid) {
371 $items = array();
372 foreach (element_children($form['info'][$uid]) as $profile_field) {
373 $items[] = drupal_render($form['info'][$uid][$profile_field]);
374 }
375 $items[] = array('data'=> drupal_render($form['notes'][$uid]));
376 $rows[] = $items;
377 }
378
379 $output = theme('table', $form['header']['#value'], $rows, array('class' => 'volunteer-timeslots'), t('Volunteer roster'));
380 return $output. drupal_render($form);
381 }
382
383
384 function _timeslots_roster_form_submit($form_id, $form_values) {
385 $node = node_load($form_values['nid']);
386 if ($form_values['notes'] == $node->timeslot_data[0]['notes']) {
387 drupal_set_message(t('No changes were made.'));
388 return;
389 }
390
391 $node->timeslot_data[0]['notes'] = array(); //clear old notes
392 foreach ($form_values['notes'] as $uid => $note) {
393 $node->timeslot_data[0]['notes'][$uid] = $note;
394 }
395 $node->revision = TRUE;
396 node_save($node);
397 drupal_set_message(t('Your changes to the notes were made.'));
398 }
399
400 function _timeslots_signup_form($node, $admin) {
401 global $user;
402 $form = array(
403 '#theme' => 'timeslots_signup_form',
404 '#tree' => TRUE,
405 );
406 $none = theme('placeholder', t('volunteer needed'));
407
408 $form['nid'] = array('#type' => 'value', '#value' => $node->nid);
409
410 $access = user_access('access user profiles');
411
412 if (count($node->timeslot_data[0]['all_volunteers'])) {
413 $result = db_query("SELECT * FROM {users} WHERE uid in (". implode(',', $node->timeslot_data[0]['all_volunteers']). ")");
414 while ($account = db_fetch_object($result)) {
415 $users[$account->uid] = $account;
416 }
417 }
418 $box = FALSE; //flag to see if we have any checkbox elements in the form
419 $openings = array();
420 $form['num_slots'] = array( '#type' => 'value', '#value' => count($node->timeslot_data));
421 foreach ($node->timeslot_data as $slot => $data) {
422 $form['timeslot'][$slot]['start_time'] = array(
423 '#value' => format_date($data['start_time'], 'custom', 'g:i a', $node->start_offset),
424 );
425 $form['timeslot'][$slot]['end_time'] = array(
426 '#value' => format_date($data['end_time'], 'custom', 'g:i a', $node->start_offset),
427 );
428 if (count($data['volunteers']) < $node->num_volunteers) {
429 $openings[$slot] = $form['timeslot'][$slot]['start_time']['#value'];
430 }
431 if ($user->uid && ($node->event_end > time()) &&
432 (($checked = in_array($user->uid, $data['volunteers'])) || (isset($openings[$slot])))) {
433 $form['timeslot'][$slot]['box'] = array(
434 '#type' => 'checkbox',
435 '#default_value' => $checked,
436 );
437 $form['timeslot'][$slot]['was_checked'] = array(
438 '#type' => 'value',
439 '#value' => $checked,
440 );
441 $box = TRUE;
442 }
443 else {
444 $form['timeslot'][$slot]['box'] = array( '#value' => '', );
445 }
446 for ($i = 0; $i < $node->num_volunteers; $i++) {
447 $set = isset($data['volunteers'][$i]);
448 if (!$set) {
449 $name = $none;
450 }
451 elseif ($access) {
452 $name = l($users[$data['volunteers'][$i]]->name, 'user/'. $users[$data['volunteers'][$i]]->uid);;
453 }
454 else {
455 $name = $users[$data['volunteers'][$i]]->name;
456 }
457 $form['timeslot'][$slot]['name'][$i] = array(
458 '#value' => $name,
459 );
460 if ($set && $admin) {
461 $form['timeslot'][$slot]['remove'][$i] = array(
462 '#type' => 'checkbox',
463 '#return_value' => $users[$data['volunteers'][$i]]->uid,
464 );
465 }
466 else {
467 $form['timeslot'][$slot]['remove'][$i] = array('#type' => 'value', '#value' => 0, );
468 }
469 }
470 }
471 $form['event_end'] = array(
472 '#value' => t('The event ends %time.', array( '%time' => format_date($node->event_end, 'custom', 'D, g:i a', $node->end_offset))),
473 );
474 $form['box'] = array(
475 '#type' => 'value',
476 '#value' => $box,
477 );
478 $form['admin'] = array(
479 '#type' => 'value',
480 '#value' => $admin,
481 );
482 if ($admin) {
483 if (count($openings)) {
484 $form['add_volunteer'] = array(
485 '#type' => 'fieldset',
486 '#title' => t('Add a volunteer to the schedule'),
487 '#collapsible' => TRUE,
488 '#collapsed' => TRUE,
489 '#prefix' => '<div class="volunteer-timeslots">',
490 '#suffix' => '</div>',
491 );
492 $form['add_volunteer']['name'] = array(
493 '#type' => 'textfield',
494 '#maxlength' => 60,
495 '#autocomplete_path' => 'user/autocomplete',
496
497 '#description' => t("Enter a %s username. For example: %name.", array('%s' => variable_get('site_name', 'local'), '%name' => $user->name)),
498 );
499 $form['add_volunteer']['slot'] = array(
500 '#type' => 'select',
501 '#options' => $openings,
502 '#description' => t("The time slot to add the volunteer"),
503 );
504 }
505 else {
506 $form['no_openings'] = array(
507 '#value' => t('There are no open slots in the schedule.'),
508 );
509 }
510 }
511 if ($box || $admin) {
512 $form['send_me'] = array(
513 '#type' => 'checkbox',
514 '#title' => t("Send me a copy of this event's information"),
515 '#default_value' => !$admin, //checked by default except for admins/organizers
516 '#attributes' => array('class' => 'volunteer-timeslots'),
517 );
518 $form['submit'] = array(
519 '#type' => 'submit',
520 '#value' => t('Submit'),
521 '#attributes' => array('class' => 'volunteer-timeslots'),
522 );
523 $form['submit_info'] = array(
524 '#value' => '<p>'. t('After checking or unchecking boxes, click on the submit button to add your username, %name, to the schedule or to make the changes.', array('%name' => $user->name)). '</p>',
525 );
526 }
527 return $form;
528 }
529
530 function _timeslots_signup_form_validate($form_id, $form_values, $form) {
531
532 $node = node_load($form_values['nid']);
533 if (!empty($form_values['add_volunteer']['name'])) {
534 $name = trim($form_values['add_volunteer']['name']);
535 if (!empty($name)) {
536 if (!($account = user_load(array('name' => $name)))) {
537 form_set_error("add_volunteer][name", t('The username %name does not exist.', array ('%name' => theme('placeholder', $name))));
538 }
539 else {
540 global $user;
541 $slot = $form_values['add_volunteer']['slot'];
542 if ($form_values['timeslot'][$slot]['box'] && !$form_values['timeslot'][$slot]['was_checked']) {
543 if ((count($node->timeslot_data[$slot]['volunteers']) >= ($node->num_volunteers - 1)) &&
544 ($account->uid != $user->uid)) {
545 form_set_error('add_volunteer', t('Error: you cannot add both yourself and another volunteer to that time slot'));
546 }
547 }
548 }
549 }
550 }
551 else { // does this work???
552 if ($form_values['timeslot'][$slot]['box'] && !$form_values['timeslot'][$slot]['was_checked']) {
553 if (count($node->timeslot_data[$slot]['volunteers']) >= $node->num_volunteers) {
554 form_set_error('', t('Sorry: That time slot has been filled.'));
555 }
556 }
557 }
558 }
559
560 function theme_timeslots_signup_form($form) {
561
562 $header = array(t('Time slot'));
563 if ($form['box']['#value']) {
564 $header[] = t('Sign up for this slot');
565 }
566 else {
567 $header[] = '';
568 }
569 $header[] = t('Volunteers');
570 if ($form['admin']['#value']) {
571 $header[] = t('Remove');
572 }
573 else {
574 $header[] = '';
575 }
576 $rows = array();
577 for ($slot = 0; $slot < $form['num_slots']['#value']; $slot++) {
578 foreach (element_children($form['timeslot'][$slot]['name']) as $i) {
579 if ($i == 0) {
580 $arow = array(drupal_render($form['timeslot'][$slot]['start_time']).' - '. drupal_render($form['timeslot'][$slot]['end_time']));
581 if ($form['box']['#value']) {
582 $arow[] = drupal_render($form['timeslot'][$slot]['box']);
583 }
584 else {
585 $arow[] = '';
586 }
587 $arow[] = drupal_render($form['timeslot'][$slot]['name'][0]);
588 $arow[] = drupal_render($form['timeslot'][$slot]['remove'][0]);
589 $rows[] = array(data => $arow, 'class' => 'ugly');
590 }
591 else {
592 $rows[] = array('', '', drupal_render($form['timeslot'][$slot]['name'][$i]), drupal_render($form['timeslot'][$slot]['remove'][$i]));
593 }
594 }
595 $rows[] = array(array('data' => '<hr />', 'colspan' => '4'));
596 }
597 $rows[] = array(array('data' => drupal_render($form['event_end']), 'colspan' => '4'));
598 $output = theme('table', $header, $rows, array('class' => 'volunteer-timeslots'), t('Event volunteer schedule'));
599
600 return $output . drupal_render($form);
601 }
602
603 function _timeslots_signup_form_submit($form_id, $form_values) {
604 global $user;
605 $node = node_load($form_values['nid']);
606
607 $changed = array();
608 $remove = array();
609 foreach($form_values['timeslot'] as $slot => $data) {
610 if (isset($data['box']) && ($data['box'] != $data['was_checked'])) {
611 $changed[$slot] = TRUE;
612 }
613 if ($form_values['admin']) {
614 foreach ($data['remove'] as $uid) {
615 if ($uid > 0) {
616 $remove[$slot] = TRUE;
617 }
618 }
619 }
620 }
621 if (!count($changed) && !count($remove) && empty($form_values['add_volunteer']['name'])) {
622 drupal_set_message(t('No changes were made.'));
623 return;
624 }
625 $all_volunteers = array();
626
627 foreach($form_values['timeslot'] as $slot => $data) {
628 $vol = $node->timeslot_data[$slot]['volunteers'];
629 if (isset($changed[$slot])) {
630 if ($data['box']) {
631 $vol[] = $user->uid;
632 $node->timeslot_data[0]['all_volunteers'][] = $user->uid;
633 }
634 elseif ($data['was_checked']) {
635 if (($i = array_search($user->uid, $vol)) !== FALSE) {
636 $vol[$i] = $vol[count($vol) - 1];
637 array_pop($vol);
638 }
639 }
640 }
641 if (isset($remove[$slot])) { //admins and organizers can remove individual volunteers
642 foreach ($data['remove'] as $uid) {
643 if ($uid > 0) {
644 if (($i = array_search($uid, $vol)) !== FALSE) {
645 $vol[$i] = $vol[count($vol) - 1];
646 array_pop($vol);
647 }
648 }
649 }
650 }
651 if (isset($form_values['add_volunteer']['name']) && $form_values['add_volunteer']['slot'] == $slot) {
652 $name = trim($form_values['add_volunteer']['name']);
653 if (!empty($name)) {
654 $account = user_load(array('name' => $name));
655 $vol[] = $account->uid;
656 }
657 }
658 $node->timeslot_data[$slot]['volunteers'] = array_unique($vol);
659 $all_volunteers = array_merge($all_volunteers, $node->timeslot_data[$slot]['volunteers']);
660 }
661 $node->timeslot_data[0]['all_volunteers'] = array_unique($all_volunteers);
662 $node->revision = TRUE;
663 node_save($node);
664 drupal_set_message(t('Your changes to the schedule were made.'));
665 if ($form_values['send_me']) {
666 volunteer_timeslots_reminder_mail($node, $user->uid, "Information about the event:");
667 drupal_set_message(t('Information about the event was sent to your e-mail address.'));
668 }
669 }
670
671 /**
672 * Implementation of hook_nodeapi().
673 *
674 * hook_nodeapi is implemented instead of hook_submit so that event module has
675 * a chance to act first and properly process the event's start and end times.
676 */
677 function volunteer_timeslots_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
678
679 if($node->type == 'volunteer_timeslots') {
680 if ($op == 'submit') {
681 //insure a rational end time- at least one time slot after the event start.
682 if ($node->event_end <= $node->event_start) {
683 $node->event_end = $node->event_start + $node->timeslot_length;
684 }
685 $start = $node->event_start;
686 $end = $node->event_end;
687 $num_slots = ceil(($end - $start)/$node->timeslot_length);
688
689 if ($node->clear_volunteers) {
690 unset($node->timeslot_data);
691 }
692
693 $data[0]['all_volunteers'] = array();
694 for ($i=0; $i<$num_slots; $i++) {
695 $data[$i]['start_time'] = $start + $i* $node->timeslot_length;
696 if ($i+1 == $num_slots) {
697 $data[$i]['end_time'] = $end;
698 }
699 else {
700 $data[$i]['end_time'] = $start + ($i+1)* $node->timeslot_length;
701 }
702 if (count($node->timeslot_data[$i]['volunteers'])) {
703 $data[$i]['volunteers'] = $node->timeslot_data[$i]['volunteers'];
704 $data[0]['all_volunteers'] = array_merge($data[0]['all_volunteers'], $node->timeslot_data[$i]['volunteers']);
705 }
706 else {
707 $data[$i]['volunteers'] = array();
708 }
709 }
710 $data[0]['all_volunteers'] = array_unique($data[0]['all_volunteers']);
711 foreach ($data[0]['all_volunteers'] as $uid) {
712 $data[0]['notes'][$uid] = $node->timeslot_data[0]['notes'][$uid];
713 }
714 $node->timeslot_data = $data;
715 //$node->revision = TRUE;
716 $names = explode(',', $node->timeslots_organizers);
717 $organizers = array();
718 foreach($names as $n) {
719 // validation has already been done in _validate, convert to uid values
720 if ($account = user_load(array('name' => trim($n)))) {
721 $organizers[] = $account->uid;
722 }
723 }
724 $node->timeslots_organizers = $organizers;
725 }
726 }
727 }
728
729 /**
730 * Implementation of hook_insert().
731 */
732 function volunteer_timeslots_insert(&$node) {
733 db_query("INSERT INTO {volunteer_timeslots} (nid, vid, timeslot_length, num_volunteers, timeslots_organizers, timeslot_data) VALUES (%d, %d, %d, %d, '%s', '%s')",
734 $node->nid, $node->vid, $node->timeslot_length, $node->num_volunteers, implode(',', $node->timeslots_organizers), serialize($node->timeslot_data));
735 }
736
737 function _volunteer_timeslots_data_insert(&$node) {
738 }
739
740 /**
741 * Implementation of hook_update().
742 */
743 function volunteer_timeslots_update(&$node) {
744 if ($node->revision) {
745 volunteer_timeslots_insert($node);
746 }
747 else {
748 db_query("UPDATE {volunteer_timeslots} SET timeslot_length = %d, num_volunteers = %d, timeslots_organizers = '%s', timeslot_data = '%s' WHERE vid = %d",
749 $node->timeslot_length, $node->num_volunteers, implode(',', $node->timeslots_organizers), serialize($node->timeslot_data), $node->vid);
750 }
751 }
752
753 /**
754 * Implementation of hook_delete().
755 */
756 function volunteer_timeslots_delete(&$node) {
757 db_query('DELETE FROM {volunteer_timeslots} WHERE nid = %d', $node->nid);
758 }
759
760
761 function volunteer_timeslots_link($type, $node = NULL, $teaser = FALSE) {
762 $links = array();
763 global $user;
764
765 if ($type == 'node' && $node->type == 'volunteer_timeslots' && !$user->uid) {
766 $destination = "destination=". drupal_urlencode("node/". $node->nid);
767 if (variable_get('user_register', 1)) {
768 $links['volunteer_timeslots_login'] = array(
769 'title' => t('<a href="!login">Login</a> or <a href="!register">register</a> to volunteer', array('!login' => url('user/login', $destination), '!register' => check_url(url('user/register', $destination)))),
770 'html' => TRUE,
771 );
772 }
773 else {
774 $links['volunteer_timeslots_login_register'] = array(
775 'title' => t('<a href="!login">Login</a> to volunteer', array('!login' => check_url(url('user/login', $destination)))),
776 'html' => TRUE,
777 );
778 }
779 }
780
781 return $links;
782 }
783
784 /**
785 * Implementation of hook_cron().
786 */
787 function volunteer_timeslots_cron() {
788
789 if (($remind_time = variable_get('volunteer_timeslots_remind_time', 36*60)) < 0) {
790 return;
791 }
792
793 $check_time = time() - (30 * 60 * 60);
794 $result = db_query('SELECT vt.* FROM {volunteer_timeslots} vt INNER JOIN {node} n ON n.vid = vt.vid INNER JOIN {event} e ON n.nid = e.nid WHERE n.status = 1 AND n.moderate = 0 AND e.event_start >= %d ORDER BY event_start', $check_time);
795
796 while ($event = db_fetch_object($result)) {
797 $node = node_load($event->nid);
798 $minutesleft = (int)(($node->event_start - time()) / 60);
799 if (($minutesleft < $remind_time) && ($minutesleft > 0) && !variable_get($node->nid. '_timeslots_reminder_sent', FALSE)) {
800 foreach ($node->timeslot_data[0]['all_volunteers'] as $uid) {
801 volunteer_timeslots_reminder_mail($node, $uid);
802 }
803 $account = user_load(array('uid' => $node->timeslots_organizers[0], 'status' => 1));
804 watchdog('mail', t('Volunteer timeslots: reminder e-mails about %url were sent on behalf of %name-from.', array('%name-from' => l($account->name,'user/'. $account->uid), '%url' => l('node/'.$node->nid,'node/'.$node->nid))));
805 variable_set($node->nid. '_timeslots_reminder_sent', TRUE);
806 }
807 elseif ($minutesleft < 0) {
808 variable_del($node->nid. '_timeslots_reminder_sent');
809 }
810 }
811 }
812
813 /**
814 * Send an e-mail with information or a reminder
815 */
816 function volunteer_timeslots_reminder_mail($node, $uid, $opening = "Reminder- you have volunteered for a time slot at:") {
817 static $organizer = array();
818 static $text = array();
819
820 if (empty($organizer[$node->nid])) {
821 $organizer[$node->nid] = user_load(array('uid' => $node->timeslots_organizers[0], 'status' => 1));
822 if (empty($organizer[$node->nid])) {
823 watchdog('user', t("Volunteer timeslots: the user ID '%s' for node/%n could not be loaded.", array('%s' => $node->timeslots_organizers[0], '%n' => $node->nid)), WATCHDOG_ERROR);
824 $organizer[$node->nid]->mail = variable_get('site_mail', ini_get('sendmail_from'));
825 }
826 }
827
828 $account = user_load(array('uid' => $uid, 'status' => 1));
829 if (empty($account)) {
830 watchdog('user', t("Volunteer timeslots: the user ID '%s' for node/%n could not be loaded.", array('%s' => $uid, '%n' => $node->nid)), WATCHDOG_ERROR);
831 return;
832 }
833
834 // Compose the body:
835 if (empty($text[$node->nid])) {
836 switch (variable_get('event_timezone_display', 'event')) {
837 case 'event' :
838 include_once(EVENT_PATH .'/event_timezones.inc');
839 $start_offset = event_get_offset($node->timezone, $node->event_start);
840 break;
841 case 'user' :
842 $start_offset = $account->timezone;
843 break;
844 case 'site' :
845 $start_offset = variable_get('date_default_timezone', 0);
846 break;
847 }
848 $start_format = format_date($node->event_start, 'small', '', $start_offset);
849 $message[] = t($opening. ' @title', array('@title' => $node->title));
850 $message[] = t('This is scheduled for @event_start. To see which time slot you volunteered for, go to !url', array('@event_start' => $start_format, '!url' => url("node/".$node->nid, NULL, NULL, TRUE)));
851 $message[] = vt_mail_output(check_markup($node->body, $node->format, FALSE));
852 // Tidy up the body:
853 foreach ($message as $key => $value) {
854 $message[$key] = wordwrap($value);
855 }
856 $text[$node->nid] = implode("\n\n", $message);
857 }
858
859 // Prepare all fields:
860 $to = $account->mail;
861 $from = $organizer[$node->nid]->mail;
862
863 // Format the subject:
864 $subject = '['. variable_get('site_name', 'drupal') .'] '. t('Event volunteer information');
865
866 // Prepare the body:
867 $body = $account->name.",\n\n". $text[$node->nid];
868
869 // Send the e-mail:
870 drupal_mail('volunteer_timeslots_reminder', $to, $subject, $body, $from);
871 }
872
873 // takes filtered HTML as input and transforms for email
874 // modified from og.module
875 function vt_mail_output($body, $html = TRUE) {
876
877 if ($html) {
878 $pattern = '@(<a href="(.+?)">(.+?)</a>)@i';
879 $body = preg_replace($pattern, '$3 ($2)', $body);
880 $body = preg_replace('!</?blockquote>!i', '"', $body);
881 $body = preg_replace('!</?(em|i)>!i', '/', $body);
882 $body = preg_replace('!</?(b|strong)>!i', '*', $body);
883 $body = preg_replace("@<br />(?!\n)@i", "\n", $body);
884 $body = preg_replace("@</p>(?!\n\n)@i", "\n\n", $body);
885 $body = preg_replace("@<li>@i", "\n* ", $body);
886 $body = strip_tags($body);
887 $body = decode_entities($body);
888 }
889 else {
890 $body = decode_entities($body);
891 }
892 return $body;
893 }

  ViewVC Help
Powered by ViewVC 1.1.2