Projet

Général

Profil

Paste
Télécharger (27,7 ko) Statistiques
| Branche: | Révision:

root / htmltest / sites / all / modules / fivestar / includes / fivestar.field.inc @ 3cb08e71

1
<?php
2

    
3
/**
4
 * @file
5
 * Provides CCK integration for fivestar module
6
 */
7

    
8
/**
9
 * Implementation of hook_field_info().
10
 */
11
function fivestar_field_info() {
12
  return array(
13
    'fivestar' => array(
14
      'label' => t('Fivestar Rating'),
15
      'description' => t('Store a rating for this piece of content.'),
16
      'default_widget' => 'exposed',
17
      'default_formatter' => 'fivestar_formatter_default',
18
      'settings' => array(
19
        'axis' => 'vote',
20
      ),
21
      'instance_settings' => array(
22
        'stars' => 5,
23
      ),
24
      'property_type' => 'fivestar',
25
      'property_callbacks' => array('fivestar_property_info_callback'),
26
      'microdata' => TRUE,
27
    ),
28
  );
29
}
30

    
31
function fivestar_form_field_ui_field_edit_form_alter(&$form, $form_state) {
32
  $field = $form['#field'];
33
  $instance = $form['#instance'];
34
  if ($field['type'] == 'fivestar') {
35
    // Multiple values is not supported with Fivestar.
36
    $form['field']['cardinality']['#access'] = FALSE;
37
    $form['field']['cardinality']['#value'] = 1;
38
    // Setting "default value" here is confusing and for all practical purposes
39
    // with existing widgets provided by fivestar (and anything else available
40
    // in contrib) meaningless.
41
    $form['instance']['default_value_widget']['#access'] = FALSE;
42
  }
43
}
44

    
45
/**
46
 * Implementation of hook_field_settings_form().
47
 */
48
function fivestar_field_settings_form($field, $instance) {
49
  $form['axis'] = array(
50
    '#type' => 'select',
51
    '#required' => TRUE,
52
    '#title' => 'Voting Tag',
53
    '#options' => fivestar_get_tags(),
54
    '#description' => t('The tag this rating will affect. Enter a property on which that this rating will affect, such as <em>quality</em>, <em>satisfaction</em>, <em>overall</em>, etc.'),
55
    '#default_value' => isset($field['settings']['axis']) ? $field['settings']['axis'] : '',
56
    '#disabled' => field_has_data($field),
57
  );
58

    
59
  return $form;
60
}
61

    
62
function fivestar_field_instance_settings_form($field, $instance) {
63
  $form = array();
64

    
65
  $form['stars'] = array(
66
    '#type' => 'select',
67
    '#title' => $instance['widget']['type'] == 'select' ? t('Number of options') : t('Number of stars'),
68
    '#options' => drupal_map_assoc(range(1, 10)),
69
    '#default_value' => isset($instance['settings']['stars']) ? $instance['settings']['stars'] : 5,
70
  );
71
  
72
  $form['allow_clear'] = array(
73
    '#type' => 'checkbox',
74
    '#title' => t('Allow users to cancel their ratings.'),
75
    '#default_value' => isset($instance['settings']['allow_clear']) ? $instance['settings']['allow_clear'] : FALSE,
76
    '#return_value' => 1,
77
  );
78

    
79
  $options = fivestar_get_targets($field, $instance);
80
  $form['target'] = array(
81
    '#title' => t('Voting target'),
82
    '#type' => 'select',
83
    '#default_value' => (isset($instance['settings']['target']) && $instance['widget']['type'] != 'exposed') ? $instance['settings']['target'] : 'none',
84
    '#options' => $options,
85
    '#description' => t('The voting target will make the value of this field cast a vote on another node. Use node reference fields module to create advanced reviews. Use the Parent Node Target when using fivestar with comments. More information available on the <a href="http://drupal.org/handbook/modules/fivestar">Fivestar handbook page</a>.'),
86
    '#access' => (count($options) > 1 && $instance['widget']['type'] != 'exposed'),
87
  );
88
  
89
  return $form;
90
}
91

    
92
/**
93
 * Implementation of hook_field_insert().
94
 */
