Projet

Général

Profil

Paste
Télécharger (44,1 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / pollfield / pollfield.module @ 62f5c69e

1
<?php
2

    
3
/**
4
 * @file
5
 * Pollfield module
6
 */
7

    
8
/**
9
 * Implements hook_init().
10
 *
11
 * Executed at the begining of page requests to add custom css.
12
 */
13
function pollfield_init() {
14
  $css_file = drupal_get_path('module', 'pollfield') . '/pollfield.css';
15
  drupal_add_css($css_file, 'module');
16
}
17

    
18
/**
19
 * Implements hook_menu().
20
 *
21
 * Provides a simple user interface that tells the developer where to go.
22
 */
23
function pollfield_menu() {
24
  $items = array();
25
  $items['pollfield/add_choice'] = array(
26
    'title' => 'Add choice',
27
    'page callback' => 'pollfield_add_choice',
28
    'access arguments' => array('access content'),
29
    'type' => MENU_CALLBACK,
30
  );
31
  return $items;
32
}
33

    
34
/**
35
 * Implements hook_field_info().
36
 *
37
 * Provides the description of the field.
38
 */
39
function pollfield_field_info() {
40
  return array(
41
    // We name our field as the associative name of the array.
42
    // This is name of field that evetrhing else is connected.
43
    'pollfield_poll' => array(
44
      'label' => t('Pollfield module'),
45
      'description' => t('This is to store poll as a field and not as a node.'),
46
      'default_widget' => 'pollfield_main', // Each field can have many widget.
47
      'default_formatter' => 'pollfield_default',
48
    ),
49
  );
50
}
51

    
52
/**
53
 * Implements hook_field_validate().
54
 *
55
 * This hook gives us a chance to validate content that's in our
56
 * field. We're really only interested in the $items parameter, since
57
 * it holds arrays representing content in the field we've defined.
58
 * We want to verify that the items only contain RGB hex values like
59
 * this: #RRGGBB. If the item validates, we do nothing. If it doesn't
60
 * validate, we add our own error notification to the $errors parameter.
61
 *
62
 * @see field_example_field_widget_error()
63
 */
64
function pollfield_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
65
  foreach ($items as $delta => $item) {
66

    
67
  }
68
}
69

    
70
/**
71
 * Implements hook_field_is_empty().
72
 *
73
 * hook_field_is_emtpy() is where Drupal asks us if this field is empty.
74
 * Return TRUE if it does not contain data, FALSE if it does. This lets
75
 * the form API flag an error when required fields are empty.
76
 */
77
function pollfield_field_is_empty($item, $field) {
78
  // For now field are always full.
79
  return FALSE;
80
}
81

    
82
/**
83
 * Implements hook_field_formatter_info().
84
 *
85
 * We need to tell Drupal that we have two different types of formatters
86
 * for this field. One will change the text color, and the other will
87
 * change the background color.
88
 *
89
 * @see field_example_field_formatter_view()
90
 */
91
function pollfield_field_formatter_info() {
92
  return array(
93
    // This formatter just displays the hex value in the color indicated.
94
    'pollfield_default' => array(
95
      'label' => t('Default'),
96
      'field types' => array('pollfield_poll'),
97
    ),
98
    // This formatter changes the background color of the content region.
99
    'pollfield_choice' => array(
100
      'label' => t('Only choices'),
101
      'field types' => array('pollfield_poll'),
102
    ),
103
    // This formatter changes the background color of the content region.
104
    'pollfield_question' => array(
105
      'label' => t('Only questions'),
106
      'field types' => array('pollfield_poll'),
107
    ),
108
    'pollfield_results' => array(
109
      'label' => t('Only results'),
110
      'field types' => array('pollfield_poll'),
111
    ),
112
    'pollfield_runtime' => array(
113
      'label' => t('Only runtime'),
114
      'field types' => array('pollfield_poll'),
115
    ),
116
  );
117
}
118

    
119
/**
120
 * Implements hook_field_presave().
121
 *
122
 * Used to serialize some pollfield settings.
123
 */
124
function pollfield_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
125
  foreach ($items as $delta => $item) {
126
    // Poll settings.
127
    $poll_settings = array(
128
      'poll_type' => $item['poll_type'],
129
      'cancelvote_allow' => $item['cancelvote_allow'],
130
      'result_allow' => $item['result_allow'],
131
    );
132
    $items[$delta]['poll_features'] = serialize($poll_settings);
133

    
134
    // Delete all votes.
135
    if ($item['delete_votes'] && !empty($entity->nid)) {
136
      db_delete('pollfield_votes')
137
        ->condition('nid', $entity->nid)
138
        ->execute();
139
    }
140

    
141
    // Delete empty choices.
142
    $choices_items = array();
143
    foreach ($item['group'] as $key => $value) {
144
      $choice = trim($value['choice']);
145
      if (!empty($choice)) {
146
        $choices_items[$key] = $value;
147
      }
148
    }
149
    $items[$delta]['choice'] = serialize($choices_items);
150
  }
151
}
152

    
153
/**
154
 * Implements hook_field_formatter_view().
155
 *
156
 * Two formatters are implemented.
157
 * - field_example_simple_text just outputs markup indicating the color that
158
 *   was entered and uses an inline style to set the text color to that value.
159
 * - field_example_color_background does the same but also changes the
160
 *   background color of div.region-content.
161
 *
162
 * @see field_example_field_formatter_info()
163
 */
164
function pollfield_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
165
  $element = array();
166

    
167
  switch ($display['type']) {
168
    // This formatter simply outputs the field as text and with a color.
169
    case 'pollfield_default':
170
      foreach ($items as $delta => $item) {
171
        $elements = array(
172
          'item'   => $item,
173
          'entity' => $entity,
174
          'delta'  => $delta,
175
          'field'  => $field,
176
        );
177
        $element[$delta] = array(
178
          '#markup' => theme('pollfield_default_formatter', array('elements' => $elements)),
179
        );
180
      }
181
      break;
182

    
183
    // This formatter adds css to the page changing the '.region-content' area's
184
    // background color. If there are many fields, the last one will win.
185
    case 'pollfield_choices':
186
      foreach ($items as $delta => $item) {
187
        // We create a render array to produce the desired markup,
188
        // "<p style="color: #hexcolor">The color code ... #hexcolor</p>".
189
        // See theme_html_tag().
190
        $element[$delta] = array(
191
          '#type' => 'html_tag',
192
          '#tag' => 'p',
193
          '#value' => t('This is choices formater'),
194
        );
195
      }
196
      break;
197

    
198
    case 'pollfield_question':
199
      foreach ($items as $delta => $item) {
200
        // We create a render array to produce the desired markup,
201
        // "<p style="color: #hexcolor">The color code ... #hexcolor</p>".
202
        // See theme_html_tag().
203
        $element[$delta] = array(
204
          '#type' => 'html_tag',
205
          '#tag' => 'p',
206
          '#value' => t('This is defualt formater'),
207
        );
208
      }
209
      break;
210

    
211
    case 'pollfield_results':
212
      foreach ($items as $delta => $item) {
213
        // We create a render array to produce the desired markup,
214
        // "<p style="color: #hexcolor">The color code ... #hexcolor</p>".
215
        // See theme_html_tag().
216
        $element[$delta] = array(
217
          '#type' => 'html_tag',
218
          '#tag' => 'p',
219
          '#value' => t('This is results formater'),
220
        );
221
      }
222
      break;
223

    
224
    case 'pollfield_runtime':
225
      foreach ($items as $delta => $item) {
226
        // We create a render array to produce the desired markup,
227
        // "<p style="color: #hexcolor">The color code ... #hexcolor</p>".
228
        // See theme_html_tag().
229
        $element[$delta] = array(
230
          '#type' => 'html_tag',
231
          '#tag' => 'p',
232
          '#value' => t('This is runtime formater'),
233
        );
234
      }
235
      break;
236
  }
