Projet

Général

Profil

Paste
Télécharger (32,8 ko) Statistiques
| Branche: | Révision:

root / htmltest / modules / image / image.admin.inc @ 85ad3d82

1
<?php
2

    
3
/**
4
 * @file
5
 * Administration pages for image settings.
6
 */
7

    
8
/**
9
 * Menu callback; Listing of all current image styles.
10
 */
11
function image_style_list() {
12
  $page = array();
13

    
14
  $styles = image_styles();
15
  $page['image_style_list'] = array(
16
    '#markup' => theme('image_style_list', array('styles' => $styles)),
17
    '#attached' => array(
18
      'css' => array(drupal_get_path('module', 'image') . '/image.admin.css' => array()),
19
    ),
20
  );
21

    
22
  return $page;
23

    
24
}
25

    
26
/**
27
 * Form builder; Edit an image style name and effects order.
28
 *
29
 * @param $form_state
30
 *   An associative array containing the current state of the form.
31
 * @param $style
32
 *   An image style array.
33
 * @ingroup forms
34
 * @see image_style_form_submit()
35
 */
36
function image_style_form($form, &$form_state, $style) {
37
  $title = t('Edit %name style', array('%name' => $style['label']));
38
  drupal_set_title($title, PASS_THROUGH);
39

    
40
  // Adjust this form for styles that must be overridden to edit.
41
  $editable = (bool) ($style['storage'] & IMAGE_STORAGE_EDITABLE);
42

    
43
  if (!$editable && empty($form_state['input'])) {
44
    drupal_set_message(t('This image style is currently being provided by a module. Click the "Override defaults" button to change its settings.'), 'warning');
45
  }
46

    
47
  $form_state['image_style'] = $style;
48
  $form['#tree'] = TRUE;
49
  $form['#attached']['css'][drupal_get_path('module', 'image') . '/image.admin.css'] = array();
50

    
51
  // Show the thumbnail preview.
52
  $form['preview'] = array(
53
    '#type' => 'item',
54
    '#title' => t('Preview'),
55
    '#markup' => theme('image_style_preview', array('style' => $style)),
56
  );
57

    
58
  // Show the Image Style label.
59
  $form['label'] = array(
60
    '#type' => 'textfield',
61
    '#title' => t('Image style name'),
62
    '#default_value' => $style['label'],
63
    '#disabled' => !$editable,
64
    '#required' => TRUE,
65
  );
66

    
67
  // Allow the name of the style to be changed, unless this style is
68
  // provided by a module's hook_default_image_styles().
69
  $form['name'] = array(
70
    '#type' => 'machine_name',
71
    '#size' => '64',
72
    '#default_value' => $style['name'],
73
    '#disabled' => !$editable,
74
    '#description' => t('The name is used in URLs for generated images. Use only lowercase alphanumeric characters, underscores (_), and hyphens (-).'),
75
    '#required' => TRUE,
76
    '#machine_name' => array(
77
      'exists' => 'image_style_load',
78
      'source' => array('label'),
79
      'replace_pattern' => '[^0-9a-z_\-]',
80
      'error' => t('Please only use lowercase alphanumeric characters, underscores (_), and hyphens (-) for style names.'),
81
    ),
82
  );
83

    
84
  // Build the list of existing image effects for this image style.
85
  $form['effects'] = array(
86
    '#theme' => 'image_style_effects',
87
  );
88
  foreach ($style['effects'] as $key => $effect) {
89
    $form['effects'][$key]['#weight'] = isset($form_state['input']['effects']) ? $form_state['input']['effects'][$key]['weight'] : NULL;
90
    $form['effects'][$key]['label'] = array(
91
      '#markup' => $effect['label'],
92
    );
93
    $form['effects'][$key]['summary'] = array(
94
      '#markup' => isset($effect['summary theme']) ? theme($effect['summary theme'], array('data' => $effect['data'])) : '',
95
    );
96
    $form['effects'][$key]['weight'] = array(
97
      '#type' => 'weight',
98
      '#title' => t('Weight for @title', array('@title' => $effect['label'])),
99
      '#title_display' => 'invisible',
100
      '#default_value' => $effect['weight'],
101
      '#access' => $editable,
102
    );
103

    
104
    // Only attempt to display these fields for editable styles as the 'ieid'
105
    // key is not set for styles defined in code.
106
    if ($editable) {
107
      $form['effects'][$key]['configure'] = array(
108
        '#type' => 'link',
109
        '#title' => t('edit'),
110
        '#href' => 'admin/config/media/image-styles/edit/' . $style['name'] . '/effects/' . $effect['ieid'],
111
        '#access' => $editable && isset($effect['form callback']),
112
      );
113
      $form['effects'][$key]['remove'] = array(
114
        '#type' => 'link',
115
        '#title' => t('delete'),
116
        '#href' => 'admin/config/media/image-styles/edit/' . $style['name'] . '/effects/' . $effect['ieid'] . '/delete',
117
        '#access' => $editable,
118
      );
119
    }
120
  }
121

    
122
  // Build the new image effect addition form and add it to the effect list.
123
  $new_effect_options = array();
124
  foreach (image_effect_definitions() as $effect => $definition) {
125
    $new_effect_options[$effect] = check_plain($definition['label']);
126
  }
127
  $form['effects']['new'] = array(
128
    '#tree' => FALSE,
129
    '#weight' => isset($form_state['input']['weight']) ? $form_state['input']['weight'] : NULL,
130
    '#access' => $editable,
131
  );
132
  $form['effects']['new']['new'] = array(
133
    '#type' => 'select',
134
    '#title' => t('Effect'),
135
    '#title_display' => 'invisible',
136
    '#options' => $new_effect_options,
137
    '#empty_option' => t('Select a new effect'),
138
  );
139
  $form['effects']['new']['weight'] = array(
140
    '#type' => 'weight',
141
    '#title' => t('Weight for new effect'),
142
    '#title_display' => 'invisible',
143
    '#default_value' => count($form['effects']) - 1,
144
  );
145
  $form['effects']['new']['add'] = array(
146
    '#type' => 'submit',
147
    '#value' => t('Add'),
148
    '#validate' => array('image_style_form_add_validate'),
149
    '#submit' => array('image_style_form_submit', 'image_style_form_add_submit'),
150
  );
151

    
152
  // Show the Override or Submit button for this style.
153
  $form['actions'] = array('#type' => 'actions');
154
  $form['actions']['override'] = array(
155
    '#type' => 'submit',
156
    '#value' => t('Override defaults'),
157
    '#validate' => array(),
158
    '#submit' => array('image_style_form_override_submit'),
159
    '#access' => !$editable,
160
  );
161
  $form['actions']['submit'] = array(
162
    '#type' => 'submit',
163
    '#value' => t('Update style'),
164
    '#access' => $editable,
165
  );
166

    
167
  return $form;
168
}
169

    
170
/**
171
 * Validate handler for adding a new image effect to an image style.
172
 */
