Projet

Général

Profil

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

root / drupal7 / sites / all / modules / votingapi / votingapi.admin.inc @ f419e8de

1
<?php
2

    
3
/**
4
 * @file
5
 * Configuration forms and helper functions for VotingAPI module.
6
 */
7

    
8
/**
9
 * Administrative settings for VotingAPI.
10
 */
11
function votingapi_settings_form($form_state) {
12
  $period = array(0 => t('Immediately')) + drupal_map_assoc(array(
13
      300,
14
      900,
15
      1800,
16
      3600,
17
      10800,
18
      21600,
19
      32400,
20
      43200,
21
      86400,
22
      172800,
23
      345600,
24
      604800,
25
    ), 'format_interval') + array(-1 => t('Never'));
26

    
27
  $form['votingapi_anonymous_window'] = array(
28
    '#type' => 'select',
29
    '#title' => t('Anonymous vote rollover'),
30
    '#description' => t('The amount of time that must pass before two anonymous votes from the same computer are considered unique. Setting this to \'never\' will eliminate most double-voting, but will make it impossible for multiple anonymous on the same computer (like internet cafe customers) from casting votes.'),
31
    '#default_value' => variable_get('votingapi_anonymous_window', 86400),
32
    '#options' => $period,
33
  );
34

    
35
  $form['votingapi_user_window'] = array(
36
    '#type' => 'select',
37
    '#title' => t('Registered user vote rollover'),
38
    '#description' => t('The amount of time that must pass before two registered user votes from the same user ID are considered unique. Setting this to \'never\' will eliminate most double-voting for registered users.'),
39
    '#default_value' => variable_get('votingapi_user_window', -1),
40
    '#options' => $period,
41
  );
42

    
43
  $form['votingapi_calculation_schedule'] = array(
44
    '#type' => 'radios',
45
    '#title' => t('Vote tallying'),
46
    '#description' => t('On high-traffic sites, administrators can use this setting to postpone the calculation of vote results.'),
47
    '#default_value' => variable_get('votingapi_calculation_schedule', 'immediate'),
48
    '#options' => array(
49
      'immediate' => t('Tally results whenever a vote is cast'),
50
      'cron' => t('Tally results at cron-time'),
51
      'manual' => t('Do not tally results automatically: I am using a module that manages its own vote results.'),
52
    ),
53
  );
54

    
55
  return system_settings_form($form);
56
}
57

    
58
/**
59
 * Developer tool to generate dummy votes.
60
 */
61
function votingapi_generate_votes_form() {
62
  $form['node_types'] = array(
63
    '#type' => 'checkboxes',
64
    '#title' => t('Which node types should receive votes?'),
65
    '#options' => node_type_get_names(),
66
    '#default_value' => array_keys(node_type_get_names()),
67
  );
68

    
69
  $form['vote_type'] = array(
70
    '#type' => 'select',
71
    '#title' => t('What type of votes should be generated?'),
72
    '#options' => array(
73
      'percent' => t('Percentage (Fivestar style)'),
74
      'points' => t('Point-based (Digg style)'),
75
    ),
76
    '#default_value' => 'percent',
77
  );
78

    
79
  $form['kill_votes'] = array(
80
    '#type' => 'checkbox',
81
    '#title' => t('Delete existing votes before generating new ones.'),
82
    '#default_value' => FALSE,
83
  );
84
  $form['submit'] = array(
85
    '#type' => 'submit',
86
    '#value' => t('Do it!'),
87
  );
88
  return $form;
89
}
90

    
91
/**
92
 * Submit handler for votingapi_generate_votes_form.
93
 */
94
function votingapi_generate_votes_form_submit($form, &$form_state) {
95
  $options = array(
96
    'types' => $form_state['values']['node_types'],
97
    'kill' => $form_state['values']['kill_votes'],
98
  );
99
  require_once(drupal_get_path('module', 'votingapi') . '/votingapi.devel.inc');
100
  votingapi_generate_votes('node', $form_state['values']['vote_type'], $options);
101
}
102

    
103
/**
104
 * Rebuild the voting results and clear the voting cache.
105
 */
106
function votingapi_rebuild_form($form, $form_state) {
107
  $query = db_select('votingapi_vote')
108
    ->fields('votingapi_vote', array('tag'))
109
    ->distinct(TRUE);
110

    
111
  $results = $query
112
    ->execute()
113
    ->fetchAll(PDO::FETCH_ASSOC);
114

    
115
  $tags = array('All Tags');
116
  foreach ($results as $tag_type) {
117
    $tags[] = $tag_type['tag'];
118
  }
119

    
120
  $form['results'] = array(
121
    '#type' => 'fieldset',
122
    '#title' => t('Rebuild voting results'),
123
  );
124
  $form['results']['votingapi_rebuild_content_selected_tag'] = array(
125
    '#type' => 'select',
126
    '#title' => t('Content tags'),
127
    '#options' => $tags,
128
  );
129
  $form['results']['votingapi_rebuild_content_tags'] = array(
130
    '#type' => 'hidden',
131
    '#value' => $tags,
132
  );
133
  $form['results']['votingapi_recalculate_all'] = array(
134
    '#type' => 'submit',
135
    '#value' => t('Rebuild all Voting Results'),
136
  );
137
  $form['results']['help'] = array(
138
    '#prefix' => '<div class="description">',
139
    '#markup' => t('This action rebuilds all voting results, and may be a lengthy process.')
140
      . '<br>' . t("In regular site confirurations, this process does not re-determine <em>validity</em> of votes, so if you change 'rollover' settings on the General Settings page, this does not mean that e.g. Fivestar votes attached to comments will be re-evaluated."),
141
    '#suffix' => '</div>',
142
  );
143

    
144
  return $form;
145
}
146

    
147
/**
148
 * Submit handler for votingapi_rebuild_form.
149
 *
150
 * Recalculates voting results for all content, using the batch API.
151
 */
