Projet

Général

Profil

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

root / drupal7 / modules / profile / profile.admin.inc @ db2d93dd

1
<?php
2

    
3
/**
4
 * @file
5
 * Administrative page callbacks for the profile module.
6
 */
7

    
8
/**
9
 * Form builder to display a listing of all editable profile fields.
10
 *
11
 * @ingroup forms
12
 * @see profile_admin_overview_submit()
13
 */
14
function profile_admin_overview($form) {
15
  $result = db_query('SELECT title, name, type, category, fid, weight FROM {profile_field} ORDER BY category, weight');
16

    
17
  $categories = array();
18
  foreach ($result as $field) {
19
    // Collect all category information
20
    $categories[] = $field->category;
21

    
22
    // Save all field information
23
    $form[$field->fid]['name'] = array('#markup' => check_plain($field->name));
24
    $form[$field->fid]['title'] = array('#markup' => check_plain($field->title));
25
    $form[$field->fid]['type'] = array('#markup' => $field->type);
26
    $form[$field->fid]['category'] = array(
27
      '#type' => 'select',
28
      '#title' => t('Category for @title', array('@title' => $field->title)),
29
      '#title_display' => 'invisible',
30
      '#default_value' => $field->category,
31
      '#options' => array(),
32
    );
33
    $form[$field->fid]['weight'] = array(
34
      '#type' => 'weight',
35
      '#title' => t('Weight for @title', array('@title' => $field->title)),
36
      '#title_display' => 'invisible',
37
      '#default_value' => $field->weight,
38
    );
39
    $form[$field->fid]['edit'] = array('#type' => 'link', '#title' => t('edit'), '#href' => "admin/config/people/profile/edit/$field->fid");
40
    $form[$field->fid]['delete'] = array('#type' => 'link', '#title' => t('delete'), '#href' => "admin/config/people/profile/delete/$field->fid");
41
  }
42

    
43
  // Add the category combo boxes
44
  $categories = array_unique($categories);
45
  foreach ($form as $fid => $field) {
46
    foreach ($categories as $cat => $category) {
47
      $form[$fid]['category']['#options'][$category] = $category;
48
    }
49
  }
50

    
51
  // Display the submit button only when there's more than one field
52
  if (count($form) > 1) {
53
    $form['actions'] = array('#type' => 'actions');
54
    $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration'));
55
  }
56
  else {
57
    // Disable combo boxes when there isn't a submit button
58
    foreach ($form as $fid => $field) {
59
      unset($form[$fid]['weight']);
60
      $form[$fid]['category']['#type'] = 'value';
61
    }
62
  }
63
  $form['#tree'] = TRUE;
64

    
65
  // @todo: Any reason this isn't done using an element with #theme = 'links'?
66
  $addnewfields = '<h2>' . t('Add new field') . '</h2>';
67
  $addnewfields .= '<ul>';
68
  foreach (_profile_field_types() as $key => $value) {
69
    $addnewfields .= '<li>' . l($value, "admin/config/people/profile/add/$key") . '</li>';
70
  }
71
  $addnewfields .= '</ul>';
72
  $form['addnewfields'] = array('#markup' => $addnewfields);
73

    
74
  return $form;
75
}
76

    
77
/**
78
 * Submit handler to update changed profile field weights and categories.
79
 *
80
 * @see profile_admin_overview()
81
 */
82
function profile_admin_overview_submit($form, &$form_state) {
83
  foreach (element_children($form_state['values']) as $fid) {
84
    if (is_numeric($fid)) {
85
      $weight = $form_state['values'][$fid]['weight'];
86
      $category = $form_state['values'][$fid]['category'];
87
      if ($weight != $form[$fid]['weight']['#default_value'] || $category != $form[$fid]['category']['#default_value']) {
88
        db_update('profile_field')
89
          ->fields(array(
90
            'weight' => $weight,
91
            'category' => $category,
92
          ))
93
          ->condition('fid', $fid)
94
          ->execute();
95
      }
96
    }
97
  }
98

    
99
  drupal_set_message(t('Profile fields have been updated.'));
100
  cache_clear_all();
101
  menu_rebuild();
102
}
103

    
104
/**
105
 * Returns HTML for the profile field overview form into a drag and drop enabled table.
106
 *
107
 * @param $variables
108
 *   An associative array containing:
109
 *   - form: A render element representing the form.
110
 *
111
 * @see profile_admin_overview()
112
 * @ingroup themeable
113
 */