173
function image_style_form_add_validate($form, &$form_state) {
174
  if (!$form_state['values']['new']) {
175
    form_error($form['effects']['new']['new'], t('Select an effect to add.'));
176
  }
177
}
178

    
179
/**
180
 * Submit handler for adding a new image effect to an image style.
181
 */
182
function image_style_form_add_submit($form, &$form_state) {
183
  $style = $form_state['image_style'];
184
  // Check if this field has any configuration options.
185
  $effect = image_effect_definition_load($form_state['values']['new']);
186

    
187
  // Load the configuration form for this option.
188
  if (isset($effect['form callback'])) {
189
    $path = 'admin/config/media/image-styles/edit/' . $form_state['image_style']['name'] . '/add/' . $form_state['values']['new'];
190
    $form_state['redirect'] = array($path, array('query' => array('weight' => $form_state['values']['weight'])));
191
  }
192
  // If there's no form, immediately add the image effect.
193
  else {
194
    $effect['isid'] = $style['isid'];
195
    $effect['weight'] = $form_state['values']['weight'];
196
    image_effect_save($effect);
197
    drupal_set_message(t('The image effect was successfully applied.'));
198
  }
199
}
200

    
201
/**
202
 * Submit handler for overriding a module-defined style.
203
 */
204
function image_style_form_override_submit($form, &$form_state) {
205
  drupal_set_message(t('The %style style has been overridden, allowing you to change its settings.', array('%style' => $form_state['image_style']['label'])));
206
  image_default_style_save($form_state['image_style']);
207
}
208

    
209
/**
210
 * Submit handler for saving an image style.
211
 */
212
function image_style_form_submit($form, &$form_state) {
213
  // Update the image style.
214
  $style = $form_state['image_style'];
215
  $style['name'] = $form_state['values']['name'];
216
  $style['label'] = $form_state['values']['label'];
217

    
218
  // Update image effect weights.
219
  if (!empty($form_state['values']['effects'])) {
220
    foreach ($form_state['values']['effects'] as $ieid => $effect_data) {
221
      if (isset($style['effects'][$ieid])) {
222
        $effect = $style['effects'][$ieid];
223
        $effect['weight'] = $effect_data['weight'];
224
        image_effect_save($effect);
225
      }
226
    }
227
  }
228

    
229
  image_style_save($style);
230
  if ($form_state['values']['op'] == t('Update style')) {
231
    drupal_set_message(t('Changes to the style have been saved.'));
232
  }
233
  $form_state['redirect'] = 'admin/config/media/image-styles/edit/' . $style['name'];
234
}
235

    
236
/**
237
 * Form builder; Form for adding a new image style.
238
 *
239
 * @ingroup forms
240
 * @see image_style_add_form_submit()
241
 */