237

    
238
  return $element;
239
}
240

    
241
/**
242
 * Implements hook_field_widget_info().
243
 *
244
 * Three widgets are provided.
245
 * - A simple text-only widget where the user enters the '#ffffff'.
246
 * - A 3-textfield widget that gathers the red, green, and blue values
247
 *   separately.
248
 * - A farbtastic colorpicker widget that chooses the value graphically.
249
 *
250
 * These widget types will eventually show up in hook_field_widget_form,
251
 * where we will have to flesh them out.
252
 *
253
 * @see field_example_field_widget_form()
254
 */
255
function pollfield_field_widget_info() {
256
  return array(
257
    'pollfield_main' => array(
258
      'label' => t('Pollfield'),
259
      'field types' => array('pollfield_poll'),
260
    ),
261
  );
262
}
263

    
264
/**
265
 * Implements hook_field_widget_form().
266
 *
267
 * hook_widget_form() is where Drupal tells us to create form elements for
268
 * our field's widget.
269
 *
270
 * We provide one of three different forms, depending on the widget type of
271
 * the Form API item provided.
272
 */
273
function pollfield_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
274
  $value = isset($items[$delta]['question']) ? $items[$delta]['question'] : '';
275

    
276
  $widget = $element;
277
  $widget['#delta'] = $delta;
278
  
279
  if (isset($form['#node'])) {
280
  $node = $form['#node'];
281
  }
282
  //dpr($form);
283
  if (!empty($items[$delta]['poll_features'])) {
284
    if (is_array($items[$delta]['poll_features'])) {
285
      $poll_features = $items[$delta]['poll_features'];
286
    }
287
    else {
288
      $poll_features = unserialize($items[$delta]['poll_features']);
289
    }
290
  }
