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

Contents of /contributions/modules/photobar/photobar.module

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


Revision 1.2 - (show annotations) (download) (as text)
Sun Sep 3 21:24:51 2006 UTC (3 years, 2 months ago) by jakin
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +183 -38 lines
File MIME type: text/x-php
Merge from 4.7 branch
1 <?php
2 // $Id: photobar.module,v 1.1.2.9 2006/09/03 21:19:16 jakin Exp $
3
4 /*
5 Photobar for Drupal
6 Copyright (C) 2006 Jason Kivlighn <jkivlighn@gmail.com>
7
8 Documentation available at http://students.washington.edu/jkivligh/drupal_photobar/docs/
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25 /**
26 * @file
27 * Enables automatically importing directories as galleries of images on a per-date basic.
28 * For each gallery, a photobar preview of the gallery is created.
29 */
30
31 /**
32 * Implementation of hook_help().
33 */
34 function photobar_help($section) {
35 switch ($section) {
36 case 'admin/help#photobar':
37 $output = '<p>'. t('The photobar module is used to manage automatated uploads of image galleries and display a preview (the \'photobar\') of the gallery. This module automatically creates an image node of every photo in a given directory, creates a gallery, and associates the images with the gallery. The photobar manages this gallery and image nodes, so when the photobar is deleted, so are all the nodes it created') .'</p>';
38 $output .= '<p>'. t('<em>Folders must be in the form YYYY-MM-DD</em>, meaning this module provides a per-date gallery.') .'</p>';
39 $output .= '<p>'. t('This module will automatically create photobars for every folder in files/photos when cron is run. It will add new images to an existing photobar if new images are added to a folder after the photobar has already been created.') .'</p>';
40 $output .= t('<p>You can</p>
41 <ul>
42 <li>post a photobar at <a href="%node-add-photobar">create content &gt;&gt; photobar</a>.</li>
43 <li>configure photobar settings at <a href="%admin-settings-photobar">administer &gt;&gt; settings &gt;&gt; photobar</a>.</li>
44 <li>configure photobar at <a href="%admin-settings-content-types-photobar">administer &gt;&gt; settings &gt;&gt; content types &gt;&gt; configure photobar</a>.</li>
45 </ul>
46 ', array('%node-add-photobar' => url('node/add/photobar'), '%admin-settings-content-types-photobar' => url('admin/settings/content-types/photobar'), '%admin-settings-photobar' => url('admin/settings/photobar')));
47 return $output;
48 case 'admin/modules#description':
49 if (module_exist('photobar') && (!module_exist('image_gallery')||!module_exist('image')) ) {
50 drupal_set_message(t("The %image_gallery and %image module must be enabled for photobar to work. Please download it from the drupal modules site and enable it below.", array('%image_gallery'=>'image_gallery','%image'=>'image')), 'error');
51 }
52 return t('Allows automatically displaying photos');
53 case 'node/add#photobar':
54 return t('A photobar allows displaying a preview of a photo gallery on the front page. All photos in a directory chosen are added to a gallery and managed by this photobar node.');
55 }
56 }
57
58 /**
59 * Get the associated gallery term id.
60 *
61 * This is based on the creation date of the given node.
62 */
63 function _photobar_get_gallery( &$bar_node ) {
64 $result = taxonomy_get_term_by_name($bar_node->title);
65 if ( count($result) == 0 ) {
66 return false;
67 }
68 return $result[0];
69 }
70
71 /**
72 * @param $folder_name The name of the folder
73 * @return the timestamp that a folder with this name will be shown as authored on
74 */
75 function _photobar_get_timestamp( $folder_name ) {
76 return strtotime($folder_name)+(3600*24-1);
77 }
78
79 /**
80 * Theme a photobar.
81 *
82 * @param $images An array of paths to the images to create a photobar of
83 * @param $term The term of the image gallery that this photobar links to. $term->tid must be set to the term id.
84 *
85 * @return HTML of a themed photobar.
86 */
87 function theme_photobar( $images, $gallery_path, $height ) {
88 $max_disp = count($images);
89
90 $content .= '<table cellpadding="0" cellspacing="0" border="0" width="100%"><tr>';
91 $x = true;
92 foreach ( $images as $path ) {
93 if ($x) {
94 $content .= '<td align="center" class="first" width="'.floor(100/$max_disp).'%">';
95 $x=false;
96 } else {
97 $content .= '<td align="center" width="'.floor(100/$max_disp).'%">';
98 }
99 $content .= "<img src=\"$path\" height=\"$height\" />";
100 //$content .= $path;
101 $content .= '</td>';
102 }
103 unset($x);
104 $content .= '</tr></table>';
105
106 $content = l($content, $gallery_path, array(), NULL, NULL, TRUE, TRUE);
107
108 return '<div class="photobar">
109 <div class="hd"><div class="c"></div></div>
110 <div class="bd">
111 <div class="c">
112 <div class="s">
113 '.$content.'
114 </div>
115 </div>
116 </div>
117 <div class="ft"><div class="c"></div></div>
118 </div>';
119 }
120
121 /**
122 * @param bar_node photobar node to create HTML for
123 * @return photobar HTML code. Photos for the bar are chosen at even intervals to include
124 * photos from the beginning, middle, and end of the event.
125 */
126 function _photobar_create( &$bar_node ) {
127 $max_disp = variable_get('photobar_maxdisp', 3);
128 if ( $max_disp == 0 ){ return; }
129 $image_label = variable_get('photobar_img_label', 'thumbnail');
130
131 $term = _photobar_get_gallery($bar_node);
132 if ( $term === false ){ return; }
133
134 $count = db_result(db_query("SELECT COUNT(1) FROM {node} n INNER JOIN {term_node} t ON n.nid=t.nid WHERE type='image' AND t.tid='%d'",$term->tid));
135 if ( $count == 0 ) { return; }
136
137 $max_disp = ($max_disp<$count)?$max_disp:$count;
138 $interval = 1.0*($count)/$max_disp;
139 for ( $i = 0; round($i) < $count; $i+=$interval ) {
140 $queryResult = db_query_range("SELECT n.nid FROM {node} n INNER JOIN {term_node} t ON n.nid=t.nid WHERE type='image' AND t.tid='%d' ORDER BY n.created", $term->tid, round($i), 1);
141 while ($photo = db_fetch_object($queryResult)) {
142 $node = node_load(array('nid' => $photo->nid));
143 //$images[] = image_display($node,$image_label);
144 $images[] = file_create_url(file_directory_path() ."/".$node->images[$image_label]);
145 }
146 }
147
148 $sizes = _image_get_sizes();
149 foreach ($sizes as $size) {
150 if ( $size['label'] == $image_label ) {
151 $height = $size['height'];
152 break;
153 }
154 }
155
156 return theme( 'photobar', $images, image_gallery_term_path($term), $height );
157 }
158
159 /**
160 * @param nid Photobar node id
161 * @return photobar HTML code. Photos for the bar are chosen at even intervals to include
162 * photos from the beginning, middle, and end of the event.
163 */
164 function photobar_create( $nid = 0 ) {
165 if ( $nid ) {
166 return _photobar_create(node_load(array('nid' => $nid)));
167 }
168 }
169
170 function _photobar_convert_to_dec($value) {
171 $result = "";
172
173 if (isset($value)) {
174 eval ("\$result = 1.0*$value;");
175 }
176 return $result;
177 }
178
179 /**
180 * Creates an image node used with a photobar.
181 *
182 * If enabled in the settings, this function will automatically orient photos
183 * based on exif information. The original photos are unaltered.
184 *
185 * @param file File path to the photo to create
186 * @param folder_time Timestamp for this photo. This photo will be added to the correct gallery based on this value.
187 * @param uid Create image nodes owned by this user.
188 */
189 function photobar_create_image( $file, $folder_time, $uid ) {
190 if ( ini_get('safe_mode') != "1" )
191 set_time_limit(30);
192
193 $basename = basename($file);
194
195 $node = new stdClass();
196 $node->type = "image";
197 $node->title = basename($file);
198 if ( !variable_get('photobar_keep_ext', true) ) {
199 $ext = strrchr($node->title, '.');
200 $node->title = basename( $node->title, $ext );
201 }
202
203 $node->uid = $uid;
204 $node->promote = 0;
205 $node->created = $folder_time;
206
207 //requires php with exif enabled
208 $exif = exif_read_data($file);
209
210 $enable_locations = variable_get('location_image', 0);
211
212 if ($exif && $enable_locations && isset($exif['GPSLatitude'])) {
213 $deg = _photobar_convert_to_dec($exif['GPSLatitude'][0]);
214 $min = _photobar_convert_to_dec($exif['GPSLatitude'][1]);
215 $sec = _photobar_convert_to_dec($exif['GPSLatitude'][2]);
216
217 $latitude = ($min * 60.0 + $sec)/60.0;
218 $latitude = ($deg*60.0 + $latitude)/60.0;
219 }
220 else {
221 $latitude = -1;
222 }
223
224 if ($exif && $enable_locations && isset($exif['GPSLongitude'])) {
225 $deg = _photobar_convert_to_dec($exif['GPSLongitude'][0]);
226 $min = _photobar_convert_to_dec($exif['GPSLongitude'][1]);
227 $sec = _photobar_convert_to_dec($exif['GPSLongitude'][2]);
228
229 $longitude = ($min * 60.0 + $sec)/60.0;
230 $longitude = ($deg*60.0 + $longitude)/60.0;
231 }
232 else {
233 $longitude = -1;
234 }
235
236 if ($latitude != -1 && $longitude != -1) {
237 $node->location['latitude'] = $latitude;
238 $node->location['longitude'] = $longitude;
239 $node->location['lat'] = $latitude;
240 $node->location['lon'] = $longitude;
241 }
242
243 if ( $exif && isset($exif['DateTime']) ) {
244 $exif_datetime = $exif['DateTime'];
245 $node->created = strtotime($exif_datetime);
246
247 if ( $node->created == 0 ) {
248 list($date, $time) = split(" ", $exif_datetime);
249 list($year, $month, $day) = split(":",$date);
250 list($hour, $minute, $second) = split(":",$time);
251 $node->created = mktime($hour,$minute,$second,$month,$day,$year);
252 }
253 }
254 $node->format = 1;
255 $node->status = 1;
256
257 $path = variable_get('image_default_path', 'images');
258 $src = $file;
259 $dest = file_directory_path() . "/$path/temp/$basename";
260
261 if ( $exif && variable_get('photobar_auto_orient', false) ) {
262 switch ( $exif['Orientation'] ) {
263 case 3: image_rotate($src, $dest, 180); break;
264 case 8: image_rotate($src, $dest, 90); break;
265 case 6: image_rotate($src, $dest, 270); break;
266 default: file_copy( $src, $dest );
267 }
268 }
269 else {
270 file_copy( $src, $dest );
271 }
272
273 $node->images['_original'] = $dest;
274 _image_build_derivatives($node, true);
275 node_save($node);
276 return $node->nid;
277 }
278
279 function _photobar_is_image_valid($file)
280 {
281 if ( variable_get('photobar_validate_images', true) ) {
282 $info = @image_get_info($file);
283 if ( $info === false ) {
284 return false;
285 } else {
286 switch ($info['mime_type']) {
287 case 'image/jpeg': return (@imagecreatefromjpeg($file) !== false);
288 case 'image/gif' : return (@imagecreatefromgif($file) !== false);
289 case 'image/png' : return (@imagecreatefrompng($file) !== false);
290 default: return true; //assume valid?
291 }
292 }
293 } else {
294 $ext = strtoupper(strrchr($file, '.'));
295 if ( $ext == ".JPG" || $ext == ".JPEG" || $ext == ".PNG" || $ext == ".GIF" )
296 return true;
297 else
298 return false;
299 }
300 }
301
302 /**
303 * Creates a image nodes that will be a part of the photobar associated with the given date.
304 *
305 * A gallery is created and each image is added to that gallery.
306 *
307 * @param date_str Folder name in the form "YYYY-MM-DD"
308 * @param uid Create image nodes owned by this user.
309 */
310 function photobar_create_images( $date_str, $uid )
311 {
312 $folder_time = _photobar_get_timestamp($date_str);
313
314 $term['name'] = $date_str;
315 //$term['description'] = "Day ".floor(($folder_time-strtotime("2006-06-23"))/60/60/24+1);
316 $term['vid'] = variable_get('image_gallery_nav_vocabulary', '');
317 taxonomy_save_term($term);
318 $gallery_term['tid'] = $term['tid'];
319
320 $path = variable_get('photobar_img_dir', 'photos') . "/" . $date_str;
321 $files = file_scan_directory(file_create_path($path), '.*');
322 foreach ($files as $file => $info) {
323 if ( !_photobar_is_image_valid($file) ) {
324 watchdog('photobar', t('%file: Not a valid image, skipping', array('%file' => $file)));
325 } else if ( strpos(basename($file),'.') != 0 ) { //ignore hidden files
326 $nid = photobar_create_image( $file, $folder_time, $uid );
327 taxonomy_node_save($nid, $gallery_term);
328 }
329 }
330 }
331
332 /**
333 * Implementation of hook_cron().
334 *
335 * Check a particular path for new photo directories or updated photo directories.
336 * All new photos will be either added to a new photobar or added to an existing photobar
337 * if a photobar of the given date already exists.
338 */
339 function photobar_cron() {
340 $uid = variable_get('photobar_default_user', 1);
341
342 $dir = file_create_path(variable_get('photobar_img_dir', 'photos'));
343 $dir_hdl = opendir($dir);
344 while($entry_name = readdir($dir_hdl))
345 {
346 if ( is_dir("$dir/$entry_name") &&
347 $entry_name != "." && $entry_name != ".." &&
348 ($folder_time = strtotime($entry_name)) > 0 ) {
349 $folder_time = _photobar_get_timestamp($entry_name);
350 $queryResult = db_query("SELECT created,title FROM {node} WHERE type='photobar' AND created='%d'", $folder_time);
351 if ( db_num_rows($queryResult) == 0 ) { //create new
352 $node = new stdClass();
353 $node->type = "photobar";
354 $node->title = $entry_name;
355 $node->uid = $uid;
356 $node->promote = 1;
357 $node->created = $folder_time;
358 $node->format = 1;
359 $node->status = 1;
360 node_save($node);
361 watchdog('photobar', t('Created and populated new photobar for %date', array('%date' => $entry_name)));
362 } else { //update existing
363 while ($node = db_fetch_object($queryResult)) {
364 $gallery_term = _photobar_get_gallery($node);
365 if ( $gallery_term === false ) { continue; }
366
367 $queryResult = db_query("SELECT n.title FROM {node} n INNER JOIN {term_node} t ON n.nid=t.nid WHERE type='image' AND t.tid='%d'", $gallery_term->tid);
368 while ($photo = db_fetch_object($queryResult)) {
369 $photos[] = $photo->title;
370 }
371
372 $path = variable_get('photobar_img_dir', 'photos') . "/" . $entry_name;
373 $files = file_scan_directory(file_create_path($path), '.*');
374 foreach ($files as $file => $info) {
375 $basename = basename($file);
376
377 if ( !_photobar_is_image_valid($file) ) {
378 watchdog('photobar', t('%file: Not a valid image, skipping', array('%file' => $file)));
379 continue;
380 } else if ( strpos($basename,'.') == 0 ) { continue; } //skip hidden
381
382 $ext = strrchr($basename, '.');
383 if ( !in_array(basename($basename,$ext),$photos) && !in_array($basename,$photos) ) {
384 $nid = photobar_create_image($file,$folder_time,$uid);
385 taxonomy_node_save($nid, array($gallery_term));
386
387 $new_photos[] = $file;
388 }
389 }
390
391 if ( isset($new_photos) ) {
392 //generate a log message
393 watchdog('photobar', t('Added the following %count new photo(s) to the existing photobar, %photobar: %photo_list',
394 array('%count' => count($new_photos),
395 '%photobar' => $entry_name,
396 '%photo_list' => implode(', ',$new_photos)))
397 );
398 }
399
400 unset($photos);
401 unset($new_photos);
402 }
403 }
404 }
405 }
406
407 // close directory
408 closedir($dir_hdl);
409
410 /*
411 $image_label = variable_get('photobar_img_label', 'thumbnail');
412 $queryResult = db_query("SELECT nid FROM {node} WHERE type='image'");
413 while ($id = db_fetch_object($queryResult)) {
414 if ( ini_get('safe_mode') != "1" )
415 set_time_limit(30);
416 $node = node_load($id->nid);
417 image_display($node,$image_label); //rebuilds images if label changed, doesn't display it
418 }
419 */
420 }
421
422 /**
423 * Implementation of hook_view
424 *
425 * Set the body and teaser to the HTML code of the photobar
426 */
427 function photobar_view(&$node, $teaser = 0, $page = 0) {
428 $node->teaser = _photobar_create($node);
429 $node->body = $node->teaser;
430 }
431
432 /**
433 * Implementation of hook_insert.
434 *
435 * Photobars created via 'Create Content' have the folder name as the title, so use that
436 * and create a new photobar of the photos in that directory.
437 */
438 function photobar_insert($node) {
439 photobar_create_images($node->title, $node->uid);
440 }
441
442 /**
443 * Implementation of hook_delete.
444 *
445 * Delete the associated gallery and image nodes in that gallery.
446 */
447 function photobar_delete($node) {
448 $gallery_term = _photobar_get_gallery($node);
449
450 $queryResult = db_query("SELECT n.nid FROM {node} n INNER JOIN {term_node} t ON n.nid=t.nid WHERE type='image' AND t.tid='%d'", $gallery_term->tid);
451 while ($photo = db_fetch_object($queryResult)) {
452 node_delete($photo->nid);
453 }
454
455 taxonomy_del_term($gallery_term->tid);
456 }
457
458 /**
459 * Implementation of hook_node_info().
460 */
461 function photobar_node_info() {
462 return array('photobar' => array('name' => t('photobar'), 'base' => 'photobar'));
463 }
464
465 /**
466 * Implementation of hook_perm().
467 */
468 function photobar_perm() {
469 return array('create photobar', 'edit own photobar', 'photobar superuser');
470 }
471
472 /**
473 * Implementation of hook_access().
474 */
475 function photobar_access($op, $node) {
476 global $user;
477
478 if ($op == 'create') {
479 return user_access('create photobar');
480 }
481
482 if ($op == 'update' || $op == 'delete') {
483 if (user_access('edit own photobar') && ($user->uid == $node->uid)) {
484 return TRUE;
485 }
486 }
487 }
488
489 /**
490 * Implementation of hook_menu().
491 */
492 function photobar_menu($may_cache) {
493 $items = array();
494
495 if ($may_cache) {
496 $items[] = array('path' => 'node/add/photobar', 'title' => t('photobar'),
497 'access' => user_access('create photobar'));
498 }
499
500 return $items;
501 }
502
503 /**
504 * Implementation of hook_form().
505 *
506 * Make the folder name the title.
507 */
508 function photobar_form(&$node) {
509 $form['title'] = array('#type' => 'textfield',
510 '#title' => t('Folder (in the form: YYYY-MM-DD)'),
511 '#required' => TRUE,
512 '#default_value' => "",
513 '#weight' => -5);
514
515 return $form;
516 }
517
518 /**
519 * Implementation of hook_validate
520 *
521 * Three validations:
522 * 1) The folder is in the required format, YYYY-MM-DD
523 * 2) The folder exists
524 * 3) A photobar of this date doesn't already exist
525 */
526 function photobar_validate(&$node) {
527 $created = _photobar_get_timestamp($node->title);
528
529 if ( $created === false || $created == -1 ) {
530 form_set_error('title',t('Folder "%folder" is not in the required format, YYYY-MM-DD', array('%folder' => $node->title)));
531 }
532
533 $path = variable_get('photobar_img_dir', 'photos') . "/" . $node->title;
534 if ( !is_dir(file_create_path($path)) ) {
535 form_set_error('title',t('Folder "%folder" does not exist in %photo_dir',
536 array('%folder' => $node->title,
537 '%photo_dir' => file_directory_path()."/".variable_get('photobar_img_dir', 'photos')))
538 );
539 }
540
541 $count = db_result(db_query("SELECT COUNT(1) FROM {node} WHERE type='photobar' AND created='%d'", $created));
542 if ( $count > 0 ) {
543 form_set_error('title',
544 t('A photobar from the date "%folder" already exists. Either run cron to update this photobar with new images, or delete the photobar node and re-submit.',
545 array('%folder' => $node->title))
546 );
547 }
548 }
549
550 /**
551 * Implementation of hook_submit
552 *
553 * Override the creation time based on the folder name
554 */
555 function photobar_submit(&$node) {
556 $node->created = _photobar_get_timestamp($node->title);
557 }
558
559 /**
560 * Implementation of hook_settings
561 */
562 function photobar_settings() {
563 $form['photobar_img_dir'] = array('#type' => 'textfield',
564 '#title' => t('Photo search path'),
565 '#default_value' => variable_get('photobar_img_dir', 'photos'),
566 '#description' => t("Directory to look in for finding new photos."));
567
568 $form['photobar_maxdisp'] = array('#type' => 'textfield',
569 '#title' => t('Maximum number of photos to display in the bar'),
570 '#default_value' => variable_get('photobar_maxdisp', 3),
571 '#description' => t("The maximum number of photos to display in the bar."),
572 '#maxlength' => '2', '#size' => '2');
573
574 $form['photobar_img_label'] = array('#type' => 'textfield',
575 '#title' => t('Image label'),
576 '#default_value' => variable_get('photobar_img_label', 'thumbnail'),
577 '#description' => t("Image label (from Image module settings). 'preview' and 'thumbnail' are available by default.<br /><br />NOTE: Labels must already exist at the time the photos were added. If you input photos, then create a new label and set it here, photos won't appear for this label."));
578
579 $form['photobar_keep_ext'] = array('#type' => 'checkbox',
580 '#title' => t('Image extension in title'),
581 '#default_value' => variable_get('photobar_keep_ext', true),
582 '#description' => t("For created 'image' nodes, whether or not to keep image extensions in the node title."));
583
584 $form['photobar_validate_images'] = array('#type' => 'checkbox',
585 '#title' => t('Validate images'),
586 '#default_value' => variable_get('photobar_validate_images', true),
587 '#description' => t("Check that each image is valid before adding it. This slows down the update process quite a bit, but it isn't pretty when invalid images are added. If not enabled, it only does an extension-based validation."));
588
589 $form['photobar_auto_orient'] = array('#type' => 'checkbox',
590 '#title' => t('Auto-orient'),
591 '#default_value' => variable_get('photobar_auto_orient', false),
592 '#description' => t("Automatically orient photos based on exif information (Requires php configured with --enable-exif)."));
593
594 $form['photobar_default_user'] = array('#type' => 'textfield',
595 '#title' => t('Default user id'),
596 '#default_value' => variable_get('photobar_default_user', 1),
597 '#maxlength' => '2', '#size' => '2',
598 '#description' => t("User to own nodes created by automatic cron jobs."));
599
600 return $form;
601 }

  ViewVC Help
Powered by ViewVC 1.1.2