242
function image_style_add_form($form, &$form_state) {
243
  $form['label'] = array(
244
    '#type' => 'textfield',
245
    '#title' => t('Style name'),
246
    '#default_value' => '',
247
    '#required' => TRUE,
248
  );
249
  $form['name'] = array(
250
    '#type' => 'machine_name',
251
    '#description' => t('The name is used in URLs for generated images. Use only lowercase alphanumeric characters, underscores (_), and hyphens (-).'),
252
    '#size' => '64',
253
    '#required' => TRUE,
254
    '#machine_name' => array(
255
      'exists' => 'image_style_load',
256
      'source' => array('label'),
257
      'replace_pattern' => '[^0-9a-z_\-]',
258
      'error' => t('Please only use lowercase alphanumeric characters, underscores (_), and hyphens (-) for style names.'),
259
    ),
260
  );
261

    
262
  $form['submit'] = array(
263
    '#type' => 'submit',
264
    '#value' => t('Create new style'),
265
  );
266

    
267
  return $form;
268
}
269

    
270
/**
271
 * Submit handler for adding a new image style.
272
 */
273
function image_style_add_form_submit($form, &$form_state) {
274
  $style = array(
275
    'name' => $form_state['values']['name'],
276
    'label' => $form_state['values']['label'],
277
  );
278
  $style = image_style_save($style);
279
  drupal_set_message(t('Style %name was created.', array('%name' => $style['label'])));
280
  $form_state['redirect'] = 'admin/config/media/image-styles/edit/' . $style['name'];
281
}
282

    
283
/**
284
 * Element validate function to ensure unique, URL safe style names.
285
 *
286
 * This function is no longer used in Drupal core since image style names are
287
 * now validated using #machine_name functionality. It is kept for backwards
288
 * compatibility (since non-core modules may be using it) and will be removed
289
 * in Drupal 8.
290
 */
291
function image_style_name_validate($element, $form_state) {
292
  // Check for duplicates.
293
  $styles = image_styles();
294
  if (isset($styles[$element['#value']]) && (!isset($form_state['image_style']['isid']) || $styles[$element['#value']]['isid'] != $form_state['image_style']['isid'])) {
295
    form_set_error($element['#name'], t('The image style name %name is already in use.', array('%name' => $element['#value'])));
296
  }
297

    
298
  // Check for illegal characters in image style names.
299
  if (preg_match('/[^0-9a-z_\-]/', $element['#value'])) {
300
    form_set_error($element['#name'], t('Please only use lowercase alphanumeric characters, underscores (_), and hyphens (-) for style names.'));
301
  }
302
}
303

    
304
/**
305
 * Form builder; Form for deleting an image style.
306
 *
307
 * @param $style
308
 *   An image style array.
309
 *
310
 * @ingroup forms
311
 * @see image_style_delete_form_submit()
312
 */
313
function image_style_delete_form($form, &$form_state, $style) {
314
  $form_state['image_style'] = $style;
315

    
316
  $replacement_styles = array_diff_key(image_style_options(TRUE, PASS_THROUGH), array($style['name'] => ''));
317
  $form['replacement'] = array(
318
    '#title' => t('Replacement style'),
319
    '#type' => 'select',
320
    '#options' => $replacement_styles,
321
    '#empty_option' => t('No replacement, just delete'),
322
  );
323

    
324
  return confirm_form(
325
    $form,
326
    t('Optionally select a style before deleting %style', array('%style' => $style['label'])),
327
    'admin/config/media/image-styles',
328
    t('If this style is in use on the site, you may select another style to replace it. All images that have been generated for this style will be permanently deleted.'),
329
    t('Delete'),  t('Cancel')
330
  );
331
}
332

    
333
/**
334
 * Submit handler to delete an image style.
335
 */
336
function image_style_delete_form_submit($form, &$form_state) {
337
  $style = $form_state['image_style'];
338

    
339
  image_style_delete($style, $form_state['values']['replacement']);
340
  drupal_set_message(t('Style %name was deleted.', array('%name' => $style['label'])));
341
  $form_state['redirect'] = 'admin/config/media/image-styles';
342
}
343

    
344
/**
345
 * Confirmation form to revert a database style to its default.
346
 */
347
function image_style_revert_form($form, &$form_state, $style) {
348
  $form_state['image_style'] = $style;
349

    
350
  return confirm_form(
351
    $form,
352
    t('Revert the %style style?', array('%style' => $style['label'])),
353
    'admin/config/media/image-styles',
354
    t('Reverting this style will delete the customized settings and restore the defaults provided by the @module module.', array('@module' => $style['module'])),
355
    t('Revert'),  t('Cancel')
356
  );
357
}
358

    
359
/**
360
 * Submit handler to convert an overridden style to its default.
361
 */
