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

Contents of /contributions/modules/slideshow/slideshow.module

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


Revision 1.20 - (show annotations) (download) (as text)
Mon Jun 25 18:22:57 2007 UTC (2 years, 5 months ago) by timcn
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-5--2
Changes since 1.19: +3 -3 lines
File MIME type: text/x-php
#135350 by Shiny: Add PostgreSQL support
1 <?php
2 // $Id: slideshow.module,v 1.19 2007/04/21 16:53:34 timcn Exp $
3
4 /**
5 * @file
6 * slideshow.module provides basic slideshow capabilities. It transforms images
7 * attached to nodes to a JavaScript enhanced slideshow. If the user does not have
8 * JavaScript enabled, it degrades to a "regular" slideshow where the "next"
9 * link points to the next image and a whole new page is loaded.
10 */
11
12 // Define constants for slideshow settings
13 define('SLIDESHOW_LOCATION_DEFAULT', 0);
14 define('SLIDESHOW_LOCATION_NONE', 1);
15 define('SLIDESHOW_LOCATION_ABOVE', 2);
16 define('SLIDESHOW_LOCATION_BELOW', 3);
17 define('SLIDESHOW_LOCATION_TAG', 4);
18
19 define('SLIDESHOW_ALIGN_DEFAULT', 0);
20 define('SLIDESHOW_ALIGN_FULL', 1);
21 define('SLIDESHOW_ALIGN_LEFT', 2);
22 define('SLIDESHOW_ALIGN_RIGHT', 3);
23
24
25 /**
26 * Implementation of hook_menu().
27 */
28 function slideshow_menu($may_cache) {
29 $items = array();
30
31 if ($may_cache) {
32 $items[] = array(
33 'path' => 'admin/settings/slideshow',
34 'title' => t('Slideshow'),
35 'callback' => 'drupal_get_form',
36 'callback arguments' => array('slideshow_admin_settings'),
37 'access' => user_access('administer site configuration'),
38 'description' => t('Change default settings for slideshows, such as the image dimensions.')
39 );
40 }
41
42 return $items;
43 }
44
45
46 /**
47 * Implementation of hook_perm().
48 */
49 function slideshow_perm() {
50 return array('configure slideshows');
51 }
52
53
54 /**
55 * Implementation of hook_form_alter().
56 */
57 function slideshow_form_alter($form_id, &$form) {
58 if ($form_id == 'slideshow_node_form' && isset($form['attachments'])) {
59 $form['attachments']['#title'] = t('Images');
60 $form['attachments']['#collapsed'] = FALSE;
61
62 // Preserve the title of the file, even if it's empty.
63 foreach ($form['#node']->files as $key => $file) {
64 $form['attachments']['wrapper']['files'][$key]['description']['#default_value'] = $file->description;
65
66 if ($form['attachments']['wrapper']['files'][$key]['description']['#default_value'] == $file->filename) {
67 $form['attachments']['wrapper']['files'][$key]['description']['#default_value'] = '';
68 }
69 }
70 }
71
72 // Add the ability to enable/disable the slideshow for a content type
73 if ($form_id == 'node_type_form' && isset($form['identity']['type'])) {
74 $form['workflow']['slideshow'] = array(
75 '#type' => 'radios',
76 '#title' => t('Slideshow'),
77 '#description' => t('If enabled, images attached to the post are displayed in the form of a slideshow.'),
78 '#default_value' => variable_get('slideshow_'. $form['#node_type']->type, 0),
79 '#options' => array(t('Disabled'), t('Enabled')),
80 );
81 }
82
83 // If this is a node form...
84 if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
85 // ... add the slideshow settings page
86 if (variable_get('slideshow_'. $form['type']['#value'], FALSE) && user_access('configure slideshows')) {
87 _slideshow_node_form($form);
88 }
89 }
90 }
91
92 /**
93 * Implementation of hook_settings()
94 */
95 function slideshow_admin_settings() {
96 $maximum_size = variable_get('upload_max_resolution', 0);
97 if (!preg_match('~^[1-9]\d*x[1-9]\d*$~', $maximum_size)) {
98 $maximum_size = t('not set');
99 }
100
101 $form['slideshow_default_location'] = array(
102 '#type' => 'select',
103 '#title' => t('Default display location'),
104 '#description' => t('Select where the slideshow appears by default. If you select %above, users have to explicitly active the slideshow for each post.', array('%above' => t('Above'))),
105 '#options' => array(
106 SLIDESHOW_LOCATION_NONE => t('Nowhere'),
107 SLIDESHOW_LOCATION_ABOVE => t('Above'),
108 SLIDESHOW_LOCATION_BELOW => t('Below'),
109 SLIDESHOW_LOCATION_TAG => t('Within')
110 ),
111 '#default_value' => variable_get('slideshow_default_location', SLIDESHOW_LOCATION_ABOVE),
112 );
113
114 $form['slideshow_default_align'] = array(
115 '#type' => 'select',
116 '#title' => t('Default alignment'),
117 '#description' => t('Select how the slideshow box should be displayed by default.'),
118 '#options' => array(
119 SLIDESHOW_ALIGN_FULL => t('Full width'),
120 SLIDESHOW_ALIGN_LEFT => t('Left'),
121 SLIDESHOW_ALIGN_RIGHT => t('Right')
122 ),
123 '#default_value' => variable_get('slideshow_default_align', SLIDESHOW_ALIGN_FULL),
124 );
125
126 $form['slideshow_default_dimensions'] = array(
127 '#type' => 'textfield',
128 '#title' => t('Default image size'),
129 '#default_value' => variable_get('slideshow_default_dimensions', '640x480'),
130 '#size' => 20,
131 '#maxlength' => 20,
132 '#description' => t('The maximum size of images displayed in a slideshow. Cannot be bigger than the maximum image size for upload module (which is @maximum-size).', array('@maximum-size' => $maximum_size)),
133 '#field_suffix' => t('<kbd>WIDTHxHEIGHT</kbd>'),
134 );
135
136 $form['slideshow_image_path'] = array(
137 '#type' => 'textfield',
138 '#title' => t('Slideshow image path'),
139 '#default_value' => variable_get('slideshow_image_path', 'slideshow'),
140 '#field_prefix' => variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC ? file_create_url('') : '&lt;'. t('Private') .'&gt;/',
141 '#description' => t('Subdirectory in the global file directory where resized images for slideshows will be stored.'),
142 );
143
144 return system_settings_form($form);
145 }
146
147 function slideshow_admin_settings_validate($form_id, $form_values) {
148 // Test for a valid image size
149 if (!preg_match('~^[1-9]\d*x[1-9]\d*$~', $form_values['slideshow_default_dimensions'])) {
150 form_set_error('slideshow_default_dimensions', t('The specified default slideshow image size is invalid.'));
151 }
152 }
153
154 /**
155 * Retrieve the directory where slideshow images are stored in.
156 */
157 function slideshow_image_directory() {
158 $slideshow_path = file_create_path(variable_get('slideshow_image_path', 'slideshow'));
159
160 // Make sure that the directory exists
161 if (!file_check_directory($slideshow_path, FILE_CREATE_DIRECTORY)) {
162 drupal_set_message(t("Slideshow images can't be created because the directory %directory has not been properly configured.", array('%directory' => $slideshow_path)), 'error');
163 }
164
165 return $slideshow_path;
166 }
167
168 /**
169 * Helper function for hook_form_alter(). Adds form elements to node submission forms
170 */
171 function _slideshow_node_form(&$form) {
172 // Remove the body requirement
173 if (isset($form['body_filter']) && isset($form['body_filter']['body'])) {
174 $form['body_filter']['body']['#required'] = FALSE;
175 }
176
177 $form['slideshow'] = array(
178 '#type' => 'fieldset',
179 '#access' => user_access('attach images as slideshow'),
180 '#title' => t('Slideshow settings'),
181 '#collapsible' => TRUE,
182 '#collapsed' => TRUE,
183 '#description' => t('Attached images are displayed in the form of a slideshow.'),
184 '#weight' => 35,
185 '#suffix' => '</div>',
186 '#tree' => TRUE,
187 );
188
189 // Fetch the values for the <Default: ...> select values
190 $location = variable_get('slideshow_default_location', SLIDESHOW_LOCATION_ABOVE);
191 $options = array(
192 SLIDESHOW_LOCATION_NONE => t('Nowhere'),
193 SLIDESHOW_LOCATION_ABOVE => t('Above'),
194 SLIDESHOW_LOCATION_BELOW => t('Below'),
195 SLIDESHOW_LOCATION_TAG => t('Tag')
196 );
197
198 $form['slideshow']['location'] = array(
199 '#type' => 'select',
200 '#title' => t('Display location'),
201 '#description' => t('Select where the slideshow appears. To specify a place within the content, use <var>[slideshow]</var> and select the appropriate location here.'),
202 '#options' => array(SLIDESHOW_LOCATION_DEFAULT => '<'. t('Default') .': '. $options[$location] .'>') + $options,
203 '#default_value' => isset($form['#node']->slideshow) ? $form['#node']->slideshow['location'] : SLIDESHOW_LOCATION_DEFAULT,
204 );
205
206 $align = variable_get('slideshow_default_align', SLIDESHOW_ALIGN_FULL);
207 $options = array(
208 SLIDESHOW_ALIGN_FULL => t('Full width'),
209 SLIDESHOW_ALIGN_LEFT => t('Left'),
210 SLIDESHOW_ALIGN_RIGHT => t('Right')
211 );
212
213 $form['slideshow']['align'] = array(
214 '#type' => 'select',
215 '#title' => t('Alignment'),
216 '#description' => t('Select whether the slideshow box is displayed with full width or floated on the left or right side.'),
217 '#options' => array(SLIDESHOW_ALIGN_DEFAULT => '<'. t('Default') .': '. $options[$align] .'>') + $options,
218 '#default_value' => isset($form['#node']->slideshow) ? $form['#node']->slideshow['align'] : SLIDESHOW_ALIGN_DEFAULT,
219 );
220
221 $form['slideshow']['dimensions'] = array(
222 '#type' => 'textfield',
223 '#title' => t('Image size'),
224 '#default_value' => isset($form['#node']->slideshow) ? $form['#node']->slideshow['dimensions'] : '',
225 '#size' => 20,
226 '#maxlength' => 20,
227 '#description' => t('The maximum size of images displayed in a slideshow. Leave blank to use the default size (<kbd>@default-size</kbd>).', array('@default-size' => variable_get('slideshow_default_dimensions', '640x480'))),
228 '#field_suffix' => t('<kbd>WIDTHxHEIGHT</kbd>'),
229 );
230
231 if (!isset($form['#validate'])) {
232 $form['#validate'] = array();
233 }
234 $form['#validate']['_slideshow_node_form_validate'] = array();
235 }
236
237 function _slideshow_node_form_validate($form_id, $form_values) {
238 // Test for a valid image size or for an empty value
239 if (!empty($form_values['slideshow']['dimensions']) && !preg_match('~^[1-9]\d*x[1-9]\d*$~', $form_values['slideshow']['dimensions'])) {
240 form_set_error('slideshow][dimensions', t('The specified slideshow image size is invalid.'));
241 }
242 }
243
244 /**
245 * Implementation of hook_nodeapi()
246 */
247 function slideshow_nodeapi(&$node, $op, $teaser) {
248 if (variable_get('slideshow_'. $node->type, FALSE)) {
249 // Only act if slideshow is activated for this content type
250
251 if (isset($node->slideshow)) {
252 // determine if this node's slideshow values are not default
253 $default_settings = ($node->slideshow['location'] == SLIDESHOW_LOCATION_DEFAULT && $node->slideshow['align'] == SLIDESHOW_ALIGN_DEFAULT && empty($node->slideshow['dimensions']));
254 }
255 else {
256 $default_settings = TRUE;
257 }
258
259 switch ($op) {
260 case 'delete':
261 slideshow_delete_images($node);
262 slideshow_delete_records($node);
263 break;
264 case 'delete revision':
265 slideshow_delete_revision_record($node);
266 break;
267 case 'update':
268 slideshow_update_images($node);
269 if ($node->revision && !$default_settings) {
270 slideshow_insert_record($node);
271 }
272 else {
273 slideshow_delete_revision_record($node);
274 if (!$default_settings) {
275 slideshow_insert_record($node);
276 }
277 }
278 break;
279 case 'insert':
280 slideshow_update_images($node);
281 if (!$default_settings) {
282 slideshow_insert_record($node);
283 }
284 break;
285 case 'load':
286 return slideshow_load_record($node);
287 break;
288 case 'view':
289 slideshow_view($node, $teaser);
290 break;
291 }
292 }
293 }
294
295 /**
296 * Add a slideshow settings record for a node revision.
297 *
298 * @param $node The node revision whose slideshow record should be added. The
299 * slideshow property must be set.
300 */
301 function slideshow_insert_record(&$node) {
302 db_query("INSERT INTO {slideshow} (nid, vid, location, align, dimensions) VALUES (%d, %d,%d, %d, '%s')", $node->nid, $node->vid, $node->slideshow['location'], $node->slideshow['align'], $node->slideshow['dimensions']);
303 }
304
305 /**
306 * Load a slideshow settings record for a node.
307 *
308 * @param $node The node revision whose slideshow record should be loaded.
309 * @return The slideshow settings for the node. If no record is available, the
310 * default values are returned.
311 */
312 function slideshow_load_record(&$node) {
313 $result = db_fetch_array(db_query("SELECT location, align, dimensions FROM {slideshow} WHERE nid = %d AND vid = %d;", $node->nid, $node->vid));
314
315 if (empty($result)) {
316 $result = array(
317 'location' => SLIDESHOW_LOCATION_DEFAULT,
318 'align' => SLIDESHOW_ALIGN_DEFAULT,
319 'dimensions' => '',
320 );
321 }
322
323 return array('slideshow' => $result);
324 }
325
326 /**
327 * Delete a slideshow settings record for a node revision.
328 *
329 * @param $node The node revision whose slideshow record should be deleted.
330 */
331 function slideshow_delete_revision_record(&$node) {
332 db_query("DELETE FROM {slideshow} WHERE nid = %d AND vid = %d;", $node->nid, $node->vid);
333 }
334
335 /**
336 * Delete all slideshow settings record for a node.
337 *
338 * @param $node The node whose slideshow records should be deleted.
339 */
340 function slideshow_delete_records(&$node) {
341 db_query("DELETE FROM {slideshow} WHERE nid = %d;", $node->nid);
342 }
343
344 /**
345 * Delete all slideshow images associated with the node.
346 *
347 * @param $node The node whose slideshow images should be deleted.
348 */
349 function slideshow_delete_images(&$node) {
350 if ($node->files) {
351 $path = slideshow_image_directory();
352
353 foreach ($node->files as $file) {
354 file_delete($path .'/'. $file->filename);
355 }
356 }
357 }
358
359 /**
360 * Update the slideshow images for a node. Old images will be deleted and new ones
361 * will be added. If the dimensions change, images are recalculated.
362 *
363 * @param $node The node whose slideshow images should be updated.
364 */
365 function slideshow_update_images(&$node) {
366 $path = slideshow_image_directory();
367
368 // Get the image dimensions for this node (or the default dimensions if there are none).
369 $dimensions = !empty($node->slideshow['dimensions']) ? $node->slideshow['dimensions'] : variable_get('slideshow_default_dimensions', '640x480');
370
371 // Check if the previous revision contains files that this revision doesn't
372 if ($node->revision) {
373 // List all files for this node (regardless of their revision)
374 $result = db_query("SELECT fid, filename, filemime FROM {files} WHERE nid = %d", $node->nid);
375
376 // Loop through all the files this node has in any revision
377 while ($file = db_fetch_object($result)) {
378 // Don't treat non-image files
379 if (strpos($file->filemime, 'image/') !== 0) continue;
380 $image = $path .'/'. $file->filename;
381
382 // When the file is not present in the current revision, simply delete it
383 if (!isset($node->files[$file->fid])) {
384 file_delete($image);
385 }
386 }
387 }
388
389 // create all images in the currently active revision
390 if (!empty($node->files)) {
391 // Determine if the file size has to be changed
392 $result = db_fetch_array(db_query("SELECT dimensions FROM {slideshow} WHERE nid = %d ORDER BY vid DESC LIMIT 1", $node->nid));
393 $recreate = !(($result && $result['dimensions'] == $dimensions) || (!$result && empty($node->slideshow['dimensions'])));
394
395 $dimensions = explode('x', $dimensions);
396
397 // Loop through all files
398 foreach ($node->files as $file) {
399 $file = (object) $file;
400 // Don't treat non-image files
401 if (strpos($file->filemime, 'image/') !== 0) continue;
402
403 // Create the slideshow image path
404 $destination = $path .'/'. $file->filename;
405
406 // Remove the file if it is completely removed or recreated
407 if ($file->remove || $recreate) {
408 file_delete($destination);
409 }
410
411 // If the file is not removed and the file doesn't exist or should be recreated
412 if (!$file->remove && (!is_file($destination) || $recreate)) {
413 slideshow_create_image($file->filepath, $destination, $dimensions[0], $dimensions[1]);
414 }
415 }
416 }
417 }
418
419 /**
420 * Create an image with the given parameters. If the image can't be scaled,
421 * try to copy it (e.g. if the destination image size is larger than the actual file).
422 *
423 * @param $source The path to the source image.
424 * @param $destination The destination path.
425 * @param $width The new width.
426 * @param $height The new height.
427 */
428 function slideshow_create_image($source, $destination, $width, $height) {
429 if (!image_scale($source, $destination, $width, $height)) {
430 if (!file_copy($source, $destination, FILE_EXISTS_ERROR)) {
431 drupal_set_message(t('The file %file could not be created.', array('%file' => $destination)));
432 }
433 }
434 }
435
436 /**
437 * Add the slideshow to the node.
438 *
439 * @param $node The node the slideshow should be displayed for.
440 */
441 function slideshow_view(&$node) {
442 $location = $node->slideshow['location'];
443 if ($location == SLIDESHOW_LOCATION_DEFAULT) {
444 $location = variable_get('slideshow_default_location', SLIDESHOW_LOCATION_ABOVE);
445 }
446
447 // If there are no files or the slideshow is set to hidden, don't continue processing
448 if (empty($node->files) || $location == SLIDESHOW_LOCATION_NONE) return;
449
450 $images = array();
451 $files = array();
452
453 // First, sort the file attachments by their type (image vs. non-image)
454 foreach ($node->files as $key => $file) {
455 if (strpos($file->filemime, 'image/') === 0) {
456 $images[] = $file;
457 $node->files[$key]->list = FALSE;
458 }
459 else {
460 $files[$key] = $file;
461 }
462 }
463
464 // If there are no images attached, don't continue processing
465 if (empty($images)) return;
466
467 // Get the base path for all slideshow images
468 $path = variable_get('slideshow_image_path', 'slideshow');
469
470 // Construct the settings array
471 $settings = array(
472 'images' => array(),
473 'total' => count($images),
474 'current' => 0,
475 'link' => url('node/'. $node->nid, 'slide=$slideshow$'),
476 );
477
478 if (isset($_GET['slide'])) {
479 $current = (int)$_GET['slide'];
480 $settings['current'] = ($current < 1 || $current > $settings['total']) ? 0 : $current - 1;
481 }
482
483 foreach ($images as $key => $image) {
484 $settings['images'][$key] = array(
485 'src' => file_create_url($path .'/'. $image->filename),
486 'title' => check_plain($image->description),
487 );
488 }
489
490 // Construct the base slideshow element
491 $slideshow = array(
492 '#type' => 'slideshow',
493 '#attributes' => array('class' => 'slideshow', 'id' => 'slideshow-'. $node->nid),
494 '#slideshow' => array(
495 'settings' => array('slideshow-'. $node->nid => $settings),
496 'status' => array(
497 'current' => $settings['current'] + 1,
498 'total' => $settings['total'],
499 'previous' => $settings['current'] <= 0 ? $settings['total'] : $settings['current'],
500 'next' => $settings['current'] >= $settings['total'] - 1 ? 1 : $settings['current'] + 2,
501 ),
502 'url' => 'node/'. $node->nid,
503 'title' => $settings['images'][$settings['current']]['title'],
504 'image' => $settings['images'][$settings['current']]['src'],
505 ),
506 '#weight' => 0,
507 );
508
509 $align = $node->slideshow['align'];
510 if ($align == SLIDESHOW_ALIGN_DEFAULT) {
511 $align = variable_get('slideshow_default_align', SLIDESHOW_ALIGN_FULL);
512 }
513
514 switch ($align) {
515 case SLIDESHOW_ALIGN_LEFT:
516 $slideshow['#attributes']['class'] .= ' align-left';
517 break;
518 case SLIDESHOW_ALIGN_RIGHT:
519 $slideshow['#attributes']['class'] .= ' align-right';
520 break;
521 case SLIDESHOW_ALIGN_FULL:
522 default:
523 $slideshow['#attributes']['class'] .= ' align-full';
524 }
525
526 // Determine if the tag location is valid, otherwise set it to the default location
527 if ($location == SLIDESHOW_LOCATION_TAG &&
528 (!isset($node->content['body']) ||
529 empty($node->content['body']['#value']) ||
530 strpos($node->content['body']['#value'], '[slideshow]') === FALSE)) {
531 $location = SLIDESHOW_LOCATION_ABOVE; // the variable could contain SLIDESHOW_LOCATION_TAG
532 }
533
534 // Figure out where to insert the slideshow
535 switch ($location) {
536 case SLIDESHOW_LOCATION_BELOW:
537 $slideshow['#weight'] = 5;
538 $slideshow['#attributes']['class'] .= ' location-below';
539 $node->content['slideshow'] = $slideshow;
540 break;
541 case SLIDESHOW_LOCATION_TAG:
542 $body = explode('[slideshow]', $node->content['body']['#value']);
543 unset($node->content['body']['#value']);
544 $slideshow['#attributes']['class'] .= ' location-tag';
545 $node->content['body']['above'] = array('#value' => array_shift($body), '#weight' => -5);
546 $node->content['body']['slideshow'] = $slideshow;
547 $node->content['body']['below'] = array('#value' => implode('', $body), '#weight' => 5);
548 break;
549 case SLIDESHOW_LOCATION_ABOVE:
550 default:
551 $slideshow['#weight'] = -5;
552 $slideshow['#attributes']['class'] .= ' location-above';
553 $node->content['slideshow'] = $slideshow;
554 }
555
556 // If the attachment listing is present, overwrite or remove it
557 if (isset($node->content['files'])) {
558 if (!empty($files)) {
559 // Regenerate the attachment listing with the actual (non-image) files
560 $node->content['files'] = array(
561 '#value' => theme('upload_attachments', $files),
562 '#weight' => 50,
563 );
564 }
565 else {
566 // No regular files are present in this node
567 unset($node->content['files']);
568 }
569 }
570 }
571
572 function theme_slideshow($element) {
573 $slideshow = $element['#slideshow'];
574 $status = $element['#slideshow']['status'];
575
576 drupal_add_js(drupal_get_path('module', 'slideshow') .'/slideshow.js');
577 drupal_add_css(drupal_get_path('module', 'slideshow') .'/slideshow.css');
578 drupal_add_js(array('slideshow' => $slideshow['settings']), 'setting');
579
580 $output = (isset($element['#prefix']) ? $element['#prefix'] : '') .'<div'. drupal_attributes($element['#attributes']) .'>';
581 $output .= '<div class="header">';
582 $output .= l(t('Previous'), $slideshow['url'], array('class' => 'previous'), 'slide='. $status['previous']) .' | ';
583 $output .= t('Image !current of !total', array('!current' => '<span class="current">'. $status['current'] .'</span>', '!total' => '<span class="total">'. $status['total'] .'</span>')) .' | ';
584 $output .= l(t('Next'), $slideshow['url'], array('class' => 'next'), 'slide='. $status['next']);
585 $output .= '</div>';
586 $output .= '<img class="image" src="'. $slideshow['image'] .'" />';
587 $output .= '<span class="title">'. check_plain($slideshow['title']) .'</span>';
588 $output .= '</div>'. (isset($element['#suffix']) ? $element['#suffix'] : '');
589
590 return $output;
591 }

  ViewVC Help
Powered by ViewVC 1.1.2