cms/drupal/modules/image/image.admin.inc
changeset 541 e756a8c72c3d
equal deleted inserted replaced
540:07239de796bb 541:e756a8c72c3d
       
     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 left'),
       
   596       'center-top'    => t('Top center'),
       
   597       'right-top'     => t('Top right'),
       
   598       'left-center'   => t('Center left'),
       
   599       'center-center' => t('Center'),
       
   600       'right-center'  => t('Center right'),
       
   601       'left-bottom'   => t('Bottom left'),
       
   602       'center-bottom' => t('Bottom center'),
       
   603       'right-bottom'  => t('Bottom 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 }