114
function theme_profile_admin_overview($variables) {
115
  $form = $variables['form'];
116

    
117
  drupal_add_css(drupal_get_path('module', 'profile') . '/profile.css');
118
  // Add javascript if there's more than one field.
119
  if (isset($form['actions'])) {
120
    drupal_add_js(drupal_get_path('module', 'profile') . '/profile.js');
121
  }
122

    
123
  $rows = array();
124
  $categories = array();
125
  $category_number = 0;
126
  foreach (element_children($form) as $key) {
127
    // Don't take form control structures.
128
    if (isset($form[$key]['category'])) {
129
      $field = &$form[$key];
130
      $category = $field['category']['#default_value'];
131

    
132
      if (!isset($categories[$category])) {
133
        // Category classes are given numeric IDs because there's no guarantee
134
        // class names won't contain invalid characters.
135
        $categories[$category] = $category_number;
136
        $category_field['#attributes']['class'] = array('profile-category', 'profile-category-' . $category_number);
137
        $rows[] = array(array('data' => check_plain($category), 'colspan' => 7, 'class' => array('category')));
138
        $rows[] = array('data' => array(array('data' => '<em>' . t('No fields in this category. If this category remains empty when saved, it will be removed.') . '</em>', 'colspan' => 7)), 'class' => array('category-' . $category_number . '-message', 'category-message', 'category-populated'));
139

    
140
        // Make it draggable only if there is more than one field
141
        if (isset($form['actions'])) {
142
          drupal_add_tabledrag('profile-fields', 'order', 'sibling', 'profile-weight', 'profile-weight-' . $category_number);
143
          drupal_add_tabledrag('profile-fields', 'match', 'sibling', 'profile-category', 'profile-category-' . $category_number);
144
        }
145
        $category_number++;
146
      }
147

    
148
      // Add special drag and drop classes that group fields together.
149
      $field['weight']['#attributes']['class'] = array('profile-weight', 'profile-weight-' . $categories[$category]);
150
      $field['category']['#attributes']['class'] = array('profile-category', 'profile-category-' . $categories[$category]);
151

    
152
      // Add the row
153
      $row = array();
154
      $row[] = drupal_render($field['title']);
155
      $row[] = drupal_render($field['name']);
156
      $row[] = drupal_render($field['type']);
157
      if (isset($form['actions'])) {
158
        $row[] = drupal_render($field['category']);
159
        $row[] = drupal_render($field['weight']);
160
      }
161
      $row[] = drupal_render($field['edit']);
162
      $row[] = drupal_render($field['delete']);
163
      $rows[] = array('data' => $row, 'class' => array('draggable'));
164
    }
165
  }
166

    
167
  $header = array(t('Title'), t('Name'), t('Type'));
168
  if (isset($form['actions'])) {
169
    $header[] = t('Category');
170
    $header[] = t('Weight');
171
  }
172
  $header[] = array('data' => t('Operations'), 'colspan' => 2);
173

    
174
  $output = theme('table', array('header' => $header, 'rows' => $rows, 'empty' => t('No fields available.'), 'attributes' => array('id' => 'profile-fields')));
175
  $output .= drupal_render_children($form);
176

    
177
  return $output;
178
}
179

    
180
/**
181
 * Menu callback: Generate a form to add/edit a user profile field.
182
 *
183
 * @ingroup forms
184
 * @see profile_field_form_validate()
185
 * @see profile_field_form_submit()
186
 */