291

    
292
  switch ($instance['widget']['type']) {
293
    case 'pollfield_main':
294
      // Question.
295
      $widget['question'] = array(
296
        '#type' => 'textfield',
297
        '#title' => t('Question'),
298
        '#default_value' => $value,
299
      );
300
      // Status.
301
      $admin_pollfield = TRUE;
302
      $_active = array(
303
        t('Closed'),
304
        t('Active'),
305
      );
306
      $widget['active'] = array(
307
        '#type' => 'radios',
308
        '#access' => $admin_pollfield,
309
        '#title' => t('Status'),
310
        // If no value exists, always default to active (1).
311
        '#default_value' => isset($items[$delta]['active']) ? $items[$delta]['active'] : 1,
312
        '#options' => $_active,
313
        '#description' => t('When a pollfield is closed, visitors can no longer vote for it.'),
314
      );
315
      // Runtime - duration.
316
      $widget['runtime'] = array(
317
        '#type' => 'select',
318
        '#access' => $admin_pollfield,
319
        '#title' => t('Duration'),
320
        // If no value exists, always default to Unlimited (0).
321
        '#default_value' => isset($items[$delta]['runtime']) ? $items[$delta]['runtime'] : 0,
322
        '#options' => pollfield_duration_options(),
323
        '#description' => t('After this period, the pollfield will be closed automatically.'),
324
      );
325
      // Anonymous voting.
326
      $widget['anonymous'] = array(
327
        '#type' => 'select',
328
        '#access' => $admin_pollfield,
329
        '#title' => t('Anonymous voting'),
330
        // If no value exists, always default to Not allowed (anon_non).
331
        '#default_value' => isset($items[$delta]['anonymous']) ? $items[$delta]['anonymous'] : 'anon_non',
332
        '#options' => array(
333
          'anon_non' => t('Not allowed'),
334
          'anon_by_ip' => t('Allowed, filtered by user IP'),
335
          'anon_by_cookie' => t('Allowed, filtered by user cookie'),
336
          'anon_all' => t('Allowed'),
337
        ),
338
        '#description' => t('Allow or disallow anonymous users to vote on this poll. Filtering by user IP or cookie ensures only one vote is allowed per user IP.'),
339
      );
340
      // Cancel permission.
341
      $options_allow = array(
342
        t('Disallow'),
343
        t('Allow'),
344
      );
345
      $widget['cancelvote_allow'] = array(
346
        '#type' => 'radios',
347
        '#access' => $admin_pollfield,
348
        '#title' => t('Cancel Vote'),
349
        '#default_value' => isset($poll_features['cancelvote_allow']) ? $poll_features['cancelvote_allow'] : 1,
350
        '#options' => $options_allow,
351
        '#description' => t('Allow or disallow "Cancel vote" button. "Cancel vote" button allows voters to cancel their vote and choose a different one if they want.'),
352
      );
353
      // Show result befor a voting.
354
      $widget['result_allow'] = array(
355
        '#type' => 'radios',
356
        '#access' => $admin_pollfield,
357
        '#title' => t('Show results before voting'),
358
        '#default_value' => isset($poll_features['result_allow']) ? $poll_features['result_allow'] : 0,
359
        '#options' => $options_allow,
360
        '#description' => t('Allow or disallow users to see current poll results before voting on this poll. If set to disallow, anonymous users can never see the results. Permissions under pollfield module override this setting.'),
361
      );
362

    
363
      // Poll type
364
      // Can users vote on multiple choices or just one?
365
      $_poll_type = array(
366
        'single' => t('Single choice'),
367
        'multiple' => t('Multiple choice'),
368
      );
369
      $widget['poll_type'] = array(
370
        '#type' => 'radios',
371
        '#title' => t('Poll type'),
372
        '#default_value' => isset($poll_features['poll_type']) ? $poll_features['poll_type'] : 'multiple',
373
        '#options' => $_poll_type,
374
        '#description' => t('In a Single choice poll only one of the responses can be voted for while in a Multiple choice poll it is possible to choose more than one at the same time.'),
375
      );
376

    
377
      // Delete votes from this poll.
378
      $widget['delete_votes'] = array(
379
        '#type' => 'checkbox',
380
        '#title' => t('Delete all votes'),
381
        '#description' => t('Delete all votes on this poll. <strong>This action can not be undone!</strong>'),
382
        '#default_value' => FALSE,
383
        '#access' => $admin_pollfield,
384
      );
385

    
386
      $widget['poll_features'] = array(
387
        '#type' => 'value',
388
        '#value' => isset($poll_features) ? $poll_features : NULL,
389
      );
390
      $widget['choice'] = array(
391
        '#type' => 'value',
392
        '#value' => isset($items[$delta]['choice']) ? $items[$delta]['choice'] : array(),
393
      );
394

    
395
      // Choices.
396
      $choices = !empty($items[$delta]['choice']) ? unserialize($items[$delta]['choice']) : array();
397
      $number_in_data_base = $number_of_choices = count($choices);
398
      // Ajax wrapper.
399
      $wrapper = 'pollfield-ajax-wrapper-' . $delta;
400
      $field_name = $field['field_name'];
401
      if (isset($form_state['count_choices'])) {
402
        $number_of_choices = $form_state['count_choices'];
403
      }
404
      else {
405
        $form_state['count_choices'] = $number_of_choices;
406
      }
407
      // Forming field definition for form return in ajax.
408
      $form_state['field_name'] = $field_name;
409

    
410
      if (isset($node->$field_name)) {
411
        global $language;
412
        if (isset($node->{$field_name}[$language->language])) {
413
          $field_lang = $node->{$field_name}[$language->language];
414
        }
415
        else {
416
          $field_lang = LANGUAGE_NONE;
417
        }
418
      }
419
      else {
420
        $field_lang = LANGUAGE_NONE;
421
      }
422
      $form_state['field_lang'] = $field_lang;
423
      $form_state['field_delta'] = $delta;
424

    
425
      $widget['group'] = array(
426
        '#prefix' => '<div id="' . $wrapper . '">',
427
        '#suffix' => '</div>',
428
      );
429

    
430
      for ($i = 1; $i <= ($number_of_choices + 1); $i++) {
431
        $widget['group'][$i] = array(
432
          '#type' => 'fieldset',
433
          '#title' => t('Choice #%delta', array('%delta' => $i)),
434
          '#collapsible' => TRUE,
435
          '#collapsed' => FALSE,
436
          '#weight' => $i,
437
        );
438
        $widget['group'][$i]['choice'] = array(
439
          '#title' => t('Response'),
440
          '#type' => 'textfield',
441
          '#default_value' => isset($choices[$i]['choice']) ? $choices[$i]['choice'] : '',
442
          '#rows' => 2,
443
          '#description' => t('If you want to delete this choice leave the field empty.'),
444
        );
445
        $widget['group'][$i]['votes'] = array(
446
          '#title' => t('Starting votes count (optional)'),
447
          '#access' => $admin_pollfield,
448
          '#type' => 'textfield',
449
          '#default_value' => isset($choices[$i]['votes']) ? $choices[$i]['votes'] : '',
450
          '#element_validate' => array('_pollfield_is_digits_validate'),
451
          '#size' => 10,
452
        );
453
      }
454

    
455
      $widget['add-more'] = array(
456
        '#type' => 'submit',
457
        '#value' => t('More choices'),
458
        '#description' => t("If the amount of boxes above isn't enough, click here to add more choices."),
459
        '#submit' => array('pollfield_more_choice_callback_submit'),
460
        '#ajax' => array(
461
          'callback' => 'pollfield_more_choice_callback_js',
462
          'wrapper' => $wrapper,
463
        ),
464
      );
465
      break;
466
  }
467

    
468
  // Question is name of field in field database.
469
  $element['question'] = $widget['question'];
470
  $element['active'] = $widget['active'];
471
  $element['anonymous'] = $widget['anonymous'];
472
  $element['runtime'] = $widget['runtime'];
473
  $element['poll_type'] = $widget['poll_type'];
474
  $element['cancelvote_allow'] = $widget['cancelvote_allow'];
475
  $element['result_allow'] = $widget['result_allow'];
476
  $element['delete_votes'] = $widget['delete_votes'];
477
  $element['group'] = $widget['group'];
478
  $element['add-more'] = $widget['add-more'];
479
  // Hidden elements for serialized fields.
480
  $element['poll_features'] = $widget['poll_features'];
481
  $element['choice'] = $widget['choice'];
482

    
483
  return $element;
484
}
485

    
486
/**
487
 * ajax more choice callback
488
 */
489
function pollfield_more_choice_callback_js($form, $form_state) {
490
  $field = $form[$form_state['field_name']];
491
  $lang = $form_state['field_lang'];
492
  if (!isset($field[$lang])) {
493
    $lang = LANGUAGE_NONE;
494
  }
495
  $delta = $form_state['field_delta'];
496
  return $field[$lang][$delta]['group'];
497
}
498

    
499
/**
500
 * submit more choice callback
501
 */
502
function pollfield_more_choice_callback_submit($form, &$form_state) {
503
  $form_state['count_choices'] += 1;
504
  $form_state['rebuild'] = TRUE;
505
}
506

    
507
/**
508
 * Implements hook_field_widget_error().
509
 *
510
 * hook_field_widget_error() lets us figure out what to do with errors
511
 * we might have generated in hook_field_validate(). Generally, we'll just
512
 * call form_error().
513
 *
514
 * @see field_example_field_validate()
515
 * @see form_error()
516
 */
517
function pollfield_field_widget_error($element, $error, $form, &$form_state) {
518
  switch ($error['error']) {
519
    case 'field_example_invalid':
520
      form_error($element, $error['message']);
521
      break;
522
  }
523
}
524

    
525
/**
526
 * Save vote information.
527
 */