362
function image_style_revert_form_submit($form, &$form_state) {
363
  drupal_set_message(t('The %style style has been reverted to its defaults.', array('%style' => $form_state['image_style']['label'])));
364
  image_default_style_revert($form_state['image_style']);
365
  $form_state['redirect'] = 'admin/config/media/image-styles';
366
}
367

    
368
/**
369
 * Form builder; Form for adding and editing image effects.
370
 *
371
 * This form is used universally for editing all image effects. Each effect adds
372
 * its own custom section to the form by calling the form function specified in
373
 * hook_image_effects().
374
 *
375
 * @param $form_state
376
 *   An associative array containing the current state of the form.
377
 * @param $style
378
 *   An image style array.
379
 * @param $effect
380
 *   An image effect array.
381
 *
382
 * @ingroup forms
383
 * @see hook_image_effects()
384
 * @see image_effects()
385
 * @see image_resize_form()
386
 * @see image_scale_form()
387
 * @see image_rotate_form()
388
 * @see image_crop_form()
389
 * @see image_effect_form_submit()
390
 */
391
function image_effect_form($form, &$form_state, $style, $effect) {
392
  if (!empty($effect['data'])) {
393
    $title = t('Edit %label effect', array('%label' => $effect['label']));
394
  }
395
  else{
396
    $title = t('Add %label effect', array('%label' => $effect['label']));
397
  }
398
  drupal_set_title($title, PASS_THROUGH);
399

    
400
  $form_state['image_style'] = $style;
401
  $form_state['image_effect'] = $effect;
402

    
403
  // If no configuration for this image effect, return to the image style page.
404
  if (!isset($effect['form callback'])) {
405
    drupal_goto('admin/config/media/image-styles/edit/' . $style['name']);
406
  }
407

    
408
  $form['#tree'] = TRUE;
409
  $form['#attached']['css'][drupal_get_path('module', 'image') . '/image.admin.css'] = array();
410
  if (function_exists($effect['form callback'])) {
411
    $form['data'] = call_user_func($effect['form callback'], $effect['data']);
412
  }
413

    
414
  // Check the URL for a weight, then the image effect, otherwise use default.
415
  $form['weight'] = array(
416
    '#type' => 'hidden',
417
    '#value' => isset($_GET['weight']) ? intval($_GET['weight']) : (isset($effect['weight']) ? $effect['weight'] : count($style['effects'])),
418
  );
419

    
420
  $form['actions'] = array('#tree' => FALSE, '#type' => 'actions');
421
  $form['actions']['submit'] = array(
422
    '#type' => 'submit',
423
    '#value' => isset($effect['ieid']) ? t('Update effect') : t('Add effect'),
424
  );
425
  $form['actions']['cancel'] = array(
426
    '#type' => 'link',
427
    '#title' => t('Cancel'),
428
    '#href' => 'admin/config/media/image-styles/edit/' . $style['name'],
429
  );
430

    
431
  return $form;
432
}
433

    
434
/**
435
 * Submit handler for updating an image effect.
436
 */
437
function image_effect_form_submit($form, &$form_state) {
438
  $style = $form_state['image_style'];
439
  $effect = array_merge($form_state['image_effect'], $form_state['values']);
440
  $effect['isid'] = $style['isid'];
441
  image_effect_save($effect);
442
  drupal_set_message(t('The image effect was successfully applied.'));
443
  $form_state['redirect'] = 'admin/config/media/image-styles/edit/' . $style['name'];
444
}
445

    
446
/**
447
 * Form builder; Form for deleting an image effect.
448
 *
449
 * @param $style
450
 *   Name of the image style from which the image effect will be removed.
451
 * @param $effect
452
 *   Name of the image effect to remove.
453
 * @ingroup forms
454
 * @see image_effect_delete_form_submit()
455
 */
456
function image_effect_delete_form($form, &$form_state, $style, $effect) {
457
  $form_state['image_style'] = $style;
458
  $form_state['image_effect'] = $effect;
459

    
460
  $question = t('Are you sure you want to delete the @effect effect from the %style style?', array('%style' => $style['label'], '@effect' => $effect['label']));
461
  return confirm_form($form, $question, 'admin/config/media/image-styles/edit/' . $style['name'], '', t('Delete'));
462
}
463

    
464
/**
465
 * Submit handler to delete an image effect.
466
 */
467
function image_effect_delete_form_submit($form, &$form_state) {
468
  $style = $form_state['image_style'];
469
  $effect = $form_state['image_effect'];
470

    
471
  image_effect_delete($effect);
472
  drupal_set_message(t('The image effect %name has been deleted.', array('%name' => $effect['label'])));
473
  $form_state['redirect'] = 'admin/config/media/image-styles/edit/' . $style['name'];
474
}
475

    
476
/**
477
 * Element validate handler to ensure an integer pixel value.
478
 *
479
 * The property #allow_negative = TRUE may be set to allow negative integers.
480
 */
