Projet

Général

Profil

Paste
Télécharger (28,3 ko) Statistiques
| Branche: | Révision:

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

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
    $element[0] = drupal_get_form('fivestar_custom_widget', $values, $settings);
481
    // Our work here is done.
482
    return $element;
483
  }
484

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

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

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

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

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

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

    
588
  return $element;
589
}
590

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

    
616
  return $settings;
617
}
618

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

    
640
  // Stars (rated while viewing) is $type = 'exposed'.
641
  // Stars (rated while editing) is $type = 'stars'.
642
  $type = $instance['widget']['type'];
643

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

    
659
  $widget = array(
660
    'name' => isset($widgets[$fivestar_widget]) ? strtolower($widgets[$fivestar_widget]) : 'default',
661
    'css' => $fivestar_widget,
662
  );
663

    
664
  return $widget;
665
}
666

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

    
702
/**
703
 * Implements hook_microdata_value_type_alter().
704
 */
705
function fivestar_microdata_value_type_alter(&$types) {
706
  $types['fivestar'] = 'item';
707
}
708

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

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

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

    
756
      foreach ($entity_info[$field['field_name']]['property info'] as $property_name => $property) {
757
        $microdata[$property_name]['#attributes'] = array();
758
      }
759
    }
760
  }
761

    
762
  return $microdata;
763
}
764

    
765

    
766
/**
767
 * Implements hook_microdata_field_defaults.
768
 *
769
 * Sets default mappings for different vocabularies; for example, schema.org.
770
 * This enables fields to provide mappings for different use cases.
771
 */
772
function fivestar_microdata_field_defaults() {
773
  $field_settings = array();
774

    
775
  // Add the vocabulary terms that are used to describe the data. Multiple
776
  // schemes can be defined, allowing the user to choose which mapping to use.
777
  // The array key is used to choose which mapping to use in the field instance
778
  // settings form.
779
  $field_settings['default_mappings']['schema.org'] = array(
780
    '#itemprop'    => array('aggregateRating'),
781
    '#itemtype'    => 'http://schema.org/AggregateRating',
782
    'average_rating' => array(
783
      '#itemprop' => array('ratingValue'),
784
    ),
785
  );
786

    
787
  return $field_settings;
788

    
789
}