528
function pollfield_save_choice($vote, $node) {
529
  // Get total votes.
530
  $field = field_get_items('node', $node, $vote->field_name);
531
  $total_votes = isset($field[0]['votes']) ? $field[0]['votes'] : 0;
532

    
533
  $vote->table = 'field_revision_' . $vote->field_name;
534
  // Make sure the voter filled out the poll form correctly.
535
  $vote_error = FALSE;
536

    
537
  if ($vote->type == 'single' && !isset($vote->choice)) {
538
    $vote_error = TRUE;
539
  }
540
  else {
541
    if (!isset($vote->choice) || !count($vote->choice)) {
542
      $vote_error = TRUE;
543
    }
544
  }
545
  if ($vote_error) {
546
    drupal_set_message(t('Choice is not selected. Select your answer and vote.'), 'warning');
547
    return FALSE;
548
  }
549

    
550
  // Check if the user has already voted on this pollfield.
551
  $elements['entity'] = $node;
552
  $elements['field']['field_name'] = $vote->field_name;
553
  $elements['delta'] = $vote->field_name_delta;
554
  $elements['item'] = $vote->item;
555

    
556
  if (!pollfield_user_voted($elements)) {
557
    // Save votes.
558
    foreach ($vote->choice as $choice) {
559
      pollfield_save_vote_record($vote, $choice);
560
    }
561

    
562
    // Increment total votes for this pollfield.
563
    $total_votes++;
564
    $node->{$vote->field_name}[LANGUAGE_NONE][0]['votes'] = $total_votes;
565
    field_attach_update('node', $node);
566

    
567
    // Any time a vote is recorded, clear the CCK cache
568
    // so the votes can be updated.
569
    pollfield_clear($node);
570

    
571
    drupal_set_message(t('Your vote was recorded.'));
572
  }
573
  else {
574
    drupal_set_message(t('You already voted or you are not allowed to vote'), 'error');
575
    return FALSE;
576
  }
577
  return TRUE;
578
}
579

    
580
/**
581
 * Write a vote to the database.
582
 */
583
function pollfield_save_vote_record($vote, $choice) {
584
  // Store user id if the user is logged in.
585
  if ($vote->uid > 0) {
586
    db_insert('pollfield_votes')
587
      ->fields(array(
588
        'nid' => $vote->nid,
589
        'field_table' => $vote->table,
590
        'field_name' => $vote->field_name,
591
        'uid' => $vote->uid,
592
        'delta' => $choice,
593
        'field_name_delta' => $vote->field_name_delta,
594
      ))
595
      ->execute();
596
  }
597
  // Store IP or cookie if the user is anonymous.
598
  else {
599
    db_insert('pollfield_votes')
600
      ->fields(array(
601
        'nid' => $vote->nid,
602
        'field_table' => $vote->table,
603
        'field_name' => $vote->field_name,
604
        'uid' => $vote->uid,
605
        'delta' => $choice,
606
        'hostname' => $vote->hostname,
607
        'field_name_delta' => $vote->field_name_delta,
608
        'cookie' => $vote->cookie,
609
      ))
610
      ->execute();
611
  }
612
}
613

    
614
/**
615
 * Cancel a user's vote on a poll.
616
 */
617
function pollfield_cancel_choice($vote, $node) {
618
  // Get total votes.
619
  $field = field_get_items('node', $node, $vote->field_name);
620
  $total_votes = isset($field[0]['votes']) ? $field[0]['votes'] : 0;
621

    
622
  // Cancel all the votes by this user on this poll.
623
  pollfield_cancel_vote_record($vote);
624

    
625
  // Decrement total votes for this pollfield.
626
  $total_votes--;
627
  $total_votes = ($total_votes < 0) ? 0 : $total_votes;
628
  $node->{$vote->field_name}[LANGUAGE_NONE][0]['votes'] = $total_votes;
629
  field_attach_update('node', $node);
630

    
631
  return TRUE;
632
}
633

    
634
/**
635
 * Delete votes from the database.
636
 *
637
 * Delete votes made by a specific user on a specific pollfield.
638
 */
639
function pollfield_cancel_vote_record($vote) {
640
  $query = db_delete('pollfield_votes')
641
    ->condition('nid', $vote->nid)
642
    ->condition('field_table', $vote->field_table)
643
    ->condition('field_name', $vote->field_name)
644
    ->condition('field_name_delta', $vote->field_name_delta);
645

    
646
  if ($vote->uid) {
647
    $query->condition('uid', $vote->uid);
648
    $query->execute();
649
  }
650
  else {
651
    if ($vote->anonymous == 'anon_by_ip') {
652
      $query->condition('hostname', $vote->hostname);
653
      $query->execute();
654
    }
655
    elseif ($vote->anonymous == 'anon_by_cookie') {
656
      $query->condition('cookie', $vote->cookie);
657
      $query->execute();
658
    }
659
  }
660
}
661

    
662
/**
663
 * Saving or canceling user poll vote.
664
 */
665
function pollfield_vote($form, &$form_state) {
666

    
667
$vote = new stdClass();
668
  $values = $form_state['input'];
669
  // Build vote object.
670
  $vote->nid = $values['nid'];
671
  $vote->field_name = $values['field_name'];
672
  $vote->field_name_delta = $values['field_name_delta'];
673
  $vote->field_table = $values['table'];
674
  $vote->cancel = $values['cancel'];
675
  if (isset($values['choice'])) {
676
    if (is_array($values['choice'])) {
677
      $choices = array_filter($values['choice']);
678
      $vote->choice = array_keys($choices);
679
    }
680
    else {
681
      $vote->choice = array($values['choice']);
682
    }
683
  }
684
  $item = unserialize($values['item']);
685
  $vote->item = $item;
686

    
687
  // Information about the voter.
688
  global $user;
689
  $vote->uid = $user->uid;
690
  $vote->hostname = ip_address();
691

    
692
  // If we need a cookie add it here.
693
  $cookie = pollfield_cookie_id_generator($values);
694
  $vote->cookie = ($cookie) ? serialize($cookie) : $cookie;
695

    
696
  $node = node_load($vote->nid);
697

    
698
  // Get poll features.
699
  $poll_features = unserialize($item['poll_features']);
700
  $vote->anonymous = $item['anonymous'];
701

    
702
  if ($vote->nid) {
703
    // Cancel vote.
704
    if ($vote->cancel) {
705
      pollfield_cancel_choice($vote, $node);
706
    }
707
    // Vote.
708
    else {
709
      $vote->type = $poll_features['poll_type'];
710
      pollfield_save_choice($vote, $node);
711
    }
712
  }
713
  // Clear the cache.
714
  pollfield_clear($node);
715
}
716

    
717
/**
718
 * Cookie generator for anonymous voting.
719
 */