481
function image_effect_integer_validate($element, &$form_state) {
482
  $value = empty($element['#allow_negative']) ? $element['#value'] : preg_replace('/^-/', '', $element['#value']);
483
  if ($element['#value'] != '' && (!is_numeric($value) || intval($value) <= 0)) {
484
    if (empty($element['#allow_negative'])) {
485
      form_error($element, t('!name must be an integer.', array('!name' => $element['#title'])));
486
    }
487
    else {
488
      form_error($element, t('!name must be a positive integer.', array('!name' => $element['#title'])));
489
    }
490
  }
491
}
492

    
493
/**
494
 * Element validate handler to ensure a hexadecimal color value.
495
 */
496
function image_effect_color_validate($element, &$form_state) {
497
  if ($element['#value'] != '') {
498
    $hex_value = preg_replace('/^#/', '', $element['#value']);
499
    if (!preg_match('/^#[0-9A-F]{3}([0-9A-F]{3})?$/', $element['#value'])) {
500
      form_error($element, t('!name must be a hexadecimal color value.', array('!name' => $element['#title'])));
501
    }
502
  }
503
}
504

    
505
/**
506
 * Element validate handler to ensure that either a height or a width is
507
 * specified.
508
 */
509
function image_effect_scale_validate($element, &$form_state) {
510
  if (empty($element['width']['#value']) && empty($element['height']['#value'])) {
511
    form_error($element, t('Width and height can not both be blank.'));
512
  }
513
}
514

    
515
/**
516
 * Form structure for the image resize form.
517
 *
518
 * Note that this is not a complete form, it only contains the portion of the
519
 * form for configuring the resize options. Therefore it does not not need to
520
 * include metadata about the effect, nor a submit button.
521
 *
522
 * @param $data
523
 *   The current configuration for this resize effect.
524
 */
525
function image_resize_form($data) {
526
  $form['width'] = array(
527
    '#type' => 'textfield',
528
    '#title' => t('Width'),
529
    '#default_value' => isset($data['width']) ? $data['width'] : '',
530
    '#field_suffix' => ' ' . t('pixels'),
531
    '#required' => TRUE,
532
    '#size' => 10,
533
    '#element_validate' => array('image_effect_integer_validate'),
534
    '#allow_negative' => FALSE,
535
  );
536
  $form['height'] = array(
537
    '#type' => 'textfield',
538
    '#title' => t('Height'),
539
    '#default_value' => isset($data['height']) ? $data['height'] : '',
540
    '#field_suffix' => ' ' . t('pixels'),
541
    '#required' => TRUE,
542
    '#size' => 10,
543
    '#element_validate' => array('image_effect_integer_validate'),
544
    '#allow_negative' => FALSE,
545
  );
546
  return $form;
547
}
548

    
549
/**
550
 * Form structure for the image scale form.
551
 *
552
 * Note that this is not a complete form, it only contains the portion of the
553
 * form for configuring the scale options. Therefore it does not not need to
554
 * include metadata about the effect, nor a submit button.
555
 *
556
 * @param $data
557
 *   The current configuration for this scale effect.
558
 */
559
function image_scale_form($data) {
560
  $form = image_resize_form($data);
561
  $form['#element_validate'] = array('image_effect_scale_validate');
562
  $form['width']['#required'] = FALSE;
563
  $form['height']['#required'] = FALSE;
564
  $form['upscale'] = array(
565
    '#type' => 'checkbox',
566
    '#default_value' => (isset($data['upscale'])) ? $data['upscale'] : 0,
567
    '#title' => t('Allow Upscaling'),
568
    '#description' => t('Let scale make images larger than their original size'),
569
  );
570
  return $form;
571
}
572

    
573
/**
574
 * Form structure for the image crop form.
575
 *
576
 * Note that this is not a complete form, it only contains the portion of the
577
 * form for configuring the crop options. Therefore it does not not need to
578
 * include metadata about the effect, nor a submit button.
579
 *
580
 * @param $data
581
 *   The current configuration for this crop effect.
582
 */
