2009-10-12 05:22:57 +00:00
< ? php
/**
* @ file
* Implement an image field , based on the file module ' s file field .
*/
2012-12-17 21:54:13 +00:00
use Drupal\Component\Utility\NestedArray ;
2013-01-07 11:22:28 +00:00
use Drupal\Core\Entity\EntityInterface ;
2012-12-17 21:54:13 +00:00
2009-10-12 05:22:57 +00:00
/**
2009-12-04 16:49:48 +00:00
* Implements hook_field_info () .
2009-10-12 05:22:57 +00:00
*/
function image_field_info () {
return array (
'image' => array (
'label' => t ( 'Image' ),
'description' => t ( 'This field stores the ID of an image file as an integer value.' ),
'settings' => array (
Issue #1496480 by mrf, disasm, kbasarab, pfrenssen, cam8001, typhonius, Letharion, ACF, vijaycs85, heyrocker, Berdir, alexpott: Convert file system settings to the new configuration system.
2013-02-08 23:36:06 +00:00
'uri_scheme' => file_default_scheme (),
2013-06-03 19:37:59 +00:00
'default_image' => 0 ,
2013-02-19 06:57:04 +00:00
'column_groups' => array (
'file' => array (
'label' => t ( 'File' ),
2013-06-27 01:52:15 +00:00
'columns' => array ( 'target_id' , 'width' , 'height' ),
2013-02-19 06:57:04 +00:00
),
'alt' => array (
'label' => t ( 'Alt' ),
'translatable' => TRUE ,
),
'title' => array (
'label' => t ( 'Title' ),
'translatable' => TRUE ,
),
),
2009-10-12 05:22:57 +00:00
),
'instance_settings' => array (
'file_extensions' => 'png gif jpg jpeg' ,
'file_directory' => '' ,
'max_filesize' => '' ,
'alt_field' => 0 ,
2012-11-29 07:32:14 +00:00
'alt_field_required' => 0 ,
2009-10-12 05:22:57 +00:00
'title_field' => 0 ,
2012-11-29 07:32:14 +00:00
'title_field_required' => 0 ,
2009-10-12 05:22:57 +00:00
'max_resolution' => '' ,
'min_resolution' => '' ,
2013-06-03 19:37:59 +00:00
'default_image' => 0 ,
2009-10-12 05:22:57 +00:00
),
'default_widget' => 'image_image' ,
'default_formatter' => 'image' ,
2013-06-25 10:27:47 +00:00
'class' => '\Drupal\image\Type\ImageItem' ,
2009-10-12 05:22:57 +00:00
),
);
}
/**
2009-12-04 16:49:48 +00:00
* Implements hook_field_settings_form () .
2009-10-12 05:22:57 +00:00
*/
function image_field_settings_form ( $field , $instance ) {
$defaults = field_info_field_settings ( $field [ 'type' ]);
$settings = array_merge ( $defaults , $field [ 'settings' ]);
$scheme_options = array ();
2010-01-26 08:29:25 +00:00
foreach ( file_get_stream_wrappers ( STREAM_WRAPPERS_WRITE_VISIBLE ) as $scheme => $stream_wrapper ) {
$scheme_options [ $scheme ] = $stream_wrapper [ 'name' ];
2009-10-12 05:22:57 +00:00
}
$form [ 'uri_scheme' ] = array (
'#type' => 'radios' ,
'#title' => t ( 'Upload destination' ),
'#options' => $scheme_options ,
'#default_value' => $settings [ 'uri_scheme' ],
'#description' => t ( 'Select where the final files should be stored. Private file storage has significantly more overhead than public files, but allows restricted access to files within this field.' ),
);
2011-06-15 04:13:14 +00:00
// When the user sets the scheme on the UI, even for the first time, it's
// updating a field because fields are created on the "Manage fields"
// page. So image_field_update_field() can handle this change.
2009-10-12 05:22:57 +00:00
$form [ 'default_image' ] = array (
'#title' => t ( 'Default image' ),
'#type' => 'managed_file' ,
'#description' => t ( 'If no image is uploaded, this image will be shown on display.' ),
2013-06-03 19:37:59 +00:00
'#default_value' => empty ( $field [ 'settings' ][ 'default_image' ]) ? array () : array ( $field [ 'settings' ][ 'default_image' ]),
2011-06-15 04:13:14 +00:00
'#upload_location' => $settings [ 'uri_scheme' ] . '://default_images/' ,
2009-10-12 05:22:57 +00:00
);
return $form ;
}
/**
2009-12-04 16:49:48 +00:00
* Implements hook_field_instance_settings_form () .
2009-10-12 05:22:57 +00:00
*/
function image_field_instance_settings_form ( $field , $instance ) {
$settings = $instance [ 'settings' ];
// Use the file field instance settings form as a basis.
$form = file_field_instance_settings_form ( $field , $instance );
// Add maximum and minimum resolution settings.
$max_resolution = explode ( 'x' , $settings [ 'max_resolution' ]) + array ( '' , '' );
$form [ 'max_resolution' ] = array (
2010-08-30 06:19:42 +00:00
'#type' => 'item' ,
2009-10-12 05:22:57 +00:00
'#title' => t ( 'Maximum image resolution' ),
'#element_validate' => array ( '_image_field_resolution_validate' ),
'#weight' => 4.1 ,
2010-08-30 06:19:42 +00:00
'#field_prefix' => '<div class="container-inline">' ,
'#field_suffix' => '</div>' ,
2012-07-15 13:18:37 +00:00
'#description' => t ( 'The maximum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Leave blank for no restriction. If a larger image is uploaded, it will be resized to reflect the given width and height. Resizing images on upload will cause the loss of <a href="@url">EXIF data</a> in the image.' , array ( '@url' => 'http://en.wikipedia.org/wiki/Exchangeable_image_file_format' )),
2009-10-12 05:22:57 +00:00
);
$form [ 'max_resolution' ][ 'x' ] = array (
2012-04-19 11:31:47 +00:00
'#type' => 'number' ,
2010-10-20 01:31:07 +00:00
'#title' => t ( 'Maximum width' ),
'#title_display' => 'invisible' ,
2009-10-12 05:22:57 +00:00
'#default_value' => $max_resolution [ 0 ],
2012-04-19 11:31:47 +00:00
'#min' => 1 ,
2009-10-12 05:22:57 +00:00
'#field_suffix' => ' x ' ,
);
$form [ 'max_resolution' ][ 'y' ] = array (
2012-04-19 11:31:47 +00:00
'#type' => 'number' ,
2010-10-20 01:31:07 +00:00
'#title' => t ( 'Maximum height' ),
'#title_display' => 'invisible' ,
2009-10-12 05:22:57 +00:00
'#default_value' => $max_resolution [ 1 ],
2012-04-19 11:31:47 +00:00
'#min' => 1 ,
2009-10-12 05:22:57 +00:00
'#field_suffix' => ' ' . t ( 'pixels' ),
);
$min_resolution = explode ( 'x' , $settings [ 'min_resolution' ]) + array ( '' , '' );
$form [ 'min_resolution' ] = array (
2010-08-30 06:19:42 +00:00
'#type' => 'item' ,
2009-10-12 05:22:57 +00:00
'#title' => t ( 'Minimum image resolution' ),
'#element_validate' => array ( '_image_field_resolution_validate' ),
'#weight' => 4.2 ,
2010-08-30 06:19:42 +00:00
'#field_prefix' => '<div class="container-inline">' ,
'#field_suffix' => '</div>' ,
2009-10-12 05:22:57 +00:00
'#description' => t ( 'The minimum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Leave blank for no restriction. If a smaller image is uploaded, it will be rejected.' ),
);
$form [ 'min_resolution' ][ 'x' ] = array (
2012-04-19 11:31:47 +00:00
'#type' => 'number' ,
2010-10-20 01:31:07 +00:00
'#title' => t ( 'Minimum width' ),
'#title_display' => 'invisible' ,
2009-10-12 05:22:57 +00:00
'#default_value' => $min_resolution [ 0 ],
2012-04-19 11:31:47 +00:00
'#min' => 1 ,
2009-10-12 05:22:57 +00:00
'#field_suffix' => ' x ' ,
);
$form [ 'min_resolution' ][ 'y' ] = array (
2012-04-19 11:31:47 +00:00
'#type' => 'number' ,
2010-10-20 01:31:07 +00:00
'#title' => t ( 'Minimum height' ),
'#title_display' => 'invisible' ,
2009-10-12 05:22:57 +00:00
'#default_value' => $min_resolution [ 1 ],
2012-04-19 11:31:47 +00:00
'#min' => 1 ,
2009-10-12 05:22:57 +00:00
'#field_suffix' => ' ' . t ( 'pixels' ),
);
// Remove the description option.
unset ( $form [ 'description_field' ]);
// Add title and alt configuration options.
$form [ 'alt_field' ] = array (
'#type' => 'checkbox' ,
'#title' => t ( 'Enable <em>Alt</em> field' ),
'#default_value' => $settings [ 'alt_field' ],
'#description' => t ( 'The alt attribute may be used by search engines, screen readers, and when the image cannot be loaded.' ),
2012-11-29 07:32:14 +00:00
'#weight' => 9 ,
);
$form [ 'alt_field_required' ] = array (
'#type' => 'checkbox' ,
'#title' => t ( '<em>Alt</em> field required' ),
'#default_value' => $settings [ 'alt_field_required' ],
2009-10-12 05:22:57 +00:00
'#weight' => 10 ,
2012-11-29 07:32:14 +00:00
'#states' => array (
'visible' => array (
':input[name="instance[settings][alt_field]"]' => array ( 'checked' => TRUE ),
),
),
2009-10-12 05:22:57 +00:00
);
$form [ 'title_field' ] = array (
'#type' => 'checkbox' ,
'#title' => t ( 'Enable <em>Title</em> field' ),
'#default_value' => $settings [ 'title_field' ],
'#description' => t ( 'The title attribute is used as a tooltip when the mouse hovers over the image.' ),
'#weight' => 11 ,
);
2012-11-29 07:32:14 +00:00
$form [ 'title_field_required' ] = array (
'#type' => 'checkbox' ,
'#title' => t ( '<em>Title</em> field required' ),
'#default_value' => $settings [ 'title_field_required' ],
'#weight' => 12 ,
'#states' => array (
'visible' => array (
':input[name="instance[settings][title_field]"]' => array ( 'checked' => TRUE ),
),
),
);
2009-10-12 05:22:57 +00:00
2012-04-24 02:03:13 +00:00
// Add the default image to the instance.
$form [ 'default_image' ] = array (
'#title' => t ( 'Default image' ),
'#type' => 'managed_file' ,
'#description' => t ( " If no image is uploaded, this image will be shown on display and will override the field's default image. " ),
2013-06-03 19:37:59 +00:00
'#default_value' => empty ( $settings [ 'default_image' ]) ? array () : array ( $settings [ 'default_image' ]),
2012-04-24 02:03:13 +00:00
'#upload_location' => $field [ 'settings' ][ 'uri_scheme' ] . '://default_images/' ,
);
2009-10-12 05:22:57 +00:00
return $form ;
}
/**
* Element validate function for resolution fields .
*/
function _image_field_resolution_validate ( $element , & $form_state ) {
if ( ! empty ( $element [ 'x' ][ '#value' ]) || ! empty ( $element [ 'y' ][ '#value' ])) {
foreach ( array ( 'x' , 'y' ) as $dimension ) {
2012-04-19 11:31:47 +00:00
if ( ! $element [ $dimension ][ '#value' ]) {
2009-10-12 05:22:57 +00:00
form_error ( $element [ $dimension ], t ( 'Both a height and width value must be specified in the !name field.' , array ( '!name' => $element [ '#title' ])));
return ;
}
}
2012-04-19 11:31:47 +00:00
form_set_value ( $element , $element [ 'x' ][ '#value' ] . 'x' . $element [ 'y' ][ '#value' ], $form_state );
2009-10-12 05:22:57 +00:00
}
else {
form_set_value ( $element , '' , $form_state );
}
}
2010-02-17 05:39:51 +00:00
/**
* Implements hook_field_presave () .
*/
2013-01-07 11:22:28 +00:00
function image_field_presave ( EntityInterface $entity , $field , $instance , $langcode , & $items ) {
2011-10-17 16:34:18 +00:00
// Determine the dimensions if necessary.
foreach ( $items as & $item ) {
if ( ! isset ( $item [ 'width' ]) || ! isset ( $item [ 'height' ])) {
2013-06-27 01:52:15 +00:00
$info = image_get_info ( file_load ( $item [ 'target_id' ]) -> getFileUri ());
2011-10-17 16:34:18 +00:00
if ( is_array ( $info )) {
$item [ 'width' ] = $info [ 'width' ];
$item [ 'height' ] = $info [ 'height' ];
}
}
}
2010-02-17 05:39:51 +00:00
}
2010-08-22 13:52:59 +00:00
/**
* Implements hook_field_insert () .
*/
2013-01-07 11:22:28 +00:00
function image_field_insert ( EntityInterface $entity , $field , $instance , $langcode , & $items ) {
file_field_insert ( $entity , $field , $instance , $langcode , $items );
2010-08-22 13:52:59 +00:00
}
2009-10-12 05:22:57 +00:00
/**
2009-12-04 16:49:48 +00:00
* Implements hook_field_update () .
2009-10-12 05:22:57 +00:00
*/
2013-01-07 11:22:28 +00:00
function image_field_update ( EntityInterface $entity , $field , $instance , $langcode , & $items ) {
file_field_update ( $entity , $field , $instance , $langcode , $items );
2009-10-12 05:22:57 +00:00
}
/**
2009-12-04 16:49:48 +00:00
* Implements hook_field_delete () .
2009-10-12 05:22:57 +00:00
*/
2013-01-07 11:22:28 +00:00
function image_field_delete ( EntityInterface $entity , $field , $instance , $langcode , & $items ) {
file_field_delete ( $entity , $field , $instance , $langcode , $items );
2009-10-12 05:22:57 +00:00
}
/**
2009-12-04 16:49:48 +00:00
* Implements hook_field_delete_revision () .
2009-10-12 05:22:57 +00:00
*/
2013-01-07 11:22:28 +00:00
function image_field_delete_revision ( EntityInterface $entity , $field , $instance , $langcode , & $items ) {
file_field_delete_revision ( $entity , $field , $instance , $langcode , $items );
2009-10-12 05:22:57 +00:00
}
/**
2009-12-04 16:49:48 +00:00
* Implements hook_field_is_empty () .
2009-10-12 05:22:57 +00:00
*/
2013-06-16 08:27:11 +00:00
function image_field_is_empty ( $item , $field_type ) {
return file_field_is_empty ( $item , $field_type );
2009-10-12 05:22:57 +00:00
}
/**
* An element #process callback for the image_image field type.
*
* Expands the image_image type to include the alt and title fields .
*/
function image_field_widget_process ( $element , & $form_state , $form ) {
$item = $element [ '#value' ];
2013-04-20 03:34:14 +00:00
$item [ 'fids' ] = $element [ 'fids' ][ '#value' ];
2009-10-12 05:22:57 +00:00
$element [ '#theme' ] = 'image_widget' ;
2013-06-07 10:48:55 +00:00
$element [ '#attached' ][ 'css' ][] = drupal_get_path ( 'module' , 'image' ) . '/css/image.theme.css' ;
2009-10-12 05:22:57 +00:00
// Add the image preview.
2013-04-20 03:34:14 +00:00
if ( ! empty ( $element [ '#files' ]) && $element [ '#preview_image_style' ]) {
$file = reset ( $element [ '#files' ]);
2011-10-17 16:34:18 +00:00
$variables = array (
2012-11-16 11:57:40 +00:00
'style_name' => $element [ '#preview_image_style' ],
2013-06-15 08:46:11 +00:00
'uri' => $file -> getFileUri (),
2011-10-17 16:34:18 +00:00
);
// Determine image dimensions.
if ( isset ( $element [ '#value' ][ 'width' ]) && isset ( $element [ '#value' ][ 'height' ])) {
$variables [ 'width' ] = $element [ '#value' ][ 'width' ];
$variables [ 'height' ] = $element [ '#value' ][ 'height' ];
}
else {
2013-06-15 08:46:11 +00:00
$info = image_get_info ( $file -> getFileUri ());
2011-10-17 16:34:18 +00:00
if ( is_array ( $info )) {
$variables [ 'width' ] = $info [ 'width' ];
$variables [ 'height' ] = $info [ 'height' ];
}
else {
$variables [ 'width' ] = $variables [ 'height' ] = NULL ;
}
}
2009-10-12 05:22:57 +00:00
$element [ 'preview' ] = array (
2011-10-17 16:34:18 +00:00
'#markup' => theme ( 'image_style' , $variables ),
);
// Store the dimensions in the form so the file doesn't have to be accessed
// again. This is important for remote files.
$element [ 'width' ] = array (
'#type' => 'hidden' ,
'#value' => $variables [ 'width' ],
);
$element [ 'height' ] = array (
'#type' => 'hidden' ,
'#value' => $variables [ 'height' ],
2009-10-12 05:22:57 +00:00
);
}
// Add the additional alt and title fields.
$element [ 'alt' ] = array (
'#title' => t ( 'Alternate text' ),
'#type' => 'textfield' ,
'#default_value' => isset ( $item [ 'alt' ]) ? $item [ 'alt' ] : '' ,
'#description' => t ( 'This text will be used by screen readers, search engines, or when the image cannot be loaded.' ),
2011-12-13 03:21:08 +00:00
// @see http://www.gawds.org/show.php?contentid=28
2011-12-23 03:16:56 +00:00
'#maxlength' => 512 ,
2009-10-12 05:22:57 +00:00
'#weight' => - 2 ,
2013-04-20 03:34:14 +00:00
'#access' => ( bool ) $item [ 'fids' ] && $element [ '#alt_field' ],
2013-06-16 08:27:11 +00:00
'#element_validate' => $element [ '#alt_field_required' ] == 1 ? array ( '_image_field_required_fields_validate' ) : array (),
2009-10-12 05:22:57 +00:00
);
$element [ 'title' ] = array (
'#type' => 'textfield' ,
'#title' => t ( 'Title' ),
'#default_value' => isset ( $item [ 'title' ]) ? $item [ 'title' ] : '' ,
'#description' => t ( 'The title is used as a tool tip when the user hovers the mouse over the image.' ),
2011-12-23 03:16:56 +00:00
'#maxlength' => 1024 ,
2009-10-12 05:22:57 +00:00
'#weight' => - 1 ,
2013-04-20 03:34:14 +00:00
'#access' => ( bool ) $item [ 'fids' ] && $element [ '#title_field' ],
2013-06-16 08:27:11 +00:00
'#element_validate' => $element [ '#alt_field_required' ] == 1 ? array ( '_image_field_required_fields_validate' ) : array (),
2009-10-12 05:22:57 +00:00
);
return $element ;
}
2012-11-29 07:32:14 +00:00
/**
* Validate callback for alt and title field , if the user wants them required .
*
* This is separated in a validate function instead of a #required flag to avoid
* being validated on the process callback .
*/
function _image_field_required_fields_validate ( $element , & $form_state ) {
// Only do validation if the function is triggered from other places than
// the image process form.
if ( ! in_array ( 'file_managed_file_submit' , $form_state [ 'triggering_element' ][ '#submit' ])) {
// If the image is not there, we do not check for empty values.
$parents = $element [ '#parents' ];
$field = array_pop ( $parents );
2012-12-17 21:54:13 +00:00
$image_field = NestedArray :: getValue ( $form_state [ 'input' ], $parents );
2012-11-29 07:32:14 +00:00
// We check for the array key, so that it can be NULL (like if the user
// submits the form without using the "upload" button).
if ( ! array_key_exists ( $field , $image_field )) {
return ;
}
// Check if field is left emtpy.
elseif ( empty ( $image_field [ $field ])) {
form_error ( $element , t ( 'The field !title is required' , array ( '!title' => $element [ '#title' ])));
return ;
}
}
}
2009-10-12 05:22:57 +00:00
/**
2010-04-13 15:23:03 +00:00
* Returns HTML for an image field widget .
*
2012-07-07 20:09:35 +00:00
* @ param array $variables
2010-04-13 15:23:03 +00:00
* An associative array containing :
* - element : A render element representing the image field widget .
*
* @ ingroup themeable
2009-10-12 05:22:57 +00:00
*/
function theme_image_widget ( $variables ) {
$element = $variables [ 'element' ];
$output = '' ;
$output .= '<div class="image-widget form-managed-file clearfix">' ;
if ( isset ( $element [ 'preview' ])) {
$output .= '<div class="image-preview">' ;
$output .= drupal_render ( $element [ 'preview' ]);
$output .= '</div>' ;
}
$output .= '<div class="image-widget-data">' ;
2013-04-20 03:34:14 +00:00
if ( ! empty ( $element [ 'fids' ][ '#value' ])) {
$file = reset ( $element [ '#files' ]);
2013-06-15 08:46:11 +00:00
$element [ 'file_' . $file -> id ()][ 'filename' ][ '#markup' ] .= ' <span class="file-size">(' . format_size ( $file -> getSize ()) . ')</span> ' ;
2009-10-12 05:22:57 +00:00
}
$output .= drupal_render_children ( $element );
$output .= '</div>' ;
$output .= '</div>' ;
return $output ;
}
/**
2010-04-13 15:23:03 +00:00
* Returns HTML for an image field formatter .
*
2012-07-07 20:09:35 +00:00
* @ param array $variables
2010-04-13 15:23:03 +00:00
* An associative array containing :
* - item : An array of image data .
* - image_style : An optional image style .
2011-11-25 03:09:40 +00:00
* - path : An optional array containing the link 'path' and link 'options' .
2010-04-13 15:23:03 +00:00
*
* @ ingroup themeable
2009-10-12 05:22:57 +00:00
*/
2009-12-11 16:49:40 +00:00
function theme_image_formatter ( $variables ) {
$item = $variables [ 'item' ];
2013-07-20 01:09:04 +00:00
$image = array ();
2011-10-17 16:34:18 +00:00
2010-04-30 12:53:47 +00:00
// Do not output an empty 'title' attribute.
2013-07-20 01:09:04 +00:00
if ( isset ( $item [ 'title' ]) && drupal_strlen ( $item [ 'title' ]) != 0 ) {
$image [ '#title' ] = $item [ 'title' ];
2010-04-30 12:53:47 +00:00
}
2009-12-11 16:49:40 +00:00
2013-06-15 08:46:11 +00:00
if ( isset ( $item [ 'entity' ]) && empty ( $item [ 'uri' ])) {
2013-07-20 01:09:04 +00:00
$image [ '#uri' ] = $item [ 'entity' ] -> getFileUri ();
}
else {
$image [ '#uri' ] = $item [ 'uri' ];
}
foreach ( array ( 'width' , 'height' , 'alt' , 'attributes' ) as $key ) {
if ( isset ( $item [ $key ])) {
$image [ " # $key " ] = $item [ $key ];
}
2013-06-15 08:46:11 +00:00
}
2009-12-11 16:49:40 +00:00
if ( $variables [ 'image_style' ]) {
2013-07-20 01:09:04 +00:00
$image [ '#theme' ] = 'image_style' ;
$image [ '#style_name' ] = $variables [ 'image_style' ];
2009-12-11 16:49:40 +00:00
}
else {
2013-07-20 01:09:04 +00:00
$image [ '#theme' ] = 'image' ;
2009-12-11 16:49:40 +00:00
}
2012-07-07 18:52:47 +00:00
// The link path and link options are both optional, but for the options to be
// processed, the link path must at least be an empty string.
if ( isset ( $variables [ 'path' ][ 'path' ])) {
2010-02-11 15:52:13 +00:00
$path = $variables [ 'path' ][ 'path' ];
2012-07-07 18:52:47 +00:00
$options = isset ( $variables [ 'path' ][ 'options' ]) ? $variables [ 'path' ][ 'options' ] : array ();
2010-02-11 15:52:13 +00:00
// When displaying an image inside a link, the html option must be TRUE.
$options [ 'html' ] = TRUE ;
2013-07-20 01:09:04 +00:00
$output = l ( $image , $path , $options );
}
else {
$output = drupal_render ( $image );
2009-12-11 16:49:40 +00:00
}
return $output ;
2010-01-30 07:59:26 +00:00
}