95
function fivestar_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
96
  _fivestar_field_helper($entity_type, $entity, $field, $instance, $langcode, $items);
97
}
98

    
99
/**
100
 * Implementation of hook_field_update().
101
 */
102
function fivestar_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) {
103
  _fivestar_field_helper($entity_type, $entity, $field, $instance, $langcode, $items);
104
}
105

    
106
/**
107
 * Implementation of hook_field_delete().
108
 */
109
function fivestar_field_delete($entity_type, $entity, $field, $instance, $langcode, &$items) {
110
  _fivestar_field_helper($entity_type, $entity, $field, $instance, $langcode, $items, 'delete');
111
}
112

    
113
function _fivestar_field_helper($entity_type, $entity, $field, $instance, $langcode, &$items, $op = '') {
114
  foreach ($items as $delta => $item) {
115
    if ((isset($entity->status) && !$entity->status) || $op == 'delete') {
116
      $rating = 0;
117
    }
118
    else {
119
      $rating = (isset($items[$delta]['rating'])) ? $items[$delta]['rating'] : 0;
120
    }
121
    $target = _fivestar_field_target($entity, $field, $instance, $item, $langcode);
122
    if (!empty($target)) {
123
      _fivestar_cast_vote($target['entity_type'], $target['entity_id'], $rating, $field['settings']['axis'], $entity->uid, TRUE);
124
      votingapi_recalculate_results($target['entity_type'], $target['entity_id']);
125
    }
126
  }
127
}
128

    
129
/**
130
 * Helper function to find the id that should be rated when a field is changed.
131
 */
132
function _fivestar_field_target($entity, $field, $instance, $item, $langcode) {
133
  if ($instance['widget']['type'] == 'exposed') {
134
    return null;
135
  }
136
  if (isset($instance['settings']['target'])) {
137
    $target = fivestar_get_targets($field, $instance, $instance['settings']['target'], $entity, $langcode);
138
  }
139
  else {
140
    // If all else fails, default to voting on the instance the field is attached to.
141
    list($id, $vid, $bundle) = entity_extract_ids($instance['entity_type'], $entity);
142
    $target = array(
143
      'entity_id' => $id,
144
      'entity_type' => $instance['entity_type'],
145
    );
146
  }
147
  return $target;
148
}
149

    
150
/**
151
 * Helper function to store a rating into the field storage.
152
 */
153
function _fivestar_update_field_value($entity_type, $entity, $field_name, $langcode, $value) {
154
  $entity->{$field_name}[$langcode][0]['rating'] = $value;
155
  field_attach_presave($entity_type, $entity);
156
  field_attach_update($entity_type, $entity);
157
}
158

    
159
/**
160
 * Implementation of hook_field_is_empty().
161
 */
162
function fivestar_field_is_empty($item, $field) {
163
  return empty($item['rating']) || $item['rating'] == '-';
164
}
165

    
166
/**
167
 * Implementation of hook_field_widget_info().
168
 */
169
function fivestar_field_widget_info() {
170
  return array(
171
    'exposed' => array(
172
      'label' => t('Stars (rated while viewing)'),
173
      'field types' => array('fivestar'),
174
      'behaviors' => array('multiple values' => FIELD_BEHAVIOR_NONE),
175
    ),
176
    'stars' => array(
177
      'label' => t('Stars (rated while editing)'),
178
      'field types' => array('fivestar'),
179
      'behaviors' => array('multiple values' => FIELD_BEHAVIOR_NONE),
180
      'settings' => array(
181
        'widget' => array(
182
          'fivestar_widget' => 'default',
183
        )
184
      )
185
    ),
186
    'fivestar_select' => array(
187
      'label' => t('Select list (rated while editing)'),
188
      'field types' => array('fivestar'),
189
      'behaviors' => array('multiple values' => FIELD_BEHAVIOR_NONE),
190
    ),
191
  );
192
}
193

    
194
/**
195
 * Implementation of hook_field_widget_settings_form().
196
 */
