imagecache_customactions.module 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. <?php
  2. /**
  3. * @file Allows advanced users to code their own PHP image manipulation routines
  4. * as part of image style processing.
  5. *
  6. * @author Originally contributed by crea https://drupal.org/node/325103#comment-
  7. * 1076011
  8. *
  9. * @author merged into imagecache_actions by dman http://coders.co.nz
  10. *
  11. * custom action effect:
  12. * @todo: add description field that editors can use to define their own summary?
  13. * @todo: add form field asking if dimensions stay the same (or if the new dimensions are known).
  14. * subroutine effect:
  15. * @todo: use isid to allow for image style renaming, but also use name to allow export and import (features)
  16. */
  17. /**
  18. * Implements hook_image_effect_info().
  19. *
  20. * Defines information about the supported effects.
  21. */
  22. function imagecache_customactions_image_effect_info() {
  23. $effects = array();
  24. $effects['imagecache_customactions'] = array(
  25. 'label' => t('Custom action'),
  26. 'help' => t('Runs custom PHP code.'),
  27. 'effect callback' => 'imagecache_customactions_effect',
  28. 'dimensions callback' => 'imagecache_customactions_dimensions',
  29. 'form callback' => 'imagecache_customactions_form',
  30. 'summary theme' => 'imagecache_customactions_summary',
  31. );
  32. $effects['imagecache_subroutine'] = array(
  33. 'label' => t('Subroutine'),
  34. 'help' => t('Runs another defined preset on the image.'),
  35. 'effect callback' => 'imagecache_subroutine_effect',
  36. 'dimensions callback' => 'imagecache_subroutine_dimensions',
  37. 'form callback' => 'imagecache_subroutine_form',
  38. 'summary theme' => 'imagecache_subroutine_summary',
  39. );
  40. return $effects;
  41. }
  42. /**
  43. * Implements hook_theme().
  44. *
  45. * Registers theme functions for the effect summaries.
  46. */
  47. function imagecache_customactions_theme() {
  48. return array(
  49. 'imagecache_customactions_summary' => array(
  50. 'variables' => array('data' => NULL),
  51. ),
  52. 'imagecache_subroutine_summary' => array(
  53. 'variables' => array('data' => NULL),
  54. ),
  55. );
  56. }
  57. /**
  58. * Implements hook_image_style_flush().
  59. *
  60. * This hook checks if the image style that is being flushed is used in a
  61. * subroutine effect. If so, the style that contains the subroutine effect
  62. * should be flushed as well.
  63. *
  64. * This may lead to recursive calls to image_style_flush() and thus to this
  65. * hook. Without loops in styles that call each other as subroutine, this
  66. * recursion will always end.
  67. *
  68. * @param array $flushed_style
  69. * The image style that is being flushed.
  70. */
  71. function imagecache_customactions_image_style_flush(/*array*/ $flushed_style) {
  72. $styles = image_styles();
  73. foreach ($styles as $style) {
  74. if ($style['name'] !== $flushed_style['name']) {
  75. foreach ($style['effects'] as $effect) {
  76. if ($effect['name'] === 'imagecache_subroutine') {
  77. if (isset($effect['data']['subroutine_presetname']) && $effect['data']['subroutine_presetname'] === $flushed_style['name']) {
  78. image_style_flush($style);
  79. }
  80. }
  81. }
  82. }
  83. }
  84. }
  85. /**
  86. * Image effect form callback for the custom action effect.
  87. *
  88. * Note that this is not a complete form, it only contains the portion of the
  89. * form for configuring the effect options. Therefore it does not not need to
  90. * include metadata about the effect, nor a submit button.
  91. *
  92. * @param array $data
  93. * The current configuration for this image effect.
  94. *
  95. * @return array
  96. * The form definition for this effect.
  97. */
  98. function imagecache_customactions_form(array $data) {
  99. // Add defaults.
  100. $data += array('php' => 'return TRUE;');
  101. // Note: we also need to check for the existence of the module: admin has
  102. // all rights, so user_acccess(...) returns TRUE even if the module is not
  103. // enabled and the permission does not exist.
  104. $allow_php = module_exists('php') && user_access('use PHP for settings');
  105. $form = array(
  106. 'php' => array(
  107. '#type' => 'textarea',
  108. '#rows' => 12,
  109. '#title' => t('PHP code'),
  110. '#default_value' => $data['php'],
  111. '#disabled' => !$allow_php,
  112. '#description' => t("<p>A piece of PHP code that modifies the image.
  113. It should return a boolean indicating success or failure.
  114. You will need the '%use_php' permission, defined by the 'PHP filter' module.
  115. See the help for an extensive explanation of the possibilities.</p>",
  116. array('%use_php' => t('Use PHP for settings'))),
  117. '#wysiwyg' => FALSE,
  118. ),
  119. );
  120. return $form;
  121. }
  122. /**
  123. * Implements theme_hook() for the custom action effect summary.
  124. *
  125. * param array $variables
  126. * An associative array containing:
  127. * - data: The current configuration for this image effect.
  128. *
  129. * @return string
  130. * The HTML for the summary of this image effect.
  131. * @ingroup themeable
  132. */
  133. function theme_imagecache_customactions_summary(/*array $variables*/) {
  134. return 'Custom PHP code';
  135. }
  136. /**
  137. * Image effect callback for the custom action effect.
  138. *
  139. * @param stdClass $image
  140. * @param array $data
  141. *
  142. * @return boolean
  143. * true on success, false otherwise.
  144. */
  145. function imagecache_customactions_effect(stdClass $image, array $data) {
  146. $result = module_exists('php');
  147. if ($result) {
  148. // Get context about the image.
  149. module_load_include('inc', 'imagecache_actions', 'utility');
  150. $GLOBALS['image_context'] = imagecache_actions_get_image_context($image, $data);
  151. $GLOBALS['image'] = $image;
  152. // Get (non-alterable) context about the image style and image effect.
  153. $execution_info = imagecache_actions_get_image_effect_context();
  154. $GLOBALS['image_style'] = $execution_info['image_style'];
  155. $GLOBALS['image_effect_id'] = $execution_info['image_effect_id'];
  156. $result = php_eval('<' . '?php global $image, $image_context; ' . $data['php'] . ' ?' . '>');
  157. // php_eval returns '1' if the snippet returns true.
  158. $result = $result === '1';
  159. unset($GLOBALS['image_effect_id']);
  160. unset($GLOBALS['image_style']);
  161. unset($GLOBALS['image']);
  162. unset($GLOBALS['image_context']);
  163. }
  164. if ($result && $image->toolkit == 'GD') {
  165. $image->info['width'] = imagesx($image->resource);
  166. $image->info['height'] = imagesy($image->resource);
  167. }
  168. return $result;
  169. }
  170. /**
  171. * Image dimensions callback for the custom action effect.
  172. *
  173. * @param array $dimensions
  174. * Dimensions to be modified - an associative array containing the items
  175. * 'width' and 'height' (in pixels).
  176. * param array $data
  177. * An associative array containing the effect data.
  178. */
  179. function imagecache_customactions_dimensions(array &$dimensions/*, array $data*/) {
  180. $dimensions['width'] = NULL;
  181. $dimensions['height'] = NULL;
  182. }
  183. /**
  184. * Subroutine - an imagecache action that just calls another one.
  185. *
  186. * Contributed by Alan D
  187. * https://drupal.org/node/618784
  188. *
  189. * Reworked into customactions by dman 2010-07
  190. */
  191. /**
  192. * Image effect form callback for the subroutine effect.
  193. *
  194. * @param array $data
  195. * The current configuration for this image effect.
  196. *
  197. * @return array
  198. * The form definition for this effect.
  199. */
  200. function imagecache_subroutine_form(array $data) {
  201. // Add defaults.
  202. $data += array('subroutine_presetname' => '');
  203. // List available image styles.
  204. // The PASS_THROUGH parameter is new as of D7.23, and is added here to prevent
  205. // image_style_options() from double-encoding the human-readable image style
  206. // name, since the form API will already sanitize options in a select list.
  207. $styles = image_style_options(TRUE, PASS_THROUGH);
  208. //@todo: unset the current style to prevent obvious recursion.
  209. $form = array();
  210. $form['subroutine_presetname'] = array(
  211. '#type' => 'select',
  212. '#title' => t('Image style to call'),
  213. '#default_value' => $data['subroutine_presetname'],
  214. '#options' => $styles,
  215. '#required' => TRUE,
  216. );
  217. return $form;
  218. }
  219. /**
  220. * Implements theme_hook() for the subroutine effect summary.
  221. *
  222. * @param array $variables
  223. * An associative array containing:
  224. * - data: The current configuration for this image effect.
  225. *
  226. * @return string
  227. * The HTML for the summary of this image effect.
  228. * @ingroup themeable
  229. */
  230. function theme_imagecache_subroutine_summary(array $variables) {
  231. $data = $variables['data'];
  232. module_load_include('inc', 'imagecache_actions', 'utility');
  233. $label = imagecache_actions_get_style_label($data['subroutine_presetname']);
  234. return t('Apply image style %label', array('%label' => $label));
  235. }
  236. /**
  237. * Image effect callback for the subroutine effect.
  238. *
  239. * @param stdClass $image
  240. * @param array $data
  241. *
  242. * @return boolean
  243. * true on success, false otherwise.
  244. */
  245. function imagecache_subroutine_effect(stdClass $image, array $data) {
  246. $result = FALSE;
  247. if ($style = image_style_load($data['subroutine_presetname'])) {
  248. $result = TRUE;
  249. foreach ($style['effects'] as $effect) {
  250. $result = $result && image_effect_apply($image, $effect);
  251. }
  252. }
  253. return $result;
  254. }
  255. /**
  256. * Image dimensions callback for the subroutine effect.
  257. *
  258. * @param array $dimensions
  259. * Dimensions to be modified - an array with components width and height, in
  260. * pixels.
  261. * @param array $data
  262. * An array with the effect options.
  263. */
  264. function imagecache_subroutine_dimensions(array &$dimensions, array $data) {
  265. // Let the subroutine transform the dimensions.
  266. image_style_transform_dimensions($data['subroutine_presetname'], $dimensions);
  267. }