epsacrop.module in EPSA Crop - Image Cropping 6
Same filename and directory in other branches
The main file of module
File
epsacrop.moduleView source
<?php
/**
* @file
* The main file of module
*/
//JCrop & json2 Path
if (module_exists('libraries') && file_exists(libraries_get_path('Jcrop') . '/js/jquery.Jcrop.min.js') && file_exists(libraries_get_path('json2') . '/json2.js')) {
define('EPSACROP_JCROP_PATH', libraries_get_path('Jcrop'));
define('EPSACROP_JSON2_PATH', libraries_get_path('json2'));
}
else {
$base = 'sites/all/libraries';
if (file_exists($base . '/Jcrop/js/jquery.Jcrop.min.js') && file_exists($base . '/json2/json2.js')) {
define('EPSACROP_JCROP_PATH', $base . '/Jcrop');
define('EPSACROP_JSON2_PATH', $base . '/json2');
}
else {
$path_module = drupal_get_path('module', 'epsacrop');
define('EPSACROP_JCROP_PATH', $path_module . '/Jcrop');
define('EPSACROP_JSON2_PATH', $path_module . '/json2');
}
}
/**
* Implements hook_init
*
* @access public
* @return void
*/
function epsacrop_init() {
$paths = variable_get('epsacrop_paths', "node/add\nnode/add/*\nuser/*/edit/profile\nuser/register\nadmin/user/user/create");
$path = drupal_get_path_alias($_GET['q']);
// Compare with the internal and path alias (if any).
$page_match = drupal_match_path($path, $paths);
if ($path != $_GET['q']) {
$page_match = $page_match || drupal_match_path($_GET['q'], $paths);
}
if ($page_match) {
_epsacrop_include_html();
}
}
function _epsacrop_include_html() {
static $included = FALSE;
if ($included === FALSE) {
$path_module = drupal_get_path('module', 'epsacrop');
drupal_add_js(array(
'epsacrop' => array(
'base' => base_path(),
'path' => $path_module,
),
), 'setting');
jquery_ui_add(array(
'ui.dialog',
));
drupal_add_js(EPSACROP_JCROP_PATH . '/js/jquery.Jcrop.min.js');
drupal_add_js(EPSACROP_JSON2_PATH . '/json2.js');
drupal_add_js($path_module . '/js/epsacrop.js');
// We try to use the theme from jquery_ui module
if (function_exists('jquery_ui_get_path')) {
$css_path = jquery_ui_get_path() . '/themes/base/ui.all.css';
if (!file_exists($css_path)) {
$css_path = jquery_ui_get_path() . '/themes/default/ui.all.css';
}
drupal_add_css($css_path);
}
else {
drupal_add_css(drupal_get_path('module', 'jquery_ui') . '/jquery.ui/themes/default/ui.all.css');
}
drupal_add_css(EPSACROP_JCROP_PATH . '/css/jquery.Jcrop.css');
drupal_add_css($path_module . '/css/epsacrop.css');
$included = TRUE;
}
}
/**
* Implementation of hook_menu
*/
function epsacrop_menu() {
$items = array();
$items['crop/dialog/%/%'] = array(
'title' => 'Dialog Crop',
'page callback' => 'epsacrop_dialog',
'page arguments' => array(
2,
3,
),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
$items['admin/settings/epsacrop'] = array(
'title' => 'EPSA Crop',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'epsacrop_settings',
),
'access arguments' => array(
'administer site configuration',
),
);
return $items;
}
function epsacrop_settings(&$form_state) {
$form = array();
$form['epsacrop_box_size'] = array(
'#type' => 'textfield',
'#title' => t("Box Size"),
'#default_value' => variable_get('epsacrop_box_size', '512x384'),
'#description' => t("Size for admin thumbnail"),
);
$form['epsacrop_paths'] = array(
'#type' => 'textarea',
'#title' => t("Paths"),
'#default_value' => variable_get('epsacrop_paths', "node/add\nnode/add/*\nuser/*/edit/profile\nuser/register\nadmin/user/user/create"),
'#description' => t("Some modules don't use the conventional path to add node (content profile, etc.) this part its to add path where EPSACrop have to add the header files."),
);
return system_settings_form($form);
}
/**
* Implementation of hook_menu_alter
*/
function epsacrop_menu_alter(&$items) {
$items[file_directory_path() . '/imagecache']['page callback'] = 'epsacrop_crop';
$items[file_directory_path() . '/imagecache']['module'] = 'epsacrop';
$items['system/files/imagecache']['page callback'] = 'epsacrop_crop_private';
$items['system/files/imagecache']['module'] = 'epsacrop';
}
/**
* Callback function for Dialog popup.
*
* @param string $type_name
* Content type machine name, e.g. 'page'.
* @param string $field_name
* CCK imagefield name, e.g. 'field_image'.
*
*/
function epsacrop_dialog($type_name, $field_name) {
$args = func_get_args();
$out = '<div class="epsacrop-global">' . "\n";
$out .= '<div class="epsacrop-image-crop">' . "\n";
$out .= '<img src="_blank" id="epsacrop-target" />' . "\n";
$out .= '</div>' . "\n";
$out .= '<div class="epsacrop-presets-menu">' . "\n";
$out .= '<ul class="epsacrop-presets-menu-ul">' . "\n";
$i = 0;
$crop_actions = _epsacrop_get_field_actions($type_name, $field_name);
foreach ($crop_actions as $action) {
$id = 'epsacrop-' . $action['presetname'];
$out .= '<li class="epsacrop-presets-menu-li"><a id="' . $id . '" href="javascript:Drupal.EPSACrop.crop(\'' . $id . '\');" rel="' . $action['width'] . 'x' . $action['height'] . '"' . ($i == 0 ? ' class="selected"' : '') . '>' . $action['presetname'] . '</a></li>';
$i++;
}
$out .= '</ul>' . "\n";
$out .= '</div>' . "\n";
$out .= '<br style="clear:both;" />' . "\n";
$out .= '</div>' . "\n";
$GLOBALS['devel_shutdown'] = FALSE;
echo $out;
exit;
}
/*
* Implementation of nodeapi hook
*/
function epsacrop_nodeapi(&$node, $op, $a3, $a4) {
switch ($op) {
case 'delete':
_epsacrop_delete($node->nid);
break;
case 'insert':
case 'update':
if (!empty($node->epsacropcoords)) {
$coords = json_decode($node->epsacropcoords, TRUE);
$previous_data = FALSE;
if ($node->nid) {
// If node exists (op=update) get previous cropping data.
$previous_data = _epsacrop_get_coords_from_nid($node->nid);
}
foreach ($coords as $fid => $coord) {
// Skip file update for the files that the cropping area haven't changed for any of the presets.
if (!empty($previous_data) && strcmp(serialize($coord), serialize($previous_data[$fid])) == 0) {
continue;
}
_epsacrop_update_file($fid, $coord, $node->nid);
}
}
break;
case 'load':
// Add this when it required (for example, when editablefields exists)
if (module_exists('editablefields')) {
$node->epsacropcoords = _epsacrop_get_coords_from_nid($node->nid) ? json_encode(_epsacrop_get_coords_from_nid($node->nid)) : NULL;
}
break;
case 'prepare':
if ($node->nid) {
$node->epsacropcoords = _epsacrop_get_coords_from_nid($node->nid) ? json_encode(_epsacrop_get_coords_from_nid($node->nid)) : NULL;
}
break;
}
}
/*
* Implementation of form_alter hook
* The function add a hidden textarea for information transit between dialog popup and php
*/
function epsacrop_form_alter(&$form, $form_state, $form_id) {
if (preg_match('/_node_form/i', $form_id) || $form_id == 'editablefields_form') {
$form['#after_build'][] = '_epsacrop_form_after_build';
$node = $form['#node'];
if (empty($node) && is_array($form['#parameters'])) {
foreach ($form['#parameters'] as $param) {
if (is_object($param) && !empty($param->nid)) {
$node = $param;
break;
}
}
}
$form['epsacropcoords'] = array(
'#type' => 'textarea',
'#default_value' => !empty($node->epsacropcoords) ? $node->epsacropcoords : '',
'#prefix' => '<div id="edit-epsacropcoords-wrapper">',
'#suffix' => '</div>',
'#wysiwyg' => FALSE,
);
}
}
/*
* Return version of Jcrop plugin and make sure that exists
*/
function epsacrop_jcrop_get_version() {
$vresion = 0;
if (file_exists(EPSACROP_JCROP_PATH . '/js/jquery.Jcrop.js')) {
$lines = file(EPSACROP_JCROP_PATH . '/js/jquery.Jcrop.js');
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, check your install'), 'error');
$version = 0;
}
}
return $version;
}
/**
* Add scripts and styles on a node edit page.
*/
function _epsacrop_form_after_build($form_element, &$form_state) {
_epsacrop_include_html();
return $form_element;
}
/*
* Check if json2.js exists
*/
function _epsacrop_is_json2_exists() {
if (file_exists(EPSACROP_JSON2_PATH . '/json2.js')) {
return TRUE;
}
drupal_set_message(t('Could be find the json2.js file, check your install'), 'error');
return FALSE;
}
/*
* Check if epsacrop has references
*/
function _epsacrop_fid_exists($fid) {
return db_result(db_query('SELECT COUNT(fid) FROM {epsacrop_files} WHERE fid = %d', $fid));
}
function _epsacrop_add_file($fid, $coords, $nid) {
db_query("INSERT INTO {epsacrop_files}(fid, coords, nid) VALUES(%d, '%s', %d)", $fid, serialize($coords), $nid);
}
function _epsacrop_update_file($fid, $coords, $nid) {
db_query("UPDATE {epsacrop_files} SET coords = '%s', nid = %d WHERE fid = %d", serialize($coords), $nid, $fid);
if (db_affected_rows() == 0 && _epsacrop_fid_exists($fid) == 0) {
_epsacrop_add_file($fid, $coords, $nid);
}
$filepath = _epsacrop_get_path_from_fid($fid);
imagecache_image_flush($filepath);
}
function _epsacrop_delete_file($fid) {
db_query('DELETE FROM {epsacrop_files} WHERE fid = %d', $fid);
}
function _epsacrop_delete($nid) {
db_query('DELETE FROM {epsacrop_files} WHERE nid = %d', $nid);
}
function _epsacrop_get_coords_from_nid($nid, $reset = FALSE) {
static $nodes = array();
if (empty($nodes[$nid]) || $reset == TRUE) {
$nodes[$nid] = array();
$result = db_query('SELECT fid, coords FROM {epsacrop_files} WHERE nid = %d', $nid);
while ($res = db_fetch_array($result)) {
$nodes[$nid][$res['fid']] = unserialize($res['coords']);
}
return $nodes[$nid];
}
return $nodes[$nid];
}
function _epsacrop_get_coords_from_fid($fid) {
static $files = array();
if (empty($files[$fid])) {
$files[$fid] = array();
$result = db_query('SELECT coords FROM {epsacrop_files} WHERE fid = %d', $fid);
$has_coords = db_result(db_query('SELECT COUNT(*) FROM {epsacrop_files} WHERE fid = %d', $fid));
if ($has_coords != 0) {
$files[$fid] = unserialize(db_result($result));
}
return empty($files[$fid]) ? FALSE : $files[$fid];
}
return $files[$fid];
}
function _epsacrop_get_crop_action($preset) {
foreach ($preset['actions'] as $action) {
if (strpos($action['action'], 'crop') !== FALSE) {
return $action['data'];
}
}
}
function _epsacrop_get_fid_from_path($path) {
static $fids = array();
$fids[$path] = 0;
if (empty($fids[$path])) {
$fids[$path] = (int) db_result(db_query_range("SELECT f.fid FROM {files} f LEFT JOIN {epsacrop_files} e ON e.fid = f.fid WHERE f.filepath = '%s' AND e.fid IS NOT NULL", $path, 0, 1));
}
return $fids[$path];
}
function _epsacrop_get_path_from_fid($fid) {
if (!empty($fid) && is_numeric($fid)) {
return (string) db_result(db_query_range("SELECT filepath FROM {files} WHERE fid = %d", $fid, 0, 1));
}
return FALSE;
}
function _epsacrop_create_thumb($source, $destination) {
if (!is_file($source)) {
return FALSE;
}
$info = image_get_info($source);
$size = explode('x', variable_get('epsacrop_box_size', '512x384'));
if (is_file($destination)) {
$thumb = image_get_info($destination);
if ($thumb['width'] != $size[0] && $thumb['height'] != $size[1] && ($info['width'] > $size[0] || $info['height'] > $size[1])) {
unlink($destination);
}
else {
return;
}
}
$directories = explode('/', $destination);
array_pop($directories);
$file_system = file_directory_path();
foreach ($directories as $directory) {
$full_path = isset($full_path) ? $full_path . '/' . $directory : $directory;
if (strpos($full_path, $file_system) === 0) {
field_file_check_directory($full_path, FILE_CREATE_DIRECTORY);
}
}
if ($info['width'] <= $size[0] && $info['height'] <= $size[1]) {
file_copy($source, $destination);
}
elseif (image_get_toolkit() && @image_scale($source, $destination, $size[0], $size[1])) {
@chmod($destination, 0644);
}
else {
drupal_set_message(t("An image thumbnail was not able to be created."), 'error');
}
}
function _epsacrop_thumb_filepath($filepath, $create = TRUE) {
if (empty($filepath)) {
return FALSE;
}
$short_path = preg_replace('/^' . preg_quote(file_directory_path(), '/') . '/', '', $filepath);
$dest = file_directory_path() . '/epsacrop_thumbs' . $short_path;
if ($create) {
_epsacrop_create_thumb($filepath, $dest);
}
return $dest;
}
/**
* Implementation of hook_theme
* permet d'overider la fonction de imagefield afin d'ajouter le lien pour
* gérer le crop
*/
function epsacrop_theme($existing, $type, $theme, $path) {
$widget = $existing['imagefield_widget_item'];
$widget['function'] = 'theme_epsacrop_widget_item';
$widget['theme paths'][] = $path;
/*
$imagecache = $existing['imagecache'];
$imagecache['function'] = 'theme_epsacrop';
$imagecache['theme paths'][] = $path;
*/
// return array('imagefield_widget_item' => $widget, 'imagecache' => $imagecache);
return array(
'imagefield_widget_item' => $widget,
);
}
/**
* fonction theme qui ajouter le lien gérer le crop
*/
function theme_epsacrop_widget_item($element) {
$type_name = $element['#type_name'];
$field_name = $element['#field_name'];
if ((int) $element['fid']['#value'] > 0 && count(_epsacrop_get_field_actions($type_name, $field_name))) {
$fid = (int) $element['fid']['#value'];
$filepath = _epsacrop_get_path_from_fid($fid);
if (!empty($filepath)) {
global $base_root;
$info = @getimagesize('./' . $filepath);
$filepath = _epsacrop_thumb_filepath($filepath);
$element['epsacrop'] = array(
'#type' => 'markup',
'#value' => '[<a rel="nozoom" class="modalframe-exclude" href="javascript:Drupal.EPSACrop.dialog(\'' . $type_name . '\', \'' . $field_name . '\', \'' . $element['fid']['#value'] . '\', \'' . $base_root . base_path() . addslashes($filepath) . '\', [' . $info[0] . ', ' . $info[1] . ']);">' . t("Manage image crops") . '</a>]',
);
}
}
return theme('filefield_widget_item', $element);
}
/**
* callback for handling public files imagecache requests.
*/
function epsacrop_crop() {
$args = func_get_args();
$preset = check_plain(array_shift($args));
$path = implode('/', $args);
_epsacrop_crop($preset, $path);
}
/**
* callback for handling private files imagecache requests
*/
function epsacrop_crop_private() {
$args = func_get_args();
$preset = check_plain(array_shift($args));
$source = implode('/', $args);
if (user_access('view imagecache ' . $preset) && !in_array(-1, module_invoke_all('file_download', $source))) {
_epsacrop_crop($preset, $source);
}
else {
// if there is a 403 image, display it.
$accesspath = file_create_path('imagecache/' . $preset . '.403.png');
if (is_file($accesspath)) {
imagecache_transfer($accesspath);
exit;
}
header('HTTP/1.0 403 Forbidden');
exit;
}
}
/**
* Copy of imagecache function
*/
function _epsacrop_crop($presetname, $path) {
if (!($preset = imagecache_preset_by_name($presetname))) {
// Send a 404 if we don't know of a preset.
header("HTTP/1.0 404 Not Found");
exit;
}
// umm yeah deliver it early if it is there. especially useful
// to prevent lock files from being created when delivering private files.
$dst = imagecache_create_path($preset['presetname'], $path);
if (is_file($dst)) {
imagecache_transfer($dst);
}
// preserve path for watchdog.
$src = $path;
// Check if the path to the file exists.
if (!is_file($src) && !is_file($src = file_create_path($src))) {
watchdog('imagecache', '404: Unable to find %image ', array(
'%image' => $src,
), WATCHDOG_ERROR);
header("HTTP/1.0 404 Not Found");
exit;
}
// Bail if the requested file isn't an image you can't request .php files
// etc...
if (!getimagesize($src)) {
watchdog('imagecache', '403: File is not an image %image ', array(
'%image' => $src,
), WATCHDOG_ERROR);
header('HTTP/1.0 403 Forbidden');
exit;
}
$lockfile = file_directory_temp() . '/' . $preset['presetname'] . basename($src);
if (file_exists($lockfile)) {
watchdog('imagecache', 'ImageCache already generating: %dst, Lock file: %tmp.', array(
'%dst' => $dst,
'%tmp' => $lockfile,
), WATCHDOG_NOTICE);
// 307 Temporary Redirect, to myself. Lets hope the image is done next time around.
header('Location: ' . request_uri(), TRUE, 307);
exit;
}
touch($lockfile);
// register the shtdown function to clean up lock files. by the time shutdown
// functions are being called the cwd has changed from document root, to
// server root so absolute paths must be used for files in shutdown functions.
register_shutdown_function('file_delete', realpath($lockfile));
// Apply our actions for the crop
$data = _epsacrop_get_crop_action($preset);
$_preset = 'epsacrop-' . $presetname;
$fid = _epsacrop_get_fid_from_path($src);
$coords = _epsacrop_get_coords_from_fid($fid);
if (!empty($coords[$_preset])) {
$saved_actions = $preset['actions'];
$epsacrop_crop = array(
'actionid' => -1,
'presetid' => -1,
'weight' => -99,
'module' => 'imagecache',
'action' => 'imagecache_crop',
'data' => array(
'width' => $coords[$_preset]['w'],
'height' => $coords[$_preset]['h'],
'xoffset' => $coords[$_preset]['x'],
'yoffset' => $coords[$_preset]['y'],
),
);
$epsacrop_resize = array(
'actionid' => -1,
'presetid' => -1,
'weight' => -98,
'module' => 'imagecache',
'action' => 'imagecache_resize',
'data' => array(
'width' => $data['width'],
'height' => $data['height'],
),
);
// Remove crop action on actual actions
foreach ($saved_actions as $key => $action) {
if (preg_match('/_crop$/', $action['action'])) {
unset($saved_actions[$key]);
}
}
$preset['actions'] = array_merge(array(
$epsacrop_crop,
$epsacrop_resize,
), $saved_actions);
}
// check if deriv exists... (file was created between apaches request handler and reaching this code)
// otherwise try to create the derivative.
if (file_exists($dst) || imagecache_build_derivative($preset['actions'], $src, $dst)) {
imagecache_transfer($dst);
}
// Generate an error if image could not generate.
watchdog('imagecache', 'Failed generating an image from %image using imagecache preset %preset.', array(
'%image' => $path,
'%preset' => $preset['presetname'],
), WATCHDOG_ERROR);
header("HTTP/1.0 500 Internal Server Error");
exit;
}
/**
*Helper function for returning only imagecache preset actions with croping.
*/
function _epsacrop_get_crop_actions() {
$actions = array();
$presets = imagecache_presets();
foreach ($presets as $preset) {
foreach ($preset['actions'] as $action) {
if (strpos($action['action'], 'crop') !== FALSE) {
$actions[] = array(
'presetname' => $preset['presetname'],
'width' => $action['data']['width'],
'height' => $action['data']['height'],
);
}
}
}
return $actions;
}
/**
*Helper function for returning simple array with only imagecache preset actions with croping.
*/
function _epsacrop_get_crop_presets() {
$actions = _epsacrop_get_crop_actions();
$presets = array();
foreach ($actions as $preset) {
$presets[$preset['presetname']] = $preset['presetname'];
}
return $presets;
}
/**
* Helper function for returning only imagecache preset actions with croping that was enabled for specific field.
*
* @param string $type_name
* Content type machine name, e.g. 'page'.
* @param string $field_name
* CCK imagefield name, e.g. 'field_image'.
*
* @return Structured array, e.g.:
* array(
* 0 => array(
* 'presetname' => 'presetname',
* 'width' => 400,
* 'height' => 300,
* ),
* 1 => ...
* )
*/
function _epsacrop_get_field_actions($type_name, $field_name) {
$actions = _epsacrop_get_crop_actions();
$content_type = content_types($type_name);
$presets = $content_type['fields'][$field_name]['widget']['epsacrop_presets'];
if (!$presets['dont_show']) {
if (!empty($presets) && is_array($presets)) {
$presets = array_flip($presets);
foreach ($actions as $key => $action) {
if (!array_key_exists($action['presetname'], $presets)) {
unset($actions[$key]);
}
}
}
// Here we gonna strip the px after height and with
$_actions = array();
foreach ($actions as $key => $action) {
$_actions[$key] = array(
'presetname' => $action['presetname'],
'height' => (int) preg_replace('/[^0-9]+/', '', $action['height']),
'width' => (int) preg_replace('/[^0-9]+/', '', $action['width']),
);
}
}
return $_actions;
}
/**
* Implementation of hook_widget_settings_alter().
*/
function epsacrop_widget_settings_alter(&$settings, $op, $widget) {
$widget_type = isset($widget['widget_type']) ? $widget['widget_type'] : $widget['type'];
// Alter only imagefied_widget
if (!stristr($widget_type, 'imagefield_widget')) {
return;
}
// Add our new options to the list of settings to be saved.
if ($op == 'save') {
$settings = array_merge($settings, array(
'epsacrop_presets',
));
}
// Add the additional settings to the form.
$presets['dont_show'] = t("Don't show.");
$presets += _epsacrop_get_crop_presets();
if ($op == 'form') {
$settings['epsacrop'] = array(
'#type' => 'fieldset',
'#title' => t('EPSA Crop'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#description' => t('These options allow the user to pick imagecache presets that would be available to crop.'),
'#weight' => 15,
);
$settings['epsacrop']['epsacrop_presets'] = array(
'#title' => t('Imagecache presets'),
'#type' => 'checkboxes',
'#default_value' => $widget['epsacrop_presets'] != NULL ? $widget['epsacrop_presets'] : array(),
'#options' => $presets,
'#description' => t('Only presets utilising crop filter are available'),
);
}
}
Functions
Name![]() |
Description |
---|---|
epsacrop_crop | callback for handling public files imagecache requests. |
epsacrop_crop_private | callback for handling private files imagecache requests |
epsacrop_dialog | Callback function for Dialog popup. |
epsacrop_form_alter | |
epsacrop_init | Implements hook_init |
epsacrop_jcrop_get_version | |
epsacrop_menu | Implementation of hook_menu |
epsacrop_menu_alter | Implementation of hook_menu_alter |
epsacrop_nodeapi | |
epsacrop_settings | |
epsacrop_theme | Implementation of hook_theme permet d'overider la fonction de imagefield afin d'ajouter le lien pour gérer le crop |
epsacrop_widget_settings_alter | Implementation of hook_widget_settings_alter(). |
theme_epsacrop_widget_item | fonction theme qui ajouter le lien gérer le crop |
_epsacrop_add_file | |
_epsacrop_create_thumb | |
_epsacrop_crop | Copy of imagecache function |
_epsacrop_delete | |
_epsacrop_delete_file | |
_epsacrop_fid_exists | |
_epsacrop_form_after_build | Add scripts and styles on a node edit page. |
_epsacrop_get_coords_from_fid | |
_epsacrop_get_coords_from_nid | |
_epsacrop_get_crop_action | |
_epsacrop_get_crop_actions | Helper function for returning only imagecache preset actions with croping. |
_epsacrop_get_crop_presets | Helper function for returning simple array with only imagecache preset actions with croping. |
_epsacrop_get_fid_from_path | |
_epsacrop_get_field_actions | Helper function for returning only imagecache preset actions with croping that was enabled for specific field. |
_epsacrop_get_path_from_fid | |
_epsacrop_include_html | |
_epsacrop_is_json2_exists | |
_epsacrop_thumb_filepath | |
_epsacrop_update_file |