197
function fivestar_field_widget_settings_form($field, $instance) {
198
  $form = array();
199
  if ($instance['widget']['type'] == 'stars') {
200
    $form['widget'] = array(
201
      '#tree' => TRUE,
202
      '#type' => 'fieldset',
203
      '#title' => t('Star display options'),
204
      '#description' => t('Choose a style for your widget.'),
205
      '#weight' => -2,
206
      '#collapsible' => TRUE,
207
      '#collapsed' => TRUE,
208
    );
209

    
210
    $widgets = module_invoke_all('fivestar_widgets');
211

    
212
    $form['widget']['fivestar_widget'] = array(
213
      '#type' => 'radios',
214
      '#options' => array('default' => t('Default')) + $widgets,
215
      '#default_value' => isset($instance['widget']['settings']['widget']['fivestar_widget']) ? $instance['widget']['settings']['widget']['fivestar_widget'] : 'default',
216
      '#attributes' => array('class' => array('fivestar-widgets', 'clearfix')),
217
      '#pre_render' => array('fivestar_previews_expand'),
218
      '#attached' => array('css' => array(drupal_get_path('module', 'fivestar') . '/css/fivestar-admin.css')),
219
    );
220
  }
221

    
222
  return $form;
223
}
224

    
225
function fivestar_previews_expand($element) {
226
  
227
  foreach (element_children($element) as $css) {
228
    $vars = array(
229
      'css' => $css,
230
      'name' => strtolower($element[$css]['#title']),
231
    );
232
    $element[$css]['#description'] = theme('fivestar_preview_widget', $vars);
233
  }
234
  
235
  return $element;
236
}
237

    
238
/**
239
 * Implementation of hook_field_widget_form().
240
 */
241
function fivestar_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
242
  $element['#tree'] = TRUE;
243

    
244
  if ($instance['widget']['type'] == 'fivestar_select' || ($instance['widget']['type'] == 'stars' && isset($form['#title']) && $form['#title'] == 'Default value')) {
245
    $options = array(0 => t('No stars'));
246
    if (empty($instance['settings']['stars'])) {
247
      $instance['settings']['stars'] = 5;
248
    }
249
    for($i = 1; $i <= $instance['settings']['stars']; $i++) {
250
      $percentage = ceil($i * 100 / $instance['settings']['stars']);
251
      $options[$percentage] = format_plural($i, '1 star', '@count stars');
252
    }
253
    $element['rating'] = array(
254
      '#type' => 'select',
255
      '#title' => isset($instance['label']) ? $instance['label'] : FALSE,
256
      '#options' => $options,
257
      '#default_value' => isset($items[$delta]['rating']) ? $items[$delta]['rating'] : NULL,
258
      '#description' => isset($instance['description']) ? $instance['description'] : FALSE,
259
      '#required' => isset($instance['required']) ? $instance['required'] : FALSE,
260
    );
261
  }
262

    
263
  elseif ($instance['widget']['type'] == 'stars') {
264
    $widgets = module_invoke_all('fivestar_widgets');
265
    $active = isset($instance['widget']['settings']['widget']['fivestar_widget']) ? $instance['widget']['settings']['widget']['fivestar_widget'] : 'default';
266
    $widget = array(
267
      'name' => isset($widgets[$active]) ? strtolower($widgets[$active]) : 'default',
268
      'css' => $active,
269
    );
270

    
271
    $values = array(
272
      'user' => 0,
273
      'average' => 0,
274
      'count' => 0,
275
    );
276

    
277
    $settings = array(
278
      'stars' => $instance['settings']['stars'],
279
      'allow_clear' => !empty($instance['settings']['allow_clear']) ? $instance['settings']['allow_clear'] : FALSE,
280
      'style' => 'user',
281
      'text' => 'none',
282
      'widget' => $widget,
283
    );
284
    
285
    $element['rating'] = array(
286
      '#type'=> 'fivestar',
287
      '#title' => isset($instance['label']) ? $instance['label'] : FALSE,
288
      '#stars' => isset($instance['settings']['stars']) ? $instance['settings']['stars'] : 5,
289
      '#allow_clear' => isset($instance['settings']['allow_clear']) ? $instance['settings']['allow_clear'] : FALSE,
290
      '#default_value' => isset($items[$delta]['rating']) ? $items[$delta]['rating'] : (isset($instance['default_value'][$delta]['rating']) ? $instance['default_value'][$delta]['rating'] : 0),
291
      '#widget' => $widget,
292
      '#settings' => $settings,
293
      '#values' => $values,
294
      '#description' => isset($instance['description']) ? $instance['description'] : FALSE,
295
      '#required' => isset($instance['required']) ? $instance['required'] : FALSE,
296
    );
297
  }
