imagecache_customactions.module 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. <?php
  2. /**
  3. * @file Allow advanced users to code their own PHP image manipulation routines
  4. * as part of imagecache processing.
  5. *
  6. * @author Originally contributed by crea http://drupal.org/node/325103#comment-
  7. * 1076011
  8. *
  9. * @author merged into imagecache_actions by dman http://coders.co.nz
  10. *
  11. * Needs review - currently a security risk etc
  12. */
  13. /**
  14. * Implements hook_image_effect_info.
  15. *
  16. * @return array
  17. */
  18. function imagecache_customactions_image_effect_info() {
  19. $effects = array();
  20. // @todo: implement summary theme callback
  21. $effects['imagecache_customactions'] = array(
  22. 'label' => t('Custom action'),
  23. 'help' => t('Runs custom PHP code.'),
  24. 'effect callback' => 'imagecache_customactions_image',
  25. 'dimensions callback' => 'imagecache_customactions_dimensions',
  26. 'form callback' => 'imagecache_customactions_form',
  27. );
  28. $effects['imagecache_subroutine'] = array(
  29. 'label' => t('Subroutine'),
  30. 'help' => t('Runs another defined preset on the image.'),
  31. 'effect callback' => 'imagecache_subroutine_image',
  32. 'dimensions callback' => 'imagecache_subroutine_dimensions',
  33. 'form callback' => 'imagecache_subroutine_form',
  34. );
  35. return $effects;
  36. }
  37. /**
  38. * Implements hook_image_style_flush.
  39. *
  40. * This hook checks if the image style that is being flushed is used in an
  41. * subroutine effect. If so, the style that contains the subroutine effect,
  42. * should be flushed as well as the flushed style was probably changed.
  43. *
  44. * @param array $flushed_style
  45. * The image style that is being flushed.
  46. */
  47. function imagecache_customactions_image_style_flush($flushed_style) {
  48. $styles = image_styles();
  49. foreach ($styles as $style) {
  50. if ($style['name'] !== $flushed_style['name']) {
  51. foreach ($style['effects'] as $effect) {
  52. if ($effect['name'] === 'imagecache_subroutine') {
  53. if (isset($effect['data']['subroutine_presetname']) && $effect['data']['subroutine_presetname'] === $flushed_style['name']) {
  54. image_style_flush($style);
  55. }
  56. }
  57. }
  58. }
  59. }
  60. }
  61. /**
  62. * @deprecated replaced by summary theme callback
  63. * Implementation of theme_hook() for imagecache_customactions.module
  64. */
  65. function imagecache_customactions_theme() {
  66. return array(
  67. 'imagecache_subroutine' => array(
  68. 'render element' => 'element',
  69. ),
  70. );
  71. }
  72. /**
  73. * Implements hook_form().
  74. *
  75. * @param array $data
  76. * Array of settings for this action.
  77. * @return array
  78. * A form definition.
  79. */
  80. function imagecache_customactions_form($data) {
  81. // Add defaults.
  82. $data += array('php' => 'return TRUE;');
  83. // Note: we also need to check for the existence of the module: admin has
  84. // all rights, so user_acccess(...) returns TRUE even if the module is not
  85. // enabled and the permission does not exist.
  86. $allow_dynamic = user_access('use PHP for settings') && module_exists('php');
  87. // @todo: for imagemagick, the PHP code should add a set of commands to the
  88. // ops aray of $image. Document this in description.
  89. $form = array(
  90. 'php' => array(
  91. '#type' => 'textarea',
  92. '#rows' => 10,
  93. '#title' => t('PHP code'),
  94. '#default_value' => $data['php'],
  95. '#disabled' => !$allow_dynamic,
  96. '#description' => t("<p>A piece of PHP code that modifies the image.
  97. It should return a boolean indicating success or failure.
  98. You will need the '%use_php' permission, defined by the 'PHP filter' module.
  99. See the help for an extensive explanation of the possibilities.</p>",
  100. array('%use_php' => t('Use PHP for settings'))),
  101. '#wysiwyg' => FALSE,
  102. ),
  103. );
  104. return $form;
  105. }
  106. /**
  107. * Implements hook_image().
  108. *
  109. * @param object $image
  110. * @param array $data
  111. *
  112. * @return bool
  113. */
  114. function imagecache_customactions_image($image, $data) {
  115. // Check that the PHP filter module is enabled.
  116. $result = module_exists('php');
  117. if ($result) {
  118. // Get context about the image.
  119. module_load_include('inc', 'imagecache_actions', 'utility');
  120. $GLOBALS['image_context'] = imagecache_actions_get_image_context($image, $data);
  121. $GLOBALS['image'] = $image;
  122. $result = php_eval('<' . '?php global $image, $image_context; ' . $data['php'] . ' ?' . '>');
  123. // php_eval returns '1' if the snippet returns true.
  124. $result = $result === '1';
  125. unset($GLOBALS['image']);
  126. unset($GLOBALS['image_context']);
  127. }
  128. if ($result && $image->toolkit == 'GD') {
  129. $image->info['width'] = imagesx($image->resource);
  130. $image->info['height'] = imagesy($image->resource);
  131. }
  132. return $result;
  133. }
  134. /**
  135. * Image dimensions callback; Custom action.
  136. *
  137. * @param array $dimensions
  138. * Dimensions to be modified - an array with components width and height, in
  139. * pixels.
  140. * @param array $data
  141. * An array with the effect options.
  142. */
  143. function imagecache_customactions_dimensions(array &$dimensions, array $data) {
  144. // @todo: add form field asking if dimensions stay the same (or if they know
  145. // the new dimesions).
  146. $dimensions['width'] = NULL;
  147. $dimensions['height'] = NULL;
  148. }
  149. /**
  150. * @todo change into summary theme callback
  151. * Implementation of theme_hook() for imagecache_ui.module
  152. */
  153. function theme_imagecache_customactions($element) {
  154. // TODO: Should this theme imagecache_customactions be declared in hook_theme()?
  155. $data = $element['#value'];
  156. return "<em><strong>" . $data['text'] . "</strong></em>";
  157. }
  158. /**
  159. * Subroutine - an imagecache action that just calls another one.
  160. *
  161. * Contributed by Alan D
  162. * http://drupal.org/node/618784
  163. *
  164. * Reworked into customactions by dman 2010-07
  165. */
  166. /**
  167. * Config form for this preset.
  168. *
  169. * Implementation of imagecache_hook_form()
  170. *
  171. * @param array $data
  172. * The effect data for this effect.
  173. * @return array
  174. * The form definition.
  175. */
  176. function imagecache_subroutine_form($data) {
  177. $data = (array) $data;
  178. $form = array();
  179. // List available presets
  180. // @todo: use image_style_options and remove current style?
  181. $presets = array();
  182. foreach (image_styles(TRUE) as $preset) {
  183. $presets[$preset['name']] = $preset['name'];
  184. }
  185. $form['subroutine_presetname'] = array(
  186. '#type' => 'select',
  187. '#title' => t('Preset to call'),
  188. '#default_value' => $data['subroutine_presetname'],
  189. '#options' => $presets,
  190. );
  191. return $form;
  192. }
  193. /**
  194. * Actually invoke the action - which means just handing off to the named real
  195. * preset to do the job.
  196. *
  197. * Implementation of hook_image()
  198. *
  199. * @param object $image
  200. * @param array $data
  201. *
  202. * @return bool
  203. */
  204. function imagecache_subroutine_image($image, $data) {
  205. if ($preset = image_style_load($data['subroutine_presetname'])) {
  206. foreach ($preset['effects'] as $effect) {
  207. image_effect_apply($image, $effect);
  208. }
  209. }
  210. return TRUE;
  211. }
  212. /**
  213. * Image dimensions callback; Subroutine.
  214. *
  215. * @param array $dimensions
  216. * Dimensions to be modified - an array with components width and height, in
  217. * pixels.
  218. * @param array $data
  219. * An array with the effect options.
  220. */
  221. function imagecache_subroutine_dimensions(array &$dimensions, array $data) {
  222. // @todo: dimensions
  223. // @todo: call dimensions callback on subroutine style.
  224. $dimensions['width'] = NULL;
  225. $dimensions['height'] = NULL;
  226. }
  227. /**
  228. * @todo change into summary theme callback
  229. * This lets the user see what parameters were selected for the action
  230. */
  231. function theme_imagecache_subroutine($variables) {
  232. // @todo: better decsription, do not use internal id's, imagecache_preset_by_name does not exist: fatal error?
  233. $element = $variables['element'];
  234. $data = $element['#value'];
  235. if ($preset = imagecache_preset_by_name($data['subroutine_presetname'])) {
  236. return t('%name (pid: !presetid)', array(
  237. '%name' => $preset['presetname'],
  238. '!presetid' => $preset['presetid']
  239. ));
  240. }
  241. return t('<span class="error">Invalid reference. The referenced preset may have been deleted!</span>');
  242. }