583
function image_crop_form($data) {
584
  $data += array(
585
    'width' => '',
586
    'height' => '',
587
    'anchor' => 'center-center',
588
  );
589

    
590
  $form = image_resize_form($data);
591
  $form['anchor'] = array(
592
    '#type' => 'radios',
593
    '#title' => t('Anchor'),
594
    '#options' => array(
595
      'left-top'      => t('Top') . ' ' . t('Left'),
596
      'center-top'    => t('Top') . ' ' . t('Center'),
597
      'right-top'     => t('Top') . ' ' . t('Right'),
598
      'left-center'   => t('Center') . ' ' . t('Left'),
599
      'center-center' => t('Center'),
600
      'right-center'  => t('Center') . ' ' . t('Right'),
601
      'left-bottom'   => t('Bottom') . ' ' . t('Left'),
602
      'center-bottom' => t('Bottom') . ' ' . t('Center'),
603
      'right-bottom'  => t('Bottom') . ' ' . t('Right'),
604
    ),
605
    '#theme' => 'image_anchor',
606
    '#default_value' => $data['anchor'],
607
    '#description' => t('The part of the image that will be retained during the crop.'),
608
  );
609

    
610
  return $form;
611
}
612

    
613
/**
614
 * Form structure for the image rotate form.
615
 *
616
 * Note that this is not a complete form, it only contains the portion of the
617
 * form for configuring the rotate options. Therefore it does not not need to
618
 * include metadata about the effect, nor a submit button.
619
 *
620
 * @param $data
621
 *   The current configuration for this rotate effect.
622
 */
623
function image_rotate_form($data) {
624
  $form['degrees'] = array(
625
    '#type' => 'textfield',
626
    '#default_value' => (isset($data['degrees'])) ? $data['degrees'] : 0,
627
    '#title' => t('Rotation angle'),
628
    '#description' => t('The number of degrees the image should be rotated. Positive numbers are clockwise, negative are counter-clockwise.'),
629
    '#field_suffix' => '&deg;',
630
    '#required' => TRUE,
631
    '#size' => 6,
632
    '#maxlength' => 4,
633
    '#element_validate' => array('image_effect_integer_validate'),
634
    '#allow_negative' => TRUE,
635
  );
636
  $form['bgcolor'] = array(
637
    '#type' => 'textfield',
638
    '#default_value' => (isset($data['bgcolor'])) ? $data['bgcolor'] : '#FFFFFF',
639
    '#title' => t('Background color'),
640
    '#description' => t('The background color to use for exposed areas of the image. Use web-style hex colors (#FFFFFF for white, #000000 for black). Leave blank for transparency on image types that support it.'),
641
    '#size' => 7,
642
    '#maxlength' => 7,
643
    '#element_validate' => array('image_effect_color_validate'),
644
  );
645
  $form['random'] = array(
646
    '#type' => 'checkbox',
647
    '#default_value' => (isset($data['random'])) ? $data['random'] : 0,
648
    '#title' => t('Randomize'),
649
    '#description' => t('Randomize the rotation angle for each image. The angle specified above is used as a maximum.'),
650
  );
651
  return $form;
652
}
653

    
654
/**
655
 * Returns HTML for the page containing the list of image styles.
656
 *
657
 * @param $variables
658
 *   An associative array containing:
659
 *   - styles: An array of all the image styles returned by image_get_styles().
660
 *
661
 * @see image_get_styles()
662
 * @ingroup themeable
663
 */
664
function theme_image_style_list($variables) {
665
  $styles = $variables['styles'];
666

    
667
  $header = array(t('Style name'), t('Settings'), array('data' => t('Operations'), 'colspan' => 3));
668
  $rows = array();
669
  foreach ($styles as $style) {
670
    $row = array();
671
    $row[] = l($style['label'], 'admin/config/media/image-styles/edit/' . $style['name']);
672
    $link_attributes = array(
673
      'attributes' => array(
674
        'class' => array('image-style-link'),
675
      ),
676
    );
677
    if ($style['storage'] == IMAGE_STORAGE_NORMAL) {
678
      $row[] = t('Custom');
679
      $row[] = l(t('edit'), 'admin/config/media/image-styles/edit/' . $style['name'], $link_attributes);
680
      $row[] = l(t('delete'), 'admin/config/media/image-styles/delete/' . $style['name'], $link_attributes);
681
    }
682
    elseif ($style['storage'] == IMAGE_STORAGE_OVERRIDE) {
683
      $row[] = t('Overridden');
684
      $row[] = l(t('edit'), 'admin/config/media/image-styles/edit/' . $style['name'], $link_attributes);
685
      $row[] = l(t('revert'), 'admin/config/media/image-styles/revert/' . $style['name'], $link_attributes);
686
    }
687
    else {
688
      $row[] = t('Default');
689
      $row[] = l(t('edit'), 'admin/config/media/image-styles/edit/' . $style['name'], $link_attributes);
690
      $row[] = '';
691
    }
692
    $rows[] = $row;
693
  }
694

    
695
  if (empty($rows)) {
696
    $rows[] = array(array(
697
      'colspan' => 4,
698
      'data' => t('There are currently no styles. <a href="!url">Add a new one</a>.', array('!url' => url('admin/config/media/image-styles/add'))),
699
    ));
700
  }
701

    
702
  return theme('table', array('header' => $header, 'rows' => $rows));
703
}
704

    
705
/**
706
 * Returns HTML for a listing of the effects within a specific image style.
707
 *
708
 * @param $variables
709
 *   An associative array containing:
710
 *   - form: A render element representing the form.
711
 *
712
 * @ingroup themeable
713
 */
