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

Contents of /contributions/modules/node_images/node_images.module

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


Revision 1.12 - (show annotations) (download) (as text)
Sun Aug 17 21:19:11 2008 UTC (15 months, 1 week ago) by stefano73
Branch: MAIN
CVS Tags: HEAD
Changes since 1.11: +513 -584 lines
File MIME type: text/x-php
Initial relase for 6.x
1 <?php
2 // $Id: node_images.module,v 1.10 2007/10/07 17:12:24 stefano73 Exp $
3
4 /**
5 * @file
6 * This module will add an "Images" tab to nodes, allowing users to upload images and associate them with the current node.
7 */
8
9 /**
10 * Implementation of hook_perm().
11 */
12 function node_images_perm() {
13 $perms = array('administer node images', 'edit own node images', 'edit any node image', 'delete own node images', 'delete any node image');
14
15 foreach (node_get_types() as $type) {
16 if ($type->module == 'node') {
17 $name = check_plain($type->type);
18 $perms[] = 'add node images to own '. $name .' content';
19 $perms[] = 'add node images to any '. $name .' content';
20 }
21 }
22
23 return $perms;
24 }
25
26 /**
27 * Implementation of hook_menu().
28 */
29 function node_images_menu() {
30 $items = array();
31
32 $items['node_images/js'] = array(
33 'page callback' => '_node_images_js',
34 'file' => 'node_images.pages.inc',
35 'access arguments' => array(),
36 'type' => MENU_CALLBACK,
37 );
38 $items['admin/settings/node_images'] = array(
39 'title' => 'Node images',
40 'description' => 'Control how to upload node images.',
41 'page callback' => 'drupal_get_form',
42 'page arguments' => array('node_images_admin_settings'),
43 'access arguments' => array('administer site configuration'),
44 'file' => 'node_images.admin.inc',
45 );
46 $items['node/%node/images'] = array(
47 'title' => 'Images',
48 'page callback' => 'drupal_get_form',
49 'page arguments' => array('_node_images_edit_form', 1),
50 'access callback' => '_node_images_access',
51 'access arguments' => array('create', 1),
52 'weight' => 2,
53 'file' => 'node_images.pages.inc',
54 'type' => MENU_LOCAL_TASK,
55 );
56 $items['node/%node/image_gallery'] = array(
57 'title' => 'Gallery',
58 'page callback' => '_node_images_gallery',
59 'page arguments' => array(1),
60 'access callback' => 'node_access',
61 'access arguments' => array('view', 1),
62 'file' => 'node_images.pages.inc',
63 'type' => MENU_CALLBACK,
64 );
65
66 return $items;
67 }
68
69 /**
70 * implementation of hook_form_alter()
71 */
72 function node_images_form_alter(&$form, $form_state, $form_id) {
73 $type = $form['#node_type']->type;
74 if ($form_id == 'node_type_form' && isset($form['identity']['type'])) {
75 // radio button in the node's content type configuration page
76 _node_images_check_settings();
77 $form['node_images'] = array(
78 '#type' => 'fieldset',
79 '#title' => t('Node images'),
80 '#collapsible' => TRUE,
81 '#collapsed' => TRUE,
82 );
83 $form['node_images']['node_images_position'] = array(
84 '#type' => 'radios',
85 '#title' => t('Position'),
86 '#default_value' => variable_get('node_images_position_'.$type, 'hide'),
87 '#options' => array('hide' => t('Do not show'), 'above' => t('Show above node body'), 'below' => t('Show below node body'),
88 'node_template' => t('Manually set in node template by variable $node->node_images')),
89 '#description' => t('The position of images in the node view.'),
90 );
91 $form['node_images']['node_images_gallery_link'] = array(
92 '#type' => 'radios',
93 '#title' => t('Link to image gallery'),
94 '#default_value' => variable_get('node_images_gallery_link_'.$type, TRUE),
95 '#options' => array(t('Do not show'), t('Show')),
96 '#description' => t('Choose whether to show or not the link to the image gallery.'),
97 );
98 $form['node_images']['node_images_teaser_images'] = array(
99 '#type' => 'textfield',
100 '#title' => t('Number of images in node teaser'),
101 '#default_value' => variable_get('node_images_teaser_images_'.$type, 2),
102 '#size' => 5,
103 '#maxlength' => 2,
104 '#description' => t('The maximum number of images to show in the node teaser. 0 will not show images. Leave blank to show all images.'),
105 );
106 $form['node_images']['node_images_body_images'] = array(
107 '#type' => 'textfield',
108 '#title' => t('Number of images in node body'),
109 '#size' => 5,
110 '#maxlength' => 2,
111 '#default_value' => variable_get('node_images_body_images_'.$type, NULL),
112 '#description' => t('The maximum number of images to show in the node body. 0 will not show images. Leave blank to show all images.'),
113 );
114 $form['node_images']['node_images_teaser_format'] = array(
115 '#type' => 'radios',
116 '#title' => t('Image format in node teaser'),
117 '#default_value' => variable_get('node_images_teaser_format_'.$type, 'thumbs'),
118 '#options' => array('thumbs' => t('Thumbnails'), 'fullsize' => t('Full size images')),
119 '#description' => t('Image format in node teaser.'),
120 );
121 $form['node_images']['node_images_body_format'] = array(
122 '#type' => 'radios',
123 '#title' => t('Image format in node body'),
124 '#default_value' => variable_get('node_images_body_format_'.$type, 'thumbs'),
125 '#options' => array('thumbs' => t('Thumbnails'), 'fullsize' => t('Full size images')),
126 '#description' => t('Image format in node body.'),
127 );
128
129 // Role-based settings for image insertion
130 $result = db_query('SELECT rid, name FROM {role} ORDER BY name');
131 $role_options = array();
132 while ($role = db_fetch_object($result)) {
133 $role_options[$role->rid] = $role->name;
134 }
135 $form['node_images']['node_images_roles_add'] = array(
136 '#type' => 'checkboxes',
137 '#title' => t('Allow specific roles to add images to any node'),
138 '#default_value' => variable_get('node_images_roles_add_'.$type, array()),
139 '#options' => $role_options,
140 '#description' => t('Users having the selected role(s) will be able to add images to any existing node, even if they\'re not the node owner. If you select no roles, only node owner will be able to add images.'),
141 );
142 }
143
144 if (isset($form['type']) && isset($form['#node'])) {
145 $node = $form['#node'];
146 if (!$node->nid && $form['type']['#value'] .'_node_form' == $form_id && _node_images_access('create', $node)) {
147 // Attachments fieldset
148 $form['node_images'] = array(
149 '#type' => 'fieldset',
150 '#title' => t('Node images'),
151 '#collapsible' => TRUE,
152 '#collapsed' => empty($node->node_images),
153 '#description' => t('Changes made to the node images are not permanent until you save this post.'),
154 '#weight' => 30,
155 );
156
157 // Wrapper for fieldset contents (used by ahah.js).
158 $form['node_images']['wrapper'] = array(
159 '#prefix' => '<div id="node_images-attach-wrapper">',
160 '#suffix' => '</div>',
161 );
162
163 if (!_node_images_check_directory(NULL, $user, $node)) {
164 $form['node_images']['wrapper']['#description'] = t('Node images are disabled. The file directories have not been properly configured.');
165 if (user_access('administer site configuration')) {
166 $form['node_images']['wrapper']['#description'] .= ' '. t('Please visit the <a href="@admin-node-images">node_images configuration page</a>.', array('@admin-node-images' => url('admin/settings/node_images')));
167 }
168 else {
169 $form['node_images']['wrapper']['#description'] .= ' '. t('Please contact the site administrator.');
170 }
171 }
172 else {
173 require_once(drupal_get_path('module', 'node_images').'/node_images.pages.inc');
174 $form['node_images']['wrapper'] += _node_images_attach_form($form_state, $node);
175 $form['#attributes']['enctype'] = 'multipart/form-data';
176 }
177 }
178 $form['#submit'][] = 'node_images_node_form_submit';
179 }
180 }
181
182 /**
183 * Implementation of hook_nodeapi().
184 */
185 function node_images_nodeapi(&$node, $op, $teaser, $page) {
186 // test if images are allowed for this node
187 if ($op == 'load' || $op == 'view') {
188 if (variable_get('node_images_position_'.$node->type, 'hide') == 'hide') return;
189 // fire an additional hook for the specific node type
190 // i.e. node images might be a pro feature, so only subscribed users can view them
191 // if the hook is not present in the node type module, images are loaded by default
192 $show = module_invoke($node->type, 'node_images', $op, $node);
193 if ($show === FALSE) return;
194 }
195
196 switch ($op) {
197 case 'load':
198 // load node images for the current node
199 $where = 'WHERE nid=%d';
200 if (arg(0) != 'node' || arg(2) != 'images') $where .= ' AND status=1 AND list=1';
201 $sql = db_query('SELECT * FROM {node_images} ' .$where. ' ORDER BY weight', $node->nid);
202 while ($r = db_fetch_object($sql)) {
203 $node->node_images[$r->id] = $r;
204 }
205 break;
206
207 case 'insert':
208 if (_node_images_access('create', $node)) {
209 _node_images_save_attachments($node);
210 if (variable_get('node_images_position_'.$node->type, 'hide') != 'hide') {
211 drupal_set_message(t('Click the <strong>!images</strong> tab to edit node images.',
212 array('!images' => l(t('Images'), 'node/'.$node->nid.'/images'))));
213 }
214 }
215 break;
216
217 case 'delete':
218 // Delete image and thumbnail files
219 $sql = db_query('SELECT filepath, thumbpath FROM {node_images} WHERE nid=%d', $node->nid);
220 while ($r = db_fetch_object($sql)) {
221 file_delete($r->filepath);
222 file_delete($r->thumbpath);
223 }
224 // Delete all images associated with the node
225 db_query('DELETE FROM {node_images} WHERE nid=%d', $node->nid);
226 break;
227
228 case 'prepare':
229 // Initialize $_SESSION['node_images'] if no post occurred.
230 // This clears the variable from old forms and makes sure it
231 // is an array to prevent notices and errors in other parts
232 // of node_images.module.
233 if (!$_POST) {
234 $_SESSION['node_images'] = array();
235 }
236 break;
237
238 case 'view':
239 if (empty($node->node_images)) return;
240
241 // search for a themed view for the current node type
242 $nodetype_function = 'theme_'.$node->type.'_node_images_view';
243 if (function_exists($nodetype_function)) {
244 $output = $nodetype_function($node, $teaser, $page);
245 }
246 else {
247 // use the default theme function
248 $output = theme('node_images_view', $node, $teaser, $page);
249 }
250 $node->node_images = $output;
251
252 $output = '<div class="node_images">'.$output.'</div>';
253 $position = variable_get('node_images_position_'.$node->type, 'hide');
254 switch ($position) {
255 case 'node_template':
256 case 'hide':
257 break;
258
259 case 'above':
260 $node->content['node_images'] = array('#value' => $output, '#weight' => -1);
261 break;
262
263 default:
264 $node->content['node_images'] = array('#value' => $output, '#weight' => 1);
265 break;
266 }
267 return $node;
268 }
269 }
270
271 /**
272 * Implementation of hook_theme()
273 */
274 function node_images_theme() {
275 return array(
276 'node_images_form_list' => array(
277 'arguments' => array('form' => NULL),
278 ),
279 'node_images_form_upload' => array(
280 'arguments' => array('form' => NULL),
281 ),
282 'node_images_attach_list' => array(
283 'arguments' => array('form' => NULL),
284 ),
285 'node_images_view' => array(
286 'arguments' => array('node' => NULL, 'teaser' => NULL, 'page' => NULL),
287 ),
288 'node_images_gallery' => array(
289 'arguments' => array('element' => NULL),
290 ),
291 'node_images_gallery_thumbs' => array(
292 'arguments' => array('thumbs' => NULL, 'cols' => 2),
293 ),
294 );
295 }
296
297 /**
298 * Implementation of hook_link().
299 */
300 function node_images_link($type, $node = null, $teaser = false) {
301 $links = array();
302
303 if ($type == 'node' && $node->nid && variable_get('node_images_position_'.$node->type, 'hide') != 'hide') {
304 if (node_access('update', $node) && user_access('create node images')) {
305 $links['node_images_edit'] = array(
306 'title' => t('Edit node images'),
307 'href' => "node/$node->nid/images",
308 );
309 }
310 if (count($node->node_images) && variable_get('node_images_gallery_link_'.$node->type, TRUE)) {
311 $links['node_images_gallery'] = array(
312 'title' => t('Open the image gallery'),
313 'href' => "node/$node->nid/image_gallery",
314 );
315 }
316 }
317
318 return $links;
319 }
320
321 /**
322 * Implementation of hook_user().
323 */
324 function node_images_user($type, &$edit, &$user, $category = NULL) {
325 switch ($type) {
326 case 'delete':
327 // Set uid=0 for images uploaded by the deleted user
328 db_query('UPDATE {node_images} SET uid=0 WHERE uid=%d', $user->uid);
329 }
330 }
331
332 /**
333 * Implementation of hook_file_download().
334 * Find out if an image is accessible when download method is set to private
335 */
336 function node_images_file_download($file) {
337 $path = file_create_path($file);
338 $result = db_query("SELECT * FROM {node_images} WHERE filepath='%s' OR thumbpath='%s'", $path, $path);
339 if ($file = db_fetch_object($result)) {
340 $node = node_load($file->nid);
341 if (node_access('view', $node)) {
342 if ($path == $file->thumbpath) {
343 // update header info if thumb is requested
344 $name = mime_header_encode(basename($file->thumbpath));
345 $size = $file->thumbsize;
346 }
347 else {
348 $name = mime_header_encode($file->filename);
349 $size = $file->filesize;
350 }
351 $type = mime_header_encode($file->filemime);
352 return array(
353 'Content-Type: '. $type .'; name='. $name,
354 'Content-Length: '. $size,
355 'Cache-Control: private'
356 );
357 }
358 else {
359 return -1;
360 }
361 }
362 }
363
364
365 /************************************************************
366 * Upload functions
367 ************************************************************/
368
369 function _node_images_attach_form($form_state, $node) {
370 $form = array(
371 '#cache' => TRUE,
372 );
373 $form['node_images'] = _node_images_attach_list($node);
374
375 if (_node_images_access('create', $node)) {
376 $limits = _node_images_file_limits($user);
377 $form['node_images_file'] = array(
378 '#type' => 'file',
379 '#title' => t('Attach new image'),
380 '#size' => 40,
381 '#description' => ($limits['resolution'] ? t('Images larger than %resolution will be resized. ', array('%resolution' => $limits['resolution'])) : '') . t('The maximum upload size is %filesize. Only files with the following extensions may be uploaded: %extensions. ', array('%extensions' => $limits['extensions'], '%filesize' => format_size($limits['file_size']))),
382 '#weight' => 30,
383 );
384 $form['node_images_attach'] = array(
385 '#type' => 'submit',
386 '#value' => t('Attach'),
387 '#name' => 'attach',
388 '#ahah' => array(
389 'path' => 'node_images/js',
390 'wrapper' => 'node_images-attach-wrapper',
391 'progress' => array('type' => 'bar', 'message' => t('Please wait...')),
392 ),
393 '#submit' => array('node_form_submit_build_node'),
394 '#weight' => 31,
395 );
396 }
397
398 return $form;
399 }
400
401 function _node_images_attach_list($node) {
402 $form = array(
403 '#theme' => 'node_images_attach_list',
404 '#tree' => TRUE,
405 );
406 if (is_array($node->node_images) && !empty($node->node_images)) {
407 $delta = max(count($node->node_images), 10);
408 foreach ($node->node_images as $key => $file) {
409 $file = (object)$file;
410 $thumb = file_create_url($file->filepath);
411 $row = array();
412 $row['fid'] = array('#type' => 'value', '#value' => $file->fid);
413 $row['filepath'] = array('#type' => 'value', '#value' => $file->filepath);
414 $row['delete'] = array('#type' => 'checkbox');
415 $row['list'] = array('#type' => 'checkbox', '#default_value' => $file->list);
416 $row['thumbnail'] = array('#value' => '<img src="'.$thumb.'" width="75" alt="" />');
417 $row['description'] = array('#type' => 'textfield', '#default_value' => $file->description, '#maxlength' => 255, '#size' => 40);
418 $row['filename'] = array('#type' => 'value', '#value' => $file->filename);
419 $row['filemime'] = array('#type' => 'value', '#value' => $file->filemime);
420 $row['filesize'] = array('#value' => format_size($file->filesize));
421 $row['weight'] = array('#type' => 'weight', '#delta' => $delta, '#default_value' => $file->weight);
422 $form[$key] = $row;
423 }
424 }
425 return $form;
426 }
427
428 /**
429 * Save the current uploaded file.
430 *
431 * @return
432 * An object containing the file information, or FALSE in the event of an error.
433 */
434 function _node_images_file_upload($form, &$form_state, $node = NULL) {
435 global $user;
436
437 $limits = _node_images_file_limits($user);
438 $validators = array(
439 'file_validate_is_image' => array(),
440 'file_validate_image_resolution' => array($limits['resolution']),
441 'file_validate_size' => array($limits['file_size']),
442 '_node_images_file_validate_name' => array(),
443 );
444
445 // Save new file upload.
446 $dest = ($node ? _node_images_get_directory('', $user, $node) : file_directory_path());
447 if ($file = file_save_upload('node_images_file', $validators, $dest)) {
448 return $file;
449 }
450
451 return FALSE;
452 }
453
454 /**
455 * Save new uploads and store them in the session to be associated to the node
456 * on _node_images_save_attachments.
457 *
458 * @param $node
459 * A node object to associate with uploaded images.
460 */
461 function node_images_node_form_submit($form, &$form_state, $node = NULL) {
462 global $user;
463
464 // Save new file upload.
465 $file = _node_images_file_upload($form, $form_state);
466 if (!$file) return;
467
468 $file->list = 1;
469 $file->description = $file->filename;
470 $file->weight = 0;
471 $_SESSION['node_images'][$file->fid] = $file;
472
473 // Attach session files to node.
474 if (!empty($_SESSION['node_images'])) {
475 foreach ($_SESSION['node_images'] as $fid => $file) {
476 if (!isset($form_state['values']['node_images'][$fid]['filepath'])) {
477 $form_state['values']['node_images'][$fid] = (array)$file;
478 }
479 }
480 }
481
482 // Order the form according to the set file weight values.
483 if (!empty($form_state['values']['node_images'])) {
484 $microweight = 0.001;
485 foreach ($form_state['values']['node_images'] as $fid => $file) {
486 if (is_numeric($fid)) {
487 $form_state['values']['node_images'][$fid]['#weight'] = $file['weight'] + $microweight;
488 $microweight += 0.001;
489 }
490 }
491 uasort($form_state['values']['node_images'], 'element_sort');
492 }
493 }
494
495 function _node_images_save_attachments(&$node) {
496 global $user;
497
498 if (empty($node->node_images) || !is_array($node->node_images)) {
499 return;
500 }
501
502 $result = _node_images_check_directory(NULL, $user, $node);
503 if (!$result) return FALSE;
504 $dest = _node_images_get_directory('', $user, $node);
505
506 foreach ($node->node_images as $fid => $file) {
507 // Convert file to object for compatibility
508 $file = (object)$file;
509 if (!$file->delete) {
510 $result = file_move($file->filepath, $dest);
511 if (!$result) {
512 drupal_set_message(t('Unable to copy image "%image".',
513 array('%image' => $file->filename)), 'error');
514 }
515
516 // If we made it this far it's safe to record this file in the database.
517 $file->filepath = $dest .'/'. basename($file->filepath);
518 $thumb = _node_images_create_thumbnail($file->filepath);
519 $file->uid = $user->uid;
520 $file->nid = $node->nid;
521 $file->timestamp = time();
522 $file->filesize = filesize($file->filepath);
523 $file->thumbpath = $thumb->filepath;
524 $file->thumbsize = $thumb->filesize;
525 $file->status = 1;
526 drupal_write_record('node_images', $file);
527 }
528 else {
529 file_delete($file->filepath);
530 db_query('DELETE FROM {files} WHERE fid = %d', $fid);
531
532 // Remove it from the session in the case of new uploads,
533 // that you want to disassociate before node submission.
534 unset($_SESSION['node_images'][$fid]);
535 }
536 }
537
538 // Empty the session storage after save. We use this variable to track files
539 // that haven't been related to the node yet.
540 unset($_SESSION['node_images']);
541 }
542
543 /**
544 * Menu-callback for JavaScript-based uploads.
545 */
546 function _node_images_js() {
547 global $user;
548
549 $output = '';
550 //$nid = $_POST['nid'];
551
552 if ($_POST['form_id'] == 'page_node_form') {
553 // upload from node creation page
554
555 // Load the form from the Form API cache.
556 $cache = cache_get('form_'. $_POST['form_build_id'], 'cache_form');
557
558 // Handle new uploads, and merge tmp files into node_images.
559 $node = (object)$_POST;
560 node_images_node_form_submit($form, $form_state);
561 if (!empty($form_state['values']['node_images'])) {
562 foreach ($form_state['values']['node_images'] as $fid => $file) {
563 if (is_numeric($fid)) {
564 $node->node_images[$fid] = $file;
565 if (0 && !isset($file['filepath'])) {
566 $node->node_images[$fid] = $node_files[$fid];
567 }
568 }
569 }
570 }
571
572 $form = _node_images_attach_form($form_state, $node);
573
574 // Update the default values changed in the $_POST array.
575 $files = isset($_POST['node_images']) ? $_POST['node_images'] : array();
576 foreach ($files as $fid => $file) {
577 if (is_numeric($fid)) {
578 $form['node_images'][$fid]['description']['#default_value'] = $file['description'];
579 $form['node_images'][$fid]['list']['#default_value'] = isset($file['list']) ? 1 : 0;
580 $form['node_images'][$fid]['remove']['#default_value'] = isset($file['remove']) ? 1 : 0;
581 $form['node_images'][$fid]['weight']['#default_value'] = $file['weight'];
582 $form['node_images'][$fid]['filemime']['#value'] = $file['filemime'];
583 }
584 }
585
586 // Add the new element to the stored form state and resave.
587 $cache->data['node_images']['wrapper'] = array_merge($cache->data['node_images']['wrapper'], $form);
588 cache_set('form_'. $_POST['form_build_id'], $cache->data, 'cache_form', $cache->expire);
589
590 // Render the form for output.
591 $form += array(
592 '#post' => $_POST,
593 '#programmed' => FALSE,
594 '#tree' => FALSE,
595 '#parents' => array(),
596 );
597 drupal_alter('form', $form, array(), 'node_images_js');
598 }
599 elseif ($nid = $_POST['nid']) {
600 // upload from node images page
601 if ($node = node_load($nid)) {
602 $form = array();
603 $form_state = array('values' => $_POST);
604
605 if ($file = _node_images_upload_submit($form, $form_state, $node)) {
606 // upload successful, reload node
607 $node = node_load(array('nid' => $nid));
608 }
609
610 $form = _node_images_edit_form($form_state, $node);
611 }
612 }
613
614 $form_state = array('submitted' => FALSE, 'values' => $_POST);
615 $form = form_builder('_node_images_js', $form, $form_state);
616 $form['#sorted'] = TRUE;
617
618 $output .= theme('status_messages') . drupal_render($form);
619
620 // We send the updated node images form.
621 print drupal_to_js(array('status' => TRUE, 'data' => $output));
622 exit();
623 }
624
625 /**
626 * Upload a new image and associate it to the current node.
627 *
628 * @param $form
629 * The form structure.
630 * @param $form_state
631 * An associative array containing the current state of the form.
632 * @param $node
633 * A node object to associate with uploaded image.
634 * @return
635 * the uploaded image file, or FALSE if upload fails
636 */
637 function _node_images_upload_submit($form, &$form_state, $node = NULL) {
638 global $user;
639
640 if (!$node && is_numeric(arg(1))) {
641 $node = node_load(arg(1));
642 }
643 else {
644 }
645 if (!$node || !isset($node->nid)) {
646 drupal_set_message(t('Node not valid.'), 'error');
647 }
648
649 if (!_node_images_access('create', $node)) {
650 drupal_set_message(t('You are not allowed to upload node images.'), 'error');
651 return FALSE;
652 }
653
654 if ($file = _node_images_file_upload($form, $form_state, $node)) {
655 $description = $form_state['values']['description'];
656 if (trim($description) == '') {
657 $description = basename($file->filename);
658 }
659 $thumb = _node_images_create_thumbnail($file->filepath);
660
661 // If we made it this far it's safe to record this file in the database.
662 $file->uid = $user->uid;
663 $file->nid = $node->nid;
664 $file->timestamp = time();
665 $file->thumbpath = $thumb->filepath;
666 $file->thumbsize = $thumb->filesize;
667 $file->description = $description;
668 $file->status = 1;
669 $file->weight = $form_state['values']['weight'];
670 $file->list = (isset($form_state['values']['list']) ? $form_state['values']['list'] : 1);
671
672 $result = drupal_write_record('node_images', $file);
673 if ($result == SAVED_NEW) {
674 drupal_set_message(t('The image has been successfully uploaded.'));
675 }
676 return $file;
677 }
678
679 return FALSE;
680 }
681
682
683 /************************************************************
684 * Theme functions
685 ************************************************************/
686
687 /**
688 * Theme the list of attached images.
689 *
690 * @ingroup themeable
691 */
692 function theme_node_images_attach_list(&$form) {
693 $header = array('', t('Delete'), t('List'), t('Thumbnail'), t('Description'), t('Weight'), t('Size'));
694 drupal_add_tabledrag('node_images_attach_list', 'order', 'sibling', 'node_images-weight');
695
696 foreach (element_children($form) as $key) {
697 if (!$form[$key]['thumbnail']) continue;
698
699 // Add class to group weight fields for drag and drop.
700 $form[$key]['weight']['#attributes']['class'] = 'node_images-weight';
701
702 $row = array('');
703 $row[] = drupal_render($form[$key]['delete']);
704 $row[] = drupal_render($form[$key]['list']);
705 $row[] = drupal_render($form[$key]['thumbnail']);
706 $row[] = array('data' => drupal_render($form[$key]['description']), 'width' => '100%');
707 $row[] = drupal_render($form[$key]['weight']);
708 $row[] = array('data' => drupal_render($form[$key]['filesize']), 'class' => 'nowrap');
709 $rows[] = array('data' => $row, 'class' => 'draggable');
710 }
711
712 $output = '';
713 if (!empty($rows)) $output .= theme('table', $header, $rows, array('id' => 'node_images_attach_list'));
714 $output .= drupal_render($form);
715 return $output;
716 }
717
718 /**
719 * Show node images in the node view.
720 */
721 function theme_node_images_view($node, $teaser, $page, $block = FALSE, $count = NULL, $format = NULL) {
722 if (arg(2) == 'image_gallery' || empty($node->node_images)) return;
723
724 $output = '';
725 $i = 0;
726
727 // set maximum number of images for teaser/body
728 $view = ($teaser ? 'teaser' : 'body');
729 if (!$count) {
730 $count = variable_get('node_images_'.$view.'_images_'.$node->type, 2);
731 }
732 if (isset($count) && $count == '0') return;
733
734 // set image format
735 if (!$format) {
736 $format = variable_get('node_images_'.$view.'_format_'.$node->type, 'thumbs');
737 }
738
739 foreach((array)$node->node_images as $id => $image) {
740 $description = check_plain($image->description);
741 $pattern = '<img src="%path" alt="%description" />';
742 $thumb = strtr($pattern, array('%path'=>file_create_url($image->thumbpath), '%description'=>$description));
743 $fullsize = strtr($pattern, array('%path'=>file_create_url($image->filepath), '%description'=>$description));
744
745 if ($info = @getimagesize($image->filepath)) {
746 $width = $info[0] + 36;
747 $height = $info[1] + 36;
748 }
749 else {
750 $width = 420;
751 $height = 315;
752 }
753
754 if ($format == 'thumbs') {
755 $output .= '<a href="javascript:void(0);" title="'.$description.'" onclick="window.open(\''.
756 file_create_url($image->filepath).'\', \'\', \'height='.$height.',width='.$width.'\');">'.$thumb.'</a> ';
757 }
758 else {
759 $output .= $fullsize.' ';
760 }
761 if ($count>0 && ++$i >= $count) break;
762 }
763
764 if ($block && $count < count($node->node_images)) {
765 $output .= '<div class="node_images_block_link">'.l(t('View all images'), 'node/'.$node->nid.'/image_gallery').'</div>';
766 }
767
768 return $output;
769 }
770
771
772 /************************************************************
773 * Helper functions - other
774 ************************************************************/
775
776 /**
777 * Check access to add, edit or delete node images.
778 */
779 function _node_images_access($op, $node) {
780 global $user;
781
782 //if (node_access($op, $node)) return TRUE;
783
784 $type = node_get_types('name', $node);
785 if ($op == 'create') {
786 return (user_access('add node images to any '. $type .' content') || (user_access('add node images to own '. $type .' content') && ($user->uid == $node->uid)));
787 }
788 if ($op == 'update') {
789 return (user_access('edit any node_image') || (user_access('edit own node images') && ($user->uid == $node->uid)));
790 }
791 if ($op == 'delete') {
792 return (user_access('delete any node_image') || (user_access('delete own node images') && ($user->uid == $node->uid)));
793 }
794
795 return FALSE;
796 }
797
798 /**
799 * Checks if the upload.module is enabled, and the existence of an image toolkit.
800 *
801 * @param $form_element
802 * The form element containing the name of the directory to check.
803 */
804 function _node_images_check_settings() {
805 // Make sure we've got a working toolkit
806 if (!image_get_toolkit()) {
807 drupal_set_message(t('Make sure you have a working image toolkit installed and enabled, for more information see: %settings', array('%settings' => l(t('the settings page'), 'admin/settings/image-toolkit'))), 'error');
808 }
809 }
810
811 /**
812 * Checks the existence of the destination directory.
813 * The directory can be specified either in $form_element (when called from the admin settings)
814 * or in $path (when called from the node images edit page).
815 *
816 * @param $form_element
817 * The form element containing the name of the directory to check.
818 */
819 function _node_images_check_directory($form_element = NULL, $u = NULL, $node = NULL) {
820 $dir = (isset($form_element['#value']) ? $form_element['#value'] : '');
821 $path = _node_images_get_directory($dir, $u, $node);
822 $form_item = isset($form_element['#parents'][0]) ? $form_element['#parents'][0] : NULL;
823 $result = _node_images_mkdir_recursive($path, FILE_CREATE_DIRECTORY, $form_element['#parents'][0]);
824 if ($form_element) return $form_element;
825 return $result;
826 }
827
828 function _node_images_mkdir_recursive($path, $mode, $form_item) {
829 if (file_check_directory($path, $mode, $form_item)) return TRUE;
830
831 $folders = explode('/', $path);
832 $dirs = array();
833 foreach ($folders as $folder) {
834 $dirs[] = $folder;
835 $dir = implode('/', $dirs);
836 if (!file_check_directory($dir, $mode, $form_item)) {
837 return FALSE;
838 }
839 }
840 return TRUE;
841 }
842
843 /**
844 * Return the destination directory.
845 */
846 function _node_images_get_directory($dir = '', $u = NULL, $node = NULL) {
847 global $user;
848
849 if (!$u) $u = $user;
850 $variables = array('%uid' => $u->uid, '%username' => $u->name);
851 $variables['%nid'] = ($node ? $node->nid : 0);
852 $variables['%type'] = ($node ? $node->type: 'node');
853 $path = file_directory_path().'/';
854 $path .= ($dir ? trim($dir, '/') : variable_get('node_images_path', 'node_images'));
855 return strtr($path, $variables);
856 }
857
858 /**
859 * Validate, apply md5 and normalize filename.
860 *
861 * @param $file
862 * A Drupal file object.
863 * @return
864 * An array. If the file name is not valid, it will contain an error message.
865 */
866 function _node_images_file_validate_name(&$file) {
867 $errors = array();
868
869 if (variable_get('node_images_md5name', FALSE)) {
870 // set md5 file name
871 preg_match('/\.(.*?)$/i', $file->filename, $m);
872 $extension = $m[1];
873 $file->filename = substr(md5($dest.'/'.$file->filename), 0, 16);
874 if ($extension) $file->filename .= '.'.strtolower($extension);
875 }
876 $file->filename = preg_replace(array('/[ \']+/', '/["]+/'), array('_', ''), $file->filename);
877
878 if (strlen($file->filename) > 255) {
879 $errors[] = t('Its name exceeds the 255 characters limit. Please rename the file and try again.');
880 }
881 return $errors;
882 }
883
884 /**
885 * Create the thumbnail for the uploaded image.
886 */
887 function _node_images_create_thumbnail($source, $suffix = '_tn') {
888 $size = variable_get('node_images_thumb_resolution', '100x100');
889 list($width, $height) = explode('x', $size);
890 $dest = preg_replace('!(\.[^/.]+?)?$!', "$suffix\\1", $source, 1);
891
892 if ($size = @getimagesize($source)) {
893 if (!image_scale($source, $dest, $width, $height)) {
894 file_copy($source, $dest, FILE_EXISTS_REPLACE);
895 }
896 $info = image_get_info($dest);
897 $thumb = new stdClass();
898 $thumb->filename = basename($dest);
899 $thumb->filepath = $dest;
900 $thumb->filesize = $info['file_size'];
901 $thumb->filemime = $info['mime_type'];
902 return $thumb;
903 }
904 return NULL;
905 }
906
907 /**
908 * Determine the limitations on files that a given user may upload. The user
909 * may be in multiple roles so we select the most permissive limitations from
910 * all of their roles.
911 *
912 * @param $user
913 * A Drupal user object.
914 * @return
915 * An associative array with the following keys:
916 * 'extensions'
917 * A white space separated string containing the allowed extensions.
918 * 'file_size'
919 * The maximum size of a file upload in bytes.
920 * 'resolution'
921 * A string specifying the maximum resolution of images.
922 */
923 function _node_images_file_limits($user) {
924 return array(
925 'extensions' => variable_get('node_images_extensions', 'jpg jpeg gif png'),
926 'file_size' => variable_get('node_images_file_limit', 1) * 1024 * 1024,
927 'resolution' => variable_get('node_images_large_resolution', 0),
928 );
929 }

  ViewVC Help
Powered by ViewVC 1.1.2