298

    
299
  return array($element);
300
}
301

    
302
/**
303
 * Implementation of hook_field_formatter_info().
304
 */
305
function fivestar_field_formatter_info() {
306
  return array(
307
    'fivestar_formatter_default' => array(
308
      'label' => t('As Stars'),
309
      'field types' => array('fivestar'),
310
      'settings' =>  array(
311
        // Note: Do not set to widget to 'default' by
312
        // default. "Stars (rated while editing)" should
313
        // default to whatever was selected as a widget
314
        // setting. Let hook_field_formatter_view() handle
315
        // defaults for instances that aren't set to anything.
316
        'widget' => array('fivestar_widget' => NULL),
317
        'style' => 'average',
318
        'text' => 'average',
319
        'expose' => TRUE,
320
      ),
321
    ),
322
    'fivestar_formatter_rating' => array(
323
      'label' => t('Rating (i.e. 4.2/5)'),
324
      'field types' => array('fivestar'),
325
    ),
326
    'fivestar_formatter_percentage' => array(
327
      'label' => t('Percentage (i.e. 92)'),
328
      'field types' => array('fivestar'),
329
    ),
330
  );
331
}
332

    
333
/**
334
 * Implements hook_field_formatter_settings_form().
335
 */
336
function fivestar_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
337
  $display = $instance['display'][$view_mode];
338
  $settings = $display['settings'];
339
  
340
  if ($display['type'] != 'fivestar_formatter_default') {
341
    return;
342
  }
343

    
344
  $element['widget'] = array(
345
    '#tree' => TRUE,
346
    '#type' => 'fieldset',
347
    '#title' => t('Star display options'),
348
    '#description' => t('Choose a style for your widget.'),
349
    '#weight' => -2,
350
    '#collapsible' => TRUE,
351
    '#collapsed' => TRUE,
352
  );
353

    
354
  $widgets = module_invoke_all('fivestar_widgets');
355
  
356
  $element['widget']['fivestar_widget'] = array(
357
    '#type' => 'radios',
358
    '#options' => array('default' => t('Default')) + $widgets,
359
    '#default_value' => isset($settings['widget']['fivestar_widget']) ? $settings['widget']['fivestar_widget'] : 'default',
360
    '#attributes' => array('class' => array('fivestar-widgets', 'clearfix')),
361
    '#pre_render' => array('fivestar_previews_expand'),
362
    '#attached' => array('css' => array(drupal_get_path('module', 'fivestar') . '/css/fivestar-admin.css')),
363
  );
364

    
365
  if ($instance['widget']['type'] == 'exposed') {
366
    // Removed entity_get_info here and simplified the text. This is not saved
367
    // to used here and is honestly not need it. See http://drupal.org/node/1268972
368
    $element['expose'] = array(
369
      '#type' => 'checkbox',
370
      '#title' => t('Expose this Fivestar field for voting on the @type type.'),
371
      '#default_value' => $settings['expose'],
372
      '#return_value' => 1
373
    );
374
  }
375

    
376
  $element['style'] = array(
377
    '#type' => 'select',
378
    '#title' => t('Value to display as stars'),
379
    '#default_value' => $settings['style'],
380
    '#options' => array(
381
      'average' => t('Average vote'),
382
      'user'    => t("User's vote"),
383
      'smart'   => t("User's vote if available, average otherwise"),
384
      'dual'    => t("Both user's and average vote"),
385
    ),
386
  );