714
function theme_image_style_effects($variables) {
715
  $form = $variables['form'];
716

    
717
  $rows = array();
718

    
719
  foreach (element_children($form) as $key) {
720
    $row = array();
721
    $form[$key]['weight']['#attributes']['class'] = array('image-effect-order-weight');
722
    if (is_numeric($key)) {
723
      $summary = drupal_render($form[$key]['summary']);
724
      $row[] = drupal_render($form[$key]['label']) . (empty($summary) ? '' : ' ' . $summary);
725
      $row[] = drupal_render($form[$key]['weight']);
726
      $row[] = drupal_render($form[$key]['configure']);
727
      $row[] = drupal_render($form[$key]['remove']);
728
    }
729
    else {
730
      // Add the row for adding a new image effect.
731
      $row[] = '<div class="image-style-new">' . drupal_render($form['new']['new']) . drupal_render($form['new']['add']) . '</div>';
732
      $row[] = drupal_render($form['new']['weight']);
733
      $row[] = array('data' => '', 'colspan' => 2);
734
    }
735

    
736
    if (!isset($form[$key]['#access']) || $form[$key]['#access']) {
737
      $rows[] = array(
738
        'data' => $row,
739
        'class' => !empty($form[$key]['weight']['#access']) || $key == 'new' ? array('draggable') : array(),
740
      );
741
    }
742
  }
743

    
744
  $header = array(
745
    t('Effect'),
746
    t('Weight'),
747
    array('data' => t('Operations'), 'colspan' => 2),
748
  );
749

    
750
  if (count($rows) == 1 && $form['new']['#access']) {
751
    array_unshift($rows, array(array(
752
      'data' => t('There are currently no effects in this style. Add one by selecting an option below.'),
753
      'colspan' => 4,
754
    )));
755
  }
756

    
757
  $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'image-style-effects')));
758
  drupal_add_tabledrag('image-style-effects', 'order', 'sibling', 'image-effect-order-weight');
759
  return $output;
760
}
761

    
762
/**
763
 * Returns HTML for a preview of an image style.
764
 *
765
 * @param $variables
766
 *   An associative array containing:
767
 *   - style: The image style array being previewed.
768
 *
769
 * @ingroup themeable
770
 */
771
function theme_image_style_preview($variables) {
772
  $style = $variables['style'];
773

    
774
  $sample_image = variable_get('image_style_preview_image', drupal_get_path('module', 'image') . '/sample.png');
775
  $sample_width = 160;
776
  $sample_height = 160;
777

    
778
  // Set up original file information.
779
  $original_path = $sample_image;
780
  $original_image = image_get_info($original_path);
781
  if ($original_image['width'] > $original_image['height']) {
782
    $original_width = min($original_image['width'], $sample_width);
783
    $original_height = round($original_width / $original_image['width'] * $original_image['height']);
784
  }
785
  else {
786
    $original_height = min($original_image['height'], $sample_height);
787
    $original_width = round($original_height / $original_image['height'] * $original_image['width']);
788
  }
789
  $original_attributes = array_intersect_key($original_image, array('width' => '', 'height' => ''));
790
  $original_attributes['style'] = 'width: ' . $original_width . 'px; height: ' . $original_height . 'px;';
791

    
792
  // Set up preview file information.
793
  $preview_file = image_style_path($style['name'], $original_path);
794
  if (!file_exists($preview_file)) {
795
    image_style_create_derivative($style, $original_path, $preview_file);
796
  }
797
  $preview_image = image_get_info($preview_file);
798
  if ($preview_image['width'] > $preview_image['height']) {
799
    $preview_width = min($preview_image['width'], $sample_width);
800
    $preview_height = round($preview_width / $preview_image['width'] * $preview_image['height']);
801
  }
802
  else {
803
    $preview_height = min($preview_image['height'], $sample_height);
804
    $preview_width = round($preview_height / $preview_image['height'] * $preview_image['width']);
805
  }
806
  $preview_attributes = array_intersect_key($preview_image, array('width' => '', 'height' => ''));
807
  $preview_attributes['style'] = 'width: ' . $preview_width . 'px; height: ' . $preview_height . 'px;';
808

    
809
  // In the previews, timestamps are added to prevent caching of images.
810
  $output = '<div class="image-style-preview preview clearfix">';
811

    
812
  // Build the preview of the original image.
813
  $original_url = file_create_url($original_path);
814
  $output .= '<div class="preview-image-wrapper">';
815
  $output .= t('original') . ' (' . l(t('view actual size'), $original_url) . ')';
816
  $output .= '<div class="preview-image original-image" style="' . $original_attributes['style'] . '">';
817
  $output .= '<a href="' . $original_url . '">' . theme('image', array('path' => $original_path, 'alt' => t('Sample original image'), 'title' => '', 'attributes' => $original_attributes)) . '</a>';
818
  $output .= '<div class="height" style="height: ' . $original_height . 'px"><span>' . $original_image['height'] . 'px</span></div>';
819
  $output .= '<div class="width" style="width: ' . $original_width . 'px"><span>' . $original_image['width'] . 'px</span></div>';
820
  $output .= '</div>'; // End preview-image.
821
  $output .= '</div>'; // End preview-image-wrapper.
822

    
823
  // Build the preview of the image style.
824
  $preview_url = file_create_url($preview_file) . '?cache_bypass=' . REQUEST_TIME;
825
  $output .= '<div class="preview-image-wrapper">';
826
  $output .= check_plain($style['label']) . ' (' . l(t('view actual size'), file_create_url($preview_file) . '?' . time()) . ')';
827
  $output .= '<div class="preview-image modified-image" style="' . $preview_attributes['style'] . '">';
828
  $output .= '<a href="' . file_create_url($preview_file) . '?' . time() . '">' . theme('image', array('path' => $preview_url, 'alt' => t('Sample modified image'), 'title' => '', 'attributes' => $preview_attributes)) . '</a>';
829
  $output .= '<div class="height" style="height: ' . $preview_height . 'px"><span>' . $preview_image['height'] . 'px</span></div>';
830
  $output .= '<div class="width" style="width: ' . $preview_width . 'px"><span>' . $preview_image['width'] . 'px</span></div>';
831
  $output .= '</div>'; // End preview-image.
832
  $output .= '</div>'; // End preview-image-wrapper.
833

    
834
  $output .= '</div>'; // End image-style-preview.
835

    
836
  return $output;
837
}
838

    
839
/**
840
 * Returns HTML for a 3x3 grid of checkboxes for image anchors.
841
 *
842
 * @param $variables
843
 *   An associative array containing:
844
 *   - element: A render element containing radio buttons.
845
 *
846
 * @ingroup themeable
847
 */