152
function votingapi_rebuild_form_submit($form, &$form_state) {
153
  $tags = $form_state['values']['votingapi_rebuild_content_tags'];
154
  $selected_tag_index = $form_state['values']['votingapi_rebuild_content_selected_tag'];
155

    
156
  // Change the list of tags to remove accordingly.
157
  if ($selected_tag_index > 0) {
158
    $tags = array($tags[$selected_tag_index]);
159
  }
160
  else {
161
    unset($tags[0]);
162
  }
163

    
164
  $operations = array();
165
  foreach ($tags as $tag) {
166
    $operations[] = array('_votingapi_results_rebuild', array($tag));
167
  }
168
  $batch = array(
169
    'title' => t('Recalculating votes'),
170
    'operations' => $operations,
171
    'init_message' => 'Preparing to recalculate',
172
    'finished' => '_votingapi_results_rebuild_finished',
173
    'file' => drupal_get_path('module', 'votingapi') . '/votingapi.admin.inc',
174
  );
175
  // Set the recalculation batch so it can be processed.
176
  batch_set($batch);
177

    
178
  // Redirect the user to the votingapi rebuild page.
179
  $form_state['redirect'] = 'admin/config/search/votingapi/rebuild';
180
}
181

    
182
/**
183
 * Batch API callback for the vote rebuilding operation.
184
 */
185
function _votingapi_results_rebuild($tag, &$context) {
186
  if (empty($context['sandbox']['max_entity_id'])) {
187

    
188
    // Set up the sandbox to work within.
189
    $context['sandbox']['current_entity_id'] = 0;
190
    $context['sandbox']['current_entity_types'] = array();
191

    
192
    // Get the lowest/highest entity_id for this context, for later comparisons.
193
    $res = db_query('SELECT MIN(entity_id) as min_id, MAX(entity_id) as max_id FROM {votingapi_vote} WHERE tag = :tag', array(':tag' => $tag))->fetchAssoc();
194
    $context['sandbox']['max_entity_id'] = $res['max_id'];
195
    $context['sandbox']['min_entity_id'] = $res['min_id'] - 1;
196
    $context['sandbox']['max_entity_id_type'] = db_query('SELECT max(entity_type) FROM {votingapi_vote} WHERE entity_id = :id AND tag = :tag',
197
      array(
198
        ':id' => $context['sandbox']['max_entity_id'],
199
        ':tag' => $tag
200
      ))->fetchField();
201

    
202
    $context['results']['count'] = 0;
203
  }
204

    
205
  // Grab all entity_ids from the votingapi_vote table.
206
  // Theoretically, there can be an endless loop if there are $limit entities
207
  // (of different types) with the same entity_id... We'll take that chance.
208
  $limit = 100;
209
//  $result = db_query_range('SELECT DISTINCT entity_type, entity_id FROM {votingapi_vote} WHERE tag = :tag AND entity_id >= :cid ORDER BY entity_id  ASC',
210
  $result = db_query_range('SELECT DISTINCT entity_type, entity_id FROM {votingapi_vote}
211
      WHERE tag = :tag AND (entity_id > :current_entity_id OR (entity_id = :current_entity_id AND entity_type > :current_entity_type))
212
      ORDER BY entity_id, entity_type', 0, $limit, array(
213
    ':tag' => $tag,
214
    ':current_entity_id' => $context['sandbox']['current_entity_id'],
215
    ':current_entity_type' => $context['sandbox']['current_entity_type']
216
  ));
217

    
218
  foreach ($result as $row) {
219
    // Force vote recalculation for this entity.
220
    votingapi_recalculate_results($row->entity_type, $row->entity_id, TRUE);
221
    $context['results']['count']++;
222
    $context['sandbox']['current_entity_id'] = $row->entity_id;
223
    $context['sandbox']['current_entity_type'] = $row->entity_type;
224
  }
225

    
226
  // Check if the process has not finished yet.
227
  if ($context['sandbox']['current_entity_id'] != $context['sandbox']['max_entity_id']
228
    || $context['sandbox']['current_entity_type'] != $context['sandbox']['max_entity_id_type']
229
  ) {
230
    // Make sure 'finished' < 1. Using entity IDs here may cause the progress
231
    // bar to behave eratically, but on the other hand, we make sure we actually
232
    // process all items instead of the number of items we had at the start.
233
    // (If we compared the items processed against the number of items at the
234
    // start of the process, we would not process the highest item if an extra
235
    // (older) entity got a vote, during processing.)
236
    // Using min_entity_id as 'base' should help smoothness at the start a bit.
237
    $context['finished'] =
238
      ($context['sandbox']['current_entity_id'] - $context['sandbox']['min_entity_id'])
239
      / ($context['sandbox']['max_entity_id'] + 1 - $context['sandbox']['min_entity_id']);
240
  }
241
}
242

    
243
/**
244
 * Batch API callback for finished recalculation batch operations.
245
 */
246
function _votingapi_results_rebuild_finished($success, $results, $operations) {
247
  if ($success) {
248
    $message = format_plural($results['count'], 'One content item was recalculated.', '@count content items were recalculated');
249
  }
250
  else {
251
    $message = t('The voting results rebuild process encountered an error.');
252
  }
253
  drupal_set_message($message);
254
}