720
function pollfield_cookie_id_generator($values) {
721
  global $user;
722

    
723
  $item = unserialize($values['item']);
724
  if ($item['anonymous'] != 'anon_by_cookie') {
725
    return FALSE;
726
  }
727

    
728
  $nid = $values['nid'];
729
  $field_name = $values['field_name'];
730
  $field_name_delta = $values['field_name_delta'];
731
  $field_table = $values['table'];
732
  $node = node_load($nid);
733
  $user_id_cookie = rand(0, 100000) + time();
734
  $user_id_cookie = 'id' . $user_id_cookie;
735
  // /cookie add***************************************
736
  $cookie_name = $field_table . '_' . $field_name . '_' . $field_name_delta;
737
  $cookie_value = $user_id_cookie;
738
  $field = $node->$field_name;
739
  $duration = $item['runtime'];
740

    
741
  if (!isset($_COOKIE[$cookie_name])) {
742
    if ($duration == 0) {
743
      // If poll is unlimited set expire one month.
744
      $expire = time() + 60 * 60 * 24 * 30;
745
    }
746
    else {
747
      $expire = time() + $duration;
748
    }
749
    setcookie($cookie_name, $cookie_value, $expire, '/');
750
    $cookie = array(
751
      'cookie_name' => $cookie_name,
752
      'cookie_value' => $cookie_value,
753
    );
754
  }
755
  else {
756
    $cookie = array(
757
      'cookie_name' => $cookie_name,
758
      'cookie_value' => $_COOKIE[$cookie_name],
759
    );
760
  }
761

    
762
  return $cookie;
763
}
764

    
765
/**
766
 * Check if user has voted on a specific pollfield.
767
 *
768
 * @return int
769
 *   Integer of the number of votes.
770
 *   0 if they haven't voted.
771
 */
772
function pollfield_user_voted($elements) {
773
  global $user;
774

    
775
  $node = $elements['entity'];
776

    
777
  $field_name = $elements['field']['field_name'];
778
  $field_table = 'field_revision_' . $field_name;
779
  $field_name_delta = $elements['delta'];
780

    
781
  $nid = $node->nid;
782
  $uid = $user->uid;
783
  $hostname = ip_address();
784
  $voted = FALSE;
785
  $is_voted = 0;
786

    
787
  // There is no translation.
788
  if ($node->tnid == 0) {
789
    $t_nodes_results = array($nid);
790
  }
791
  // There is translation.
792
  else {
793
    $t_nodes_results = db_select('node', 'n')
794
      ->fields('n', array('nid'))
795
      ->condition('tnid', $node->tnid)
796
      ->execute()
797
      ->fetchAllAssoc('nid');
798
    $t_nodes_results = array_keys($t_nodes_results);
799
  }
800

    
801
  // Check all translations.
802
  foreach ($t_nodes_results as $t_nid) {
803
    // Get anonymous vote settings.
804
    $field = $elements['item'];
805
    $anonymous = $field['anonymous'];
806

    
807
    // Check if user has voted.
808
    if ($user->uid) {
809
      $voted = (int) db_select('pollfield_votes', 'pfv')
810
        ->condition('pfv.nid', $t_nid)
811
        ->condition('pfv.field_table', $field_table)
812
        ->condition('pfv.field_name', $field_name)
813
        ->condition('pfv.uid', $user->uid)
814
        ->condition('pfv.field_name_delta', $field_name_delta)
815
        ->countQuery()->execute()->fetchField();
816
    }
817
    // User is anonymous.
818
    else {
819
      if ($anonymous == 'anon_by_ip') {
820
        $voted = (int) db_select('pollfield_votes', 'pfv')
821
          ->condition('pfv.nid', $t_nid)
822
          ->condition('pfv.field_table', $field_table)
823
          ->condition('pfv.field_name', $field_name)
824
          ->condition('pfv.hostname', $hostname)
825
          ->condition('pfv.field_name_delta', $field_name_delta)
826
          ->countQuery()->execute()->fetchField();
827
      }
828
      elseif ($anonymous == 'anon_by_cookie') {
829
        // Add cookie.
830
        $cookie_name = $field_table . '_' . $field_name . '_' . $field_name_delta;
831
        $cookie_collected_value = isset($_COOKIE[$cookie_name]) ? $_COOKIE[$cookie_name] : '';
832

    
833
        $cookie_compare = array(
834
          'cookie_name' => $cookie_name,
835
          'cookie_value' => $cookie_collected_value,
836
        );
837

    
838
        $cookie_compare_db = serialize($cookie_compare);
839

    
840
        $voted = (int) db_select('pollfield_votes', 'pfv')
841
          ->condition('pfv.nid', $t_nid)
842
          ->condition('pfv.field_table', $field_table)
843
          ->condition('pfv.field_name', $field_name)
844
          ->condition('pfv.cookie', $cookie_compare_db)
845
          ->condition('pfv.field_name_delta', $field_name_delta)
846
          ->countQuery()->execute()->fetchField();
847
      }
848
    }
849

    
850
    $is_voted += $voted;
851
  }
852

    
853
  return $is_voted;
854
}
855

    
856
/**
857
 * Get user votes.
858
 *
859
 * @return array Returns an array of votes for theme functions.
860
 */
861
function pollfield_user_votes($elements) {
862
  global $user;
863
  $node = $elements['entity'];
864
  $hostname = ip_address();
865

    
866
  $field_name = $elements['field']['field_name'];
867
  $field_table = 'field_revision_' . $field_name;
868
  $field_name_delta = $elements['delta'];
869

    
870
  // There is no translation.
871
  if ($node->tnid == 0) {
872
    $t_nodes_results = array($node->nid);
873
  }
874
  // There is translation.
875
  else {
876
    $t_nodes_results = db_select('node', 'n')
877
      ->fields('n', array('nid'))
878
      ->condition('tnid', $node->tnid)
879
      ->execute()
880
      ->fetchAllAssoc('nid');
881
    $t_nodes_results = array_keys($t_nodes_results);
882
  }
883

    
884
  $votes = array();
885
  // Check all translations.
886
  foreach ($t_nodes_results as $t_nid) {
887
    $query = db_select('pollfield_votes', 'pfv')
888
      ->fields('pfv', array('delta'))
889
      ->condition('nid', $t_nid)
890
      ->condition('field_table', $field_table)
891
      ->condition('field_name', $field_name)
892
      ->condition('field_name_delta', $field_name_delta);
893

    
894
    // Get user votes.
895
    if ($user->uid) {
896
      // Delta is number of choice.
897
      $result = $query->condition('uid', $user->uid)
898
        ->execute()->fetchAllAssoc('delta');
899
      $votes = array_merge($votes, array_keys($result));
900
    }
901
    // User is anonymous.
902
    else {
903
      $anonymous = $elements['item']['anonymous'];
904
      if ($anonymous == 'anon_by_ip') {
905
        // Delta is number of choice.
906
        $result = $query->condition('hostname', $hostname)
907
          ->execute()->fetchAllAssoc('delta');
908
        $votes = array_merge($votes, array_keys($result));
909
      }
910
      elseif ($anonymous == 'anon_by_cookie') {
911
        // Generate cookie.
912
        $cookie_name = $field_table . '_' . $field_name . '_' . $field_name_delta;
913
        $cookie_collected_value = isset($_COOKIE[$cookie_name]) ? $_COOKIE[$cookie_name] : '';
914
        $cookie_compare = array(
915
          'cookie_name' => $cookie_name,
916
          'cookie_value' => $cookie_collected_value,
917
        );
918

    
919
        $result = $query->condition('cookie', serialize($cookie_compare))
920
          ->execute()->fetchAllAssoc('delta');
921
        $votes = array_merge($votes, array_keys($result));
922
      }
923
    }
924
  }
925

    
926
  return $votes;
927
}
928

    
929
/**
930
 * Build array of duration options
931
 *
932
 * The times in seconds that a pollfield can run for.
933
 */
