/[drupal]/contributions/sandbox/walkah/image/45/image.module
ViewVC logotype

Contents of /contributions/sandbox/walkah/image/45/image.module

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


Revision 1.6 - (show annotations) (download) (as text)
Thu Mar 3 16:36:08 2005 UTC (4 years, 8 months ago) by walkah
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +127 -13 lines
File MIME type: text/x-php
sync'ing 45 with the head version
1 <?php
2 // $Id: image.module,v 1.5 2005/02/18 09:39:43 killes Exp $
3
4 require_once dirname(__FILE__) . '/image.inc';
5
6 /**
7 * Implementation of hook_help
8 */
9 function image_help($section) {
10 switch ($section) {
11 case 'admin/modules#description':
12 return t('Allows uploading of images and creating image galleries.');
13 case 'node/add#image':
14 return t('An image (with thumbnail). This is ideal for publishing photographs or screenshots.');
15 case 'admin/image':
16 return t('Image galleries can be used to organize and present groups of images. Gallery "albums" may be nested. To add a new gallery click the "add album" tab.');
17 }
18 }
19
20 /**
21 * Implementation of hook_node_name
22 */
23 function image_node_name() {
24 return t('image');
25 }
26
27 /**
28 * Implementation of hook_perm
29 */
30 function image_perm() {
31 return array('administer images', 'create images');
32 }
33
34 /**
35 * Implementation of hook_access
36 */
37 function image_access($op, $node) {
38 global $user;
39
40 if ($op == 'create' && user_access('create images')) {
41 return TRUE;
42 }
43
44 if ($op == 'update' && $user->uid == $node->uid) {
45 return TRUE;
46 }
47
48 if ($op == 'delete' && $user->uid == $node->uid) {
49 return TRUE;
50 }
51 }
52
53 /**
54 * Implementation of hook_settings
55 */
56 function image_settings() {
57 _image_check_settings();
58
59 $paths .= form_textfield(t('Default image path'), 'image_default_path', variable_get('image_default_path', 'images'), 30, 255, t('Subdirectory in the directory "%dir" where pictures will be stored.', array('%dir' => '<em>'. variable_get('file_directory_path', 'files') .'/</em>')));
60 $output.= form_group(t('File paths'), $paths);
61
62 // Size and restrictions
63 $sizes = _image_get_sizes();
64 $rows = array();
65 for ($i = 0; $i < 5; $i++) {
66 $row = array();
67 if (in_array($sizes[$i]['label'], _image_required_sizes())) {
68 $row[] = form_hidden('image_sizes]['.$i.'][label', $sizes[$i]['label']) .
69 form_textfield(NULL, 'image_sizes]['. $i .'][label', $sizes[$i]['label'], 24, 255, NULL, array('disabled' => 'disabled'));
70 }
71 else {
72 $row[] = form_textfield(NULL, 'image_sizes]['. $i .'][label', $sizes[$i]['label'], 24, 255);
73 }
74 $row[] = form_textfield(NULL, 'image_sizes]['. $i .'][width', $sizes[$i]['width'], 5, 5);
75 $row[] = form_textfield(NULL, 'image_sizes]['. $i .'][height', $sizes[$i]['height'], 5, 5);
76
77 $rows[] = $row;
78 }
79 $header = array(t('Label'), t('Width'), t('Height'));
80 $size_group .= form_item(NULL, theme('table', $header , $rows), t('Select various pixel dimensions, "thumbnail" and "preview" are required.'));
81 $size_group .= form_checkbox(t('Allow users to view original image'), 'image_view_original', 1, variable_get('image_view_original', 0));
82 $output.= form_group(t('Image sizes'), $size_group);
83
84 return $output;
85 }
86
87 /**
88 * Implementation of hook_menu
89 */
90 function image_menu($may_cache) {
91 $items = array();
92
93 if ($may_cache) {
94 $items[] = array('path' => 'node/add/image', 'title' => t('image'),
95 'access' => user_access('create images'));
96 $items[] = array('path' => 'image', 'title' => t('image galleries'),
97 'access' => user_access('access content'),
98 'type' => MENU_SUGGESTED_ITEM,
99 'callback' => 'image_page');
100 $items[] = array('path' => 'image/view', 'title' => t('image'),
101 'access' => user_access('access content'),
102 'type' => MENU_CALLBACK,
103 'callback' => 'image_fetch');
104 $items[] = array('path' => 'admin/image', 'title' => t('image'),
105 'access' => user_access('administer images'),
106 'callback' => 'image_admin');
107 $items[] = array('path' => 'admin/image/list', 'title' => t('list'),
108 'access' => user_access('administer images'),
109 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
110 $items[] = array('path' => 'admin/image/add', 'title' => t('add album'),
111 'access' => user_access('administer images'),
112 'type' => MENU_LOCAL_TASK);
113 }
114
115 return $items;
116 }
117
118 /**
119 * Implements hook_cron. (deletes old temp images)
120 */
121 function image_cron() {
122 $path = variable_get('image_default_path', 'image') . '/temp';
123 $files = file_scan_directory(file_create_path($path), '.*');
124 foreach ($files as $file => $info) {
125 if (time() - filemtime($file) > 60*60*6) {
126 file_delete($file);
127 }
128 }
129 }
130
131 /**
132 * Implementation of hook_validate
133 */
134 function image_validate(&$node, $field_name) {
135 if (is_null($field_name)) {
136 $field_name = 'image';
137 }
138 if ($file = file_check_upload($field_name)) {
139 $file = file_save_upload($field_name, _image_filename($file->filename, NULL, TRUE));
140 if ($file) {
141 if (!image_get_info($file->filepath)) {
142 form_set_error($field_name, t('Uploaded file is not a valid image'));
143 return;
144 }
145 }
146 else {
147 return;
148 }
149 $node->file = $file;
150 _image_build_derivatives($node);
151 }
152 }
153
154 /**
155 * implement hook_file_download
156 */
157 function image_file_download($file) {
158 $size = image_get_info(file_create_path($file));
159 if ($size) {
160 $headers = array('Content-Type: ' . $size['mime_type']);
161 return $headers;
162 }
163 }
164
165 /**
166 * Implementation of hook_link.
167 */
168 function image_link($type, $node, $main = 0) {
169 $links = array();
170
171 if ($type == "page" && user_access('access content')) {
172 if (_image_get_vid()) {
173 $links[] = l(t("image galleries"), "image");
174 }
175 }
176
177 if ($type == 'node' && $node->type == 'image' && !$main) {
178 $sizes = array();
179 foreach (_image_get_sizes() as $size) {
180 if ($size['label'] && !in_array($size['label'], array('thumbnail', '_original'))) {
181 $sizes[] = $size;
182 }
183 }
184
185 if (count($sizes) > 1) {
186 $request = ($_GET['size']) ? $_GET['size'] : 'preview';
187 foreach ($sizes as $size) {
188 if ($request != $size['label']) {
189 $links[] = l($size['label'], 'node/'. $node->nid, NULL, 'size='.urlencode($size['label']));
190 }
191 }
192 }
193 if (variable_get('image_view_original', 0)) {
194 $links[] = l(t('view original'), 'node/'.$node->nid, NULL, 'size=_original');
195 }
196 }
197
198 return $links;
199 }
200
201 /**
202 * Implementation of hook_block.
203 *
204 * Offers 2 blocks: latest image and random image
205 */
206 function image_block($op, $delta = 0) {
207 switch ($op) {
208 case 'list':
209 $block[0]['info'] = t('Latest image');
210 $block[1]['info'] = t('Random image');
211
212 return $block;
213 case 'view':
214 switch($delta) {
215 case 0:
216 $images = image_get_latest();
217 $block['subject'] = t('Latest image');
218 $block['content'] = l(image_display($images[0], 'thumbnail'), 'node/'.$images[0]->nid);
219 break;
220 case 1:
221 $images = image_get_random();
222 $block['subject'] = t('Random image');
223 $block['content'] = l(image_display($images[0], 'thumbnail'), 'node/'.$images[0]->nid);
224 break;
225 }
226 return $block;
227 }
228 }
229
230 /**
231 * Implementation of hook_form
232 */
233 function image_form(&$node, &$param) {
234 _image_check_settings();
235
236 $param['options'] = array("enctype" => "multipart/form-data", "name" => "image_forms");
237
238 if (is_array($node->images)) {
239 foreach ($node->images as $label => $image) {
240 $output .= form_hidden('images]['.$label, $image);
241 }
242 }
243
244 // Taxonomy select form
245 $output .= implode('', taxonomy_node_form('image', $node));
246
247 if ($node->images['thumbnail']) {
248 $output.= form_item(t('Thumbnail'), image_display($node, 'thumbnail'));
249 }
250
251
252 $output .= form_file(t('Image'), 'image', 50, t('Click "Browse..." to select an image to upload.'), TRUE);
253 $output .= form_textarea(t("Description"), 'body', $node->body, 60, 5);
254 $output .= filter_form('format', $node->format);
255
256 return $output;
257 }
258
259 /**
260 * Implementation of hook_view
261 */
262 function image_view(&$node, $main = 0, $page = 0) {
263 if ($page) {
264 $terms = taxonomy_node_get_terms_by_vocabulary($node->nid, _image_get_vid());
265 $term = array_pop($terms);
266 if ($term) {
267 $vocabulary = taxonomy_get_vocabulary(_image_get_vid());
268 // Breadcrumb navigation
269 $breadcrumb = array();
270 $breadcrumb[] = array('path' => 'image', 'title' => $vocabulary->name);
271 if ($parents = taxonomy_get_parents_all($term->tid)) {
272 $parents = array_reverse($parents);
273 foreach ($parents as $p) {
274 $breadcrumb[] = array('path' => 'image/tid/'. $p->tid, 'title' => $p->name);
275 }
276 }
277 $breadcrumb[] = array('path' => 'node/'. $node->nid);
278 menu_set_location($breadcrumb);
279 }
280 }
281 $request = ($_GET['size']) ? $_GET['size'] : 'preview';
282 $node = node_prepare($node, $main);
283 $node->teaser = l(image_display($node, 'thumbnail'), 'node/'.$node->nid) . $node->teaser;
284 $node->body = image_display($node, $request) . $node->body;
285 }
286
287
288 /**
289 * Implementation of hook_load
290 */
291 function image_load(&$node) {
292 $result = db_query("SELECT filename, filepath FROM {files} WHERE nid=%d", $node->nid);
293 $node->images = array();
294 while ($file = db_fetch_object($result)) {
295 $node->images[$file->filename] = $file->filepath;
296 }
297 // special images
298 if (empty($node->images['thumbnail'])) {
299 $node->images['thumbnail'] = $node->images['_original'];
300 }
301 if (empty($node->images['preview'])) {
302 $node->images['preview'] = $node->images['_original'];
303 }
304 }
305
306 /**
307 * Implementation of hook_insert
308 */
309 function image_insert($node) {
310 foreach ($node->images as $label => $image) {
311 _image_insert($node->nid, $label, file_create_path($image));
312 }
313 }
314
315 /**
316 * Implementation of hook_update
317 */
318 function image_update($node) {
319 foreach ($node->images as $label => $image) {
320 $old_path = db_result(db_query("SELECT filepath FROM {files} WHERE filename='%s' AND nid=%d", $label, $node->nid));
321 // This is a new image.
322 if ($old_path != $image) {
323 file_delete(file_create_path($old_path));
324 db_query("DELETE FROM {files} WHERE filename='%s' AND nid=%d", $label, $node->nid);
325 _image_insert($node->nid, $label, file_create_path($image));
326 }
327 }
328 }
329
330 /**
331 * Implementation of hook_delete.
332 */
333 function image_delete($node) {
334 foreach ($node->images as $label => $image) {
335 file_delete(file_create_path($image));
336 db_query("DELETE FROM {files} WHERE filename='%s' AND nid=%d", $label, $node->nid);
337 }
338 }
339
340 /**
341 * Create an <img> tag for an image.
342 */
343 function image_display($node, $size = 'preview', $attributes = array()) {
344 if (!empty($node->images[$size])) {
345 $info = image_get_info(file_create_path($node->images[$size]));
346 $attr = 'width="'.$info['width'].'" height="'.$info['height'].'" ' . drupal_attributes($attributes);
347 $output.= '<div class="image '.$size.'">';
348 $output.= theme('image', file_create_url($node->images[$size]), check_form($node->title), check_form($node->title), $attr, FALSE);
349 $output.= "</div>\n";
350 return $output;
351 }
352 }
353
354 /**
355 * Fetches an image file, allows "shorthand" image urls such of the form:
356 * image/view/$nid/$label
357 * (e.g. image/view/25/thumbnail or image/view/14)
358 */
359 function image_fetch($nid = 0, $size = 'preview') {
360 if ($nid) {
361 $node = node_load(array('nid' => $nid));
362 if ($node->images[$size]) {
363 $file = $node->images[$size];
364 $headers = image_file_download($file);
365 file_transfer($file, $headers);
366 }
367 }
368 }
369
370 /**
371 * Image album callback, displays an image album
372 */
373 function image_page($type = NULL, $tid = 0) {
374 // ALBUMS
375 drupal_set_html_head('<style type="text/css">@import url('.module_get_path('image').'/image.css);</style>');
376 $albums = taxonomy_get_tree(_image_get_vid(), $tid, -1, 1);
377 for ($i=0; $i < count($albums); $i++) {
378 $albums[$i]->count = db_result(db_query("SELECT COUNT(*) FROM {term_node} t INNER JOIN {node} n ON t.nid=n.nid WHERE n.status=1 AND n.type='image' AND t.tid=%d", $albums[$i]->tid));
379 $last = db_fetch_object(db_query_range("SELECT n.nid FROM {node} n INNER JOIN {term_node} t ON n.nid = t.nid WHERE t.tid=%d AND n.type = 'image' AND n.status = 1 ORDER BY n.sticky DESC, n.changed DESC", $albums[$i]->tid, 0, 1));
380 $albums[$i]->latest = node_load(array('nid' => $last->nid));
381 }
382
383 $images = array();
384 if ($tid) {
385 $result = pager_query("SELECT n.nid FROM {term_node} t INNER JOIN {node} n ON t.nid=n.nid WHERE n.status=1 AND n.type='image' AND t.tid=%d ORDER BY n.sticky DESC, n.created DESC", 6, 0, NULL, $tid);
386 while ($node = db_fetch_object($result)) {
387 $images[] = node_load(array('nid' => $node->nid));
388 }
389
390 $album = taxonomy_get_term($tid);
391 $parents = taxonomy_get_parents($tid);
392 foreach ($parents as $parent) {
393 $breadcrumb[] = l($parent->name, 'image/tid/'.$parent->tid);
394 }
395 $breadcrumb[] = l(t('Image galleries'), 'image');
396 $breadcrumb[] = l(t('Home'), '');
397 $breadcrumb = array_reverse($breadcrumb);
398 drupal_set_breadcrumb($breadcrumb);
399 drupal_set_title($album->name);
400 }
401
402 $content = theme('image_album', $albums, $images);
403 print theme('page', $content);
404 }
405
406 /**
407 * Admin callback for managing galleries
408 */
409 function image_admin() {
410 _image_check_settings();
411
412 switch (arg(2)) {
413 case 'add':
414 case 'edit':
415 if ($_POST['edit']) {
416 if ($_POST['op'] == t('Delete')) {
417 if ($_POST['edit']['confirm']) {
418 taxonomy_del_term($_POST['edit']['tid']);
419 drupal_goto('admin/image');
420 }
421 else {
422 $content = _taxonomy_confirm_del_term($_POST['edit']['tid']);
423 }
424 }
425 else {
426 taxonomy_save_term($_POST['edit']);
427 drupal_goto('admin/image');
428 }
429 }
430 else {
431 $content = image_admin_album(object2array(taxonomy_get_term(arg(3))));
432 }
433 break;
434 default:
435 $content = image_admin_overview();
436 }
437 print theme('page', $content);
438 }
439
440 function image_admin_overview() {
441 $header = array(t('Name'), t('Operations'));
442
443 $tree = taxonomy_get_tree(_image_get_vid());
444 if ($tree) {
445 foreach ($tree as $term) {
446 $rows[] = array(_image_depth($term->depth) .' '. $term->name, l(t('edit album'), "admin/image/edit/$term->tid"));
447 }
448 return theme('table', $header, $rows);
449 }
450 }
451
452 function image_admin_album($edit = array()) {
453 if (empty($edit)) {
454 $edit['vid'] = _image_get_vid();
455 }
456
457 $form = form_textfield(t('Album name'), 'name', $edit['name'], 50, 64, t('The name is used to identify the album.'), NULL, TRUE);
458 $form .= form_textarea(t('Description'), 'description', $edit['description'], 60, 5, t('The description can be used to provide more information about the forum, or further details about the topic.'));
459
460 $exclude = array();
461 $parent = array_keys(taxonomy_get_parents($edit['tid']));
462 $children = taxonomy_get_tree($edit['vid'], $edit['tid']);
463 // A term can't be the child of itself, nor of its children.
464 foreach ($children as $child) {
465 $exclude[] = $child->tid;
466 }
467 $exclude[] = $edit['tid'];
468
469 $form .= _taxonomy_term_select(t('Parent'), 'parent', $parent, $edit['vid'], NULL, 0, '<'. t('root') .'>', $exclude);
470 $form .= form_weight(t('Weight'), 'weight', $edit['weight'], 10, t('In listings, the heavier (with a higher weight value) terms will sink and the lighter terms will be positioned nearer the top.'));
471
472 $form .= form_hidden('vid', $edit['vid']);
473 $form .= form_submit(t('Submit'));
474 if ($edit['tid']) {
475 $form .= form_submit(t('Delete'));
476 $form .= form_hidden('tid', $edit['tid']);
477 }
478
479 return form($form);
480 }
481
482 /**
483 * Theme a gallery page
484 */
485 function theme_image_album($albums, $images) {
486 $content = '';
487 if (count($albums)) {
488 $content.= '<ul class="albums">';
489 foreach ($albums as $album) {
490 $content.= "<li>";
491 $content.= l(image_display($album->latest, 'thumbnail'), 'image/tid/'.$album->tid);
492 $content.= "<h3>".l($album->name, 'image/tid/'.$album->tid) . "</h3>\n";
493 $content.= '<div class="description">'. check_output($album->description) ."</div>\n";
494 $content.= '<p class="count">' . format_plural($album->count, 'There is %count image in this album', 'There are %count images in this album') . "</p>\n";
495 if ($album->latest->changed) {
496 $content.= '<p class="last">'. t('Last updated: %date', array('%date' => format_date($album->latest->changed))) . "</p>\n";
497 }
498 $content.= "</li>\n";
499 }
500 $content.= "</ul>\n";
501 }
502
503 if (count($images)) {
504 $content.= '<ul class="images">';
505 foreach ($images as $image) {
506 $content .= '<li';
507 if ($image->sticky) {
508 $content .= ' class="sticky"';
509 }
510 $content .= ">\n";
511 $content .= l(image_display($image, 'thumbnail'), 'node/'.$image->nid);
512 $content .= '<h3>'.l($image->title, 'node/'.$image->nid)."</h3>";
513 $content .= '<div class="author">'. t('Posted by: %name', array('%name' => format_name($image))) . "</div>\n";
514 $content .= '<div class="date">'.format_date($image->created)."</div>\n";
515 $content .= "</li>\n";
516 }
517 $content.= "</ul>\n";
518 }
519
520 if ($pager = theme('pager', NULL, 6, 0)) {
521 $content.= $pager;
522 }
523
524 return $content;
525 }
526
527 /**
528 * Fetch a random N image(s) - optionally from a given term.
529 */
530 function image_get_random($count = 1, $tid = 0) {
531 $result = db_query_range("SELECT nid FROM {node} n WHERE n.type='image' AND n.status=1 ORDER BY RAND()", 0, $count);
532 $output = array();
533 while ($nid = db_fetch_object($result)) {
534 $output[] = node_load(array('nid' => $nid->nid));
535 }
536 return $output;
537 }
538
539 /**
540 * Fetch the latest N image(s).
541 */
542 function image_get_latest($count = 1, $tid = 0) {
543 $result = db_query_range("SELECT nid FROM {node} n WHERE n.type='image' AND n.status=1 ORDER BY changed DESC", 0, $count);
544 $output = array();
545 while ($nid = db_fetch_object($result)) {
546 $output[] = node_load(array('nid' => $nid->nid));
547 }
548 return $output;
549 }
550
551 /**
552 * Verify the image module and toolkit settings.
553 */
554 function _image_check_settings() {
555 // File paths
556 $image_path = file_create_path(variable_get('image_default_path', 'images'));
557 $temp_path = $image_path . '/temp';
558
559 file_check_directory($image_path, FILE_CREATE_DIRECTORY, 'image_default_path');
560 file_check_directory($temp_path, FILE_CREATE_DIRECTORY, 'image_default_path');
561 }
562
563 /**
564 * Generate image derivatives.
565 */
566 function _image_build_derivatives(&$node) {
567 $info = image_get_info($node->file->filepath);
568 $sizes = _image_get_sizes();
569 foreach ($sizes as $size) {
570 $file = NULL;
571 if ($size['label'] && $size['width'] && $size['height']) {
572 if ($info['width'] > $size['width'] || $info['height'] > $size['height']) {
573 $filename = _image_filename($node->file->filename, $size['label'], TRUE);
574 if (!image_scale($node->file->filepath, file_create_path($filename), $size['width'], $size['height'])) {
575 drupal_set_message(t('Unable to create %label image', array('%label' => $size['label'])), 'error');
576 }
577 else {
578 $node->images[$size['label']] = $filename;
579 }
580 }
581 }
582 }
583 $node->images['_original'] = $node->file->filepath;
584 }
585
586 /**
587 * Creates an image filename.
588 */
589 function _image_filename($filename, $type = NULL, $temp = FALSE) {
590 if ($type) {
591 $pos = strrpos($filename, '.');
592 $filename = substr($filename, 0, $pos) .'.'. $type . substr($filename, $pos);
593 }
594
595 $output = variable_get('image_path', 'images') .'/';
596 if ($temp) {
597 $output .= 'temp/';
598 }
599 $output .= $filename;
600
601 return $output;
602 }
603
604 /**
605 * Helper function to return the defined sizes (or proper defaults).
606 */
607 function _image_get_sizes() {
608 return variable_get('image_sizes', array(array('width' => 100, 'height' => 100, 'label' => t('thumbnail')),
609 array('width' => 640, 'height' => 640, 'label' => t('preview'))));
610 }
611
612 function _image_required_sizes() {
613 return array('thumbnail', 'preview', '_original');
614 }
615
616 /**
617 * Moves temporary (working) images to the final directory and stores
618 * relevant information in the files table
619 */
620 function _image_insert($nid, $label, $image) {
621 $dest = _image_filename(basename($image));
622 if (file_move($image, $dest)) {
623 $info = image_get_info(file_create_path($dest));
624 $file->filename = $label;
625 $file->filepath = _image_filename(basename($image));
626 $file->filemime = $info['mime_type'];
627 $file->filesize = filesize(file_create_path($dest));
628 $fid = db_next_id('{files}_fid');
629 db_query("INSERT INTO {files} (fid, nid, filename, filepath, filemime, filesize, list) VALUES (%d, %d, '%s', '%s', '%s', '%s', %d)",
630 $fid, $nid, $file->filename, $file->filepath, $file->filemime, $file->filesize, 0);
631 }
632 }
633
634 /**
635 * Helper function used to generate indentation for gallery list
636 *
637 * @param $depth Depth of the indentation
638 * @param $graphic HTML text to be repeated for each stage of depth
639 */
640 function _image_depth($depth, $graphic = '--') {
641 for ($n = 0; $n < $depth; $n++) {
642 $result .= $graphic;
643 }
644 return $result;
645 }
646
647
648 /**
649 * Returns (and possibly creates) a new vocabulary for Image galleries.
650 */
651 function _image_get_vid() {
652 $vid = variable_get('image_nav_vocabulary', '');
653 if (empty($vid)) {
654 $vocabulary = taxonomy_save_vocabulary(array('name' => t('Image Galleries'), 'multiple' => '0', 'required' => '0', 'hierarchy' => '1', 'relations' => '0', 'module' => 'image', 'nodes' => array('image')));
655 $vid = $vocabulary['vid'];
656 variable_set('image_nav_vocabulary', $vid);
657 }
658
659 return $vid;
660 }
661
662 ?>

  ViewVC Help
Powered by ViewVC 1.1.2