848
function theme_image_anchor($variables) {
849
  $element = $variables['element'];
850

    
851
  $rows = array();
852
  $row = array();
853
  foreach (element_children($element) as $n => $key) {
854
    $element[$key]['#attributes']['title'] = $element[$key]['#title'];
855
    unset($element[$key]['#title']);
856
    $row[] = drupal_render($element[$key]);
857
    if ($n % 3 == 3 - 1) {
858
      $rows[] = $row;
859
      $row = array();
860
    }
861
  }
862

    
863
  return theme('table', array('header' => array(), 'rows' => $rows, 'attributes' => array('class' => array('image-anchor'))));
864
}
865

    
866
/**
867
 * Returns HTML for a summary of an image resize effect.
868
 *
869
 * @param $variables
870
 *   An associative array containing:
871
 *   - data: The current configuration for this resize effect.
872
 *
873
 * @ingroup themeable
874
 */
875
function theme_image_resize_summary($variables) {
876
  $data = $variables['data'];
877

    
878
  if ($data['width'] && $data['height']) {
879
    return check_plain($data['width']) . 'x' . check_plain($data['height']);
880
  }
881
  else {
882
    return ($data['width']) ? t('width @width', array('@width' => $data['width'])) : t('height @height', array('@height' => $data['height']));
883
  }
884
}
885

    
886
/**
887
 * Returns HTML for a summary of an image scale effect.
888
 *
889
 * @param $variables
890
 *   An associative array containing:
891
 *   - data: The current configuration for this scale effect.
892
 *
893
 * @ingroup themeable
894
 */
895
function theme_image_scale_summary($variables) {
896
  $data = $variables['data'];
897
  return theme('image_resize_summary', array('data' => $data)) . ' ' . ($data['upscale'] ? '(' . t('upscaling allowed') . ')' : '');
898
}
899

    
900
/**
901
 * Returns HTML for a summary of an image crop effect.
902
 *
903
 * @param $variables
904
 *   An associative array containing:
905
 *   - data: The current configuration for this crop effect.
906
 *
907
 * @ingroup themeable
908
 */
909
function theme_image_crop_summary($variables) {
910
  return theme('image_resize_summary', $variables);
911
}
912

    
913
/**
914
 * Returns HTML for a summary of an image rotate effect.
915
 *
916
 * @param $variables
917
 *   An associative array containing:
918
 *   - data: The current configuration for this rotate effect.
919
 *
920
 * @ingroup themeable
921
 */
922
function theme_image_rotate_summary($variables) {
923
  $data = $variables['data'];
924
  return ($data['random']) ? t('random between -@degrees&deg and @degrees&deg', array('@degrees' => str_replace('-', '', $data['degrees']))) : t('@degrees&deg', array('@degrees' => $data['degrees']));
925
}