934
function pollfield_duration_options() {
935
  $options = array(86400, 172800, 345600, 604800, 1209600, 2419200, 4838400, 9676800, 31536000);
936
  $duration_options = array(0 => t('Unlimited')) + drupal_map_assoc($options, "format_interval");
937
  return $duration_options;
938
}
939

    
940
/**
941
 * Internal callback to validate starting vote totals.
942
 *
943
 * Check that this value is an integer.
944
 */
945
function _pollfield_is_digits_validate($element, &$form_state) {
946
  if ($element['#value'] != NULL) {
947
    if (!ctype_digit($element['#value'])) {
948
      form_error($element, t('The starting votes count must be a whole number.'));
949
    }
950
  }
951
}
952

    
953
/**
954
 * Default field formatter function.
955
 */
956
function theme_pollfield_default_formatter($elements) {
957
  // Node object.
958
  $node = $elements['elements']['entity'];
959
  $delta = $elements['elements']['delta'];
960
  // Get the available choices for this poll.
961
  $choices = unserialize($elements['elements']['item']['choice']);
962
  $item = $elements['elements']['item'];
963

    
964
  $output = '';
965
  if (!empty($choices)) {
966
    $pollfield_title = check_plain($elements['elements']['item']['question']);
967
    $poll_result = pollfield_build_results($elements['elements']);
968

    
969
    // Build voting form.
970
    $form = drupal_get_form('pollfield_voting_form', $elements['elements']);
971

    
972
    $output  = '<div class="pollfield">';
973
    $output .= '<div id="pollfield-' . $node->nid . '-' . $delta . '" class="pollfield-form">';
974
    $output .= '<div class="pollfield-title">' . $pollfield_title . '</div>';
975
    $output .= $poll_result;
976
    $output .= render($form);
977
    $output .= '</div>';
978
    $output .= '</div>';
979
  }
980

    
981
  return $output;
982
}
983

    
984
/**
985
 * Build voting form
986
 *
987
 * Checks all the various rules associate with the current
988
 * pollfield and builds a form that lets you vote on
989
 * or cancel a pollfield.
990
 */
991
function pollfield_voting_form($form, $form_state, $elements) {
992
  if (empty($elements['item']['active'])) {
993
    return NULL;
994
  }
995

    
996
  global $user;
997
  $table = 'field_revision_' . $elements['field']['field_name'];
998
  $field_name = $elements['field']['field_name'];
999
  $field_name_delta = $elements['delta'];
1000
  $items = $elements['item'];
1001
  $node = $elements['entity'];
1002

    
1003
  // Get poll features.
1004
  if (is_array($elements['item']['poll_features'])) {
1005
    $poll_features = $elements['item']['poll_features'];
1006
  }
1007
  else {
1008
    $poll_features = unserialize($elements['item']['poll_features']);
1009
  }
1010

    
1011
  // Get anonymous vote settings.
1012
  $anonymous = $elements['item']['anonymous'];
1013

    
1014
  // If the user has voted, build the cancel vote form.
1015
  if (pollfield_user_voted($elements)) {
1016
    if ($user->uid) {
1017
      // Allow cancel vote.
1018
      if ($poll_features['cancelvote_allow']) {
1019
        $cancel = 1;
1020
        pollfield_voting_form_data($form, $field_name_delta, $field_name, $node->nid, $table, $cancel, $items);
1021
      }
1022
    }
1023
    else {
1024
      if ($anonymous == 'anon_non') {
1025
        return NULL;
1026
      }
1027
      else {
1028
        if ($poll_features['cancelvote_allow']) {
1029
          $cancel = 1;
1030
          pollfield_voting_form_data($form, $field_name_delta, $field_name, $node->nid, $table, $cancel, $items);
1031
        }
1032
      }
1033
    }
1034
  }
1035

    
1036
  // If the user hasn't voted, build the vote form.
1037
  else {
1038
    if ($user->uid == 0) {
1039
      if ($anonymous == 'anon_non') {
1040
        return NULL;
1041
      }
1042
    }
1043
    if ($items) {
1044
      $list = array();
1045
      $choices = unserialize($items['choice']);
1046
      if (!empty($choices)) {
1047
        // Build choices array.
1048
        foreach ($choices as $delta => $choice) {
1049
          if (!empty($choice['choice'])) {
1050
            $list[$delta] = check_plain($choice['choice']);
1051
          }
1052
        }
1053
        // Build single choice poll.
1054
        if ($poll_features['poll_type'] == 'single') {
1055
          $form['choice'] = array(
1056
            '#type' => 'radios',
1057
            '#title' => check_plain($items['question']),
1058
            '#title_display' => 'invisible',
1059
            '#options' => $list,
1060
          );
1061
        }
1062
        // Build multiple choice poll.
1063
        else {
1064
          $form['choice'] = array(
1065
            '#type' => 'checkboxes',
1066
            '#title' => check_plain($items['question']),
1067
            '#title_display' => 'invisible',
1068
            '#options' => $list,
1069
          );
1070
        }
1071
      }
1072
    }
1073
    $cancel = 0;
1074
    pollfield_voting_form_data($form, $field_name_delta, $field_name, $node->nid, $table, $cancel, $items);
1075
  }
1076

    
1077
  return $form;
1078
}
1079

    
1080
/**
1081
 * Voting form data.
1082
 */
1083
function pollfield_voting_form_data(&$form, $field_name_delta, $field_name, $nid, $table, $cancel, $items) {
1084
  $form['field_name_delta'] = array(
1085
    '#type' => 'hidden',
1086
    '#value' => $field_name_delta,
1087
  );
1088
  $form['field_name'] = array(
1089
    '#type' => 'hidden',
1090
    '#value' => $field_name,
1091
  );
1092
  $form['nid'] = array(
1093
    '#type' => 'hidden',
1094
    '#value' => $nid,
1095
  );
1096
  $form['item'] = array(
1097
    '#type' => 'hidden',
1098
    '#value' => serialize($items),
1099
  );
1100
  $form['table'] = array(
1101
    '#type' => 'hidden',
1102
    '#value' => $table,
1103
  );
1104
  $form['cancel'] = array(
1105
    '#type' => 'hidden',
1106
    '#value' => $cancel,
1107
  );
1108
  $form['vote'] = array(
1109
    '#type' => 'submit',
1110
    '#value' => $cancel ? t('Cancel Vote') : t('Vote'),
1111
    '#submit' => array('pollfield_vote'),
1112
  );
1113
}
1114

    
1115
/**
1116
 * Build the results display
1117
 *
1118
 * @param array $elements Elements
1119
 *
1120
 * @return pollfield_result
1121
 *   A formatted HTML string of the appropriate pollfield
1122
 *   result display. Will output empty HTML structure if
1123
 *   the user can't view results b/c of permissions.
1124
 */
