/[drupal]/contributions/modules/upload_preview/upload_preview.module
ViewVC logotype

Contents of /contributions/modules/upload_preview/upload_preview.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.13 - (show annotations) (download) (as text)
Mon Dec 29 03:27:08 2008 UTC (11 months ago) by rmiddle
Branch: MAIN
CVS Tags: DRUPAL-6--1-0, HEAD
Branch point for: DRUPAL-6--1
Changes since 1.12: +47 -23 lines
File MIME type: text/x-php
Initial port of Drupal 6.
1 <?php
2 // $Id: upload_preview.module,v 1.12 2008/12/29 01:13:17 rmiddle Exp $
3
4 /**
5 * @file
6 * Adds image preview thumbnails to the file attachment section.
7 */
8
9
10 /**
11 * Implementation of hook_form_alter().
12 */
13 function upload_preview_form_alter(&$form, $form_state, $form_id) {
14 if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id && variable_get('upload_'. $form['type']['#value'], 1)) {
15 _upload_preview_node_form($form['attachments']['wrapper']['files'], $form['#node']->vid);
16 }
17 else {
18 switch ($form_id) {
19 case 'upload_admin_settings':
20 // Add configuration options to the upload settings page.
21 _upload_preview_admin_form($form);
22 break;
23 case 'upload_js':
24 _upload_preview_node_form($form['files'], $form['current']['vid']['#value']);
25 break;
26 }
27 }
28 }
29
30 /**
31 * Implementation of hook_cron().
32 */
33 function upload_preview_cron() {
34 $previews = variable_get('upload_preview_files', array());
35 $threshold = time() - variable_get('upload_preview_lifetime', 1000000000);
36
37 // Delete all files that are older than the maximum preview file lifetime.
38 foreach ($previews as $file => $timestamp) {
39 if ($timestamp < $threshold) {
40 file_delete($file);
41 unset($previews[$file]);
42 }
43 }
44
45 variable_set('upload_preview_files', $previews);
46 }
47
48 /**
49 * Helper function for hook_form_alter().
50 */
51 function _upload_preview_node_form(&$files, $vid) {
52 // Overwrite the theme function with the two-row theme which includes the
53 // preview image.
54 $files['#theme'] = 'upload_preview_form_current';
55
56 foreach (element_children($files) as $id) {
57 $file = new stdClass();
58 $file->fid = $files[$id]['fid']['#value'];
59 $file->filename = $files[$id]['filename']['#value'];
60 $file->filepath = $files[$id]['filepath']['#value'];
61 $file->filemime = $files[$id]['filemime']['#value'];
62 $file->filesize = $files[$id]['filesize']['#value'];
63 $file->vid = $vid;
64 $file->description = $files[$id]['description']['#default_value'];
65 $file->list = $files[$id]['list']['#default_value'];
66
67 $files[$id]['preview'] = module_invoke_all('upload_preview', $file);
68
69 if (empty($files[$id]['preview'])) {
70 // When there is no preview (image could not be created or the file is not
71 // an image), add an info text stating that fact.
72 $files[$id]['preview'] = array(
73 '#value' => '('. t('No preview') .')',
74 );
75 }
76
77 // Add the values for our custom theme function.
78 $files[$id]['remove']['#title'] = t('Delete');
79 $files[$id]['list']['#title'] = t('List');
80 $files[$id]['size']['#prefix'] = t('Size') .': ';
81
82 // Check if the file is already saved or still in the temp directory.
83 $dirty = !is_numeric($file->fid);
84 $url = file_create_url($dirty ? file_create_filename($file->filename, file_create_path()) : $file->filepath);
85
86 // Modify the description field to be a textarea and change its description text.
87 $files[$id]['description']['#type'] = 'textarea';
88 $files[$id]['description']['#rows'] = 3;
89 $files[$id]['description']['#resizable'] = FALSE;
90 if ($dirty) {
91 $files[$id]['description']['#description'] = t('This file is not yet saved, but will be available at <a href="@url">@url</a>', array('@url' => $url));
92 }
93 else {
94 $files[$id]['description']['#description'] = t('This file can be found at <a href="@url">@url</a>.', array('@url' => $url));
95 }
96 }
97 }
98
99 /**
100 * Implementation of hook_upload_preview().
101 */
102 function upload_preview_upload_preview($file) {
103 // Only check for images
104 if (strpos($file->filemime, 'image/') === 0) {
105 // Create the preview image file path based on the actual filename or the
106 // preliminary filename (in the temp directory).
107 $path = file_create_path(variable_get('upload_preview_path', 'preview')) .'/';
108 $path .= md5($file->filepath) .'.'. _upload_preview_mime_to_extension($file->filemime);
109
110 // If the file does not exist, try to scale it down
111 if (!file_exists($path)) {
112 $size = explode('x', variable_get('upload_preview_size', '150x150'));
113 if (!image_scale($file->filepath, $path, $size[0], $size[1])) {
114 // Scaling failed, now try copying the original file over.
115 if (!file_copy($file->filepath, $path, FILE_EXISTS_ERROR)) {
116 // If every attempt failed, don't show a preview.
117 $path = NULL;
118 }
119 }
120 else {
121 // The image creation succeeded. Now, add the image to the preview files
122 // array so that we can delete it later when it's not needed anymore.
123 $previews = variable_get('upload_preview_files', array());
124 $previews[$path] = time();
125 variable_set('upload_preview_files', $previews);
126 }
127 }
128
129 if ($path) {
130 // The image exists and the preview can be added.
131 $image = theme('upload_preview_image', file_create_url($path), $file->description);
132 return array(
133 '#value' => l($image, file_create_url($file->filepath), array('html' => TRUE)),
134 );
135 }
136 }
137 }
138
139 function upload_preview_nodeapi(&$node, $op, $teaser) {
140 switch ($op) {
141 case 'view':
142 if (isset($node->content['files'])) {
143 $node->content['files'] = array(
144 '#theme' => 'upload_preview_attachments',
145 '#files' => $node->files,
146 '#weight' => $node->content['files']['#weight'],
147 );
148 if ($node->nid) {
149 foreach ($node->content['files']['#files'] as $fid => $file) {
150 $node->content['files']['#files'][$fid]->preview = module_invoke_all('upload_preview', $file);
151 }
152 }
153 }
154 break;
155 }
156 }
157
158 /**
159 * Displays an extended file attachments in table
160 */
161 function theme_upload_preview_attachments($element) {
162 $header = array(t('Preview'), t('Attachment'), t('Size'));
163 $rows = array();
164 foreach ($element['#files'] as $file) {
165 $file = (object)$file;
166 if ($file->list && !$file->remove) {
167 // Generate valid URL for both existing attachments and preview of new attachments (these have 'upload' in fid)
168 $href = file_create_url((strpos($file->fid, 'upload') === FALSE ? $file->filepath : file_create_filename($file->filename, file_create_path())));
169 $text = $file->description ? $file->description : $file->filename;
170 $rows[] = array(drupal_render($file->preview), l($text, $href), format_size($file->filesize));
171 }
172 }
173 if (count($rows)) {
174 return theme('table', $header, $rows, array('id' => 'attachments'));
175 }
176 }
177
178 /**
179 * Implementation of hook_file_download().
180 */
181 function upload_preview_file_download($file) {
182 $preview = file_create_path(variable_get('upload_preview_path', 'preview'));
183 $file_info = pathinfo(file_create_path($file));
184 if ($file_info['dirname'] == $preview) {
185 return array('Content-Type: image/'. drupal_strtolower($file_info['extension']));
186 }
187 }
188
189 /**
190 * Helper function. Returns the correct file ending for an image mime type.
191 */
192 function _upload_preview_mime_to_extension($mime) {
193 switch ($mime) {
194 case 'image/jpeg':
195 case 'image/jpg':
196 return 'jpg';
197 break;
198 case 'image/gif':
199 return 'gif';
200 break;
201 case 'image/png':
202 default:
203 return 'png';
204 }
205 }
206
207 /**
208 * Helper function for hook_form_alter().
209 */
210 function _upload_preview_admin_form(&$form) {
211 // Ensure that the buttons are at the very bottom.
212 $form['buttons']['#weight'] = 50;
213
214 $mode = variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC);
215 $path = file_directory_path();
216 $preview = file_create_path(variable_get('upload_preview_path', 'preview'));
217
218 $form['preview'] = array(
219 '#type' => 'fieldset',
220 '#title' => t('Previews'),
221 '#weight' => 5,
222 '#description' => t('Controls the behavior of previews in the file attachment section.'),
223 '#collapsible' => TRUE,
224 '#collapsed' => FALSE,
225 );
226
227 $form['preview']['upload_preview_path'] = array(
228 '#type' => 'textfield',
229 '#title' => t('Preview path'),
230 '#default_value' => drupal_substr($preview, drupal_strlen($path) + 1),
231 '#field_prefix' => $mode == FILE_DOWNLOADS_PUBLIC ? file_create_url('') : '&lt;'. t('Private') .'&gt;/',
232 '#description' => t('Subdirectory in the global file directory where previews will be stored.'),
233 );
234
235 $form['preview']['upload_preview_size'] = array(
236 '#type' => 'textfield',
237 '#title' => t('Image size'),
238 '#default_value' => variable_get('upload_preview_size', '150x150'),
239 '#size' => 15,
240 '#maxlength' => 10,
241 '#description' => t('The image size for the preview images (e.g. 150x150). The aspect ratio will be maintained while resizing.'),
242 '#field_suffix' => '<kbd>'. t('WIDTHxHEIGHT') .'</kbd>'
243 );
244
245 $period = drupal_map_assoc(array(600, 1800, 3600, 7200, 14400, 28800, 86400, 172800, 604800), 'format_interval');
246 $period['1000000000'] = t('Never');
247 $form['preview']['upload_preview_lifetime'] = array(
248 '#type' => 'select',
249 '#title' => t('File lifetime'),
250 '#description' => t('The period until upload preview files are deleted. In case they get deleted before the user saved the post, they are regenerated automatically. Requires crontab.'),
251 '#default_value' => variable_get('upload_preview_lifetime', 1000000000),
252 '#options' => $period,
253 );
254
255 if (!isset($form['#validate'])) {
256 $form['#validate'] = array();
257 }
258
259 $form['#validate'][] = '_upload_preview_admin_form_validate';
260 _upload_preview_prerequisites($preview);
261 }
262
263 /**
264 * Validate the preview image size.
265 */
266 function _upload_preview_admin_form_validate($form, &$form_state) {
267 if (!preg_match('~^[1-9]\d*x[1-9]\d*$~', $form_state['values']['upload_preview_size'])) {
268 form_set_error('upload_preview_size', t('The specified preview image size is invalid.'));
269 }
270 }
271
272 /**
273 * Ensure that the preview image directory exists. If it doesn't, try to create it.
274 */
275 function _upload_preview_prerequisites(&$preview) {
276 if (!file_check_directory($preview, FILE_CREATE_DIRECTORY)) {
277 drupal_set_message(t('Attachment previews are disabled. The preview directory %directory has not been properly configured.', array('%directory' => $preview)), 'error');
278 form_set_error('upload_preview_path');
279 }
280
281 // Also ensure, that we have a image toolkit available.
282 if (!image_get_toolkit()) {
283 drupal_set_message(t('Make sure you have a working image toolkit installed and enabled. Further information can be found on the <a href="@url">Image toolkit settings page</a>.', array('@url' => url('admin/settings/image-toolkit'))), 'error');
284 }
285 }
286
287 /**
288 * Theme the attachments list.
289 */
290 function theme_upload_preview_form_current(&$form) {
291 $header = array(t('Preview'), t('Description'), t('Weight'));
292 drupal_add_tabledrag('upload-attachments', 'order', 'sibling', 'upload-weight');
293
294 foreach (element_children($form) as $key) {
295 // Add class to group weight fields for drag and drop.
296 $form[$key]['weight']['#attributes']['class'] = 'upload-weight';
297 $form[$key]['description']['#cols'] = 20;
298
299 // Split up in two rows as the addition image would make the table too wide.
300 // The first row contains the image and the description...
301 $divs = array();
302 $divs[] = drupal_render($form[$key]['remove']);
303 $divs[] = drupal_render($form[$key]['list']);
304 $divs[] = drupal_render($form[$key]['size']);
305
306 $divs = '<br /><div style="float: left;margin-right:20px;">'. implode('</div><div style="float: left;margin-right:20px;">', $divs) .'</div>';
307
308 $row = array();
309 $row[] = array('data' => drupal_render($form[$key]['preview']));
310 $row[] = array('data' => drupal_render($form[$key]['description']) . $divs);
311 $row[] = array('data' => drupal_render($form[$key]['weight']));
312 $rows[] = array('data' => $row, 'class' => 'draggable');
313
314 // ... and the second row contains the list/remove checkboxes and the size information.
315 }
316
317 if (count($rows)) {
318 $output = theme('table', $header, $rows, array('id' => 'upload-attachments'));
319 $output .= drupal_render($form);
320 }
321
322 return $output;
323 }
324
325 /**
326 * Theme a file upload preview image.
327 */
328 function theme_upload_preview_image($url, $alt) {
329 return '<img src="'. $url .'" alt="'. $alt .'" class="upload_preview_image" />';
330 }
331
332 /**
333 * Implementation of hook_theme().
334 */
335 function upload_preview_theme() {
336 return array(
337 'upload_preview_form_current' => array(
338 'arguments' => array('form' => NULL),
339 /* 'file' => 'upload_preview.module' */
340 ),
341 'upload_preview_image' => array(
342 'arguments' => array('element' => NULL),
343 /* 'file' => 'upload_preview.module' */
344 )
345 );
346 }
347

  ViewVC Help
Powered by ViewVC 1.1.2