387
  $element['text'] = array(
388
    '#type' => 'select',
389
    '#title' => t('Text to display under the stars'),
390
    '#default_value' => $settings['text'],
391
    '#options' => array(
392
      'none'    => t('No text'),
393
      'average' => t('Average vote'),
394
      'user'    => t("User's vote"),
395
      'smart'   => t("User's vote if available, average otherwise"),
396
      'dual'    => t("Both user's and average vote"),
397
    ),
398
  );
399

    
400
  return $element;
401
}
402

    
403
/**
404
 * Implements hook_field_formatter_settings_summary().
405
 */
406
function fivestar_field_formatter_settings_summary($field, $instance, $view_mode) {
407
  $display = $instance['display'][$view_mode];
408
  $settings = $display['settings'];
409

    
410
  if ($display['type'] != 'fivestar_formatter_default') {
411
    return;
412
  }
413

    
414
  $widgets = module_invoke_all('fivestar_widgets');
415

    
416
  if ($instance['widget']['type'] == 'exposed') {
417
    $summary = t("Style: @widget, Exposed: @expose, Stars display: @style, Text display: @text", array(
418
      '@widget' => isset($widgets[$settings['widget']['fivestar_widget']]) ? strtolower($widgets[$settings['widget']['fivestar_widget']]) : t('default'),
419
      '@expose' => ($settings['expose']) ? 'yes' : 'no',
420
      '@style' => strtolower($settings['style']),
421
      '@text' => strtolower($settings['text'])));
422
    return $summary;
423
  }
424
  
425
  $summary = t("Style: @widget, Stars display: @style, Text display: @text", array(
426
    '@widget' => isset($widgets[$settings['widget']['fivestar_widget']]) ? $widgets[$settings['widget']['fivestar_widget']] : t('default'),
427
    '@style' => strtolower($settings['style']),
428
    '@text' => strtolower($settings['text'])));
429

    
430
  return $summary;
431
}
432

    
433
/**
434
 * Implements hook_field_formatter_view().
435
 *
436
 * This function returns a renderable array for each fivestar field
437
 * to be displayed when viewing a node (in any view mode).
438
 * The render array will be either a form array created with
439
 * drupal_get_form() or a custom render array, to be sent to a
440
 * fivestar theme function.
441
 *
442
 * @param $items
443
 *  Array. Generated by fivestar_field_prepare_view(). This array contains
444
 *  processed voting info.
445
 *
446
 * @return $element
447
 *  Renderable array. This array will always be $element[0], with only one
448
 *  top level item, because Fivestar does not offer multi-value fields.
449
 */
450
function fivestar_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
451
  $element = array();
452
  $settings = $display['settings'];
453
  $widgets = module_invoke_all('fivestar_widgets');
454
  $widget = _fivestar_get_widget($widgets, $display, $instance);
455
  $values = $items[0];
456

    
457
  // Determine if any set of stars to be displayed need to be
458
  // displayed in a form. (That is, can the user click the stars
459
  // to cast a vote?) If yes, hand off everything we know to the
460
  // fivestar_custom_widget form, and let it take care of the rest.
461
  // Note: Stars will only be displayed in a form in the following circumstance:
462
  // - Fivestar widget selected is "Stars (rated while viewing)"
463
  // - Fivestar display setting = "exposed"
464
  $is_form = ($instance['widget']['type'] == 'exposed'
465
              && user_access('rate content')
466
              && $display['type'] == 'fivestar_formatter_default'
467
              && $display['settings']['expose']) ? TRUE : FALSE;
468
  if ($is_form) {
469
    // TODO. Get rid of voting categories setting, then change this so
470
    // axis = field name.
471
    $tag = (isset($field['settings']['axis'])) ? $field['settings']['axis'] : 'vote';
472
    list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
473
    $settings = _fivestar_custom_widget_settings($entity_type, $instance, $display, $id, $tag, $widget);
474
    // Store entity and field data for later reuse.
475
    $settings += array(
476
      'entity' => $entity,
477
      'field_name' => $instance['field_name'],
478
      'langcode' => $langcode,
479
    );
480
    // If microdata module is enabled, attach the microdata attributes.
481
    $settings['microdata'] = module_exists('microdata') ? $entity->microdata[$field['field_name']] : array();
482

    
483
    $element[0] = drupal_get_form('fivestar_custom_widget', $values, $settings);
484
    // Our work here is done.
485
    return $element;
486
  }