1125
function pollfield_build_results($elements) {
1126
  $poll_result = '';
1127

    
1128
  $active = $elements['item']['active'];
1129
  $display_before = pollfield_display_results_before_vote($elements['item']);
1130

    
1131
  // Get the available choices for this poll.
1132
  $choices = unserialize($elements['item']['choice']);
1133

    
1134
  // Determine if the user voted on this node.
1135
  $user_voted = pollfield_user_voted($elements);
1136
  $user_votes = pollfield_user_votes($elements);
1137

    
1138
  // Array of vote totals for each choice.
1139
  $votes = pollfield_sum_all_votes($elements['entity'], $choices, $elements);
1140
  // Total of all votes.
1141
  $sum = array_sum($votes);
1142

    
1143
  // If the user has permission to view results and
1144
  // this node allows results viewing, show them.
1145
  if (user_access('view pollfield results ' . $elements['field']['field_name'])) {
1146
    if ($user_voted || $display_before || !$active) {
1147
      foreach ($choices as $delta => $choice) {
1148
        if (!empty($choice['choice'])) {
1149
          $percent = ($sum == 0) ? 0 : round(floatval(($votes[$delta] * 100.0) / $sum), 1);
1150
          $percent_string = $percent . '% (' . format_plural($votes[$delta], '1 vote', '@count votes') . ')';
1151
          $user_choice = (is_array($user_votes) && in_array($delta, $user_votes)) ? TRUE : FALSE;
1152

    
1153
          $variables = array(
1154
            'choice' => $choice['choice'],
1155
            'percent' => $percent,
1156
            'percent_string' => $percent_string,
1157
            'user_choice' => $user_choice,
1158
          );
1159
          $poll_result .= theme('pollfield_row', $variables);
1160
        }
1161
      }
1162
    }
1163
  }
1164

    
1165
  return $poll_result;
1166
}
1167

    
1168
/**
1169
 * Return an array of vote totals for each choice in a pollfield.
1170
 */
1171
function pollfield_sum_all_votes($node, $choices, $elements) {
1172
  $field_name = $elements['field']['field_name'];
1173
  $field_name_delta = $elements['delta'];
1174
  $table = 'field_revision_' . $field_name;
1175
  // This check is required until we can stop empty pollfields from
1176
  // requesting a vote count, which would be more efficient.
1177
  $choice_count = array();
1178
  if (is_array($choices)) {
1179
    foreach ($choices as $delta => $group) {
1180
      // Count user submitted votes.
1181
      $count = (int) db_select('pollfield_votes', 'pfv')
1182
        ->condition('nid', $node->nid)
1183
        ->condition('delta', $delta)
1184
        ->condition('field_table', $table)
1185
        ->condition('field_name', $field_name)
1186
        ->condition('field_name_delta', $field_name_delta)
1187
        ->countQuery()->execute()->fetchField();
1188
      $choice_count[$delta] = $choices[$delta]['votes'] + $count;
1189
    }
1190
  }
1191
  return $choice_count;
1192
}
1193

    
1194
/**
1195
 * Return a sum of the total votes on a pollfield.
1196
 *
1197
 * TODO: dead code?
1198
 */
1199
function pollfield_sum_starting_votes($choices) {
1200
  // This check is required until we can stop empty pollfields from
1201
  // requesting a vote count, which would be more efficient.
1202
  if (is_array($choices)) {
1203
    foreach ($choices as $delta => $group) {
1204
      // Count starting votes.
1205
      $total_votes = $total_votes + $choices[$delta]['votes'];
1206
    }
1207
    return $total_votes;
1208
  }
1209
}
1210

    
1211
/**
1212
 * Does this node allow the user to view results?
1213
 *
1214
 * @param $item Array of the pollfield information
1215
 *
1216
 * @return boolean
1217
 *   Boolean value. Defaults to FALSE, meaning you can't view the results
1218
 *   before you vote on the pollfield.
1219
 */
1220
function pollfield_display_results_before_vote($item) {
1221
  $poll_features = unserialize($item['poll_features']);
1222
  if ($poll_features['result_allow']) {
1223
    return TRUE;
1224
  }
1225
  return FALSE;
1226
}
1227

    
1228
/**
1229
 * choices field formatter function
1230
 */
1231
function theme_pollfield_choices_formatter($item, $entity) {
1232
  // Node object.
1233
  $node = $elements['elements']['entity'];
1234
  $delta = $elements['elements']['delta'];
1235
  // Get the available choices for this poll.
1236
  $choices = unserialize($elements['elements']['item']['choice']);
1237

    
1238
  $output = '';
1239
  if (!empty($choices)) {
1240
    $pollfield_title = check_plain($elements['elements']['item']['question']);
1241
    $poll_result = pollfield_build_results($elements['elements']);
1242

    
1243
    // Build voting form.
1244
    $form = drupal_get_form('pollfield_voting_form', $elements['elements']);
1245

    
1246
    $output  = '<div class="pollfield">';
1247
    $output .= '<div id="pollfield-' . $node->nid . '-' . $delta . '" class="pollfield-form">';
1248
    $output .= '<div class="pollfield-title">' . $pollfield_title . '</div>';
1249
    $output .= '</div>';
1250
    $output .= '</div>';
1251
  }
1252

    
1253
  return $output;
1254
}
1255
/**
1256
 * Results field formatter function.
1257
 */
1258
function theme_pollfield_results_formatter($item, $entity) {
1259
  // Node object.
1260
  $node = $elements['elements']['entity'];
1261
  $delta = $elements['elements']['delta'];
1262
  // Get the available choices for this poll.
1263
  $choices = unserialize($elements['elements']['item']['choice']);
1264

    
1265
  $output = '';
1266
  if (!empty($choices)) {
1267
    $pollfield_title = check_plain($elements['elements']['item']['question']);
1268
    $poll_result = pollfield_build_results($elements['elements']);
1269

    
1270
    // Build voting form.
1271
    $form = drupal_get_form('pollfield_voting_form', $elements['elements']);
1272

    
1273
    $output  = '<div class="pollfield">';
1274
    $output .= '<div id="pollfield-' . $node->nid . '-' . $delta . '" class="pollfield-form">';
1275
    $output .= '<div class="pollfield-title">' . $pollfield_title . '</div>';
1276
    $output .= $poll_result;
1277
    $output .= '</div>';
1278
    $output .= '</div>';
1279
  }
1280
  return $output;
1281
}
1282
/**
1283
 * Runtime field formatter function.
1284
 */