187
function profile_field_form($form, &$form_state, $arg = NULL) {
188
  if (arg(4) == 'edit') {
189
    if (is_numeric($arg)) {
190
      $fid = $arg;
191

    
192
      $edit = db_query('SELECT * FROM {profile_field} WHERE fid = :fid', array('fid' => $fid))->fetchAssoc();
193

    
194
      if (!$edit) {
195
        drupal_not_found();
196
        return;
197
      }
198
      drupal_set_title(t('Edit %title', array('%title' => $edit['title'])), PASS_THROUGH);
199
      $form['fid'] = array('#type' => 'value',
200
        '#value' => $fid,
201
      );
202
      $type = $edit['type'];
203
    }
204
    else {
205
      drupal_not_found();
206
      return;
207
    }
208
  }
209
  else {
210
    $types = _profile_field_types();
211
    if (!isset($types[$arg])) {
212
      drupal_not_found();
213
      return;
214
    }
215
    $type = $arg;
216
    drupal_set_title(t('Add new %type', array('%type' => $types[$type])), PASS_THROUGH);
217
    $edit = array('name' => 'profile_');
218
    $form['type'] = array('#type' => 'value', '#value' => $type);
219
  }
220
  $edit += array(
221
    'category' => '',
222
    'title' => '',
223
    'explanation' => '',
224
    'weight' => 0,
225
    'page' => '',
226
    'autocomplete' => '',
227
    'required' => '',
228
    'register' => '',
229
  );
230
  $form['category'] = array('#type' => 'textfield',
231
    '#title' => t('Category'),
232
    '#default_value' => $edit['category'],
233
    '#autocomplete_path' => 'admin/config/people/profile/autocomplete',
234
    '#description' => t('The category the new field should be part of. Categories are used to group fields logically. An example category is "Personal information".'),
235
    '#required' => TRUE,
236
  );
237
  $form['title'] = array('#type' => 'textfield',
238
    '#title' => t('Title'),
239
    '#default_value' => $edit['title'],
240
    '#description' => t('The title of the new field. The title will be shown to the user. An example title is "Favorite color".'),
241
    '#required' => TRUE,
242
  );
243
  $form['name'] = array('#type' => 'textfield',
244
    '#title' => t('Form name'),
245
    '#default_value' => $edit['name'],
246
    '#description' => t('The name of the field. The form name is not shown to the user but used internally in the HTML code and URLs.
247
Unless you know what you are doing, it is highly recommended that you prefix the form name with <code>profile_</code> to avoid name clashes with other fields. Spaces or any other special characters except dash (-) and underscore (_) are not allowed. An example name is "profile_favorite_color" or perhaps just "profile_color".'),
248
    '#required' => TRUE,
249
  );
250
  $form['explanation'] = array('#type' => 'textarea',
251
    '#title' => t('Explanation'),
252
    '#default_value' => $edit['explanation'],
253
    '#description' => t('An optional explanation to go with the new field. The explanation will be shown to the user.'),
254
  );
255
  if ($type == 'selection') {
256
    $form['fields']['options'] = array('#type' => 'textarea',
257
      '#title' => t('Selection options'),
258
      '#default_value' => isset($edit['options']) ? $edit['options'] : '',
259
      '#description' => t('A list of all options. Put each option on a separate line. Example options are "red", "blue", "green", etc.'),
260
    );
261
  }
262
  $form['visibility'] = array('#type' => 'radios',
263
    '#title' => t('Visibility'),
264
    '#default_value' => isset($edit['visibility']) ? $edit['visibility'] : PROFILE_PUBLIC,
265
    '#options' => array(PROFILE_HIDDEN => t('Hidden profile field, only accessible by administrators, modules and themes.'), PROFILE_PRIVATE => t('Private field, content only available to privileged users.'), PROFILE_PUBLIC => t('Public field, content shown on profile page but not used on member list pages.'), PROFILE_PUBLIC_LISTINGS => t('Public field, content shown on profile page and on member list pages.')),
266
  );
267
  if ($type == 'selection' || $type == 'list' || $type == 'textfield') {
268
    $form['fields']['page'] = array('#type' => 'textfield',
269
      '#title' => t('Page title'),
270
      '#default_value' => $edit['page'],
271
      '#description' => t('To enable browsing this field by value, enter a title for the resulting page. The word <code>%value</code> will be substituted with the corresponding value. An example page title is "People whose favorite color is %value" . This is only applicable for a public field.'),
272
    );
273
  }
274
  elseif ($type == 'checkbox') {
275
    $form['fields']['page'] = array('#type' => 'textfield',
276
      '#title' => t('Page title'),
277
      '#default_value' => $edit['page'],
278
      '#description' => t('To enable browsing this field by value, enter a title for the resulting page. An example page title is "People who are employed" . This is only applicable for a public field.'),
279
    );
280
  }
281
  $form['weight'] = array('#type' => 'weight',
282
    '#title' => t('Weight'),
283
    '#default_value' => $edit['weight'],
284
    '#description' => t('The weights define the order in which the form fields are shown. Lighter fields "float up" towards the top of the category.'),
285
  );
286
  $form['autocomplete'] = array('#type' => 'checkbox',
287
    '#title' => t('Form will auto-complete while user is typing.'),
288
    '#default_value' => $edit['autocomplete'],
289
    '#description' => t('For security, auto-complete will be disabled if the user does not have access to user profiles.'),
290
  );
291
  $form['required'] = array('#type' => 'checkbox',
292
    '#title' => t('The user must enter a value.'),
293
    '#default_value' => $edit['required'],
294
  );
295
  $form['register'] = array('#type' => 'checkbox',
296
    '#title' => t('Visible in user registration form.'),
297
    '#default_value' => $edit['register'],
298
  );
299

    
300
  $form['actions'] = array('#type' => 'actions');
301
  $form['actions']['submit'] = array('#type' => 'submit',
302
    '#value' => t('Save field'),
303
  );
304
  return $form;
305
}
306

    
307
/**
308
 * Validate profile_field_form submissions.
309
 */
310
function profile_field_form_validate($form, &$form_state) {
311
  // Validate the 'field name':
312
  if (preg_match('/[^a-zA-Z0-9_-]/', $form_state['values']['name'])) {
313
    form_set_error('name', t('The specified form name contains one or more illegal characters. Spaces or any other special characters except dash (-) and underscore (_) are not allowed.'));
314
  }
315

    
316
  $users_table = drupal_get_schema('users');
317
  if (!empty($users_table['fields'][$form_state['values']['name']])) {
318
    form_set_error('name', t('The specified form name is reserved for use by Drupal.'));
319
  }
320
  // Validate the category:
321
  if (!$form_state['values']['category']) {
322
    form_set_error('category', t('You must enter a category.'));
323
  }
324
  if (strtolower($form_state['values']['category']) == 'account') {
325
    form_set_error('category', t('The specified category name is reserved for use by Drupal.'));
326
  }
327
  $query = db_select('profile_field');
328
  $query->fields('profile_field', array('fid'));
329

    
330
  if (isset($form_state['values']['fid'])) {
331
    $query->condition('fid', $form_state['values']['fid'], '<>');
332
  }
333
  $query_name = clone $query;
334

    
335
  $title = $query
336
    ->condition('title', $form_state['values']['title'])
337
    ->condition('category', $form_state['values']['category'])
338
    ->execute()
339
    ->fetchField();
340
  if ($title) {
341
    form_set_error('title', t('The specified title is already in use.'));
342
  }
343
  $name = $query_name
344
    ->condition('name', $form_state['values']['name'])
345
    ->execute()
346
    ->fetchField();
347
  if ($name) {
348
    form_set_error('name', t('The specified name is already in use.'));
349
  }
350
  if ($form_state['values']['visibility'] == PROFILE_HIDDEN) {
351
    if ($form_state['values']['required']) {
352
      form_set_error('required', t('A hidden field cannot be required.'));
353
    }
354
    if ($form_state['values']['register']) {
355
      form_set_error('register', t('A hidden field cannot be set to visible on the user registration form.'));
356
    }
357
  }
358
}
359

    
360
/**
361
 * Process profile_field_form submissions.
362
 */
363
function profile_field_form_submit($form, &$form_state) {
364
  if (!isset($form_state['values']['options'])) {
365
    $form_state['values']['options'] = '';
366
  }
367
  if (!isset($form_state['values']['page'])) {
368
    $form_state['values']['page'] = '';
369
  }
370
  // Remove all elements that are not profile_field columns.
371
  $values = array_intersect_key($form_state['values'], array_flip(array('type', 'category', 'title', 'name', 'explanation', 'visibility', 'page', 'weight', 'autocomplete', 'required', 'register', 'options')));
372
  if (!isset($form_state['values']['fid'])) {
373
    db_insert('profile_field')
374
      ->fields($values)
375
      ->execute();
376
    drupal_set_message(t('The field has been created.'));
377
    watchdog('profile', 'Profile field %field added under category %category.', array('%field' => $form_state['values']['title'], '%category' => $form_state['values']['category']), WATCHDOG_NOTICE, l(t('view'), 'admin/config/people/profile'));
378
  }
379
  else {
380
    db_update('profile_field')
381
      ->fields($values)
382
      ->condition('fid', $form_state['values']['fid'])
383
      ->execute();
384
    drupal_set_message(t('The field has been updated.'));
385
  }
386
  cache_clear_all();
387
  menu_rebuild();
388

    
389
  $form_state['redirect'] = 'admin/config/people/profile';
390
  return;
391
}
392

    
393
/**
394
 * Menu callback; deletes a field from all user profiles.
395
 */
396
function profile_field_delete($form, &$form_state, $fid) {
397
  $field = db_query("SELECT title FROM {profile_field} WHERE fid = :fid", array(':fid' => $fid))->fetchObject();
398
  if (!$field) {
399
    drupal_not_found();
400
    return;
401
  }
402
  $form['fid'] = array('#type' => 'value', '#value' => $fid);
403
  $form['title'] = array('#type' => 'value', '#value' => $field->title);
404

    
405
  return confirm_form($form,
406
    t('Are you sure you want to delete the field %field?', array('%field' => $field->title)), 'admin/config/people/profile',
407
    t('This action cannot be undone. If users have entered values into this field in their profile, these entries will also be deleted. If you want to keep the user-entered data, instead of deleting the field you may wish to <a href="@edit-field">edit this field</a> and change it to a hidden profile field so that it may only be accessed by administrators.', array('@edit-field' => url('admin/config/people/profile/edit/' . $fid))),
408
    t('Delete'), t('Cancel'));
409
}
410

    
411
/**
412
 * Process a field delete form submission.
413
 */
414
function profile_field_delete_submit($form, &$form_state) {
415
  db_delete('profile_field')
416
    ->condition('fid', $form_state['values']['fid'])
417
    ->execute();
418
  db_delete('profile_value')
419
    ->condition('fid', $form_state['values']['fid'])
420
    ->execute();
421

    
422
  cache_clear_all();
423

    
424
  drupal_set_message(t('The field %field has been deleted.', array('%field' => $form_state['values']['title'])));
425
  watchdog('profile', 'Profile field %field deleted.', array('%field' => $form_state['values']['title']), WATCHDOG_NOTICE, l(t('view'), 'admin/config/people/profile'));
426

    
427
  $form_state['redirect'] = 'admin/config/people/profile';
428
  return;
429
}
430

    
431
/**
432
 * Retrieve a pipe delimited string of autocomplete suggestions for profile categories
433
 */
434
function profile_admin_settings_autocomplete($string) {
435
  $matches = array();
436
  $result = db_select('profile_field')
437
    ->fields('profile_field', array('category'))
438
    ->condition('category', db_like($string) . '%', 'LIKE')
439
    ->range(0, 10)
440
    ->execute();
441

    
442
  foreach ($result as $data) {
443
    $matches[$data->category] = check_plain($data->category);
444
  }
445
  drupal_json_output($matches);
446
}