487

    
488
  // No stars will be displayed in a form. Build a renderable array.
489
  $element[0] = array(
490
    // Add a container div around this field with the clearfix class on it.
491
    '#attributes' => array('class' => array('clearfix')),
492
    '#theme_wrappers' => array('container'),
493
  );
494

    
495
  // Determine if we are going to display stars, rating or percentage.
496
  $formatter = $display['type'];
497
  if ($formatter == 'fivestar_formatter_percentage' || $formatter == 'fivestar_formatter_rating') {
498
    $element[0]['user'] = array(
499
      '#theme' => $formatter,
500
      '#instance_settings' => $instance['settings'],
501
      '#display_settings' => $settings,
502
      '#item' => $values,
503
    );
504
    // No stars to display. Our work here is done.
505
    return $element;
506
  }
507

    
508
  // Determine which sets of stars are going to be displayed.
509
  // Options:
510
  // - Only show average of all votes.
511
  // - Only show the user his/her own vote.
512
  // - Show both the average and the user's own votes.
513
  $style = $display['settings']['style'];
514
  $show_average_stars = ($style == 'average' || $style == 'dual' || ($style == 'smart' && empty($values['user'])));
515
  $show_user_stars = ($style == 'user' || $style == 'dual' || ($style == 'smart' && !empty($values['user'])));
516
  if ($show_user_stars) {
517
    $element[0]['user'] = array(
518
      '#theme' => $display['type'],
519
      '#rating' => $values['user'],
520
      '#instance_settings' => $instance['settings'],
521
      '#display_settings' => $settings,
522
      '#widget' => $widget,
523
    );
524
    $element[0]['#attributes']['class'][] = 'fivestar-user-stars';
525
  }
526
  if ($show_average_stars) {
527
    $element[0]['average'] = array(
528
      '#theme' => $display['type'],
529
      '#rating' => $values['average'],
530
      '#instance_settings' => $instance['settings'],
531
      '#display_settings' => $settings,
532
      '#widget' => $widget,
533
    );
534
    $element[0]['#attributes']['class'][] = 'fivestar-average-stars';
535
  }
536
  if ($style === 'smart') {
537
    $element[0]['#attributes']['class'][] = 'fivestar-smart-stars';
538
  }
539
  elseif ($style === 'dual') {
540
    $element[0]['#attributes']['class'][] = 'fivestar-combo-stars';
541
  }
542

    
543
  // Determine which text is to be displayed.
544
  $text = $display['settings']['text'];
545
  $summary_options = array(
546
    'stars' => $instance['settings']['stars'],
547
    'votes' => NULL,
548
  );
549

    
550
 $summary_options['microdata'] = _fivestar_get_microdata_property_info($entity_type, $entity, $field, $instance);
551

    
552
  // If we're displaying both user and average ratings, add a description to
553
  // both the 'user' and 'average' elements.
554
  if ($style === 'dual') {
555
    $element[0]['user']['#description'] = theme('fivestar_summary', array(
556
      'user_rating' => $values['user'],
557
    ) + $summary_options);
558
    $element[0]['average']['#description'] = theme('fivestar_summary', array(
559
      'average_rating' => $values['average'],
560
      'votes' => $values['count'],
561
    ) + $summary_options);
562
  }
563
  // If we're only creating one element (either 'user' or 'average'), prepare
564
  // the correct description, and place it on that element.
