You are here

epsacrop.module in EPSA Crop - Image Cropping 7.2

Same filename and directory in other branches
  1. 8.2 epsacrop.module
  2. 6.2 epsacrop.module
  3. 6 epsacrop.module

The main file of module

@TODO Pass dialog popo throw theme functions @TODO Add the in place edition

File

epsacrop.module
View source
<?php

/**
 * @file
 * The main file of module
 *
 * @TODO Pass dialog popo throw theme functions
 * @TODO Add the in place edition
 */

/**
 * Implements hook_permission.
 *
 * @access public
 * @return void
 */
function epsacrop_permission() {
  return array(
    'epsacrop create crops' => array(
      'title' => t("Create crops"),
      'description' => t("Show the %label_link link in the field.", array(
        '%label_link' => t("mangage image crops"),
      )),
    ),
    'epsacrop edit all crops' => array(
      'title' => t("Edit crops"),
      'description' => t("Allow the user to edit coordinates for each style (show the link field)."),
    ),
    /*
    'epsacrop edit my crops' => array(
      'title' => t(""),
      'description' => t("")
    ),
    */
    'epsacrop delete all crops' => array(
      'title' => t("Delete crops"),
      'description' => t("Allow the user to delete coordinates and use the default style."),
    ),
    /*
    'epsacrop delete my crops' => array(
      'title' => t(""),
      'description' => t("")
    ),
    'epsacrop view all crops' => array(
      'title' => t(""),
      'description' => t("")
    ),
    'epsacrop view own crops' => array(
      'title' => t(""),
      'description' => t("")
    ),
    'epsacrop edit my crops in place' => array(
      'title' => t(""),
      'description' => t("")
    ),
    'epsacrop edit my crops with all styles' => array(
      'title' => t(""),
      'description' => t("")
    ),
    'epsacrop edit all crops with all styles' => array(
      'title' => t("Edit crop in place"),
      'description' => t("When it's a image from EPSACrop, add a link that allow the user edit coordonates in place.")
    ),
    */
    'epsacrop administer available crops' => array(
      'title' => t("Administer available crops"),
      'description' => t("Allow user to select which styles are shown in each field."),
    ),
  );
}

/**
 * Implements hook_menu.
 *
 * @access public
 * @return array
 */
