6 * Dynamic image resizer and image cacher.
8 * Imagecache allows you to setup specialized identifiers for dynamic image
9 * processing and caching. It abuses the rewrite rules used for drupal's clean
10 * URLs to provide dynamic image generation.
12 * Earlier security flaws were overcome by using 'presets' similar to
13 * image.module. We don't fuss with the database, and creating data that we have
14 * to keep up within Drupal. We do it on the fly and flush it when we want to,
15 * or when a preset changes.
17 * URLs are of the form: files/imagecache/<preset>/path
19 * @todo: improve image resizing, reduce distortion.
20 * @todo: add watermarking capabilities.
21 * @todo: split action/handlers into their own little .inc files.
22 * @todo: enforce permissions.
25 * To add a new handler,
26 * add fields and select option to _imagecache_actions_form;
27 * add handling code to imagecache_cache
32 /*********************************************************************************************
34 *********************************************************************************************/
37 * Implementation of hook_perm().
39 function imagecache_perm() {
40 $perms = array('administer imagecache', 'flush imagecache');
41 foreach(imagecache_presets() as
$preset) {
42 $perms[] = 'view imagecache '.
$preset['presetname'];
48 * Implementation of hook_menu().
50 function imagecache_menu($may_cache) {
54 // standard imagecache callback.
56 'path' => file_directory_path() .
'/imagecache',
57 'callback' => 'imagecache_cache',
59 'type' => MENU_CALLBACK
62 // private downloads imagecache callback
64 'path' => 'system/files/imagecache',
65 'callback' => 'imagecache_cache_private',
67 'type' => MENU_CALLBACK
72 'path' => 'admin/settings/imagecache',
73 'title' => t('Image cache'),
74 'description' => t('Configure rulesets and actions for imagecache.'),
75 'access' => user_access('administer imagecache'),
76 'callback' => 'drupal_get_form',
77 'callback arguments' => array('imagecache_admin'),
86 * Implementation of hook_requirements().
88 function imagecache_requirements($phase) {
89 $requirements = array();
90 // Ensure translations don't break at install time.
93 if ($phase == 'runtime') {
94 // Check for an image library.
95 if (count(image_get_available_toolkits()) == 0) {
96 $requirements['clean_urls'] = array(
97 'title' => $t('Image Toolkit'),
98 'value' => $t('No image toolkits available'),
99 'severity' => REQUIREMENT_ERROR
,
100 'description' => $t('Imagecache requires an imagetoolkit such as <a href="http://php.net/gd">GD2</a> or <a href="http://www.imagemagick.org">Imagemagick</a> be installed on your server.'),
103 // Check for JPEG/PNG/GIF support.
104 if ('gd' == image_get_toolkit()) {
105 foreach (array('gif', 'jpeg', 'png') as
$format) {
106 if (!function_exists('imagecreatefrom'.
$format)) {
107 $requirements['gd_'.
$format] = array(
108 'title' => $t('GD !format Support', array('!format' => drupal_ucfirst($format))),
109 'value' => $t('Not installed'),
110 'severity' => REQUIREMENT_INFO
,
111 'description' => $t('PHP was not compiled with %format support. Imagecache will not be able to process %format images.', array('%format' => $format)),
117 return $requirements;
122 * Implementation of hook_imagecache_actions.
125 * An array of information on the actions implemented by a module. The array contains a
126 * sub-array for each action node type, with the machine-readable action name as the key.
127 * Each sub-array has up to 3 attributes. Possible attributes:
129 * "name": the human-readable name of the action. Required.
130 * "description": a brief description of the action. Required.
131 * "file": the name of the include file the action can be found
132 * in relative to the implementing module's path.
134 function imagecache_imagecache_actions() {
136 'imagecache_resize' => array(
138 'description' => 'Resize an image to an exact set of dimensions, ignoring aspect ratio.',
140 'imagecache_scale' => array(
142 'description' => 'Resize an image maintaining the original aspect-ratio (only one value necessary).',
143 'file' => 'imagecache_actions.inc',
145 'imagecache_deprecated_scale' => array(
146 'name' => 'Deprecated Scale',
147 'description' => 'Precursor to Scale and Crop. Has inside and outside dimension support. This action will be removed in Imagecache 2.1).',
148 'file' => 'imagecache_actions.inc',
150 'imagecache_scale_and_crop' => array(
151 'name' => 'Scale And Crop',
152 'description' => 'Resize an image to an exact set of dimensions, ignoring aspect ratio.',
153 'file' => 'imagecache_actions.inc',
155 'imagecache_crop' => array(
157 'description' => 'Crop an image to the rectangle specified by the given offsets and dimensions.',
158 'file' => 'imagecache_actions.inc',
160 'imagecache_desaturate' => array(
161 'name' => 'Desaturate',
162 'description' => 'Convert an image to grey scale.',
163 'file' => 'imagecache_actions.inc',
171 * Pull in actions exposed by other modules using hook_imagecache_actions().
174 * Boolean flag indicating whether the cached data should be
175 * wiped and recalculated.
178 * An array of actions to be used when transforming images.
180 function imagecache_action_definitions($reset = FALSE
) {
182 if (!isset($actions) || $reset) {
183 if (!$reset && ($cache = cache_get('imagecache_actions')) && !empty($cache->data
)) {
184 $actions = unserialize($cache->data
);
187 foreach(module_implements('imagecache_actions') as
$module) {
188 foreach (module_invoke($module, 'imagecache_actions') as
$key => $action) {
189 $action['module'] = $module;
190 if ($action['file']) {
191 $action['file'] = drupal_get_path('module', $action['module']) .
'/'.
$action['file'];
193 $actions[$key] = $action;
196 uasort($actions, '_imagecache_definitions_sort');
197 cache_set('imagecache_actions', 'cache', serialize($actions));
203 function _imagecache_definitions_sort($a, $b) {
209 return ($a < $b) ?
-1 : 1;
212 function imagecache_action_definition($action) {
213 static
$definition_cache;
214 if (!isset($definition_cache[$action])) {
215 $definitions = imagecache_action_definitions();
216 $definition = (isset($definitions[$action])) ?
$definitions[$action] : array();
218 if ($definition && $definition['file']) {
219 require_once($definition['file']);
221 $definition_cache[$action] = $definition;
223 return $definition_cache[$action];
227 * Return a URL that points to the location of a derivative of the
228 * original image at @p $path, transformed with the given @p $preset.
230 function imagecache_create_url($presetname, $path) {
231 $path = _imagecache_strip_file_directory($path);
232 return file_create_url(file_directory_path() .
'/imagecache/'.
$presetname .
'/'.
$path);
236 * Return a file system location that points to the location of a derivative
237 * of the original image at @p $path, transformed with the given @p $preset.
238 * Keep in mind that the image might not yet exist and won't be created.
240 function imagecache_create_path($presetname, $path) {
241 $path = _imagecache_strip_file_directory($path);
242 return file_create_path() .
'/imagecache/'.
$presetname .
'/'.
$path;
246 * Remove a possible leading file directory path from the given path.
248 function _imagecache_strip_file_directory($path) {
249 $dirpath = file_directory_path();
250 $dirlen = strlen($dirpath);
251 if (substr($path, 0, $dirlen + 1) == $dirpath .
'/') {
252 $path = substr($path, $dirlen + 1);
259 * callback for handling public files imagecache requests.
261 function imagecache_cache() {
262 $args = func_get_args();
263 $preset = check_plain(array_shift($args));
264 $path = implode('/', $args);
265 _imagecache_cache($preset, $path);
269 * callback for handling private files imagecache requests
271 function imagecache_cache_private() {
272 $args = func_get_args();
273 $preset = check_plain(array_shift($args));
274 $source = implode('/', $args);
276 if (user_access('view imagecache '.
$preset)) {
277 _imagecache_cache($preset, $source);
280 // if there is a 40333mage uploaded for the preset display it.
281 $accesspath = file_create_path('imagecache/'.
$preset .
'.403.png');
282 if (file_exists($accesspath)) {
283 imagecache_transfer($accesspath);
286 header('HTTP/1.0 403 Forbidden');
292 * handle request validation and responses to imagecache requests.
294 function _imagecache_cache($presetname, $path) {
295 if (!$preset = imagecache_preset_by_name($presetname)) {
296 // send a 404 if we dont' know of a preset.
297 header("HTTP/1.0 404 Not Found");
300 $src = file_create_path($path);
301 if (!is_file($src)) {
302 // if there is a 404 image uploaded for the preset display it.
303 $notfoundpath = file_create_path('imagecache/'.
$preset['presetname'] .
'.404.png');
304 if (file_exists($notfoundpath)) {
305 imagecache_transfer($notfoundpath);
308 // otherwise send a 404.
309 header("HTTP/1.0 404 Not Found");
313 $dst = imagecache_create_path($preset['presetname'], $path);
314 $tmp = file_directory_temp() .
'/'.
$preset['presetname'] .
str_replace(dirname($src) .
'/', '', $src);
316 if (file_exists($tmp)) {
317 watchdog('imagecache', t('Imagecache already generating: %dst, Lock file: %tmp.', array('%dst' => $dst, '%tmp' => $tmp)), WATCHDOG_NOTICE
);
318 // send a response code that will make the browser wait and reload in a 1/2 sec.
323 // check if deriv exists... (file was created between apaches request handler and reaching this code)
324 // otherwise try to create the derivative.
325 if (!file_exists($dst) && !imagecache_build_derivative($preset['actions'], $src, $dst, $tmp)) {
326 // Generate an error if image could not generate.
327 watchdog('imagecache', t('Failed generating an image from %image using imagecache preset %preset.', array('%image' => $path, '%preset' => $preset)), WATCHDOG_ERROR
);
328 header("HTTP/1.0 500 Internal Server Error");
329 // remove lock file on error.
333 imagecache_transfer($dst);
336 function _imagecache_apply_action($action, $image) {
337 $actions = imagecache_action_definitions();
339 if ($definition = imagecache_action_definition($action['action'])) {
340 return call_user_func($action['action'] .
'_image', $image, $action['data']);
342 // skip undefined actions.. module probably got uninstalled or disabled.
343 watchdog('imagecache', t('non-existant action %action', array('%action' => $action['action'])), WATCHDOG_NOTICE
);
348 * helper function to transfer files from imagecache. Determines mime type and sets a last modified header.
349 * @param $path path to file to be transferred.
353 function imagecache_transfer($path) {
354 if (function_exists('mime_content_type')) {
355 $mime = mime_content_type($path);
358 $size = getimagesize($path);
359 $mime = $size['mime'];
361 $headers = array('Content-Type: '.
mime_header_encode($mime));
362 if ($fileinfo = stat($path)) {
363 $headers[] = 'Last-Modified: '.
gmdate('D, d M Y H:i:s', $fileinfo[9]) .
' GMT';
365 file_transfer($path, $headers);
372 function _imagecache_mkdir($dir) {
373 $folders = explode("/", $dir);
375 foreach ($folders as
$folder) {
377 $path = implode("/", $dirs);
381 if (is_file($path)) {
382 watchdog('imagecache', t('file exists where we would like a directory: %path', array('%path' => $path)), WATCHDOG_ERROR
);
385 if (!@
mkdir($path)) {
386 watchdog('imagecache', t('Could not create destination: %dir halted at: %path', array('%dir' => $dir, '%path' => $path)), WATCHDOG_ERROR
);
394 * build an image cache derivative
396 * @param $actions, array of imagecache actions.
397 * @param $source, source file.
398 * @param $dest, $destination file.
399 * @return TRUE - derivative generated, FALSE - no derivative generated, NULL - derivative being generated
401 function imagecache_build_derivative($actions, $src, $dst, $tmp) {
402 // Copy src to tmp. We use the existence of tmp as a lock.
403 if (!file_copy($src, $tmp)) {
404 // can't copy source to temp... ack..
405 watchdog('imagecache', t('Could not create temporary file: %path', array('%path' => $tmp)), WATCHDOG_ERROR
);
409 // get the folder for the final location of this preset...
410 $dir = dirname($dst);
412 // Build the destination folder tree if it doesn't already exists.
413 if (!file_check_directory($dir) && !_imagecache_mkdir($dir)) {
414 watchdog('imagecache', t('Failed to create imagecache directory: %dir', array('%dir' => $dir)), WATCHDOG_ERROR
);
418 foreach ($actions as
$action) {
419 $size = getimagesize($tmp);
420 if (count($action['data'])) {
421 $new_width = _imagecache_filter('width', $action['data']['width'], $size[0], $size[1]);
422 $new_height = _imagecache_filter('height', $action['data']['height'], $size[0], $size[1]);
423 foreach ($action['data'] as
$key => $value) {
424 $action['data'][$key] = _imagecache_filter($key, $value, $size[0], $size[1], $new_width, $new_height);
427 if (!_imagecache_apply_action($action, $tmp)) {
428 watchdog( 'imagecache', t('action(id:%id): %action failed for %src', array('%id' => $action['actionid'], '%action' => $action['action'], '%src' => $src)), WATCHDOG_ERROR
);
432 if (!file_move($tmp, $dst)) {
433 watchdog('imagecache', t('failed to move tmp(%tmp) to dst(%dst)', array('%tmp' => $tmp, '%dst' => $dst)), WATCHDOG_ERROR
);
444 * Implementation of hook_field_formatter_info().
446 function imagecache_field_formatter_info() {
447 foreach (imagecache_presets() as
$preset) {
448 $formatters[$preset['presetname']] = array(
449 'label' => $preset['presetname'],
450 'field types' => array('image'),
452 $formatters[$preset['presetname'] .
'_linked'] = array(
453 'label' => $preset['presetname'] .
' as link',
454 'field types' => array('image'),
461 * Implementation of hook_field_formatter().
463 function imagecache_field_formatter($field, $item, $formatter) {
464 if (!isset($item['fid'])) {
467 // Views does not load the file for us, while CCK display fields does.
468 if (!isset($item['filepath'])) {
469 $file = _imagecache_file_load($item['fid']);
470 $item = array_merge($item, $file);
473 $presetname = preg_replace('/_linked$/', '', $formatter);
474 if ($preset = imagecache_preset_by_name($presetname)) {
475 return theme('imagecache_formatter', $field, $item, $formatter);
479 function _imagecache_file_load($fid = NULL
) {
480 // Don't bother if we weren't passed an fid.
481 if (isset($fid) && is_numeric($fid)) {
482 $result = db_query('SELECT * FROM {files} WHERE fid = %d', $fid);
483 $file = db_fetch_array($result);
485 return ($file) ?
$file : array();
490 * Filter key word values such as 'top', 'right', 'center', and also percentages.
491 * All returned values are in pixels relative to the passed in height and width.
493 function _imagecache_filter($key, $value, $current_width, $current_height, $new_width = NULL
, $new_height = NULL
) {
496 $value = _imagecache_percent_filter($value, $current_width);
499 $value = _imagecache_percent_filter($value, $current_height);
502 $value = _imagecache_keyword_filter($value, $current_width, $new_width);
505 $value = _imagecache_keyword_filter($value, $current_height, $new_height);
512 * Accept a percentage and return it in pixels.
514 function _imagecache_percent_filter($value, $current_pixels) {
515 if (strpos($value, '%') !== FALSE
) {
516 $value = str_replace('%', '', $value) * 0.01 * $current_pixels;
522 * Accept a keyword (center, top, left, etc) and return it as an offset in pixels.
524 function _imagecache_keyword_filter($value, $current_pixels, $new_pixels) {
532 $value = $current_pixels - $new_pixels;
535 $value = $current_pixels/2 - $new_pixels/2;
542 * Recursively delete all files and folders in the specified filepath, then
543 * delete the containing folder.
545 * Note that this only deletes visible files with write permission.
547 * @param string $path
548 * A filepath relative to file_directory_path.
550 function _imagecache_recursive_delete($path) {
551 $listing = $path .
'/*';
552 foreach (glob($listing) as
$file) {
553 if (is_file($file) === TRUE
) {
556 elseif (is_dir($file) === TRUE
) {
557 _imagecache_recursive_delete($file);
563 function _imagecache_action_create($action) {
564 $preset = imagecache_preset($action['presetid']);
565 imagecache_preset_flush($preset);
566 $next_id = db_next_id('{imagecache_action}_actionid');
567 db_query("INSERT INTO {imagecache_action} (actionid, presetid, weight, action, data) VALUES (%d, %d, %d,'%s', '%s')", $next_id, $action['presetid'], $action['weight'], $action['action'], serialize($action['data']));
570 function _imagecache_action_update($action) {
571 $preset = imagecache_preset($action['presetid']);
572 imagecache_preset_flush($preset);
573 db_query("UPDATE {imagecache_action} SET weight=%d, data='%s' WHERE actionid=%d", $action['weight'], serialize($action['data']), $action['actionid']);
576 function _imagecache_action_delete($action) {
577 $preset = imagecache_preset($action['presetid']);
578 imagecache_preset_flush($preset);
579 db_query('DELETE FROM {imagecache_action} WHERE actionid = %d', $action['actionid']);
583 * Theme an img tag for displaying the image.
585 function theme_imagecache_display($node, $label, $url, $attributes) {
586 return '<img src="'.
check_url($url) .
'" alt="'.
check_plain($node->title
) .
'" title="'.
check_plain($node->title
) .
'" '.
drupal_attributes($attributes) .
' />';
590 * Verify the image module and toolkit settings.
592 function _imagecache_check_settings() {
593 // Sanity check : make sure we've got a working toolkit.
594 if (!image_get_toolkit()) {
595 drupal_set_message(t('Make sure you have a working image toolkit installed and enabled, for more information see: %settings.', array('%settings' => l(t('Image toolkit settings'), 'admin/settings/image-toolkit'))), 'error');
602 function theme_imagecache_formatter($field, $item, $formatter) {
603 if (preg_match('/_linked$/', $formatter)) {
604 $formatter = preg_replace('/_linked$/', '', $formatter);
605 $image = theme('imagecache', $formatter, $item['filepath'], $item['alt'], $item['title']);
606 $output = l($image, 'node/'.
$item['nid'], array(), NULL
, NULL
, FALSE
, TRUE
);
609 $output = theme('imagecache', $formatter, $item['filepath'], $item['alt'], $item['title']);
614 function theme_imagecache($namespace, $path, $alt = '', $title = '', $attributes = NULL
) {
615 $attributes = drupal_attributes($attributes);
617 $imagecache_path = imagecache_create_url($namespace, $path);
618 return '<img src="'.
$imagecache_path .
'" alt="'.
check_plain($alt) .
'" title="'.
check_plain($title) .
'" '.
$attributes .
' />';
622 /************************************************************************************
623 * ImageCache action implementation example in module.
625 function imagecache_resize_image($image, $data) {
626 if (!image_resize($image, $image, $data['width'], $data['height'])) {
627 watchdog('imagecache', t('imagecache_resize_image failed. image: %image, data: %data.', array('%path' => $image, '%data' => print_r($data, TRUE
))), WATCHDOG_ERROR
);
633 function imagecache_resize_form($action) {
634 $form['width'] = array(
635 '#type' => 'textfield',
636 '#title' => t('Width'),
637 '#default_value' => $action['width'],
638 '#description' => t('Enter a width in pixels or as a percentage. i.e. 500 or 80%.'),
640 $form['height'] = array(
641 '#type' => 'textfield',
642 '#title' => t('Height'),
643 '#default_value' => $action['height'],
644 '#description' => t('Enter a height in pixels or as a percentage. i.e. 500 or 80%.'),
649 function theme_imagecache_resize($element) {
650 $data = $element['#value'];
651 return 'width: '.
$data['width'] .
', height: '.
$data['height'];
659 * The API for imagecache has changed. There is a compatibility layer for
660 * imagecache 1.x. Please see the imagecache_compat.module
662 * The 2.x API returns more structured data, has shorter function names, and
663 * implements more aggressive metadata caching.
668 * Get an array of all presets and their settings.
671 * if set to true it will clear the preset cache
674 * array of presets array( $preset_id => array('presetid' => integer, 'presetname' => string))
676 function imagecache_presets($reset = FALSE
) {
677 static
$presets = array();
679 // Clear caches if $reset is TRUE;
682 cache_clear_all('imagecache:presets', 'cache');
684 // Clear the content.module cache (refreshes the list of formatters provided by imagefield.module).
685 if (module_exists('content')) {
686 content_clear_type_cache();
689 // Return presets if the array is populated.
690 if (!empty($presets)) {
694 // Grab from cache or build the array.
695 if ($cache = cache_get('imagecache:presets', 'cache')) {
696 $presets = unserialize($cache->data
);
699 $result = db_query('SELECT * FROM {imagecache_preset} ORDER BY presetname');
700 while ($preset = db_fetch_array($result)) {
701 $presets[$preset['presetid']] = $preset;
702 $presets[$preset['presetid']]['actions'] = imagecache_preset_actions($preset);
704 cache_set('imagecache:presets', 'cache', serialize($presets));
710 * Load a preset by preset_id.
713 * The numeric id of a preset.
716 * preset array( 'presetname' => string, 'presetid' => integet)
717 * empty array if preset_id is an invalid preset
719 function imagecache_preset($preset_id, $reset = FALSE
) {
720 $presets = imagecache_presets($reset);
721 return (isset($presets[$preset_id])) ?
$presets[$preset_id] : array();
725 * Load a preset by name.
730 * preset array( 'presetname' => string, 'presetid' => integer)
731 * empty array if preset_name is an invalid preset
734 function imagecache_preset_by_name($preset_name) {
735 static
$presets_by_name = array();
736 if (!$presets_by_name && $presets = imagecache_presets()) {
737 foreach ($presets as
$preset) {
738 $presets_by_name[$preset['presetname']] = $preset;
741 return (isset($presets_by_name[$preset_name])) ?
$presets_by_name[$preset_name] : array();
745 * Save an ImageCache preset.
748 * an imagecache preset array.
750 * a preset array. In the case of a new preset, 'presetid' will be populated.
752 function imagecache_preset_save($preset) {
753 // @todo: CRUD level validation?
754 if (isset($preset['presetid']) && is_numeric($preset['presetid'])) {
755 db_query('UPDATE {imagecache_preset} SET presetname =\'%s\' WHERE presetid = %d', $preset['presetname'], $preset['presetid']);
758 $preset['presetid'] = db_next_id('{imagecache_preset}_presetid');
759 db_query('INSERT INTO {imagecache_preset} (presetid, presetname) VALUES (%d, \'%s\')', $preset['presetid'], $preset['presetname']);
762 // Reset presets cache.
763 imagecache_preset_flush($preset);
764 imagecache_presets(TRUE
);
768 function imagecache_preset_delete($preset) {
769 imagecache_preset_flush($preset['presetid']);
770 db_query('DELETE FROM {imagecache_action} where presetid = %d', $preset['presetid']);
771 db_query('DELETE FROM {imagecache_preset} where presetid = %d', $preset['presetid']);
772 imagecache_presets(TRUE
);
776 function imagecache_preset_actions($preset, $reset = FALSE
) {
777 static
$actions_cache = array();
779 if ($reset || empty($actions_cache[$preset['presetid']])) {
780 $result = db_query('SELECT * FROM {imagecache_action} where presetid = %d order by weight', $preset['presetid']);
781 while ($row = db_fetch_array($result)) {
782 $row['data'] = unserialize($row['data']);
783 $actions_cache[$preset['presetid']][] = $row;
787 return isset($actions_cache[$preset['presetid']]) ?
$actions_cache[$preset['presetid']] : array();
791 * Flush cached media for a preset.
795 function imagecache_preset_flush($preset) {
796 if (user_access('flush imagecache')) {
797 $presetdir = realpath(file_directory_path() .
'/imagecache/'.
$preset['presetname']);
798 if (is_dir($presetdir)) {
799 _imagecache_recursive_delete($presetdir);
805 * Clear cached versions of a specific file in all presets.
807 * The Drupal file path to the original image.
809 function imagecache_image_flush($path) {
810 foreach (imagecache_presets() as
$preset) {
811 $ipath = file_directory_path() .
'/imagecache/'.
$preset['presetname'] .
'/'.
$path;
816 function imagecache_action($actionid) {
819 if (!isset($actions[$actionid])) {
822 $result = db_query('SELECT * FROM {imagecache_action} WHERE actionid=%d', $actionid);
823 if ($row = db_fetch_array($result)) {
825 $action['data'] = unserialize($action['data']);
827 $definition = imagecache_action_definition($action['action']);
828 $action = array_merge($definition, $action);
829 $actions[$actionid] = $action;
832 return $actions[$actionid];
835 function imagecache_action_save($action) {
836 if ($action['actionid']) {
837 db_query("UPDATE {imagecache_action} SET weight=%d, data='%s' WHERE actionid=%d", $action['weight'], serialize($action['data']), $action['actionid']);
840 $action['actionid'] = db_next_id('{imagecache_action}_actionid');
841 db_query("INSERT INTO {imagecache_action} (actionid, presetid, weight, action, data) VALUES (%d, %d, %d,'%s', '%s')", $action['actionid'], $action['presetid'], $action['weight'], $action['action'], serialize($action['data']));
843 $preset = imagecache_preset($action['presetid']);
844 imagecache_preset_flush($preset);
845 imagecache_presets(TRUE
);
849 function imagecache_action_delete($action) {
850 db_query("DELETE FROM {imagecache_action} WHERE actionid=%d", $action['actionid']);
851 $preset = imagecache_preset($action['presetid']);
852 imagecache_preset_flush($preset);
853 imagecache_presets(TRUE
);
858 * Imagecache 1.x Compatability Wrappers
862 * Several functions got renamed in the 2.x upgrade. The following wrapper
863 * functions are available for compatability sake. They will be removed in
869 * Legacy get_presets function superceeded by imagecache_presets
874 * array of presets in presetid => presetname format.
876 function _imagecache_get_presets($reset = FALSE
) {
877 static
$compat_presets = array();
880 $compat_presets = array();
883 if (empty($compat_presets)) {
884 if ($presets = imagecache_presets($reset)) {
885 foreach ($presets as
$preset) {
886 $compat_preset[$preset['presetid']] = $preset['name'];
890 return $compat_presets;
894 * Load a preset by id.
898 function _imagecache_preset_load($id) {
899 return imagecache_preset($id);
903 * Load a preset by name.
907 function _imagecache_preset_load_by_name($name) {
908 return imagecache_preset_by_name($name);
914 * Name of the preset to be created.
916 function _imagecache_preset_create($name) {
917 $preset = array('presetname' => $name);
918 return imagecache_preset_save($preset);
926 * new name for the preset
928 function _imagecache_preset_update($id, $name) {
929 $preset = array('presetid' => $id, 'presetname' => $name);
930 $return = imagecache_preset_save($preset);
931 drupal_set_message(t('Updated preset "%name" (ID: @id)', array('%name' => $name, '@id' => $id)));
936 function _imagecache_preset_delete($id, $name) {
937 $preset = array('presetid' => $id, 'presetname' => $name);
938 $return = imagecache_preset_delete($preset);
939 drupal_set_message(t('Preset "%name" (ID: @id) deleted.', array('%name' => $name, '@id' => $id)));
943 function _imagecache_actions_get_by_presetid($presetid) {
944 $presets = imagecache_presets();
945 return (isset($presets[$presetid]['actions'])) ?
$presets[$presetid]['actions'] : array();
948 function _imagecache_preset_flush($id) {
949 $preset = imagecache_preset($id);
950 imagecache_preset_flush($preset);
951 drupal_set_message(t('Preset "%name" (ID: @id) flushed.', array('%name' => $preset['presetname'], '@id' => $preset['presetid'])));