1285
function theme_pollfield_runtime_formatter($item, $entity) {
1286
  $node = $elements['elements']['entity'];
1287
  $delta = $elements['elements']['delta'];
1288
  // Get the available choices for this poll.
1289
  $choices = unserialize($elements['elements']['item']['choice']);
1290

    
1291
  $output = '';
1292
  if (!empty($choices)) {
1293

    
1294
    if ($elements['elements']['item']['runtime'] > 0) {
1295
      $runtime = t('!duration duration of poll in seconds', array('!duration' => $elements['elements']['item']['runtime']));
1296
    }
1297
    else {
1298
      $runtime = t('Unlimited poll duration.');
1299
    }
1300
    $out = '<div class="pollfield-runtime">' . check_plain($runtime) . '</div>';
1301
    return $out;
1302
  }
1303
  return $output;
1304
}
1305

    
1306
/**
1307
 * Question field formatter function.
1308
 */
1309
function theme_pollfield_question_formatter($item, $entity) {
1310
  // TODO: fix.
1311
  $node = $elements['elements']['entity'];
1312
  $delta = $elements['elements']['delta'];
1313
  // Get the available choices for this poll.
1314
  $choices = unserialize($elements['elements']['item']['choice']);
1315

    
1316
  $output = '';
1317
  if (!empty($choices)) {
1318
    $output = '<div class="pollfield-questions">';
1319

    
1320
    if ($elements['elements']['item']['question'] != "' '") {
1321
      $output .= '<div class="pollfield-row">' . check_plain($elements['elements']['item']['question']) . '</div>';
1322
    }
1323
    $output .= '</div>';
1324
  }
1325
  return $output;
1326
}
1327

    
1328
/**
1329
 * Implements hook_theme().
1330
 *
1331
 * Define the theme hooks for pollfield.
1332
 *
1333
 * These setup the various display styles you can choose
1334
 * in the CCK display settings for this field.
1335
 */
1336
function pollfield_theme() {
1337
  return array(
1338
    'pollfield_default_formatter' => array(
1339
      'variables' => array('elements'),
1340
    ),
1341
    'pollfield_row' => array(
1342
      'variables' => array(
1343
        'choice' => NULL,
1344
        'user_choice' => FALSE,
1345
        'percent' => NULL,
1346
        'percent_string' => NULL,
1347
      ),
1348
    ),
1349
    'pollfield_results_formatter' => array(
1350
      'variables' => array('elements'),
1351
    ),
1352
    'pollfield_question_formatter' => array(
1353
      'variables' => array('elements'),
1354
    ),
1355
    'pollfield_runtimeformatter_' => array(
1356
      'variables' => array('elements'),
1357
    ),
1358
    'pollfield_choices_formatter' => array(
1359
      'variables' => array('elements'),
1360
    ),
1361
  );
1362
}
1363

    
1364
/**
1365
 * Theme function for an single results row.
1366
 */
1367
function theme_pollfield_row($variables) {
1368
  // Mark the user's vote.
1369
  $row_class = '';
1370
  if ($variables['user_choice']) {
1371
    $row_class = ' pollfield-chosen';
1372
  }
1373
  $output  = '<div class="pollfield-row' . $row_class . '">';
1374
  $output .= '<div class="text">' . check_plain($variables['choice']) . '</div>';
1375
  $output .= '<div class="barcell">';
1376
  $output .= '<div class="bar"><div class="pollfield-foreground" style="width: ' . $variables['percent'] . '%;"></div></div>';
1377
  $output .= '</div>';
1378
  $output .= '<div class="pollfield-percent">' . $variables['percent_string'] . '</div>';
1379
  $output .= '</div>';
1380
  return $output;
1381
}
1382

    
1383
/**
1384
 * Implements hook_permission().
1385
 *
1386
 * Defines the permission options for pollfields.
1387
 */
1388
function pollfield_permission() {
1389
  $permissions = array();
1390
  $fields = field_read_fields(array('type' => 'pollfield_poll'));
1391
  // Build a permission for each pollfield enabled content type.
1392
  foreach ($fields as $field_name => $field) {
1393
    $permissions['view pollfield results ' . $field_name] = array(
1394
      'title' => t('%field_name: View pollfield results', array('%field_name' => $field_name)),
1395
    );
1396
    $permissions['admin pollfield ' . $field_name] = array(
1397
      'title' => t('%field_name: Full admin access to pollfield edit options', array('%field_name' => $field_name)),
1398
    );
1399
  }
1400
  return $permissions;
1401
}
1402

    
1403
/**
1404
 * Clear the Drupal cache
1405
 *
1406
 * The cache is generally cleared after a vote is recorded
1407
 *
1408
 * TODO - really? clear the entire cache every time a vote is recorded?
1409
 */
1410
function pollfield_clear($node) {
1411
  $cid = 'field:node:' . $node->nid;
1412
  cache_clear_all($cid, db_table_exists('cache_field') ? 'cache_field' : 'cache', TRUE);
1413
  cache_clear_all();
1414
}
1415

    
1416
/**
1417
 * Implements hook_node_delete().
1418
 */
1419
function pollfield_node_delete($node) {
1420
  db_delete('pollfield_votes')
1421
    ->condition('nid', $node->nid)
1422
    ->execute();
1423
}
1424

    
1425
/**
1426
 * Implementation of hook_cron().
1427
 * Closes pollfields that have exceeded their allowed runtime.
1428
 */
1429
function pollfield_cron() {
1430
  $time = time();
1431
	$fields_query = db_query("SELECT field_name FROM {field_config} WHERE type='pollfield_poll'");
1432
	while ($field_name=$fields_query->fetchField()){
1433
		$query="SELECT p.* FROM {field_revision_".$field_name."} p LEFT JOIN {node} n ON n.nid=p.entity_id WHERE (n.created + p.".$field_name."_runtime)<".$time;
1434
		$polls_query = db_query($query);
1435
		while ($polls=$polls_query->fetchObject()){
1436
			$query_update = "UPDATE {field_revision_".$field_name."} SET ".$field_name."_active = 0 WHERE entity_id=".$polls->entity_id." AND delta = ".$polls->delta;
1437
			db_query($query_update);
1438
			$query_update = "UPDATE {field_data_".$field_name."} SET ".$field_name."_active = 0 WHERE entity_id=".$polls->entity_id." AND delta = ".$polls->delta;
1439
			db_query($query_update);
1440
		}
1441
	}
1442
  
1443
}