collageformatter.module in Collage Formatter 7
Same filename and directory in other branches
Main file for Collage Formatter module.
File
collageformatter.moduleView source
<?php
/**
* @file
* Main file for Collage Formatter module.
*/
/**
* Implements hook_field_formatter_info().
*/
function collageformatter_field_formatter_info() {
return array(
'collageformatter' => array(
'label' => t('Collage'),
'field types' => array(
'image',
),
'settings' => _collageformatter_default_settings(),
'description' => t('Display multi-value image fields as collage.'),
),
);
}
/**
* Default Collage Formatter settings.
*/
function _collageformatter_default_settings() {
return array(
'collage_number' => 1,
'images_per_collage' => NULL,
'images_to_skip' => 0,
'collage_orientation' => 0,
'collage_width' => 500,
'collage_height' => '',
'collage_border_size' => 0,
'collage_border_color' => '#ffffff',
'gap_size' => 0,
'gap_color' => '#ffffff',
'border_size' => 0,
'border_color' => '#000000',
'image_link' => 'file',
'image_link_image_style' => NULL,
'image_link_modal' => NULL,
'image_link_class' => NULL,
'image_link_rel' => NULL,
'generate_image_derivatives' => 0,
'prevent_upscale' => 0,
'advanced' => array(
'original_image_reference' => 'symlink',
),
);
}
/**
* Implements hook_field_formatter_settings_form().
*/
function collageformatter_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
$element = _collageformatter_settings_form($settings);
$element['image_link_image_style']['#states'] = array(
'visible' => array(
':input[name="fields[' . $field['field_name'] . '][settings_edit_form][settings][image_link]"]' => array(
'value' => 'file',
),
),
);
$element['image_link_modal']['#states'] = array(
'visible' => array(
':input[name="fields[' . $field['field_name'] . '][settings_edit_form][settings][image_link]"]' => array(
'value' => 'file',
),
),
);
$element['image_link_class']['#states'] = array(
'invisible' => array(
':input[name="fields[' . $field['field_name'] . '][settings_edit_form][settings][image_link]"]' => array(
'value' => '',
),
),
);
$element['image_link_rel']['#states'] = array(
'invisible' => array(
':input[name="fields[' . $field['field_name'] . '][settings_edit_form][settings][image_link]"]' => array(
'value' => '',
),
),
);
// Field formatter in Views - doesn't work.
if ($view_mode == '_custom') {
$element['image_link_image_style']['#states'] = array(
'visible' => array(
':input[name="options[settings][image_link]"]' => array(
'value' => 'file',
),
),
);
$element['image_link_modal']['#states'] = array(
'visible' => array(
':input[name="options[settings][image_link]"]' => array(
'value' => 'file',
),
),
);
$element['image_link_class']['#states'] = array(
'invisible' => array(
':input[name="options[settings][image_link]"]' => array(
'value' => '',
),
),
);
$element['image_link_rel']['#states'] = array(
'invisible' => array(
':input[name="options[settings][image_link]"]' => array(
'value' => '',
),
),
);
}
return $element;
}
/**
* Settings form for Collage Formatter.
*/
function _collageformatter_settings_form($settings) {
$options_0_50 = drupal_map_assoc(range(0, 50));
$options_1_50 = drupal_map_assoc(range(1, 50));
$element['collage_number'] = array(
'#type' => 'select',
'#title' => t('Number of collages'),
'#title_display' => 'invisible',
'#options' => $options_1_50,
'#default_value' => $settings['collage_number'],
'#field_prefix' => t('Generate'),
'#field_suffix' => t('collage(s)'),
'#prefix' => '<div class="container-inline">',
);
$element['images_per_collage'] = array(
'#type' => 'select',
'#title' => t('Images per collage'),
'#title_display' => 'invisible',
'#options' => $options_1_50,
'#default_value' => $settings['images_per_collage'],
'#empty_option' => t('all'),
'#field_prefix' => t('with'),
'#field_suffix' => t('image(s) per collage') . ';',
);
$element['images_to_skip'] = array(
'#type' => 'select',
'#title' => t('Images to skip'),
'#title_display' => 'invisible',
'#options' => $options_0_50,
'#default_value' => $settings['images_to_skip'],
'#field_prefix' => t('Skip'),
'#field_suffix' => t('image(s) from the start'),
'#suffix' => '</div>',
);
$element['collage_orientation'] = array(
'#type' => 'select',
'#title' => t('Collage orientation'),
'#description' => t('Select if it should be a wide collage (landscape) or a tall one (portrait).'),
'#options' => array(
'0' => t('Landscape'),
'1' => t('Portrait'),
),
'#default_value' => $settings['collage_orientation'],
'#prefix' => '<div class="container-inline">',
'#field_suffix' => '</br>',
'#suffix' => '</div>',
);
$element['collage_width'] = array(
'#type' => 'textfield',
'#title' => t('Collage width'),
'#title_display' => 'invisible',
'#default_value' => $settings['collage_width'],
'#element_validate' => array(
'element_validate_integer_positive',
),
'#size' => 4,
'#maxlength' => 4,
'#prefix' => '<div class="container-inline"><strong>' . t('Collage width & height') . '</strong>',
// '#field_prefix' => '</br>',
'#field_suffix' => 'x',
);
$element['collage_height'] = array(
'#type' => 'textfield',
'#title' => t('Collage height'),
'#title_display' => 'invisible',
'#description' => t('Total collage width and height with all the borders and gaps. If you specify both then the images will be cropped.'),
'#default_value' => $settings['collage_height'],
'#element_validate' => array(
'element_validate_integer_positive',
),
'#size' => 4,
'#maxlength' => 4,
'#field_suffix' => 'px</br>',
'#suffix' => '</div>',
);
$element['collage_border_size'] = array(
'#type' => 'select',
'#title' => t('Collage border'),
'#options' => $options_0_50,
'#default_value' => $settings['collage_border_size'],
'#field_suffix' => 'px',
'#prefix' => '<div class="container-inline">',
);
$element['collage_border_color'] = array(
'#type' => 'textfield',
'#title' => t('Collage border color'),
'#default_value' => $settings['collage_border_color'],
'#size' => 7,
'#maxlength' => 7,
'#suffix' => '<div class="collageformatter-color-picker"></div>' . '</div>',
'#attached' => array(
'library' => array(
array(
'system',
'farbtastic',
),
),
'js' => array(
drupal_get_path('module', 'collageformatter') . '/js/collageformatter.admin.js' => array(
'type' => 'file',
),
),
),
);
$element['gap_size'] = $element['collage_border_size'];
$element['gap_size']['#title'] = t('Image gap');
$element['gap_size']['#default_value'] = $settings['gap_size'];
$element['gap_color'] = $element['collage_border_color'];
$element['gap_color']['#title'] = t('Image gap color');
$element['gap_color']['#default_value'] = $settings['gap_color'];
$element['border_size'] = $element['collage_border_size'];
$element['border_size']['#title'] = t('Image border');
$element['border_size']['#default_value'] = $settings['border_size'];
$element['border_color'] = $element['collage_border_color'];
$element['border_color']['#title'] = t('Image border color');
$element['border_color']['#default_value'] = $settings['border_color'];
$link_types = array(
'content' => t('Content'),
'file' => t('File'),
);
$element['image_link'] = array(
'#title' => t('Link image to'),
'#type' => 'select',
'#default_value' => $settings['image_link'],
'#empty_option' => t('Nothing'),
'#options' => $link_types,
'#prefix' => '<div class="container-inline">',
);
$image_styles = image_style_options(FALSE);
$element['image_link_image_style'] = array(
'#title' => t('Target image style'),
'#type' => 'select',
'#default_value' => $settings['image_link_image_style'],
'#empty_option' => t('None (original image)'),
'#options' => $image_styles,
);
$modal_options = array();
if (module_exists('colorbox')) {
$modal_options['colorbox'] = t('Colorbox');
}
if (module_exists('shadowbox')) {
$modal_options['shadowbox'] = t('Shadowbox');
}
if (module_exists('fancybox')) {
$modal_options['fancybox'] = t('fancyBox');
}
if (module_exists('photobox')) {
$modal_options['photobox'] = t('Photobox');
}
if (module_exists('photoswipe')) {
$modal_options['photoswipe'] = t('PhotoSwipe');
}
if (module_exists('lightbox2')) {
$modal_options['lightbox2'] = t('Lightbox2');
}
$element['image_link_modal'] = array(
'#title' => t('Modal gallery'),
'#type' => 'select',
'#default_value' => $settings['image_link_modal'],
'#empty_option' => t('None'),
'#options' => $modal_options,
'#suffix' => '</div>',
);
$element['image_link_class'] = array(
'#type' => 'textfield',
'#title' => t('Image link class'),
// '#description' => t('Custom class to add to all image links.'),
'#default_value' => $settings['image_link_class'],
'#size' => 30,
'#prefix' => '<div class="container-inline">',
);
$element['image_link_rel'] = array(
'#type' => 'textfield',
'#title' => t('Image link rel'),
// '#description' => t('Custom rel attribute to add to all image links.'),
'#default_value' => $settings['image_link_rel'],
'#size' => 30,
'#suffix' => '</div>',
);
$element['generate_image_derivatives'] = array(
'#type' => 'checkbox',
'#title' => t('Generate image derivatives'),
'#description' => t('Generate image derivatives used in the collage while rendering it, before displaying.'),
'#default_value' => $settings['generate_image_derivatives'],
);
$element['prevent_upscale'] = array(
'#type' => 'checkbox',
'#title' => t('Prevent images upscaling'),
'#description' => t('Generated collage dimensions might be smaller.'),
'#default_value' => $settings['prevent_upscale'],
);
$element['advanced'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced settings'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$element['advanced']['original_image_reference'] = array(
'#type' => 'radios',
'#title' => t('Original image reference method'),
'#description' => t('If you need to add additional image effects to collageformatter image style before the "Collage Formatter" effect then you need to use "Symlink" or "Copy" method.'),
'#options' => array(
'symlink' => t('Symlink'),
'fake' => t('Fake image'),
'copy' => t('Copy'),
),
'#default_value' => $settings['advanced']['original_image_reference'],
);
return $element;
}
/**
* Implements hook_field_formatter_settings_summary().
*/
function collageformatter_field_formatter_settings_summary($field, $instance, $view_mode) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
$summary = array();
$summary[] = t('Generate') . ' <strong>' . $settings['collage_number'] . '</strong> ' . t('collage(s)') . ' ' . t('with') . ' <strong>' . ($settings['images_per_collage'] ? $settings['images_per_collage'] : t('all')) . '</strong> ' . t('image(s) per collage') . '; ' . t('Skip') . ' <strong>' . $settings['images_to_skip'] . '</strong> ' . t('image(s) from the start');
$summary[] = t('Collage orientation') . ': ' . ($settings['collage_orientation'] ? t('Portrait') : t('Landscape'));
$summary[] = t('Collage width') . ': ' . ($settings['collage_width'] ? $settings['collage_width'] . 'px' : t('Not set'));
$summary[] = t('Collage height') . ': ' . ($settings['collage_height'] ? $settings['collage_height'] . 'px' : t('Not set'));
$summary[] = t('Collage border') . ': ' . $settings['collage_border_size'] . 'px <span style="background-color: ' . $settings['collage_border_color'] . ';">' . $settings['collage_border_color'] . '</span>';
$summary[] = t('Image gap') . ': ' . $settings['gap_size'] . 'px <span style="background-color: ' . $settings['gap_color'] . ';">' . $settings['gap_color'] . '</span>';
$summary[] = t('Image border') . ': ' . $settings['border_size'] . 'px <span style="background-color: ' . $settings['border_color'] . ';">' . $settings['border_color'] . '</span>';
$link_types = array(
'content' => t('Images linked to content'),
'file' => t('Images linked to file'),
);
if (isset($link_types[$settings['image_link']])) {
$summary[] = $link_types[$settings['image_link']];
if ($settings['image_link'] == 'file') {
if (empty($settings['image_link_image_style'])) {
$summary[] = t('Target image style') . ': ' . t('None (original image)');
}
else {
$image_styles = image_style_options(FALSE);
$summary[] = t('Target image style') . ': ' . $image_styles[$settings['image_link_image_style']];
}
// Modal gallery summary.
if (empty($settings['image_link_modal'])) {
$summary[] = t('Modal gallery') . ': ' . t('None');
}
else {
$summary[] = t('Modal gallery') . ': ' . $settings['image_link_modal'];
}
// Custom class/rel summary.
$custom = array();
if (!empty($settings['image_link_class'])) {
$custom[] = 'class="' . check_plain($settings['image_link_class']) . '"';
}
if (!empty($settings['image_link_rel'])) {
$custom[] = 'rel="' . check_plain($settings['image_link_rel']) . '"';
}
$summary[] = implode(' ', $custom);
}
}
else {
$summary[] = t('Images without links');
}
if ($settings['generate_image_derivatives']) {
$summary[] = t('Generate image derivatives');
}
else {
$summary[] = t('Do not generate image derivatives');
}
if ($settings['prevent_upscale']) {
$summary[] = t('Prevent images upscaling');
}
return implode('<br />', $summary);
}
/**
* Implements hook_field_formatter_view().
*/
function collageformatter_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
// If there are no images, don't do anything.
if (empty($items)) {
return '';
}
$settings = $display['settings'];
$ids = entity_extract_ids($entity_type, $entity);
$entity_id = $ids[0];
$settings['gallery'] = 'collageformatter-' . $field['field_name'] . '-' . $entity_id;
if ($settings['image_link'] == 'content') {
$content_uri = entity_uri($entity_type, $entity);
foreach ($items as &$item) {
$item['content_uri'] = $content_uri['path'];
}
}
$collage = collageformatter_render_collage($items, $settings);
return $collage;
}
/**
* Returns renderable array of collages.
*/
function collageformatter_render_collage($images, $settings) {
$collage = array();
// Remove images to skip.
if ($settings['images_to_skip']) {
$images = array_slice($images, $settings['images_to_skip']);
}
// Prepare images.
foreach ($images as $delta => &$image) {
if (!isset($image['width']) || !isset($image['height'])) {
if ($image_info = image_get_info($image['uri'])) {
$image += $image_info;
}
}
$image += array(
'box_type' => 'image',
'delta' => $delta,
'total_width' => $image['width'] + 2 * $settings['border_size'] + $settings['gap_size'],
'total_height' => $image['height'] + 2 * $settings['border_size'] + $settings['gap_size'],
);
}
// Determine number of collages and how many images per collage.
$collage_number = $settings['collage_number'];
$images_per_collage = $settings['images_per_collage'] ? $settings['images_per_collage'] : round(count($images) / $collage_number);
// Generate collages.
while ($collage_number > 0) {
$collage_number--;
// If last collage and all images option - take all images.
if ($collage_number == 0 && !$settings['images_per_collage']) {
$collage_images = $images;
}
else {
$collage_images = array_slice($images, 0, $images_per_collage);
// Update images array and set as the last collage if there are no more images.
if (!($images = array_slice($images, $images_per_collage))) {
$collage_number = 0;
}
}
// Generate collage layout.
$box = _collageformatter_layout_box($collage_images, $settings['collage_orientation']);
// Scale the collage.
if ($settings['collage_width']) {
$box['parent_total_width'] = $settings['collage_width'] - 2 * $settings['collage_border_size'];
$dimensions = array(
'width' => $box['parent_total_width'] - $settings['gap_size'],
);
$box = _collageformatter_scale_box($box, $dimensions);
$box['parent_total_height'] = $box['total_height'] + $settings['gap_size'];
}
elseif ($settings['collage_height']) {
$box['parent_total_height'] = $settings['collage_height'] - 2 * $settings['collage_border_size'];
$dimensions = array(
'height' => $box['parent_total_height'] - $settings['gap_size'],
);
$box = _collageformatter_scale_box($box, $dimensions);
$box['parent_total_width'] = $box['total_width'] + $settings['gap_size'];
}
else {
$box['parent_total_width'] = $box['total_width'] + $settings['gap_size'];
$box['parent_total_height'] = $box['total_height'] + $settings['gap_size'];
}
// Resize the collage if both with and height are set.
if ($settings['collage_width'] && $settings['collage_height']) {
$box['parent_total_width'] = $settings['collage_width'] - 2 * $settings['collage_border_size'];
$box['parent_total_height'] = $settings['collage_height'] - 2 * $settings['collage_border_size'];
$dimensions = array(
'width' => $box['parent_total_width'] - $settings['gap_size'],
'height' => $box['parent_total_height'] - $settings['gap_size'],
);
$box = _collageformatter_resize_box($box, $dimensions);
}
// Check for upscaled images and prevent upscaling.
if ($settings['prevent_upscale']) {
$scale = _collageformatter_upscaling_check($box, $settings);
if ($scale < 1) {
$dimensions = array(
'width' => $scale * $box['total_width'],
);
$box = _collageformatter_scale_box($box, $dimensions);
$box['parent_total_width'] = $box['total_width'] + $settings['gap_size'];
$box['parent_total_height'] = $box['total_height'] + $settings['gap_size'];
}
}
$collage_wrapper_style = array();
$collage_wrapper_style[] = 'max-width: ' . round($box['parent_total_width'] + 2 * $settings['collage_border_size'] - 0.5) . 'px;';
// $collage_wrapper_style[] = 'box-sizing: border-box; -webkit-box-sizing: border-box; -moz-box-sizing: border-box;';
$collage_style = array();
// $collage_style[] = 'box-sizing: border-box; -webkit-box-sizing: border-box; -moz-box-sizing: border-box;';
if ($settings['collage_border_size']) {
$border = 'border: ' . $settings['collage_border_size'] . 'px solid';
$border .= $settings['collage_border_color'] ? ' ' . $settings['collage_border_color'] : '';
$collage_style[] = $border . ';';
}
if ($settings['gap_color']) {
$collage_style[] = 'background-color: ' . $settings['gap_color'] . ';';
}
$collage_wrapper_class = array(
'collageformatter-collage-wrapper',
);
if ($settings['image_link_modal'] == 'photoswipe') {
$collage_wrapper_class[] = 'photoswipe-gallery';
}
$collage[] = array(
'#theme' => 'collageformatter_collage',
'#collage' => _collageformatter_render_box($box, $settings),
'#collage_wrapper_class' => implode(' ', $collage_wrapper_class),
'#collage_wrapper_style' => implode(' ', $collage_wrapper_style),
'#collage_style' => implode(' ', $collage_style),
'#collage_bottom_style' => 'clear: both; margin-bottom: ' . 100 * ($settings['gap_size'] / round($box['parent_total_width'] - 0.5)) . '%',
);
}
return $collage;
}
/**
* Recursive function to build the layout.
* * @param $type
* boolean - TRUE for portrait (horizontal contact - vertical box type);
* FALSE for landscape (vertical contact - horizontal box type).
*/
function _collageformatter_layout_box($images, $type) {
$box = array();
$count = count($images);
if ($count >= 2) {
$size1 = floor($count / 2);
$size2 = $count - $size1;
$images1 = array_slice($images, 0, $size1);
$images2 = array_slice($images, $size1, $size2);
$box = array(
'box_type' => 'box',
'box_orientation' => $type ? 'vertical' : 'horizontal',
'pixel_check' => FALSE,
);
$box[1] = _collageformatter_layout_box($images1, !$type);
$box[2] = _collageformatter_layout_box($images2, !$type);
$box[1]['parent_box_orientation'] = $box[2]['parent_box_orientation'] = $box['box_orientation'];
$box[1]['pixel_check'] = FALSE;
$box[2]['pixel_check'] = TRUE;
if ($type) {
// Horizontal contact; vertical box type.
$dimensions = array(
'width' => $box[1]['total_width'],
);
}
else {
// Vertical contact; horizontal box type.
$dimensions = array(
'height' => $box[1]['total_height'],
);
}
$box[2] = _collageformatter_scale_box($box[2], $dimensions);
if ($type) {
// Horizontal contact; vertical box type.
$box['total_height'] = $box[1]['total_height'] + $box[2]['total_height'];
$box['total_width'] = $box[1]['total_width'];
}
else {
// Vertical contact; horizontal box type.
$box['total_width'] = $box[1]['total_width'] + $box[2]['total_width'];
$box['total_height'] = $box[1]['total_height'];
}
$box[1]['parent_total_width'] = $box[2]['parent_total_width'] = $box['total_width'];
$box[1]['parent_total_height'] = $box[2]['parent_total_height'] = $box['total_height'];
$box[1]['siblings_total_width'] = $box[2]['total_width'];
$box[1]['siblings_total_height'] = $box[2]['total_height'];
$box[2]['siblings_total_width'] = $box[1]['total_width'];
$box[2]['siblings_total_height'] = $box[1]['total_height'];
}
elseif ($count == 1) {
$box = array_pop($images);
$box['pixel_check'] = FALSE;
}
return $box;
}
/**
* Recursive function to scale the box using only one dimension.
*/
function _collageformatter_scale_box($box, $dimensions) {
// If it is an image - just scale it (change dimensions).
if ($box['box_type'] == 'image') {
if (array_key_exists('width', $dimensions)) {
$box['total_height'] = $dimensions['width'] / $box['total_width'] * $box['total_height'];
$box['total_width'] = $dimensions['width'];
}
elseif (array_key_exists('height', $dimensions)) {
$box['total_width'] = $dimensions['height'] / $box['total_height'] * $box['total_width'];
$box['total_height'] = $dimensions['height'];
}
return $box;
}
// If it is a box - then it should consist of two box elements;
// Determine sizes of elements and scale them.
if (array_key_exists('width', $dimensions)) {
// Vertical box type; horizontal contact.
if ($box['box_orientation'] == 'vertical') {
$dimensions1 = $dimensions2 = $dimensions;
}
elseif ($box['box_orientation'] == 'horizontal') {
$dimensions1 = array(
'width' => $box[1]['total_width'] / ($box[1]['total_width'] + $box[2]['total_width']) * $dimensions['width'],
);
$dimensions2 = array(
'width' => $box[2]['total_width'] / ($box[1]['total_width'] + $box[2]['total_width']) * $dimensions['width'],
);
}
}
elseif (array_key_exists('height', $dimensions)) {
// Vertical box type; horizontal contact.
if ($box['box_orientation'] == 'vertical') {
$dimensions1 = array(
'height' => $box[1]['total_height'] / ($box[1]['total_height'] + $box[2]['total_height']) * $dimensions['height'],
);
$dimensions2 = array(
'height' => $box[2]['total_height'] / ($box[1]['total_height'] + $box[2]['total_height']) * $dimensions['height'],
);
}
elseif ($box['box_orientation'] == 'horizontal') {
$dimensions1 = $dimensions2 = $dimensions;
}
}
$box[1] = _collageformatter_scale_box($box[1], $dimensions1);
$box[2] = _collageformatter_scale_box($box[2], $dimensions2);
if ($box['box_orientation'] == 'vertical') {
$box['total_height'] = $box[1]['total_height'] + $box[2]['total_height'];
$box['total_width'] = $box[1]['total_width'];
}
elseif ($box['box_orientation'] == 'horizontal') {
$box['total_width'] = $box[1]['total_width'] + $box[2]['total_width'];
$box['total_height'] = $box[1]['total_height'];
}
$box[1]['parent_total_width'] = $box[2]['parent_total_width'] = $box['total_width'];
$box[1]['parent_total_height'] = $box[2]['parent_total_height'] = $box['total_height'];
$box[1]['siblings_total_width'] = $box[2]['total_width'];
$box[1]['siblings_total_height'] = $box[2]['total_height'];
$box[2]['siblings_total_width'] = $box[1]['total_width'];
$box[2]['siblings_total_height'] = $box[1]['total_height'];
return $box;
}
/**
* Recursive function to resize the box.
*/
function _collageformatter_resize_box($box, $dimensions) {
// If it is an image - just resize it (change dimensions).
if ($box['box_type'] == 'image') {
$box['total_width'] = $dimensions['width'];
$box['total_height'] = $dimensions['height'];
return $box;
}
// If it is a box - then it should consist of two box elements;
// Determine sizes of elements and resize them.
// Vertical box type; horizontal contact.
if ($box['box_orientation'] == 'vertical') {
$dimensions1 = array(
'width' => $dimensions['width'],
'height' => $box[1]['total_height'] / ($box[1]['total_height'] + $box[2]['total_height']) * $dimensions['height'],
);
$dimensions2 = array(
'width' => $dimensions['width'],
'height' => $box[2]['total_height'] / ($box[1]['total_height'] + $box[2]['total_height']) * $dimensions['height'],
);
}
elseif ($box['box_orientation'] == 'horizontal') {
$dimensions1 = array(
'width' => $box[1]['total_width'] / ($box[1]['total_width'] + $box[2]['total_width']) * $dimensions['width'],
'height' => $dimensions['height'],
);
$dimensions2 = array(
'width' => $box[2]['total_width'] / ($box[1]['total_width'] + $box[2]['total_width']) * $dimensions['width'],
'height' => $dimensions['height'],
);
}
$box[1] = _collageformatter_resize_box($box[1], $dimensions1);
$box[2] = _collageformatter_resize_box($box[2], $dimensions2);
if ($box['box_orientation'] == 'vertical') {
$box['total_height'] = $box[1]['total_height'] + $box[2]['total_height'];
$box['total_width'] = $box[1]['total_width'];
}
elseif ($box['box_orientation'] == 'horizontal') {
$box['total_width'] = $box[1]['total_width'] + $box[2]['total_width'];
$box['total_height'] = $box[1]['total_height'];
}
$box[1]['parent_total_width'] = $box[2]['parent_total_width'] = $box['total_width'];
$box[1]['parent_total_height'] = $box[2]['parent_total_height'] = $box['total_height'];
$box[1]['siblings_total_width'] = $box[2]['total_width'];
$box[1]['siblings_total_height'] = $box[2]['total_height'];
$box[2]['siblings_total_width'] = $box[1]['total_width'];
$box[2]['siblings_total_height'] = $box[1]['total_height'];
return $box;
}
/**
* Recursive function to render the box.
*/
function _collageformatter_render_box($box, $settings) {
$output = '';
// Check if parent dimensions changed - and change yourself.
if (array_key_exists('parent_box_orientation', $box)) {
if ($box['parent_box_orientation'] == 'vertical') {
$box['total_width'] = $box['parent_total_width'];
}
elseif ($box['parent_box_orientation'] == 'horizontal') {
$box['total_height'] = $box['parent_total_height'];
}
}
// Perform pixel check.
if ($box['pixel_check']) {
if ($box['parent_box_orientation'] == 'vertical') {
$pixels = round($box['parent_total_height'] - 0.5) - round($box['total_height'] - 0.5) - round($box['siblings_total_height'] - 0.5);
if ($pixels) {
$box['total_height'] += $pixels;
}
}
elseif ($box['parent_box_orientation'] == 'horizontal') {
$pixels = round($box['parent_total_width'] - 0.5) - round($box['total_width'] - 0.5) - round($box['siblings_total_width'] - 0.5);
if ($pixels) {
$box['total_width'] += $pixels;
}
}
}
// Ensure that children have correct parent dimensions.
if ($box['box_type'] == 'box') {
$box[1]['parent_total_height'] = $box[2]['parent_total_height'] = $box['total_height'];
$box[1]['parent_total_width'] = $box[2]['parent_total_width'] = $box['total_width'];
}
if ($box['box_type'] == 'box') {
$box_style = array(
'float: left;',
'max-width: ' . round($box['total_width'] - 0.5) . 'px;',
);
$box_style[] = 'width: ' . 100 * (round($box['total_width'] - 0.5) / round($box['parent_total_width'] - 0.5)) . '%;';
$content[] = _collageformatter_render_box($box[1], $settings);
$content[] = _collageformatter_render_box($box[2], $settings);
$output = array(
'#theme' => 'collageformatter_collage_box',
'#box' => $content,
'#box_style' => implode(' ', $box_style),
);
}
elseif ($box['box_type'] == 'image') {
$image_uri = _collageformatter_image_file_check($box, $settings);
$image_style = array(
'display: block;',
'max-width: 100%;',
'height: auto;',
'margin: 0;',
);
// TODO: use theme('image_formatter', ... ?
$image = theme('image_style', array(
'style_name' => 'collageformatter',
'path' => $image_uri,
'alt' => $box['alt'],
'title' => $box['title'],
'attributes' => array(
'style' => implode(' ', $image_style),
),
));
// Create image derivatives.
if ($settings['generate_image_derivatives']) {
$derivative_uri = image_style_path('collageformatter', $image_uri);
if (!file_exists($derivative_uri)) {
$image_style = image_style_load('collageformatter');
if (!image_style_create_derivative($image_style, $image_uri, $derivative_uri)) {
watchdog('collageformatter', 'Unable to generate the derived image located at %path.', array(
'%path' => $derivative_uri,
));
}
}
}
$attached = array();
// Process image linking and modal gallery settings.
if ($settings['image_link'] == 'content') {
$class = $settings['image_link_class'] ? array(
$settings['image_link_class'],
) : array();
$rel = $settings['image_link_rel'];
$image = l($image, $box['content_uri'], array(
'attributes' => array(
'title' => $box['title'],
'class' => $class,
'rel' => $rel,
),
'html' => TRUE,
));
}
elseif ($settings['image_link'] == 'file') {
$image_dimensions = array(
'width' => $box['width'],
'height' => $box['height'],
);
if (empty($settings['image_link_image_style'])) {
$image_url = file_create_url($box['uri']);
}
else {
$image_url = image_style_url($settings['image_link_image_style'], $box['uri']);
image_style_transform_dimensions($settings['image_link_image_style'], $image_dimensions);
}
$class = $settings['image_link_class'] ? array(
$settings['image_link_class'],
) : array();
$rel = $settings['image_link_rel'];
$attributes = array();
switch ($settings['image_link_modal']) {
case 'colorbox':
$class[] = 'colorbox';
$rel = 'colorbox-' . $settings['gallery'];
break;
case 'shadowbox':
$rel = 'shadowbox[' . $settings['gallery'] . ']';
break;
case 'fancybox':
$class[] = 'fancybox';
$attributes['data-fancybox-group'] = 'fancybox-' . $settings['gallery'];
break;
case 'photobox':
$class[] = 'photobox';
$attached = photobox_attached_resources();
$attributes['data-photobox-gallery'] = 'photobox-' . $settings['gallery'];
break;
case 'photoswipe':
$class[] = 'photoswipe';
photoswipe_load_assets();
$attributes['data-size'] = $image_dimensions['width'] . 'x' . $image_dimensions['height'];
break;
case 'lightbox2':
$rel = 'lightbox[' . $settings['gallery'] . ']';
break;
default:
}
$image = l($image, $image_url, array(
'attributes' => array(
'title' => $box['title'],
'class' => $class,
'rel' => $rel,
) + $attributes,
'html' => TRUE,
));
}
$image_wrapper_style = array(
'float: left;',
'max-width: ' . round($box['total_width'] - $settings['gap_size'] - 0.5) . 'px;',
'width: ' . 100 * (round($box['total_width'] - $settings['gap_size'] - 0.5) / round($box['parent_total_width'] - 0.5)) . '%;',
);
if ($settings['gap_size']) {
$margin_percentage = 100 * ($settings['gap_size'] / round($box['parent_total_width'] - 0.5));
$image_wrapper_style[] = 'margin: ' . $margin_percentage . '% 0 0 ' . $margin_percentage . '%;';
}
$border = '';
if ($settings['border_size']) {
$border = 'border: ' . $settings['border_size'] . 'px solid';
if ($settings['border_color']) {
$border .= ' ' . $settings['border_color'];
}
$border .= ';';
}
$output = array(
'#theme' => 'collageformatter_collage_image',
'#image' => $image,
'#image_wrapper_class' => array(
'collageformatter-collage-image-wrapper-' . $box['delta'],
),
'#image_wrapper_style' => implode(' ', $image_wrapper_style),
'#image_style' => $border,
'#attached' => $attached,
);
}
return $output;
}
/**
* Checks for/creates the original image reference file.
*/
function _collageformatter_image_file_check($box, $settings) {
$image_width = round($box['total_width'] - 2 * $settings['border_size'] - $settings['gap_size'] - 0.5);
$image_height = round($box['total_height'] - 2 * $settings['border_size'] - $settings['gap_size'] - 0.5);
$filename = $image_width . 'x' . $image_height . '_' . $settings['advanced']['original_image_reference'] . '_' . drupal_basename($box['uri']);
$directory = drupal_dirname(file_build_uri('collageformatter/' . file_uri_target($box['uri'])));
$image_uri = $directory . '/' . $filename;
if (!file_exists($image_uri)) {
if (file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
if ($settings['advanced']['original_image_reference'] == 'symlink') {
if (!symlink(drupal_realpath($box['uri']), drupal_realpath($image_uri))) {
watchdog('collageformatter', 'Failed to symlink file @source to @destination.', array(
'@source' => $box['uri'],
'@destination' => $image_uri,
));
}
}
elseif ($settings['advanced']['original_image_reference'] == 'copy') {
if (!file_unmanaged_copy($box['uri'], $image_uri, FILE_EXISTS_REPLACE)) {
watchdog('collageformatter', 'Failed to copy file from @source to @destination.', array(
'@source' => $box['uri'],
'@destination' => $image_uri,
));
}
}
elseif ($settings['advanced']['original_image_reference'] == 'fake') {
$image = image_load($box['uri']);
image_effect_apply($image, array(
'effect callback' => 'image_scale_effect',
'data' => array(
'width' => 1,
'height' => 1,
),
));
image_save($image, $image_uri);
}
}
}
return $image_uri;
}
/**
* Checks for upscaled images and returns the scaling factor.
*/
function _collageformatter_upscaling_check($box, $settings) {
$scale1 = $scale2 = 1;
if ($box['box_type'] == 'box') {
$scale1 = _collageformatter_upscaling_check($box[1], $settings);
$scale2 = _collageformatter_upscaling_check($box[2], $settings);
}
elseif ($box['box_type'] == 'image') {
$width = $box['total_width'] - 2 * $settings['border_size'] - $settings['gap_size'];
$height = $box['total_height'] - 2 * $settings['border_size'] - $settings['gap_size'];
if ($box['width'] < $width) {
$scale1 = $box['width'] / $width;
}
if ($box['height'] < $height) {
$scale1 = $box['height'] / $height;
}
}
return $scale1 <= $scale2 ? $scale1 : $scale2;
}
/**
* Implements hook_theme().
*/
function collageformatter_theme($existing, $type, $theme, $path) {
return array(
'collageformatter_collage' => array(
'variables' => array(
'collage' => NULL,
'collage_wrapper_class' => NULL,
'collage_wrapper_style' => NULL,
'collage_style' => NULL,
'collage_bottom_style' => NULL,
),
'template' => 'templates/collageformatter_collage',
),
'collageformatter_collage_box' => array(
'variables' => array(
'box' => NULL,
'box_style' => NULL,
),
'template' => 'templates/collageformatter_collage_box',
),
'collageformatter_collage_image' => array(
'variables' => array(
'image' => NULL,
'image_wrapper_class' => NULL,
'image_wrapper_style' => NULL,
'image_style' => NULL,
),
'template' => 'templates/collageformatter_collage_image',
),
);
}
/**
* Implements hook_image_default_styles().
*/
function collageformatter_image_default_styles() {
$styles = array();
$styles['collageformatter'] = array(
'effects' => array(
array(
'name' => 'collageformatter',
'weight' => '0',
),
),
);
return $styles;
}
/**
* Implements hook_image_effect_info().
*/
function collageformatter_image_effect_info() {
$effects = array();
$effects['collageformatter'] = array(
'label' => t('Collage Formatter'),
'effect callback' => 'collageformatter_image_effect_callback',
'dimensions passthrough' => TRUE,
);
return $effects;
}
/**
* Collage Formatter image effect.
*/
function collageformatter_image_effect_callback(&$image, $data) {
if (strpos(drupal_basename($image->source), '_copy_') !== FALSE || strpos(drupal_basename($image->source), '_symlink_') !== FALSE || strpos(drupal_basename($image->source), '_fake_') !== FALSE) {
$dimensions = preg_replace('/.+\\/([\\d]+x[\\d]+)_(copy|symlink|fake)_.+/', '$1', $image->source);
list($image_width, $image_height) = explode('x', $dimensions);
$original_image_uri = preg_replace('/(.+\\/)collageformatter\\/(.+\\/)[\\d]+x[\\d]+_(copy|symlink|fake)_(.+)/', '$1$2$4', $image->source);
// If it is a fake image - we need to load the real image resource.
if (strpos(drupal_basename($image->source), '_fake_') !== FALSE) {
$original_image = image_load($original_image_uri);
$image->info = $original_image->info;
$image->resource = $original_image->resource;
}
$image->source = $original_image_uri;
$effect_callback = 'image_scale_and_crop_effect';
if (module_exists('focal_point')) {
$effect_callback = 'focal_point_scale_and_crop_effect';
}
if (isset($image_width) && isset($image_height)) {
return image_effect_apply($image, array(
'effect callback' => $effect_callback,
'data' => array(
'width' => $image_width,
'height' => $image_height,
),
));
}
}
return FALSE;
}
/**
* Flushes collageformatter style images.
*/
function collageformatter_flush_style_submit() {
$style = image_style_load('collageformatter');
image_style_flush($style);
drupal_set_message(t('Style %style has been flushed.', array(
'%style' => 'collageformatter',
)));
}
/**
* Implements hook_image_style_flush().
*/
function collageformatter_image_style_flush($style) {
// Remove symlinks and copied files.
// Doesn't work for symlinks - deletes original file instead of symlink.
if ($style['name'] == 'collageformatter') {
$directory = file_build_uri('collageformatter');
// file_unmanaged_delete_recursive($directory);
}
}
/**
* Implements hook_views_api().
*/
function collageformatter_views_api() {
return array(
'api' => 3,
);
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function collageformatter_form_field_ui_display_overview_form_alter(&$form, &$form_state) {
if (!empty($form_state['formatter_settings_edit'])) {
$field = $form_state['formatter_settings_edit'];
if ($form_state['input']['fields'][$field]['type'] == 'collageformatter') {
$form['fields'][$field]['format']['settings_edit_form']['actions']['flush'] = array(
'#type' => 'submit',
'#value' => t('Flush generated images'),
'#submit' => array(
'collageformatter_flush_style_submit',
),
);
}
}
}
/**
* Implements hook_module_implements_alter().
*/
function collageformatter_module_implements_alter(&$implementations, $hook) {
if ($hook == 'form_alter' && isset($implementations['collageformatter'])) {
$group = $implementations['collageformatter'];
unset($implementations['collageformatter']);
$implementations['collageformatter'] = $group;
}
}