PageRenderTime 46ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/Field/src/Utility/ImageToolbox.php

http://github.com/QuickAppsCMS/QuickApps-CMS
PHP | 272 lines | 161 code | 33 blank | 78 comment | 18 complexity | c9518b7cffc478be7aee64a5086aa50e MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, GPL-3.0
  1. <?php
  2. /**
  3. * Licensed under The GPL-3.0 License
  4. * For full copyright and license information, please see the LICENSE.txt
  5. * Redistributions of files must retain the above copyright notice.
  6. *
  7. * @since 2.0.0
  8. * @author Christopher Castro <chris@quickapps.es>
  9. * @link http://www.quickappscms.org
  10. * @license http://opensource.org/licenses/gpl-3.0.html GPL-3.0 License
  11. */
  12. namespace Field\Utility;
  13. use Cake\Core\Plugin;
  14. use Cake\Filesystem\File;
  15. use Cake\Filesystem\Folder;
  16. use Field\Utility\FileToolbox;
  17. /**
  18. * ImageToolbox class for handling image related tasks.
  19. *
  20. * Allows to define image preview modes, render a field instance or create
  21. * image thumbnails among other things.
  22. *
  23. * NOTE: Thumbnails files are always stored in `.tmb` directory.
  24. */
  25. class ImageToolbox extends FileToolbox
  26. {
  27. /**
  28. * List of preview modes. More modes can be defined using "addPreview()" method.
  29. *
  30. * @var array
  31. */
  32. protected static $_previews = [];
  33. /**
  34. * Renders the given field instance.
  35. *
  36. * When using the `Link to content` option, entities must define the "url"
  37. * property, and it should return a valid URL for that entity.
  38. *
  39. * @param \Cake\View\View $view Instance of view class
  40. * @param \Field\Model\Entity\Field $field Field instance to render
  41. * @return string HTML
  42. */
  43. public static function formatter($view, $field)
  44. {
  45. $out = '';
  46. $viewModeSettings = $field->viewModeSettings;
  47. foreach ((array)$field->extra as $image) {
  48. if (!empty($image['file_name'])) {
  49. $img = '';
  50. $originalURL = normalizePath("/files/{$field->metadata->settings['upload_folder']}/{$image['file_name']}", '/');
  51. $imageOptions = [];
  52. foreach (['title', 'alt'] as $attr) {
  53. if (!empty($field->metadata->settings["{$attr}_attr"]) && !empty($image[$attr])) {
  54. $imageOptions[$attr] = h($image[$attr]);
  55. }
  56. }
  57. if ($viewModeSettings['size']) {
  58. $thumbnail = static::thumbnail(normalizePath(WWW_ROOT . "/files/{$field->metadata->settings['upload_folder']}/{$image['file_name']}"), $viewModeSettings['size']);
  59. if ($thumbnail !== false) {
  60. $thumbnail = basename($thumbnail);
  61. $img = $view->Html->image(normalizePath("/files/{$field->metadata->settings['upload_folder']}/.tmb/{$thumbnail}", '/'), $imageOptions);
  62. }
  63. } else {
  64. $img = $view->Html->image($originalURL, $imageOptions);
  65. }
  66. if ($img) {
  67. switch ($viewModeSettings['link_type']) {
  68. case 'content':
  69. $entityURL = $field->metadata->entity->get('url');
  70. if ($entityURL) {
  71. $out .= $view->Html->link($img, $entityURL, ['escape' => false]);
  72. } else {
  73. $out .= $img;
  74. }
  75. break;
  76. case 'file':
  77. $out .= $view->Html->link($img, $originalURL, ['escape' => false, 'target' => '_blank']);
  78. break;
  79. default:
  80. $out .= $img;
  81. break;
  82. }
  83. }
  84. }
  85. }
  86. return $out;
  87. }
  88. /**
  89. * Creates a thumbnail for the given image.
  90. *
  91. * @param string $filePath Full path to original image file
  92. * @param string $previewSize A valid preview preset
  93. * @return false|string Full path to thumbnail file on success, false otherwise
  94. */
  95. public static function thumbnail($filePath, $previewSize)
  96. {
  97. $filePath = normalizePath($filePath);
  98. if (!is_readable($filePath)) {
  99. return false;
  100. }
  101. $srcFileName = basename($filePath);
  102. $srcPath = dirname($filePath) . DS;
  103. $dstPath = normalizePath("{$srcPath}/.tmb/");
  104. $previewInfo = static::getPreviews($previewSize);
  105. require_once Plugin::classPath('Field') . 'Lib/class.upload.php';
  106. $handle = new \upload($srcPath . $srcFileName);
  107. if (empty($previewInfo)) {
  108. $previews = static::getPreviews();
  109. $previewInfo = reset($previews);
  110. }
  111. $dstFileNameBody = static::removeExt("{$previewInfo['width']}x{$previewInfo['height']}_{$srcFileName}");
  112. $dstFilePath = normalizePath("{$dstPath}/{$dstFileNameBody}.jpg");
  113. if (is_readable($dstFilePath)) {
  114. return $dstFilePath;
  115. }
  116. $handle->image_x = $previewInfo['width'];
  117. $handle->image_y = $previewInfo['height'];
  118. $handle->image_resize = true;
  119. $handle->image_ratio = false;
  120. $handle->image_ratio_crop = true;
  121. $handle->image_convert = 'jpg';
  122. $handle->file_new_name_body = $dstFileNameBody;
  123. $handle->process($dstPath);
  124. if (empty($handle->error)) {
  125. return $handle->file_dst_pathname;
  126. }
  127. return false;
  128. }
  129. /**
  130. * Returns an array list of available previews modes suitable for select boxes.
  131. *
  132. * @return array
  133. */
  134. public static function previewsOptions()
  135. {
  136. static::_initPreviews();
  137. $options = [];
  138. foreach (static::$_previews as $value => $info) {
  139. $options[$value] = $info['label'];
  140. }
  141. return $options;
  142. }
  143. /**
  144. * Gets all defined previews, or information for an specific preview.
  145. *
  146. * @param string $slug Slug of the preview for which get its info, set to null
  147. * will retrieve info for all registered previews
  148. * @return array
  149. */
  150. public static function getPreviews($slug = null)
  151. {
  152. static::_initPreviews();
  153. if ($slug !== null) {
  154. if (isset(static::$_previews[$slug])) {
  155. return static::$_previews[$slug];
  156. }
  157. return [];
  158. }
  159. return static::$_previews;
  160. }
  161. /**
  162. * Defines a new preview configuration or overwrite if exists.
  163. *
  164. * @param string $slug Unique machine-name. e.g.: `my-preview-mode`
  165. * @param string $label Human-readable name. e.g.: `My preview mode`
  166. * @param int $width Width for images that would use this preview mode
  167. * @param int $height Height for images that would use this preview mode
  168. * @return void
  169. */
  170. public static function addPreview($slug, $label, $width, $height)
  171. {
  172. static::_initPreviews();
  173. static::$_previews[$slug] = [
  174. 'label' => $label,
  175. 'width' => $width,
  176. 'height' => $height,
  177. ];
  178. }
  179. /**
  180. * Deletes the given image and all its thumbnails.
  181. *
  182. * @param string $imagePath Full path to image file
  183. * @return void
  184. */
  185. public static function delete($imagePath)
  186. {
  187. $imagePath = normalizePath($imagePath);
  188. if (is_readable($imagePath)) {
  189. $original = new File($imagePath);
  190. static::deleteThumbnails($imagePath);
  191. $original->delete();
  192. }
  193. }
  194. /**
  195. * Delete image's thumbnails if exists.
  196. *
  197. * @param string $imagePath Full path to original image file
  198. * @return void
  199. */
  200. public static function deleteThumbnails($imagePath)
  201. {
  202. $imagePath = normalizePath("{$imagePath}/");
  203. $fileName = basename($imagePath);
  204. $tmbPath = normalizePath(dirname($imagePath) . '/.tmb/');
  205. $folder = new Folder($tmbPath);
  206. $pattern = preg_quote(static::removeExt($fileName));
  207. foreach ($folder->find(".*{$pattern}.*") as $tn) {
  208. $tn = new File($tmbPath . $tn);
  209. $tn->delete();
  210. }
  211. }
  212. /**
  213. * Initializes defaults built-in preview modes.
  214. *
  215. * @return void
  216. */
  217. protected static function _initPreviews()
  218. {
  219. if (empty(static::$_previews)) {
  220. static::$_previews = [
  221. 'thumbnail' => [
  222. 'label' => __d('field', 'Thumbnail'),
  223. 'width' => 100,
  224. 'height' => 100
  225. ],
  226. 'medium' => [
  227. 'label' => __d('field', 'Medium'),
  228. 'width' => 220,
  229. 'height' => 220
  230. ],
  231. 'large' => [
  232. 'label' => __d('field', 'Large'),
  233. 'width' => 480,
  234. 'height' => 480
  235. ],
  236. ];
  237. }
  238. }
  239. }