function simplecrop_field_widget_process in SimpleCrop 7
Element #process callback for the image_image field type.
Expands the image_image type to include the crop behavior.
1 string reference to 'simplecrop_field_widget_process'
- simplecrop_field_widget_form in includes/
simplecrop.field.inc - Implements hook_field_widget_form().
File
- includes/
simplecrop.field.inc, line 290 - Contains information about field widget and related functions.
Code
function simplecrop_field_widget_process($element, &$form_state, $form) {
// Get field instance settings.
$instance = field_widget_instance($element, $form_state);
$settings = $instance['widget']['settings']['simplecrop'];
if (!empty($element['#file'])) {
// Get file properties for better usability.
$uri = $element['#file']->uri;
$fid = $element['#file']->fid;
// Ensure that image exists. Otherwise doesn't make sense to continue.
if (!file_exists($uri)) {
watchdog('simplecrop', 'Image path %uri does not exists. Simplecrop widget process has been aborted.', array(
'%uri' => $uri,
), WATCHDOG_WARNING);
return $element;
}
// Check if current image was initially loaded in the edit form.
// If so - display widget according to configuration of the initial display setting.
if (empty($form_state['simplecrop'][$fid]['display'])) {
$form_state['simplecrop'][$fid]['display'] = $settings['initial_display'];
}
// Get current display of an image.
$display = $form_state['simplecrop'][$fid]['display'];
// Store parents of image to be able to fetch them later by parents array.
$form_state['simplecrop'][$fid]['parents'] = $element['#parents'];
// Get a current image info and keep its original resolution.
$image_info = image_get_info($uri);
// Make sure that image toolkit is installed on a server and available.
// Otherwise no possibility to continue widget process.
if (empty($image_info)) {
watchdog('simplecrop', 'No image toolkit installed. Simplecrop widget process has been aborted.', array(), WATCHDOG_ERROR);
return $element;
}
$original_width = $image_info['width'];
$original_height = $image_info['height'];
// If current form state already has info about this image crop,
// then use that data.
if (!empty($form_state['simplecrop'][$fid]['crop'])) {
$crop_data = $form_state['simplecrop'][$fid]['crop'];
}
elseif ($crop = simplecrop_crop_load($uri)) {
$form_state['simplecrop'][$fid]['crop'] = $crop_data = $crop->data;
}
$cropped_area = array();
if (!empty($crop_data)) {
// Define width and height of cropped area.
$cropped_area['width'] = abs($crop_data['x'] - $crop_data['x2']);
$cropped_area['height'] = abs($crop_data['y'] - $crop_data['y2']);
}
else {
// No crop area, means that we keep original image resolution.
$cropped_area['width'] = $original_width;
$cropped_area['height'] = $original_height;
}
$cropped_area_original_width = $cropped_area['width'];
// Downscale resolution of cropped area to width and height from settings.
image_dimensions_scale($cropped_area, $settings['cropped']['scale']['width'], $settings['cropped']['scale']['height']);
// Calculate difference between downscaled cropped area resolution and its original resolution.
$scale_ratio = $cropped_area['width'] / $cropped_area_original_width;
// Calculate resolution of cropped image that we need to display.
// Scale ratio shows how much we need to downscale original resolution.
$cropped_image_width = round($original_width * $scale_ratio);
$cropped_image_height = round($original_height * $scale_ratio);
$container_style = array(
'width:' . $cropped_area['width'] . 'px;',
'height:' . $cropped_area['height'] . 'px;',
);
// Calculate offset of crop area.
$position_left = !empty($crop_data['x']) ? round($crop_data['x'] * $scale_ratio) : 0;
$position_top = !empty($crop_data['y']) ? round($crop_data['y'] * $scale_ratio) : 0;
// Set css offsets for cropped image, so for the user will be visible
// only cropped area.
$cropped_image_style = array(
'left:' . -$position_left . 'px;',
'top:' . -$position_top . 'px;',
);
// Container for cropped image.
// Needed here to display only cropped area of image.
$element['cropped_image'] = array(
'#type' => 'container',
'#attributes' => array(
'style' => !empty($container_style) ? $container_style : array(),
),
);
// Show cropped image.
$element['cropped_image']['image'] = array(
'#theme' => 'image',
'#width' => $cropped_image_width,
'#height' => $cropped_image_height,
'#attributes' => array(
'style' => !empty($cropped_image_style) ? $cropped_image_style : array(),
),
'#path' => $uri,
);
// If settings has scale behavior, then we need to downscale current image.
if (!empty($settings['source']['scale']['width']) || !empty($settings['source']['scale']['height'])) {
image_dimensions_scale($image_info, $settings['source']['scale']['width'], $settings['source']['scale']['height']);
}
// Display downscaled original image.
// To this images we apply jCrop library.
$element['source_image'] = array(
'#theme' => 'image',
'#width' => $image_info['width'],
'#height' => $image_info['height'],
'#path' => $uri,
);
// Adjust the Ajax settings so that on upload and remove of any individual
// file, the entire group of file fields is updated together.
$field = field_widget_field($element, $form_state);
if ($field['cardinality'] != 1) {
$parents = array_slice($element['#array_parents'], 0, -1);
$path = 'simplecrop/ajax/' . implode('/', $parents) . '/' . $form['form_build_id']['#value'];
$field_element = drupal_array_get_nested_value($form, $parents);
$wrapper = $field_element['#id'] . '-ajax-wrapper';
}
else {
$path = 'simplecrop/ajax/' . implode('/', $element['#parents']) . '/' . $form['form_build_id']['#value'];
$wrapper = $element['upload_button']['#ajax']['wrapper'];
}
// Button that applies crop area and show cropped image.
$element['display_reload'] = array(
'#name' => implode('_', $element['#parents']) . '_display_reload',
'#type' => 'submit',
'#validate' => array(),
'#submit' => array(
'simplecrop_field_widget_change_display_submit',
),
'#limit_validation_errors' => array(
$element['#parents'],
),
'#ajax' => array(
'path' => $path,
'wrapper' => $wrapper,
),
);
// Keep original size for later coordinates calculations.
$element['original_size'] = array(
'#type' => 'value',
'#value' => array(
'width' => $original_width,
'height' => $original_height,
),
);
// Keep original size for later coordinates calculations.
$element['scaled_size'] = array(
'#type' => 'value',
'#value' => array(
'width' => $image_info['width'],
'height' => $image_info['height'],
),
);
// We need to keep ratio between original image and scaled image.
// We can calculate it using height or width values.
$scale_ratio = (double) number_format($original_width / $image_info['width'], 3, '.', '');
// We need to rescale min and max resolutions according to a new
// scale ratio
foreach (array(
'min_area',
'max_area',
) as $area) {
foreach (array(
'width',
'height',
) as $side) {
if (!empty($settings['crop'][$area][$side])) {
$settings['crop'][$area][$side] = round($settings['crop'][$area][$side] / $scale_ratio);
}
}
}
// Collect js settings for image. They'll be used for jCrop processment.
$js_settings = array();
// Pick cropped area as a default selection area if user already defined his crop.
if (!empty($crop_data)) {
// We need to rescale coordinates according to a new scale ratio.
foreach (array(
'x',
'y',
'x2',
'y2',
) as $name) {
$crop_data[$name] = round($crop_data[$name] / $scale_ratio);
}
$js_settings['initial_area'] = $crop_data;
}
else {
$js_settings['initial_area'] = _simplecrop_define_initial_crop_area($image_info['width'], $image_info['height'], $settings['crop']);
}
// Add resolution of scaled image to js settings.
$js_settings['resolution'] = array(
'width' => $image_info['width'],
'height' => $image_info['height'],
);
// Add aspect ratio to a settings (if exists).
if (!empty($settings['crop']['ratio']['width']) && !empty($settings['crop']['ratio']['height'])) {
$js_settings['ratio'] = $settings['crop']['ratio']['width'] / $settings['crop']['ratio']['height'];
}
// Add settings for min and max crop area resolutions.
foreach (array(
'min_area',
'max_area',
) as $area) {
if (!empty($settings['crop'][$area]['width']) && !empty($settings['crop'][$area]['height'])) {
$js_settings[$area] = array(
$settings['crop'][$area]['width'],
$settings['crop'][$area]['height'],
);
}
}
// Add js with image settings for jCrop plugin.
// Avoid duplicated additions to js scope.
$added_js =& drupal_static('simplecrop_added_js_settings');
if (empty($added_js[$fid])) {
drupal_add_js(array(
'simpleCrop' => array(
'images' => array(
array(
'fid' => $fid,
'settings' => $js_settings,
),
),
'reload' => $fid,
),
), 'setting');
$added_js[$fid] = TRUE;
}
// Prepopulate default values for coordinate fields.
foreach (array(
'x',
'y',
'x2',
'y2',
) as $name) {
$element['data'][$name] = array(
'#type' => 'hidden',
'#default_value' => !empty($js_settings['initial_area'][$name]) ? $js_settings['initial_area'][$name] : 0,
'#attributes' => array(
'class' => array(
$name,
),
),
);
}
// Hide filename if admin wants so.
if (!empty($settings['hide_filename']) && !empty($element['filename'])) {
$element['filename']['#access'] = FALSE;
}
// Show and hide different widget fields depends on current display.
_simplecrop_field_widget_switch_display($element, $display);
// Theme widget using our internal theme function.
$element['#theme'] = 'simplecrop_widget';
// Add js and css for cropping.
$element['#attached']['js'][] = drupal_get_path('module', 'simplecrop') . '/jquery.jcrop/js/jquery.Jcrop.min.js';
$element['#attached']['css'][] = drupal_get_path('module', 'simplecrop') . '/jquery.jcrop/css/jquery.Jcrop.min.css';
$element['#attached']['js'][] = drupal_get_path('module', 'simplecrop') . '/js/simplecrop.js';
$element['#attached']['css'][] = drupal_get_path('module', 'simplecrop') . '/css/simplecrop.css';
}
// Add another submit handler to upload button.
// We need this to store initial widget display after new image upload
// in forms cache storage.
if (!empty($element['upload_button'])) {
$element['upload_button']['#submit'][] = 'simplecrop_file_field_submit';
}
return $element;
}