function epsacrop_menu() {
  $items = array();
  $items['crop/dialog/%/%/%/%'] = array(
    'title' => 'Dialog Crop',
    'page callback' => 'epsacrop_dialog',
    'page arguments' => array(
      2,
      3,
      4,
      5,
    ),
    'access callback' => '_epsacrop_access',
    'type' => MENU_CALLBACK,
  );
  $items['crop/ajax/%/%/%'] = array(
    'title' => 'Crop Dialog Ajax',
    'page callback' => 'epsacrop_ajax',
    'page arguments' => array(
      2,
      3,
    ),
    'access callback' => '_epsacrop_ajax_access',
    'access arguments' => array(
      2,
      3,
      4,
    ),
    'type' => MENU_CALLBACK,
  );
  $items['crop/ajaxinfo/%'] = array(
    'title' => 'Crop File Info Ajax',
    'page callback' => 'epsacrop_ajaxinfo',
    'page arguments' => array(
      2,
    ),
    'access callback' => '_epsacrop_access',
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * epsacrop_dialog function.
 *
 * @access public
 * @param string $entity_name
 * @param string $field_name
 * @param string $bundle
 * @param int $fid
 * @return void
 */
function epsacrop_dialog($entity_name, $field_name, $bundle, $fid) {
  $out = '';

  //@TODO: If a method is added to determine if the image is used elsewhere (or number of instances), add that condition for the message

  //related issue: http://drupal.org/node/1352722
  if (module_exists('media')) {
    $out .= '<p>For convenience, cropping applies to <strong>all</strong> current and future content which uses this image. (If the image is from the library, changing the cropping will affect all existing content which uses the image.)</p>';
  }
  $data = _epsacrop_get_coords_from_fid($fid);
  if (!is_string($data)) {
    $data = drupal_json_encode((object) $data);
    $data = check_plain($data);
  }
  $out .= '<div class="epsacrop-global" data-token="' . drupal_get_token('epsacrop-put-' . $fid) . '" data-coordinates="' . urlencode($data) . '">' . "\n";
  $out .= '<div class="epsacrop-image-crop">' . "\n";
  $out .= '<img id="epsacrop-target" />' . "\n";
  $out .= '</div>' . "\n";
  $out .= '<div class="epsacrop-presets-menu">' . "\n";
  $out .= '<ul class="epsacrop-presets-menu-ul">' . "\n";
  $i = 0;
  if ($entity_name == 'all' && $field_name == 'all' && $bundle == 'all') {

    //When on the file edit page, there is no entity_name, field_name or bundle. So make all styles available for editing
    $all_styles = array_keys(_epsacrop_load_styles());
    $styles = array(
      'styles' => array_combine($all_styles, $all_styles),
    );
  }
  else {
    $styles = _epsacrop_load_styles_by_instance($entity_name, $field_name, $bundle);
  }
  foreach ($styles['styles'] as $style_name) {
    $style = _epsacrop_load_style($style_name);
    $effect = _epsacrop_get_effect($style);
    $effect = current($effect);
    $id = 'epsacrop-' . $style_name;
    $name = is_array($style) && !empty($style['label']) ? $style['label'] : $style_name;
    $out .= '<li class="epsacrop-presets-menu-li"><a data-bgcolor="' . $effect['data']['jcrop_settings']['bgcolor'] . '" data-bgopacity="' . $effect['data']['jcrop_settings']['bgopacity'] . '" data-aspect-ratio="' . $effect['data']['jcrop_settings']['aspect_ratio'] . '" id="' . $id . '" href="javascript:Drupal.EPSACrop.crop(\'' . $id . '\');" rel="' . $effect['data']['width'] . 'x' . $effect['data']['height'] . '"' . ($i++ == 0 ? ' class="selected"' : '') . '>' . $name . '</a></li>';
  }
  $out .= '</ul>' . "\n";
  $out .= '</div>' . "\n";
  $out .= '<br style="clear:both;" />' . "\n";
  $out .= '</div>' . "\n";
  $GLOBALS['devel_shutdown'] = FALSE;
  echo $out;
  drupal_exit();
}

/**
 * epsacrop_ajax function.
 *
 * @access public
 * @param string $op
 * @param string $fid
 * @return void
 */
function epsacrop_ajax($op, $fid) {
  $return = NULL;
  switch ($op) {
    case 'get':
      $return = _epsacrop_get_coords_from_fid($fid);
      if ($return == FALSE) {
        $return = array();
      }
      break;
    case 'put':
      if (isset($_POST) && (isset($_POST['coords']) && !empty($_POST['coords']))) {

        // If the json_decode returns null that means we got an invalid JSON or
        // it reaches the recursion limit.
        if (($values = drupal_json_decode($_POST['coords'])) === NULL) {
          drupal_access_denied();
          drupal_exit();
        }
        $coords = drupal_json_encode($values);
        _epsacrop_save_coords($fid, $coords);
      }
      break;
    case 'del':
      break;
  }
  drupal_json_output($return);
  drupal_exit();
}

/**
 * epsacrop_ajaxinfo function
 *
 * @access public
 * @param string $fid
 * @return void
 */
function epsacrop_ajaxinfo($fid) {
  $file = file_load($fid);
  $url = image_style_url('epsacrop_thumb', $file->uri);
  $info = image_get_info($file->uri);
  $return = array(
    'url' => $url,
    'width' => $info['width'],
    'height' => $info['height'],
  );
  drupal_json_output($return);
  drupal_exit();
}

/**
 * Implements hook_file_delete().
 *
 * @access public
 * @param stdClass $file
 * @return void
 */
function epsacrop_file_delete($file) {
  _epsacrop_delete_file($file->fid);
}

/**
 * Implements hook_image_default_styles().
 *
 * @access public
 * @return array
 */
function epsacrop_image_default_styles() {
  $styles = array();
  $styles['epsacrop_thumb'] = array();
  $styles['epsacrop_thumb']['effects'] = array(
    array(
      'name' => 'image_scale',
      'data' => array(
        'width' => 512,
        'height' => 384,
        'upscale' => 0,
      ),
      'weight' => 0,
    ),
  );
  return $styles;
}

/**
 * Implements hook_image_effect_info.
 *
 * @access public
 * @return array
 */
function epsacrop_image_effect_info() {
  $effects = array();
  $effects['epsacrop_crop'] = array(
    'label' => t("EPSA Image Crop"),
    'help' => t(""),
    'dimensions callback' => 'epsacrop_crop_dimensions',
    'effect callback' => 'epsacrop_crop_image',
    'form callback' => 'epsacrop_crop_image_form',
  );
  $effects['epsacrop_crop_reuse'] = array(
    'label' => t("Reuse EPSA Image Crop"),
    'help' => t("Use the image crop selection from another image style"),
    'effect callback' => 'epsacrop_crop_image_reuse',
    'form callback' => 'epsacrop_crop_image_reuse_form',
  );
  return $effects;
}

/**
 * A wrapper around image_resize_dimensions.
 *
 * @access public
 * @param array $dimensions
 * @param array $data
 * @return void
 */
function epsacrop_crop_dimensions(array &$dimensions, array $data) {
  if (!$data['height']) {
    $data['height'] = NULL;
  }
  if (!$data['width']) {
    $data['width'] = NULL;
  }
  image_resize_dimensions($dimensions, $data);
}

/**
 * Function that provide the effect form settings for dialog crop.
 *
 * @access public
 * @param mixed $data
 * @return void
 */
function epsacrop_crop_image_form($data) {
  $data += array(
    'jcrop_settings' => array(
      'bgcolor' => 'black',
      'bgopacity' => '0.6',
    ),
  );

  //@TODO Propose a alternative style (whitout Crop Dialog effect) instead of this
  $form = image_crop_form($data);

  // Override default
  $form['width']['#required'] = FALSE;
  $form['height']['#required'] = FALSE;

  // Add validation callbacks to ensure that at least one value has been added
  $form['height']['#element_validate'] = array(
    '_epsacrop_height_validate',
  );
  $form['width']['#element_validate'] = array(
    '_epsacrop_width_validate',
  );

  // Change description for the anchor
  $form['anchor']['#description'] = t("The part of the image that will be retained during the crop if no coordinates are set.");
  $form['disable_scale'] = array(
    '#type' => 'checkbox',
    '#title' => t('Disable image scaling'),
    '#description' => t("Only crop the image to the selected area and don't scale it. When enabled the above dimensions are used only when the cropping area is not selected."),
    '#default_value' => isset($data['disable_scale']) ? $data['disable_scale'] : 0,
  );
  $form['jcrop_settings'] = array(
    '#type' => 'fieldset',
    '#title' => t("Advanced settings"),
    '#collapsed' => TRUE,
    '#collapsible' => TRUE,
  );
  $form['jcrop_settings']['aspect_ratio'] = array(
    '#type' => 'textfield',
    '#title' => t('Aspect Ratio'),
    '#description' => t("Aspect ratio of w/h (e.g. 1 for square)"),
    '#default_value' => isset($data['jcrop_settings']['aspect_ratio']) ? $data['jcrop_settings']['aspect_ratio'] : '',
    // '#field_suffix' => ' ' . t('pixels'),
    // '#required' => TRUE,
    '#size' => 10,
    '#element_validate' => array(
      '_epsacrop_aspect_ratio_validate',
    ),
  );

  /*
  $form['jcrop_settings']['minsize'] = array();
  $form['jcrop_settings']['maxsize'] = array();
  */
  $form['jcrop_settings']['bgcolor'] = array(
    '#type' => 'textfield',
    '#title' => t('Background color'),
    '#description' => t("Set color of background container"),
    '#default_value' => isset($data['jcrop_settings']['bgcolor']) ? $data['jcrop_settings']['bgcolor'] : '',
    // '#field_suffix' => ' ' . t('pixels'),
    '#required' => TRUE,
    '#size' => 10,
  );
  $form['jcrop_settings']['bgopacity'] = array(
    '#type' => 'textfield',
    '#title' => t('Background opacity'),
    '#description' => t("Opacity of outer image when cropping"),
    '#default_value' => isset($data['jcrop_settings']['bgopacity']) ? $data['jcrop_settings']['bgopacity'] : '',
    // '#field_suffix' => ' ' . t('pixels'),
    '#required' => TRUE,
    '#size' => 10,
  );
  $form['jcrop_settings']['fallback'] = array(
    '#type' => 'checkbox',
    '#title' => t('Ignore if not manually set'),
    '#description' => t("If a user does not manually set the crop, ignore these settings.  This is useful if you want to use other effects to set a default crop, which may then be overridden manually using EPSA Crop.  When this is checked, make sure the EPSA Crop effect is above any default cropping effects."),
    '#default_value' => isset($data['jcrop_settings']['fallback']) ? $data['jcrop_settings']['fallback'] : FALSE,
  );
  return $form;
}

/**
 * Apply the effect to the image.
 *
 * @access public
 * @param stdClass $image
 * @param array $settings
 * @return void
 */
function epsacrop_crop_image(stdClass $image, $settings) {
  $fid = _epsacrop_get_fid_from_uri($image->source);
  if (!empty($fid) && $fid > 0) {
    $coords = _epsacrop_get_coords_from_fid($fid);
    if (is_string($coords)) {
      $coords = drupal_json_decode($coords);
      if (is_object($coords)) {
        $coords = (array) $coords;
      }
    }
    if (!empty($coords) && is_array($coords)) {
      if (isset($GLOBALS['jcrop_style'])) {
        $style_name = $GLOBALS['jcrop_style'];
      }
      else {
        $style_name = _epsacrop_get_style_name_from_url();
      }
      if (!empty($style_name)) {

        // Trigger presave hook.
        module_invoke_all('epsacrop_crop_image_presave', $image, $settings, $coords, $style_name);
        $style = _epsacrop_load_style($style_name);
        if (!empty($style)) {
          $effect = _epsacrop_get_effect($style);
          if (!empty($effect)) {
            $effect = current($effect);
            $preset = 'epsacrop-' . $style_name;
            $coord = isset($coords[$fid][$preset]) ? $coords[$fid][$preset] : '';
            if (!empty($coord)) {
              if (image_crop($image, $coord['x'], $coord['y'], $coord['w'], $coord['h'])) {

                // Trigger postsave hook.
                module_invoke_all('epsacrop_crop_image_postsave', $image, $settings, $coords, $style_name);
                if (isset($settings['disable_scale']) && $settings['disable_scale']) {
                  return TRUE;
                }
                return image_scale($image, $settings['width'], $settings['height']);
              }
            }
          }
        }
      }
    }
  }
  return empty($settings['jcrop_settings']['fallback']) ? image_crop_effect($image, $settings) : TRUE;
}

/**
 * Function that provide the effect form settings for reusing epsa crop.
 *
 * @access public
 * @param mixed $data
 * @return void
 */
function epsacrop_crop_image_reuse_form($data) {
  $styles = array_keys(_epsacrop_load_styles());
  $styles = array_combine($styles, $styles);

  //exclude the current style
  if ($key = array_search(arg(5), $styles)) {
    unset($styles[$key]);
  }
  if (count($styles) > 0) {
    $form['jcrop_reuse'] = array(
      '#title' => t('Reuse the crop selection from'),
      '#type' => 'select',
      '#options' => $styles,
      '#default_value' => isset($data['jcrop_reuse']) ? $data['jcrop_reuse'] : '',
    );
  }
  else {
    $form['jcrop_reuse_message'] = array(
      '#value' => t('No styles were found currently using EPSA crop. Please create a style with EPSA crop first.'),
    );
  }
  return $form;
}

/**
 * Apply the effect to the image on reuse.
 *
 * @access public
 * @param stdClass $image
 * @param array $settings
 * @return void
 */
function epsacrop_crop_image_reuse(stdClass $image, $settings) {
  if (!isset($settings['jcrop_reuse'])) {
    return;
  }
  $style = _epsacrop_load_style($settings['jcrop_reuse']);
  foreach ($style['effects'] as $effect) {
    if ($effect['name'] == 'epsacrop_crop') {
      $GLOBALS['jcrop_style'] = $style['name'];
      image_effect_apply($image, $effect);
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * @access public
 * @param array &$form
 * @param array $form_state
 * @return void
 */
function epsacrop_form_field_ui_field_edit_form_alter(&$form, $form_state) {
  if (user_access('epsacrop administer available crops')) {
    $field = $form['#field'];
    $settings = $form_state['build_info']['args'][0]['settings'];
    if (isset($field) && in_array($field['type'], array(
      'image',
      'media',
      'file',
    ))) {
      $styles = _epsacrop_load_styles();
      if (!empty($styles)) {
        $options = array();
        foreach ($styles as $style_name => $style) {
          $options[$style_name] = $style['label'];
        }
        $form['instance']['settings']['epsacrop'] = array(
          '#type' => 'fieldset',
          '#title' => t("EPSACrop settings"),
          '#collapsed' => FALSE,
          '#collapsible' => TRUE,
          '#tree' => TRUE,
        );
        $form['instance']['settings']['epsacrop']['styles'] = array(
          '#type' => 'checkboxes',
          '#title' => t("Availables EPSACrop styles"),
          '#description' => t("Select which styles should be available for this field"),
          '#options' => $options,
          '#default_value' => isset($settings['epsacrop']['styles']) ? $settings['epsacrop']['styles'] : array(),
        );

        //@TODO Add the possibility to change the size of dialog (for example, for field with only one style)

        /*
        $form['instance']['settings']['epsacrop']['dialog_width'] = array(
          '#type' => 'textfield',
          '#title' => t('Dialog width'),
          '#default_value' => isset($settings['epsacrop']['dialog_width']) ? $settings['epsacrop']['dialog_width'] : '512',
          '#field_suffix' => ' ' . t('pixels'),
          '#required' => TRUE,
          '#size' => 10,
        );

        $form['instance']['settings']['epsacrop']['dialog_height'] = array(
          '#type' => 'textfield',
          '#title' => t('Dialog height'),
          '#default_value' => isset($settings['epsacrop']['dialog_height']) ? $settings['epsacrop']['dialog_height'] : '384',
          '#field_suffix' => ' ' . t('pixels'),
          '#required' => TRUE,
          '#size' => 10,
        );
        */
      }
    }
  }
}

/**
 * Implements hook_form_media_edit_alter().
 * Add epsacrop to media edit form.
 */
function epsacrop_form_media_edit_alter(&$form, $form_state) {
  epsacrop_form_file_entity_edit_alter($form, $form_state);
}

/**
 * Implements hook_form_file_entity_edit_alter().
 * Add epsacrop to file_entity edit form.
 */
function epsacrop_form_file_entity_edit_alter(&$form, $form_state) {
  if (!_epsacrop_access() || !isset($form['preview']['#file']) || $form['preview']['#file']->type != 'image') {
    return;
  }
  _epsacrop_include_header_html();
  $setting = array(
    'entity_type' => 'all',
    'field_name' => 'all',
    'bundle' => 'all',
  );
  $file = $form['preview']['#file'];
  $info = image_get_info($file->uri);
  $setting['fid'] = $file->fid;
  $setting['url'] = str_replace('%27', '\\%27', image_style_url('epsacrop_thumb', $file->uri));
  $setting['size'] = array(
    $info['width'],
    $info['height'],
  );

  // Fix a strange bug when the image's name contains strange chars, like +
  $preview_file = image_style_path('epsacrop_thumb', $file->uri);
  if (!file_exists($preview_file)) {
    image_style_create_derivative(image_style_load('epsacrop_thumb'), $file->uri, $preview_file);
  }
  $markup = "<a href=\"javascript:Drupal.EPSACrop.dialog('" . $setting['entity_type'] . "', '" . $setting['field_name'] . "', '" . $setting['bundle'] . "', '" . $setting['fid'] . "', '" . $setting['url'] . "', [" . $setting['size'][0] . "," . $setting['size'][1] . "]);\" class=\"button epsacrop\">" . t("manage image crops") . "</a>";
  $form['epsacrop'] = array(
    '#type' => 'markup',
    '#markup' => $markup,
  );
}

/**
 * Implements hook_element_info_alter.
 *
 * @access public
 * @param array &$type
 * @return void
 */
function epsacrop_element_info_alter(&$type) {
  $type['managed_file']['#process'][] = 'epsacrop_element_process';
  if (module_exists('media')) {
    $type['media']['#process'][] = 'epsacrop_element_process';
  }
  if (isset($type['mfw_managed_file'])) {
    $type['mfw_managed_file']['#process'][] = 'epsacrop_element_process';
  }
}

/**
 * Helper function that add a link in image widget field to open a dialog for the crops.
 *
 * @access private
 * @return void
 */
function epsacrop_element_process($element, $form_state, $form) {
  if (!isset($element['#field_name']) || !_epsacrop_access()) {
    return $element;
  }
  _epsacrop_include_header_html();
  $styles = _epsacrop_load_styles_by_instance($element['#entity_type'], $element['#field_name'], $element['#bundle']);
  if (count($styles) == 0) {
    return $element;
  }
  $setting = array(
    'entity_type' => $element['#entity_type'],
    'field_name' => $element['#field_name'],
    'bundle' => $element['#bundle'],
  );
  if (isset($element['#file']) && is_object($element['#file']) && ($file = $element['#file'])) {
    $info = image_get_info($file->uri);
    $setting['fid'] = $file->fid;
    $setting['url'] = str_replace('%27', '\\%27', image_style_url('epsacrop_thumb', $file->uri));
    $setting['size'] = array(
      $info['width'],
      $info['height'],
    );

    // Fix a strange bug when the image's name contains strange chars, like +
    $preview_file = image_style_path('epsacrop_thumb', $file->uri);
    if (!file_exists($preview_file)) {
      image_style_create_derivative(image_style_load('epsacrop_thumb'), $file->uri, $preview_file);
    }
  }
  if ($element['#type'] == 'media') {

    //for media, need to include the media elements even if the file is not defined, because it's not defined when file initially selected
    $element['#attached']['js'][] = array(
      'type' => 'setting',
      'data' => array(
        'epsacrop_dialog' => array(
          $element['#id'] . '--widget' => $setting,
        ),
      ),
    );
    $element['#attached']['js'][] = drupal_get_path('module', 'epsacrop') . '/js/epsacrop-media.js';
    $element['epsacrop'] = array(
      '#type' => 'link',
      '#href' => '',
      '#title' => t('Manage image crops'),
      '#attributes' => array(
        'class' => array(
          'button',
          'manage-crop',
        ),
      ),
      '#options' => array(
        'fragment' => FALSE,
        'external' => TRUE,
      ),
      '#weight' => 0,
    );
  }
  elseif (isset($setting['fid'])) {
    $markup = "<a href=\"javascript:Drupal.EPSACrop.dialog('" . $setting['entity_type'] . "', '" . $setting['field_name'] . "', '" . $setting['bundle'] . "', '" . $setting['fid'] . "', '" . $setting['url'] . "', [" . $setting['size'][0] . "," . $setting['size'][1] . "]);\">" . t("manage image crops") . "</a>";
    $element['epsacrop'] = array(
      '#type' => 'markup',
      '#markup' => $markup,
    );
  }
  return $element;
}

/**
 * Validate a aspect ration information.
 *
 * @access public
 * @param array $element
 * @param array &$form_state
 * @return void
 */
function _epsacrop_aspect_ratio_validate($element, &$form_state) {
  $value = $element['#value'];
  if (!empty($value)) {
    $parts = explode('/', $value);
    if (count($parts) == 2) {
      if (!is_numeric($parts[0]) || !is_numeric($parts[1])) {
        form_error($element, t('Both parts of !name must be an integer.', array(
          '!name' => check_plain($element['#title']),
        )));
      }
    }
    elseif (!is_numeric($value)) {
      form_error($element, t('!name must be an integer.', array(
        '!name' => check_plain($element['#title']),
      )));
    }
  }
}

/**
 * Validate width information.
 *
 * @access private
 * @param array $element
 * @param array &$form_state
 * @return void
 */
function _epsacrop_width_validate($element, &$form_state) {
  $value = $element['#value'];
  if (empty($value)) {
    if (empty($form_state['complete form']['data']['height']['#value'])) {
      form_error($element, t('Width cannot be empty without a height value'));
    }
  }
}

/**
 * Validate height information.
 *
 * @access private
 * @param array $element
 * @param array &$form_state
 * @return void
 */
function _epsacrop_height_validate($element, &$form_state) {
  $value = $element['#value'];
  if (empty($value)) {
    if (empty($form_state['complete form']['data']['width']['#value'])) {
      form_error($element, t('Height cannot be empty without a width value'));
    }
  }
}

/**
 * Helper function that get all styles with epsacrop effect.
 *
 * @access private
 * @return array
 */
function _epsacrop_load_styles() {
  $return = array();
  $styles = image_styles();
  foreach ($styles as $style_name => $style) {
    foreach ($style['effects'] as $sid => $effect) {
      if ($effect['module'] == 'epsacrop' && $effect['name'] == 'epsacrop_crop') {
        $return[$style_name] = $style;
        break;
      }
    }
  }
  return $return;
}

/**
 * This function load only on style that implement epsacrop effect.
 *
 * @access private
 * @param string $style_name
 * @return bool
 */
function _epsacrop_load_style($style_name) {
  if (empty($style_name)) {
    return FALSE;
  }
  $styles = _epsacrop_load_styles();
  if (isset($styles[$style_name]) && !empty($styles[$style_name])) {
    return $styles[$style_name];
  }
  return FALSE;
}

/**
 * Return the effect issue from the module.
 *
 * @access private
 * @param mixed $style
 * @return void
 */
function _epsacrop_get_effect($style) {
  if (empty($style) || !is_array($style) || (!isset($style['effects']) || !is_array($style['effects']))) {
    return FALSE;
  }
  foreach ($style['effects'] as $eid => $effect) {
    if ($effect['module'] == 'epsacrop') {
      return array(
        $eid => $effect,
      );
    }
  }
  return FALSE;
}

/**
 * Get all style that are attach to one instance of field.
 *
 * @access private
 * @param string $entity_type
 * @param string $field_name
 * @param string $bundle_name
 * @return array
 */
function _epsacrop_load_styles_by_instance($entity_type, $field_name, $bundle) {
  $instance = field_info_instance($entity_type, $field_name, $bundle);
  $styles = array();
  if (isset($instance['settings']['epsacrop']) && is_array($instance['settings']['epsacrop']['styles'])) {
    $instance['settings']['epsacrop']['styles'] = array_filter($instance['settings']['epsacrop']['styles']);
    if (isset($instance['settings']['epsacrop']['styles']) && !empty($instance['settings']['epsacrop']['styles'])) {
      $styles = $instance['settings']['epsacrop'];
    }
  }

  // Allow other modules to alter list of styles
  drupal_alter('epsacrop_load_styles', $styles, $entity_type, $field_name, $bundle);
  return $styles;
}

/**
 * Helper function that get the style name from image url.
 *
 * @access private
 * @return void
 */
function _epsacrop_get_style_name_from_url() {
  $split = explode('/', $_GET['q']);
  $pointer = array_search('styles', $split);
  if ($pointer !== FALSE) {
    return $split[++$pointer];
  }
  return FALSE;
}

/**
 * This function include all files (JavaScript & CSS) needed by the module.
 *
 * @access private
 * @return void
 */
function _epsacrop_include_header_html() {
  $module_path = drupal_get_path('module', 'epsacrop');
  drupal_add_js(array(
    'epsacrop' => array(
      'path' => $module_path,
    ),
  ), 'setting');
  drupal_add_library('system', 'ui.dialog');
  drupal_add_js(libraries_get_path('Jcrop') . '/js/jquery.Jcrop.js');
  drupal_add_js(libraries_get_path('json2') . '/json2.js', array(
    'preprocess' => FALSE,
  ));
  drupal_add_js($module_path . '/js/epsacrop.js');
  drupal_add_css(libraries_get_path('Jcrop') . '/css/jquery.Jcrop.css');
  drupal_add_css($module_path . '/css/epsacrop.css');
}

/**
 * Return the version of jcrop library.
 *
 * @access public
 * @return void
 */
function _epsacrop_jcrop_get_version() {
  $version = 0;
  $filepath = libraries_get_path('Jcrop') . '/js/jquery.Jcrop.js';
  if (file_exists($filepath)) {
    $lines = file($filepath);
    array_shift($lines);

    // First line is simple comment
    if (preg_match('/v(.*)/', array_shift($lines), $matches)) {
      $version = $matches[1];
    }
    else {
      drupal_set_message(t('Could be give the version of Jcrop %path, check your install.', array(
        '%path' => $filepath,
      )), 'error');
      $version = 0;
    }
  }
  return $version;
}

/**
 * Check if json2.js is findable.
 *
 * @access private
 * @return void
 */
function _epsacrop_is_json2_exists($display_message = FALSE) {
  $filepath = libraries_get_path('json2') . '/json2.js';
  if (file_exists($filepath)) {
    return TRUE;
  }
  if ($display_message) {
    drupal_set_message(t('Could be find the json2.js file %path, check your install.', array(
      '%path' => $filepath,
    )), 'error');
  }
}

/**
 * Check if we've coordonates for one file.
 *
 * @access private
 * @param int $fid
 * @return bool
 */
function _epsacrop_fid_exists($fid) {
  if (!empty($fid)) {
    return count(db_select('epsacrop_files', 'e')
      ->fields('e')
      ->condition('fid', $fid)
      ->execute()
      ->fetchAll());
  }
  return 0;
}

/**
 * Insert coordonates for one file in the database.
 *
 * @access private
 * @param int $fid
 * @param array $coords
 * @return void
 */
function _epsacrop_add_file($fid, $coords) {
  db_insert('epsacrop_files')
    ->fields(array(
    'fid' => $fid,
    'coords' => serialize($coords),
  ))
    ->execute();
}

/**
 * Save the coordonates in the database.
 *
 * @access private
 * @param int $fid
 * @param array $coords
 * @return void
 */
function _epsacrop_save_coords($fid, $coords) {

  // Check fid is for a valid file.
  if ($file = file_load($fid)) {
    $info = image_get_info($file->uri);

    // Not an image.
    if (!$info) {
      return FALSE;
    }
    $coords_data = drupal_json_decode($coords);
    $field_coords = $coords_data[$fid];
    foreach ($field_coords as $field_coord) {

      // Check we have coordinates passed and that they are not larger
      // than the image.
      if (!empty($field_coord) && ($field_coord['x'] < 0 || $field_coord['y'] < 0 || $field_coord['x2'] > $info['width'] || $field_coord['y2'] > $info['height'])) {
        return FALSE;
      }
    }
    $affected = db_update('epsacrop_files')
      ->fields(array(
      'coords' => serialize($coords),
    ))
      ->condition('fid', $fid)
      ->execute();
    if ($affected == 0 && _epsacrop_fid_exists($fid) == 0) {
      _epsacrop_add_file($fid, $coords);
    }
    image_path_flush(_epsacrop_get_uri_from_fid($fid));
  }
}

/**
 * Delete the coordonates in the database.
 *
 * @access private
 * @param fid $fid
 * @return void
 */
function _epsacrop_delete_file($fid) {
  db_delete('epsacrop_files')
    ->condition('fid', $fid)
    ->execute();
}

/**
 * Get all coordonates for one file.
 *
 * @access private
 * @param int $fid
 * @return array
 */
function _epsacrop_get_coords_from_fid($fid) {
  $files =& drupal_static(__FUNCTION__);
  if (empty($files[$fid])) {
    $files[$fid] = new stdClass();
    $has_coords = _epsacrop_fid_exists($fid);
    if ($has_coords != 0) {
      $result = db_select('epsacrop_files', 'e')
        ->fields('e', array(
        'coords',
      ))
        ->condition('e.fid', $fid)
        ->execute()
        ->fetchField();
      $files[$fid] = unserialize($result);
    }
    return $files[$fid];
  }
  return $files[$fid];
}

/**
 * Try to find the fid from a uri.
 *
 * @access private
 * @param string $path
 * @return int
 */
function _epsacrop_get_fid_from_uri($uri) {
  $fids =& drupal_static(__FUNCTION__);
  $fids[$uri] = 0;
  if (empty($fids[$uri])) {
    $query = db_select('file_managed', 'f');
    $query
      ->leftjoin('epsacrop_files', 'e', 'e.fid = f.fid');
    $result = $query
      ->fields('f', array(
      'fid',
    ))
      ->condition('f.uri', $uri)
      ->range(0, 1)
      ->execute()
      ->fetchField();
    $fids[$uri] = (int) $result;
  }
  return $fids[$uri];
}

/**
 * Try to get the uri from a fid.
 *
 * @access private
 * @param mixed $fid
 * @return void
 */
function _epsacrop_get_uri_from_fid($fid) {
  if (!empty($fid) && is_numeric($fid)) {
    return (string) db_select('file_managed', 'f')
      ->fields('f', array(
      'uri',
    ))
      ->condition('f.fid', $fid)
      ->range(0, 1)
      ->execute()
      ->fetchField();
  }
  return FALSE;
}

/**
 * Callback for hook_menu.
 *
 * @access public
 * @param mixed $access
 * @return void
 */
function _epsacrop_access() {
  return user_access('epsacrop create crops') || user_access('epsacrop edit all crops');
}

/**
 * Callback for Crop Dialog Ajax.
 *
 * @param string $op
 * @param int $fid
 * @param string $token
 * @return bool
 */
function _epsacrop_ajax_access($op, $fid, $token) {
  return _epsacrop_access() && drupal_valid_token($token, 'epsacrop-' . $op . '-' . $fid);
}

Functions

Namesort descending Description
epsacrop_ajax epsacrop_ajax function.
epsacrop_ajaxinfo epsacrop_ajaxinfo function
epsacrop_crop_dimensions A wrapper around image_resize_dimensions.
epsacrop_crop_image Apply the effect to the image.
epsacrop_crop_image_form Function that provide the effect form settings for dialog crop.
epsacrop_crop_image_reuse Apply the effect to the image on reuse.
epsacrop_crop_image_reuse_form Function that provide the effect form settings for reusing epsa crop.
epsacrop_dialog epsacrop_dialog function.
epsacrop_element_info_alter Implements hook_element_info_alter.
epsacrop_element_process Helper function that add a link in image widget field to open a dialog for the crops.
epsacrop_file_delete Implements hook_file_delete().
epsacrop_form_field_ui_field_edit_form_alter Implements hook_form_FORM_ID_alter().
epsacrop_form_file_entity_edit_alter Implements hook_form_file_entity_edit_alter(). Add epsacrop to file_entity edit form.
epsacrop_form_media_edit_alter Implements hook_form_media_edit_alter(). Add epsacrop to media edit form.
epsacrop_image_default_styles Implements hook_image_default_styles().
epsacrop_image_effect_info Implements hook_image_effect_info.
epsacrop_menu Implements hook_menu.
epsacrop_permission Implements hook_permission.
_epsacrop_access Callback for hook_menu.
_epsacrop_add_file Insert coordonates for one file in the database.
_epsacrop_ajax_access Callback for Crop Dialog Ajax.
_epsacrop_aspect_ratio_validate Validate a aspect ration information.
_epsacrop_delete_file Delete the coordonates in the database.
_epsacrop_fid_exists Check if we've coordonates for one file.
_epsacrop_get_coords_from_fid Get all coordonates for one file.
_epsacrop_get_effect Return the effect issue from the module.
_epsacrop_get_fid_from_uri Try to find the fid from a uri.
_epsacrop_get_style_name_from_url Helper function that get the style name from image url.
_epsacrop_get_uri_from_fid Try to get the uri from a fid.
_epsacrop_height_validate Validate height information.
_epsacrop_include_header_html This function include all files (JavaScript & CSS) needed by the module.
_epsacrop_is_json2_exists Check if json2.js is findable.
_epsacrop_jcrop_get_version Return the version of jcrop library.
_epsacrop_load_style This function load only on style that implement epsacrop effect.
_epsacrop_load_styles Helper function that get all styles with epsacrop effect.
_epsacrop_load_styles_by_instance Get all style that are attach to one instance of field.
_epsacrop_save_coords Save the coordonates in the database.
_epsacrop_width_validate Validate width information.