565
  else {
566
    // Prepare the description.
567
    $show_average_text = ($text === 'average' || $text === 'dual' || ($text === 'smart' && empty($values['user'])));
568
    $show_user_text = ($text === 'user' || $text === 'dual' || ($text === 'smart' && !empty($values['user'])));
569
    if ($show_user_text) {
570
      $summary_options['user_rating'] = $values['user'];
571
      $element[0]['#attributes']['class'][] = 'fivestar-user-text';
572
    }
573
    if ($show_average_text) {
574
      $summary_options['average_rating'] = $values['average'];
575
      $summary_options['votes'] = $values['count'];
576
      $element[0]['#attributes']['class'][] = 'fivestar-average-text';
577
    }
578
    if ($text === 'smart') {
579
      $element[0]['#attributes']['class'][] = 'fivestar-smart-text';
580
    }
581
    elseif ($text === 'dual') {
582
      $element[0]['#attributes']['class'][] = 'fivestar-combo-text';
583
    }
584
    // Add the description to the set of stars. It might be named either 'user'
585
    // or 'average', so first figure out its name.
586
    $children = element_children($element[0]);
587
    $name = reset($children);
588
    $element[0][$name]['#description'] = theme('fivestar_summary', $summary_options);
589
  }
590

    
591
  return $element;
592
}
593

    
594
/**
595
 * Generate the $settings parameter to be passed to fivestar_custom_widget().
596
 *
597
 * @params
598
 *
599
 * @return $settings
600
 *  Array. @see fivestar_custom_widget().
601
 */
602
function _fivestar_custom_widget_settings($entity_type, $instance, $display, $id, $tag, $widget) {
603
  $settings = $display['settings'];
604
  $settings = array(
605
    'stars' => (!empty($instance['settings']['stars'])) ? $instance['settings']['stars'] : 5,
606
    'allow_clear' => (!empty($instance['settings']['allow_clear'])) ? $instance['settings']['allow_clear'] : 0,
607
    'style' => $settings['style'],
608
    'text' => $settings['text'],
609
    'content_type' => $entity_type,
610
    'content_id' => $id,
611
    'tag' => $tag,
612
    'autosubmit' => TRUE,
613
    'title' => FALSE,
614
    'labels_enable' => FALSE,
615
    'labels' => array(),
616
    'widget' => $widget,
617
  );
618

    
619
  return $settings;
620
}
621

    
622
/**
623
 * @param $widgets
624
 *  Array, $widgets = module_invoke_all('fivestar_widgets');
625
 *  $widgets = array('path/to/css' => 'Widget Name', 'path/to/more/css' => 'Widget 2');
626
 *
627
 * @param $display
628
 *  Array. This is the $display parameter passed to fivestar_field_formatter_view().
629
 *
630
 * @param $instance
631
 *  Array. This is the $instance parameter passed to fivestar_field_formatter_view().
632
 *
633
 * @return $widget
634
 *  Array. $widget = array('name' => 'my widget', 'css' => 'sites/all/mymodule/mywidget.css');
635
 */
636
function _fivestar_get_widget($widgets, $display, $instance) {
637
  // If the type doesn't required widgets lets get out of here.
638
  // TODO: Implement this WAY better.
639
  if (in_array($display['type'], array('fivestar_formatter_rating', 'fivestar_formatter_percentage'))) {
640
    return FALSE;
641
  }
642

    
643
  // Stars (rated while viewing) is $type = 'exposed'.
644
  // Stars (rated while editing) is $type = 'stars'.
645
  $type = $instance['widget']['type'];
646

    
647
  // Determine which widget to display.
648
  if (!$fivestar_widget = $display['settings']['widget']['fivestar_widget']) {
649
    // No display has been selected and saved by the user.
650
    if ($type == 'exposed') {
651
      // Stars rated while viewing, that is, $type = 'exposed', fall backs on 'default'
652
      // (which is the same as nothing).
653
      $fivestar_widget = 'default';
654
    }
655
    else if ($type == 'stars') {
656
      // Stars rated while editing, that is, $type = stars,
657
      // falls back on whatever the user selected to be displayed on node/add and node/%/edit
658
      $fivestar_widget = $instance['widget']['settings']['widget']['fivestar_widget'];
659
    }
660
  }
661

    
662
  $widget = array(
663
    'name' => isset($widgets[$fivestar_widget]) ? strtolower($widgets[$fivestar_widget]) : 'default',
664
    'css' => $fivestar_widget,
665
  );
666

    
667
  return $widget;
668
}
669

    
670
/**
671
 * Implements hook_field_prepare_view()
672
 */
673
function fivestar_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items) {
674
  // TODO: Clean this function up!
675
  foreach ($entities as $id => $entity) {
676
    // Populating the $items[$id] array even for items with no value forces
677
    // the render system to output a widget.
678
    if ($instances[$id]['widget']['type'] == 'exposed') {
679
      // If the widget type is exposed then we want to look up the voting api values.
680
      $tag = $field['settings']['axis'];
681
      $votes = fivestar_get_votes($entity_type, $id, $tag);
682
      $values['user'] = isset($votes['user']['value']) ? $votes['user']['value'] : 0;
683
      $values['average'] = isset($votes['average']['value']) ? $votes['average']['value'] : 0;
684
      $values['count'] = isset($votes['count']['value']) ? $votes['count']['value'] : 0;
685
      $items[$id] = array($values);
686
    }
687
    else {
688
      // If the widget type is not exposed, then the count is always 1 or 0.
689
      // The count is pointless to display.
690
      if (!empty($items[$id][0]['rating'])) {
691
        $values['count'] = 1;
692
        $values['user'] = $items[$id][0]['rating'];
693
        $values['average'] = $items[$id][0]['rating'];
694
      }
695
      else {
696
        $values['count'] = 0;
697
        $values['user'] = 0;
698
        $values['average'] = 0;
699
      }
700
      $items[$id] = array($values);
701
    }
702
  }
703
}
704

    
705
/**
706
 * Implements hook_microdata_value_type_alter().
707
 */
708
function fivestar_microdata_value_types_alter(&$types) {
709
  $types['fivestar'] = 'item_option';
710
}
711

    
712
/**
713
 * Callback to alter the property info of fivestar fields.
714
 */
715
function fivestar_property_info_callback(&$info, $entity_type, $field, $instance, $field_type) {
716
  $name = $field['field_name'];
717
  $property = &$info[$entity_type]['bundles'][$instance['bundle']]['properties'][$name];
718

    
719
  $property['property info'] = array(
720
    'average_rating' => array(
721
      'label' => t('Average Rating'),
722
      'type' => 'text',
723
      'microdata' => TRUE,
724
    ),
725
    'user_rating' => array(
726
      'label' => t('User\'s Rating'),
727
      'type' => 'text',
728
      'microdata' => TRUE,
729
    ),
730
  );
731
}
732

    
733
/**
734
 * Get microdata attributes for Fivestar field.
735
 */
736
function _fivestar_get_microdata_property_info($entity_type, $entity, $field, $instance) {
737
  // If microdata module is enabled, attach the microdata attributes the module
738
  // adds to the entity object.
739
  if (module_exists('microdata')) {
740
    $microdata = $entity->microdata[$field['field_name']];
741
  }
742
  // If microdata is not enabled, add empty arrays for each property so we
743
  // don't have to check later in the theme functions.
744
  else {
745
    $microdata = array(
746
      '#attributes' => array(),
747
    );
748
    // If Entity API is enabled, we can use that to get the properties.
749
    // Otherwise, replicate the Entity API logic for getting the properties.
750
    if (module_exists('entity')) {
751
      $entity_info = entity_get_all_property_info($entity_type);
752
    }
753
    else {
754
      $info = array();
755
      $info[$entity_type]['bundles'][$instance['bundle']]['properties'][$field['field_name']] = array();
756
      fivestar_property_info_callback($info, $entity_type, $field, $instance, 'fivestar');
757
      $entity_info = $info[$entity_type]['bundles'][$instance['bundle']]['properties'];
758
    }
759
    foreach ($entity_info[$field['field_name']]['property info'] as $property_name => $property) {
760
      $microdata[$property_name]['#attributes'] = array();
761
    }
762
  }
763

    
764
  return $microdata;
765
}