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

Contents of /contributions/modules/acidfree/acidfree.module

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


Revision 1.147 - (show annotations) (download) (as text)
Thu May 10 13:47:29 2007 UTC (2 years, 6 months ago) by vhmauery
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-6--1
Changes since 1.146: +17 -7 lines
File MIME type: text/x-php
#142294 - add option on form for setting default view for album
1 <?php
2 /* $Id: acidfree.module 486 2007-05-10 13:47:08Z vhmauery $ */
3
4 /*
5 Acidfree Photo Albums for Drupal
6 Copyright (C) 2005 Vernon Mauery
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23 /**
24 * @file
25 * Acidfree implements a better photo album than gallery. Better being
26 * defined as doing it The Right Way (TM). Acidfree was designed as a
27 * node based system and written to work seamlessly with Drupal.
28 *
29 */
30
31 /*
32 TODO:
33 * add some ajax love
34 * write an xmlrpc hook
35 *
36 */
37
38 define('ALBUM_PAGER', 0);
39 define('ELEMENT_PAGER', 1);
40 define('PAGER_STRING', "page");
41
42 /**
43 * Acidfree Classes
44 * Each class must support a basic register function and several
45 * callbacks that are used. Specifically, a class named 'foo'
46 * would be implemented in a file called class_foo.inc and be
47 * required to implement the following hooks:
48 * class_foo_init() - returns an object that has info about the class:
49 $class->class = 'foo';
50 $class->name = t('foo');
51 $class->addme = t('Add a foo');
52 $class->mime_ext = Array('bin/foo'=>'foo');
53 $class->form_alter = '_class_foo_form_alter';
54 $class->nodeapi = '_class_foo_nodeapi';
55 $class->access = 'create new foo';
56 * theme_acidfree_print_full_foo(&$node) - called from acidfree_view()
57 * theme_acidfree_print_thumb_foo(&$node, &$parent=null, $offset=0)
58 * - called theme_acidfree_print_full_album or the block hook
59 */
60
61 /**
62 * call an arbitrary method with arbitrary arguments
63 *
64 * note that if you are calling a function that only requires a single arg
65 * that is an array, you must pass it in inside of an array like:
66 * $bob = array(2,3,4); acidfree_call('chump', array($bob));
67 * if you don't chump will be called as chump(2,3,4)
68 * which probably isn't what you want
69 *
70 * passing args by reference is allowed, but you must make the call like:
71 * acidfree_call('chump', array(&$foo, $baz));
72 * where $foo would be passed by reference and $baz wouldn't. a call like:
73 * acidfree_call('chump', $foo, $baz) will pass by value
74 */
75 function acidfree_call($function) {
76 $args = false;
77 $argc = func_num_args();
78 if ($argc > 2) {
79 $args = func_get_args();
80 array_shift($args);
81 } elseif ($argc != 1) {
82 $args = func_get_arg(1);
83 if (!is_array($args)) {
84 $args = func_get_args();
85 array_shift($args);
86 }
87 }
88 if (!$args)
89 $args = array();
90 if (function_exists($function))
91 return call_user_func_array($function, $args);
92 return null;
93 }
94
95 function acidfree_node_info() {
96 return array(
97 'acidfree' => array(
98 'name' => t('album'),
99 'module' => 'acidfree',
100 'description' => t("Acidfree albums are used for the categorization of images and videos."),
101 )
102 );
103 }
104
105 function acidfree_load(&$node) {
106 $items = db_fetch_object(db_query("SELECT * FROM {acidfree_album} WHERE aid=%d", $node->nid));
107 if (isset($items->thumb) && !$items->thumb) {
108 $items->thumb = '';
109 }
110 return $items;
111 }
112
113 function acidfree_insert(&$node) {
114 $vocab = acidfree_get_vocab_id();
115 $term = array(
116 'vid' => $vocab,
117 'name' => $node->title,
118 'description' => $node->body,
119 'weight' => $node->weight,
120 'parent' => $node->taxonomy[$vocab],
121 );
122 taxonomy_save_term($term);
123 $node->tid = $term['tid'];
124 db_query("INSERT INTO {acidfree_album} (aid,tid,thumb,share,order_by,view) values ".
125 "(%d, %d, '%s', %d, '%s', '%s')", $node->nid, $node->tid, $node->thumb,
126 $node->share, $node->order_by, $node->view);
127 if (function_exists('views_invalidate_cache'))
128 views_invalidate_cache();
129 }
130
131 function acidfree_update(&$node) {
132 $vocab = acidfree_get_vocab_id();
133 $term = array(
134 'vid' => $vocab,
135 'tid' => $node->tid,
136 'name' => $node->title,
137 'description' => $node->body,
138 'weight' => $node->weight,
139 'parent' => $node->taxonomy[$vocab],
140 );
141 taxonomy_save_term($term);
142 db_query("UPDATE {acidfree_album} SET thumb='%s', share=%d, order_by='%s', view='%s' WHERE aid=%d",
143 $node->thumb, $node->share, $node->order_by, $node->view, $node->nid);
144 if (function_exists('views_invalidate_cache'))
145 views_invalidate_cache();
146 }
147
148 function acidfree_delete(&$node) {
149 taxonomy_del_term($node->tid);
150 db_query("DELETE FROM {acidfree_album} WHERE aid=%d", $node->nid);
151 }
152
153 function acidfree_view($node, $teaser = FALSE, $page = FALSE) {
154 if ($page) {
155 $view = "album_{$node->view}_view";
156 $node->content['body'] = array(
157 '#value' => acidfree_album_view($view, $node->tid),
158 //'#value' => '<div class="clear-block">' . $output . '</div>',
159 '#weight' => 0,
160 );
161 return $node;
162 } else {
163 static $head_set;
164 if (!$head_set) {
165 $size = _image_get_dimensions('thumbnail');
166 // 5px padding + 1px border on both sides of image +
167 // 5px padding and 2px border on both sides of acidfree-item
168 // gives 26. Height needs more because it contains text underneath.
169 $style = '<style type="text/css" media="all">';
170 $style .= '.acidfree-cell{width:' . ($size['width'] + 26) . 'px;}';
171 $style .= '.acidfree .acidfree-cell{height:' . ($size['height'] + 45) . 'px;}';
172 $style .= '</style>';
173 drupal_set_html_head($style);
174 $head_set = TRUE;
175 }
176
177 $node->readmore = (strlen($node->teaser) < strlen($node->body));
178 $output = theme("acidfree_print_thumb_acidfree", $node);
179 $output .= check_markup($node->teaser, $node->format, FALSE);
180 $node->content['body'] = array(
181 '#value' => '<div class="clear-block">' . $output . '</div>',
182 '#weight' => 0,
183 );
184 return $node;
185 }
186 }
187
188 function acidfree_form(&$node) {
189 if ($node->nid && !strstr($_REQUEST['q'], 'contents')) {
190 drupal_set_title(t('Edit %title', array('%title' => $node->title)));
191 drupal_set_breadcrumb(acidfree_make_breadcrumbs($node));
192 }
193 $form = array();
194 $form['title'] = array(
195 '#type' => 'textfield',
196 '#title' => t('Title'),
197 '#default_value' => $node->title,
198 '#required' => true,
199 '#weight' => -20,
200 );
201 if (!isset($node->tid)) {
202 $parent = _path_match('node', 'add', 'acidfree', '%d');
203 $parent = acidfree_get_node_by_id($parent[0]);
204 $parent = $parent->tid;
205 } else {
206 $parent = taxonomy_get_parents($node->tid);
207 $parent = array_keys($parent);
208 $parent = $parent[0];
209 }
210 // HACK -- taxonomy rudely assumes that if $form['taxonomy'] is set
211 // then in its form_alter hook, it puts it into a field set. grrr.
212 // so we fight back by calling it parent here and renaming it to
213 // taxonomy in our form_alter, which is call after taxonomy's
214 global $user;
215 if (isset($node->tid) && ($node->tid == acidfree_get_root() || $node->tid == $user->acidfree_album)) {
216 $form['parent'] = array('#type' => 'hidden', '#value' => 0);
217 } else {
218 $form['parent'] = _acidfree_parent_select($parent, $node->tid);
219 }
220 $form['body'] = array(
221 '#type' => 'textarea',
222 '#title' => t('Body'),
223 '#default_value' => $node->body,
224 '#weight' => -1,
225 );
226 $form['view'] = array(
227 '#type' => 'select',
228 '#title' => t('Default album view'),
229 '#options' => array(
230 'grid' => t('Grid view'),
231 'list' => t('List view'),
232 ),
233 '#default_value' => $node->view,
234 '#weight' => 0,
235 );
236 $form['order_by'] = array(
237 '#type' => 'select',
238 '#title' => t('Sort album by'),
239 '#options' => array(
240 '<default>' => t('Use global settings'),
241 'node.nid DESC' => t('Latest post first'),
242 'node.nid ASC' => t('Posted order'),
243 'node.title ASC' => t('Alphabetical order'),
244 'node.created ASC' => t('Chronological order by creation date'),
245 ),
246 '#default_value' => $node->order_by,
247 '#weight' => -1,
248 '#attributes' => array('class' => 'order-by'),
249 );
250 if ($node->nid) {
251 $thumb_options['0'] = 'Random';
252 $children = _acidfree_get_children($node->tid, -1, 0);
253 if (!is_array($children)) {
254 if (count($children) == 1)
255 $children = Array($children);
256 else
257 $children = Array();
258 }
259 foreach ($children as $child) {
260 $child = acidfree_get_node_by_id($child);
261 if (strlen($child->title) > 20)
262 $title = substr($child->title, 0, 20)."...";
263 else
264 $title = $child->title;
265 $thumb_options[$child->nid] = check_plain($title);
266 }
267 // in album contents mode, this would be a duplicate thumbnail
268 if (!strstr($_GET['q'], 'contents')) {
269 $prefix = theme('acidfree_print_thumb_acidfree', $node);
270 $description = t("Select a fixed album thumbnail or select 'Random' to have a random thumbnail appear for the album thumbnail");
271 }
272 global $base_url;
273 $form['thumb'] = array(
274 '#type' => 'select',
275 '#prefix' => $prefix,
276 '#title' => t('Album thumbnail'),
277 '#description' => $description,
278 '#default_value' => $node->thumb,
279 '#options' => $thumb_options,
280 '#attributes' => array(
281 'class' => 'order-by',
282 'onchange' => "set_thumb('$base_url', this, {$node->nid}, ".count($children).")",
283 ),
284 '#acidfree_form' => true,
285 );
286 } else {
287 $form['thumb'] = array('#type' => 'hidden', '#value' => '');
288 }
289 $form['share'] = array(
290 '#type' => 'checkbox',
291 '#title' => t('Allow others to post items to this album'),
292 '#default_value' => $node->share,
293 '#weight' => -1,
294 );
295 $term = taxonomy_get_term($node->tid);
296 $form['weight'] = array(
297 '#type' => 'weight',
298 '#title' => t('Weight'),
299 '#default_value' => $term->weight,
300 '#description' => t('In listings, the heavier albums will sink and the lighter albums will be positioned nearer the top.'),
301 );
302 return $form;
303 }
304
305 /**
306 * Implementation of hook_help().
307 *
308 * Throughout Drupal, hook_help() is used to display help text at the top of
309 * pages. Some other parts of Drupal pages get explanatory text from these hooks
310 * as well. We use it here to provide a description of the module on the
311 * module administration page.
312 */
313 function acidfree_help($section) {
314 global $acidfree_types;
315 switch ($section) {
316 case 'admin/settings/modules#description':
317 // This description is shown in the listing at admin/settings/modules.
318 return t('A better photo album than Gallery or Album. Acidfree is node based and well integrated into Drupal.');
319 case 'node/add#acidfree':
320 // This description shows up when users click "create content."
321 return t('Add an album here. Other elements you can add are in the \'create content\' menu.');
322 case 'admin/help/acidfree':
323 return t('<p>Acidfree is an album system that has the ability to store any kind of media (assuming the class is existent.) Currently implemented are %types. Following the example of one of the currently implemented classes, it is easy to create a new media type.</p>', array('%types' => implode(', ', array_keys($acidfree_types))));
324 case 'admin/help#acidfree':
325 return t('<p>Because Acidfree is more than simply a storage and viewing module, it requires some depenencies for the album management. First, it requires the Filemanager module. Until the Filemanager gets patched to have the exended API that Acidfree requires, Acidfree will ship with a patch for the Filemanager. Second, it requires some form of image manipulation. Drupal provides a frontend to the GD library that can do what is required. Or, if you would rather use ImageMagick or libmagick (php-imagick module), set that up (copy the image.*.inc files to the includes directory) and select it. Finally, if you want lossless rotations for your images, you will require jpegtran or exiftran.</p><p>For video thumbnailing, there are three options. You can choose a static image for all your videos (no thumbnail), upload your own thumbnail (user thumbnail) or have mplayer thumbnail them automatically for you. If you choose the first option, you will be asked to give the dimensions of the video so it can be displayed correctly in the \'full\' view. With option two, be sure to upload a thumbnail that is the same dimensions as the actual video (grab a frame from the video, do not resize it.) The third option obviously implies that you have mplayer and all the win32 codecs installed on your <b>server</b> and that you are allowed to exec other programs (i.e., not running in safe mode.). ');
326 case 'admin/settings/acidfree':
327 return t('Change these settings to however you like. You are w00t, afterall.');
328 case 'admin/content/types/acidfree':
329 return t("The common attributes that Acidfree will have are: 'Sticky at top of lists', which allows the albums to be sorted before the other media types (image, video, etc.) in the various album views; and *not* 'Promoted to front page' because that would make all the albums show up at the top of the front page, which is probably not desirable.");
330 default:
331 return "";
332 }
333 }
334
335 function include_acidfree_files($reset=false) {
336 global $acidfree_types;
337 static $loaded = false;
338
339 if ($loaded && !$reset) {
340 return;
341 }
342
343 if ($reset) {
344 variable_set('acidfree_types', array());
345 }
346
347 $acidfree_types = variable_get('acidfree_types', array());
348 $acidfree_base = dirname(drupal_get_filename('module', 'acidfree'));
349 if (!$acidfree_types) {
350 foreach (glob($acidfree_base.DIRECTORY_SEPARATOR.'class_*.inc') as $classfile) {
351 require_once($classfile);
352 $type = acidfree_call(basename($classfile, ".inc") . "_register");
353 if ($type->class)
354 $acidfree_types[$type->class] = $type;
355 }
356 variable_set('acidfree_types', $acidfree_types);
357 } else {
358 foreach ($acidfree_types as $name => $class) {
359 $file = $acidfree_base.DIRECTORY_SEPARATOR."class_{$name}.inc";
360 if (file_exists($file)) {
361 require_once($file);
362 } else {
363 include_acidfree_files(true);
364 }
365 }
366 }
367 require_once $acidfree_base.DIRECTORY_SEPARATOR.'image_manip.inc';
368 $loaded = true;
369 }
370
371 function acidfree_menu($may_cache) {
372 global $acidfree_types, $user;
373 $items = array();
374
375 include_acidfree_files();
376 if ($may_cache) {
377 $items[] = array(
378 'path' => 'node/add/acidfree',
379 'title' => t('Album'),
380 'access' => user_access('create acidfree albums'),
381 'callback' => 'node_add',
382 'callback arguments' => array('acidfree'),
383 );
384 $items[] = array('path' => 'admin/settings/acidfree',
385 'title' => t('Acidfree settings'),
386 'callback' => 'drupal_get_form',
387 'callback arguments' => array('acidfree_admin_settings'),
388 'description' => t('Site-wide Acidfree settings.'),
389 'access' => user_access('administer site configuration'),
390 'type' => MENU_NORMAL_ITEM,
391 );
392 $items[] = array('path' => 'acidfree',
393 'callback' => 'acidfree_page',
394 'title' => t('Acidfree albums'),
395 'access' => user_access('access content'),
396 'type' => MENU_SUGGESTED_ITEM);
397 // acidfree_init stuff
398 $create_acidfree_elements = false;
399 $default_class_callback = false;
400 $items[] = Array('path' => 'node/add/acidfree/mass', 'title' => t('Mass import'),
401 'access' => user_access('acidfree mass import'),
402 'callback' => 'acidfree_mass_import_form',
403 'type' => MENU_NORMAL_ITEM);
404 $items[] = array('path' => 'acidfree/thumbnail',
405 'callback' => 'acidfree_fetch_thumb',
406 'type' => 0,
407 );
408 } else {
409 $acidfree_base = drupal_get_path('module', 'acidfree');
410 drupal_add_css("$acidfree_base/acidfree.css", 'module', 'all');
411
412 $path = explode('/', $_GET['q']);
413 if ($path[0] == 'node' && is_numeric($path[1])) {
414 $album = acidfree_get_node_by_id($path[1]);
415 if ($album && $album->type == 'acidfree') {
416 $items[] = Array('path' => "node/{$path[1]}/contents",
417 'access' => node_access('update', $album),
418 'title' => t('Album contents'),
419 'callback' => 'drupal_get_form',
420 'callback arguments' => array('acidfree_album_contents', $album->tid),
421 'type' => MENU_LOCAL_TASK);
422 if (variable_get('acidfree_show_alternate_view', true)) {
423 $other_view = array('grid' => 'list', 'list' => 'grid');
424 $view_name = array('grid' => t('Grid'), 'list' => t('List'));
425 $view = $other_view[$album->view];
426 $items[] = Array('path' => "node/{$path[1]}/{$view}",
427 'access' => 1,
428 'title' => $view_name[$view],
429 'callback' => 'acidfree_album_view',
430 'callback arguments' => array("album_{$view}_view", $album->tid),
431 'type' => MENU_LOCAL_TASK,
432 'weight' => -4,
433 );
434 }
435 }
436 }
437 if (variable_get('acidfree_per_user_albums', false)) {
438 $items[] = array('path' => 'user/acidfree', 'title' => t('My Acidfree Albums'),
439 'access' => user_access('get a per-user album'),
440 'callback' => 'acidfree_page',
441 'type' => MENU_SUGGESTED_ITEM,
442 );
443 }
444 drupal_add_js(drupal_get_path('module', 'acidfree').'/acidfree.js');
445 }
446 return $items;
447 }
448
449 function acidfree_fetch_thumb($nid=0) {
450 if ($nid == 0 || !($node = acidfree_get_node_by_id($nid))) {
451 return drupal_not_found();
452 }
453 if (!node_access('view', $node)) {
454 return drupal_access_denied();
455 }
456 $file_path = _acidfree_get_thumb_path($node);
457 file_transfer($file_path, array('Content-Type: '.acidfree_mime($file_path), 'Content-Length: '. filesize($filepath), 'Content-Disposition: filename=' . basename($file_path)));
458 }
459
460 function _acidfree_can_create() {
461 return user_access('create images') ||
462 user_access('create video') ||
463 user_access('create acidfree albums');
464 }
465
466 function _acidfree_add_pager(&$node) {
467 // determine the acidfree term -- if no term, bail out
468 if (!$node->taxonomy) {
469 return;
470 }
471
472 // FIXME: this is part of our ugly pager
473 $parent = _acidfree_get_parent($node);
474 $parent = $parent->tid;
475 $offset = _acidfree_get_offset_in_parent($parent, $node);
476 $p = "pid={$parent}";
477 $pager = _acidfree_make_pager_string(array(ELEMENT_PAGER=>"$offset"));
478 $nid = $node->nid;
479
480 // Node ID was present so just hack in the other elements so the system can deal with it. No redirect needed
481 $_GET[PAGER_STRING] = $pager;
482 $_GET['pid'] = $parent->nid;
483 // END: ugly hack
484
485 $node->content['acidfree_pager'] = array(
486 '#weight' => -19,
487 '#value' => acidfree_pager_creator($node),
488 );
489 }
490
491 /**
492 * Implementation of hook_nodeapi
493 */
494 function acidfree_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
495 switch ($op) {
496 case "delete":
497 break;
498 case "insert":
499 break;
500 case "load":
501 break;
502 case "prepare":
503 break;
504 case "search result":
505 break;
506 case "print":
507 break;
508 case "update":
509 // if it is an image node, check to see if we need to rotate it
510 if ($node->type == 'image') {
511 _class_image_rotate($node);
512 }
513 break;
514 case "submit":
515 break;
516 case "update index":
517 break;
518 case "validate":
519 break;
520 case "view":
521 if (($node->type == 'image' || $node->type == 'video') && !$teaser) {
522 $node->content['body']['#weight'] = 1;
523 if ($page) {
524 drupal_set_breadcrumb(acidfree_make_breadcrumbs($node));
525 _acidfree_add_pager($node);
526 }
527 acidfree_call('_class_'.$node->type.'_view_alter', array(&$node));
528 }
529 break;
530 case "rss item":
531 break;
532 }
533 }
534
535 function &acidfree_get_node_by_id($nid) {
536 $types = array('image', 'video', 'acidfree');
537 $node =& node_load(array('nid' => $nid));
538 if (in_array($node->type, $types))
539 return $node;
540 return null;
541 }
542
543 function _acidfree_album_is_shared($option) {
544 global $user;
545 $tid = array_keys($option->option);
546 $node = _album_from_tid($tid[0]);
547 return ($node->share || $node->uid == $user->uid);
548 }
549
550 function _acidfree_filter_taxonomy(&$taxonomy) {
551 if (!user_access('can upload to any album')) {
552 $albums = array();
553 if (!is_array($taxonomy) || !is_array($taxonomy['#options']))
554 return;
555 $taxonomy['#options'] = array_filter($taxonomy['#options'], '_acidfree_album_is_shared');
556 }
557 }
558
559 function acidfree_form_alter($form_id, &$form) {
560 global $acidfree_types;
561 //dump_msg($form);
562 $q = $_GET['q'];
563 switch ($form_id) {
564 case 'acidfree_node_form':
565 acidfree_call($acidfree_types['album']->form_alter, array($form_id, &$form));
566 break;
567 case 'image_node_form':
568 acidfree_call($acidfree_types['image']->form_alter, array($form_id, &$form));
569 break;
570 case 'video_node_form':
571 acidfree_call($acidfree_types['video']->form_alter, array($form_id, &$form));
572 break;
573 case 'system_modules':
574 include_acidfree_files(true);
575 break;
576 default:
577 //drupal_set_message("form_alter: $form_id (not modified)");
578 break;
579 }
580 }
581
582 function _is_int($value) {
583 return (is_numeric($value) && ((int)$value == $value));
584 }
585 function valid_integer($value, $min=null, $max=null) {
586 if (is_null($min)) {
587 return _is_int($value);
588 }
589 if (is_null($max)) {
590 return (_is_int($value) && $value >= $min);
591 }
592 return (_is_int($value) && $value >= $min && $value <= $max);
593 }
594
595 function acidfree_settings_validate($form_id, $values, &$form) {
596 if (!valid_integer($values['acidfree_num_thumbs'], 0)) {
597 form_set_error('acidfree_num_thumbs', t('Thumbnails per page must be a non-negative integer'));
598 }
599 if (!valid_integer($values['acidfree_extra_length'], 0)) {
600 form_set_error('acidfree-extra-length', t('Thumbnail padding must be a non-negative integer'));
601 }
602 }
603
604 function acidfree_settings_submit($form, &$edit) {
605 if ($edit['acidfree_order_force']) {
606 db_query("UPDATE {acidfree_album} SET order_by = '<default>'");
607 }
608 $node = new stdClass();
609 $node->type = 'acidfree';
610 _acidfree_set_node_defaults($node);
611 if ($node->sticky != $edit['acidfree_album_sticky']) {
612 $name = 'node_options_acidfree';
613 $options = variable_get($name, array());
614 if ($edit['acidfree_album_sticky']) {
615 $options[] = 'sticky';
616 } else {
617 $options = array_filter($options, create_function('$v', 'return ($v != "sticky");'));
618 }
619 variable_set($name, $options);
620 db_query("UPDATE {node} SET sticky=%d WHERE type='acidfree'", $edit['acidfree_album_sticky']);
621 }
622 foreach ($edit as $key => $value) {
623 variable_set($key, $value);
624 }
625 }
626
627 /**
628 * Implementation of hook_settings
629 */
630 function acidfree_admin_settings() {
631 $form = array();
632 $form['#validate'] = array('acidfree_settings_validate' => array());
633 $form['#submit'] = array('acidfree_settings_submit' => array());
634 $form['general'] = array(
635 '#type' => 'fieldset',
636 '#title' => t('General Settings'),
637 );
638 $form['general']['acidfree_per_user_albums'] = array(
639 '#type' => 'checkbox',
640 '#title' => t('Per user albums'),
641 '#description' => t('This options will allow each user to have a top-level album of their own. The per user album is located at user/acidfree if logged in and acidfree/user/nnn for each individual album.'),
642 '#default_value' => variable_get('acidfree_per_user_albums', false),
643 );
644 $exiftran_path = variable_get('acidfree_path_to_exiftran', '/usr/bin/exiftran');
645 $jpegtran_path = variable_get('acidfree_path_to_jpegtran', '/usr/bin/jpegtran');
646 if (ini_get('safe_mode')) {
647 $safe_dirs = explode(PATH_SEPARATOR, ini_get('safe_mode_exec_dir'));
648 array_walk($safe_dirs, create_function('&$a, $b', '$a = realpath($a);'));
649 if (!in_array(dirname($jpegtran_path), $safe_dirs) &&
650 !in_array(dirname($exiftran_path), $safe_dirs)) {
651 drupal_set_message(t('Neither exiftran nor jpegtran executables are in the safe_mode_exec_dir (%safe_dir) &mdash; lossy jpeg rotation will be used instead', array('%safe_dir' => $safe_dir)));
652 }
653 }
654 if (!is_executable($exiftran_path) && !is_executable($jpegtran_path))
655 drupal_set_message(t('Neither exiftran nor jpegtran are available &mdash; lossy jpeg rotation will be used instead'));
656 drupal_add_js(drupal_get_path('module', 'acidfree').'/acidfree.js');
657 $form['display'] = array(
658 '#type' => 'fieldset',
659 '#title' => t('Acidfree Display'),
660 );
661 $form['display']['acidfree_show_alternate_view'] = array(
662 '#type' => 'checkbox',
663 '#title' => t('Show alternative album view'),
664 '#default_value' => variable_get('acidfree_show_alternate_view', true),
665 '#description' => t('Albums normally have two views: grid and list. This option controls whether or not when viewing the album, users can switch to the alternate view. Which view is the default view is set individually in each album'),
666 );
667 $form['display']['acidfree_order'] = array(
668 '#type' => 'select',
669 '#title' => t('Sort albums by'),
670 '#default_value' => variable_get('acidfree_order', 'node.nid DESC'),
671 '#options' => array(
672 'node.nid DESC' => t('Latest post first'),
673 'node.nid ASC' => t('Posted order'),
674 'node.title ASC' => t('Alphabetical order'),
675 'node.created ASC' => t('Chronological order by creation date'),
676 ),
677 );
678 $form['display']['acidfree_order_force'] = array(
679 '#type' => 'checkbox',
680 '#title' => t('Sort all albums'),
681 '#default_value' => 0,
682 '#description' => t('Force all albums to use this selected sort order'),
683 );
684 $node = new stdClass();
685 $node->type = 'acidfree';
686 _acidfree_set_node_defaults($node);
687 $form['display']['acidfree_album_sticky'] = array(
688 '#type' => 'checkbox',
689 '#title' => t('List albums first'),
690 '#default_value' => $node->sticky,
691 '#description' => t("Show albums first in all lists (marks them as 'sticky')"),
692 );
693 $form['display']['acidfree_num_thumbs'] = array(
694 '#type' => 'textfield',
695 '#title' => t('Thumbnails per page'),
696 '#size' => 5,
697 '#maxlength' => 10,
698 '#default_value' => variable_get('acidfree_num_thumbs', 15),
699 '#description' => t('Enter 0 for unlimited')
700 );
701 $form['display']['acidfree_filter_caption'] = array(
702 '#type' => 'checkbox',
703 '#title' => t('Show image title as default caption for inline images'),
704 '#default_value' => variable_get('acidfree_filter_caption', false),
705 );
706 $form['display']['acidfree_extra_length'] = array(
707 '#type' => 'textfield',
708 '#size' => 3,
709 '#title' => t('Amount of padding/border on each side of thumbnail image'),
710 '#default_value' => variable_get('acidfree_extra_length',12),
711 '#description' => t('In pixels. Only needs to be changed if you modify the padding/border around the thumbnail.')
712 );
713
714 if (!image_get_toolkit())
715 drupal_set_message(t('No image toolkit has been properly installed or configured. Go to admin/settings to fix this.'), 'error');
716 $form['image_manip'] = array(
717 '#type' => 'fieldset',
718 '#title' => t('Image Manipulation'),
719 );
720 $form['image_manip']['acidfree_path_to_exiftran'] = array(
721 '#type' => 'textfield',
722 '#default_value' => $exiftran_path,
723 '#description' => t('exiftran provides lossless rotation of jpeg images and keeps EXIF information. If you provide a working path, Acidfree will try to use it.'),
724 );
725 $form['image_manip']['acidfree_path_to_jpegtran'] = array(
726 '#type' => 'textfield',
727 '#default_value' => $jpegtran_path,
728 '#description' => t('jpegtran provides lossless rotation of jpeg images and can somewhat munge the EXIF information. If you provide a working path, Acidfree will try to use it.'),
729 );
730 if (function_exists('_class_video_manipulation_options'))
731 $form = array_merge($form, acidfree_call('_class_video_manipulation_options'));
732
733 return system_settings_form($form);
734 }
735
736 /**
737 * Implementation of hook_access().
738 *
739 * Node modules may implement node_access() to determine the operations
740 * users may perform on nodes. This example uses a very common access pattern.
741 */
742 function acidfree_access($op, $node=null) {
743 global $user;
744
745 if ($op == 'create') {
746 // Only users with permission to do so may create this node type.
747 return user_access('create acidfree albums');
748 }
749
750 // Users who create a node may edit or delete it later, assuming they have the
751 // necessary permissions.
752 if ($op == 'update' || $op == 'delete') {
753 if (user_access('edit own acidfree albums') && ($user->uid == $node->uid)) {
754 return TRUE;
755 }
756 }
757 }
758
759 /**
760 * Implementation of hook_perm().
761 *
762 * Since we are limiting the ability to create new nodes to certain users,
763 * we need to define what those permissions are here. We also define a permission
764 * to allow users to edit the nodes they created.
765 */
766 function acidfree_perm() {
767 $perms = Array();
768 $perms[] = 'create acidfree albums';
769 $perms[] = 'edit own acidfree albums';
770 $perms[] = 'acidfree mass import';
771 $perms[] = 'can upload to any album';
772 if (variable_get('acidfree_per_user_albums', 0)) {
773 $perms[] = 'get a per-user album';
774 }
775 return $perms;
776 }
777
778 /**
779 * Implementation of hook_link().
780 *
781 * This is implemented so that an edit link is displayed for users who have
782 * the rights to edit a node.
783 */
784 function acidfree_link($type, $node = 0, $main) {
785 $links = array();
786 if ($type == 'node' && $node->type == 'acidfree') {
787 // Don't display a redundant edit link if they are node administrators.
788 if (acidfree_access('update', $node) && !user_access('administer nodes')) {
789 // determine whether or not we are actually viewing an album or a node
790 $links['acidfree_edit_node'] = array(
791 'title' => t('edit this album'),
792 'href' => "node/{$node->nid}/edit",
793 );
794 }
795 }
796 return $links;
797 }
798
799 // FIXME: do we still need a link_alter to get rid of book module's links
800
801 function _acidfree_create_quick_links(&$album) {
802 global $acidfree_types;
803 if (isset($album->nid)) {
804 $tpath = "/{$album->nid}";
805 } else {
806 $tpath = "";
807 }
808 $links = Array();
809 $show_box = node_access('update', $album) ||
810 (_acidfree_can_create() && $album->share) ||
811 user_access('can upload to any album');
812 if (!$show_box) {
813 return $links;
814 }
815 foreach ($acidfree_types as $type) {
816 if (user_access($type->access)) {
817 $type->path = ($type->class == 'album') ? 'acidfree' : $type->class;
818 $links[] = l($type->addme, "node/add/{$type->path}{$tpath}");
819 }
820 }
821 if (user_access('acidfree mass import'))
822 $links[] = l(t('Mass import'), "node/add/acidfree/mass{$tpath}");
823 return theme('item_list',$links);
824 }
825
826 function acidfree_get_block_nodes($order, $count, $albums=array()) {
827 if ($order == 'counts') {
828 $order = 'votes DESC';
829 $join = 'INNER JOIN {node_counter} c on n.nid=c.nid ';
830 $select = ', ABS(c.daycount*10 + c.totalcount) AS votes';
831 }
832 if (count($albums) > 0) {
833 $terms = implode(',', $albums);
834 $query = "SELECT n.nid FROM {node} n ".
835 "INNER JOIN {term_node} t on n.nid=t.nid ".
836 "WHERE n.type IN ('image', 'video') AND ".
837 "t.tid IN ($terms) AND n.status=1 ".
838 "ORDER BY $order LIMIT $count";
839 } else {
840 $query = "SELECT n.nid $select FROM {node} n $join".
841 "WHERE n.type IN ('image', 'video') AND n.status=1 ".
842 "ORDER BY $order LIMIT $count";
843 }
844 $query = db_rewrite_sql($query);
845 $result = db_query($query);
846 $nodes = Array();
847 while ($row = db_fetch_object($result)) {
848 $nodes[] = acidfree_get_node_by_id($row->nid);
849 }
850 return $nodes;
851 }
852
853 function theme_acidfree_block_contents($node_array) {
854 $nodes =& $node_array[0];
855 foreach ($nodes as $node) {
856 $output .= "<div class='block-cell'>";
857 $output .= theme("acidfree_print_thumb_{$node->type}", $node);
858 $output .= "</div>";
859 }
860 $output .= "<div class='block-bottom'>&nbsp;</div>\n";
861 return $output;
862 }
863
864 function acidfree_block($op = 'list', $delta = 0, $edit=array()) {
865 $titles = array(
866 0=>variable_get("acidfree_block_0_title", t('Recent Acidfree items')),
867 1=>variable_get("acidfree_block_1_title", t('Favorite Acidfree items')),
868 2=>variable_get("acidfree_block_2_title", t('Random Acidfree items')),
869 3=>variable_get("acidfree_block_3_title", t('Add Acidfree items')),
870 );
871 switch ($op) {
872 case 'list':
873 $blocks[0]['info'] = t('Acidfree item recent selection');
874 $blocks[1]['info'] = t('Acidfree item favorite selection');
875 $blocks[2]['info'] = t('Acidfree item random selection');
876 $blocks[3]['info'] = t('Add Acidfree items quick links');
877 return $blocks;
878 case 'view':
879 if (user_access('access content')) {
880 $albums = array();
881 $block['subject'] = $titles[$delta];
882 switch ($delta) {
883 case 0:
884 $order = "nid DESC";
885 break;
886 case 1:
887 $order = "counts";
888 break;
889 case 2:
890 $all_albums = variable_get('acidfree_block_2_all_albums', 1);
891 if (!$all_albums) {
892 $albums = variable_get('acidfree_block_2_random_albums', array());
893 }
894 $order = "RAND()";
895 break;
896 case 3:
897 global $acidfree_types;
898 $q = explode('/', $_GET['q']);
899 if ($q[0] == 'node' && is_numeric($q[1])) {
900 $node = acidfree_get_node_by_id($q[1]);
901 } else if ($type = _path_match('node', 'add', '%s', '%?d')) {
902 if (in_array($type[0], array_keys($acidfree_types)) ||
903 $type[0] == 'acidfree') {
904 $node = acidfree_get_node_by_id($q[3]);
905 }
906 } else if (strstr($_GET['q'], 'node/add/acidfree')) {
907 $node = acidfree_get_node_by_id($q[4]);
908 }
909 if (isset($node)) {
910 $block['content'] = _acidfree_create_quick_links($node);
911 }
912 break;
913 default:
914 break;
915 }
916 if ($delta >= 0 && $delta <= 2) {
917 $nodes = acidfree_get_block_nodes($order,
918 variable_get("acidfree_block_{$delta}_items", 3), $albums);
919 $block['content'] = theme('acidfree_block_contents', array(&$nodes));
920 }
921 return $block;
922 }
923 case 'configure':
924 {
925 $fields = array();
926 if ($delta == 3)
927 return $fields;
928 $fields["acidfree_block_{$delta}_items"] = array(
929 '#type' => 'select',
930 '#title' => t('Number of items'),
931 '#default_value' => variable_get("acidfree_block_{$delta}_items", '5'),
932 '#options' => drupal_map_assoc(range(1,20)),
933 );
934 if ($delta == 2) {
935 drupal_add_js(drupal_get_path('module', 'acidfree').'/acidfree.js');
936 $all_albums = variable_get('acidfree_block_2_all_albums', 1);
937 $fields['acidfree_block_2_all_albums'] = array(
938 '#type' => 'checkbox',
939 '#title' => t('Include items from all albums'),
940 '#default_value' => $all_albums,
941 '#attributes' => array('onchange' => 'toggle_album_select(this);'),
942 );
943 $random_selected = variable_get('acidfree_block_2_random_albums', array());
944 $fields['acidfree_block_2_random_albums'] = _taxonomy_term_select(
945 t('Select random items from these albums'), null, $random_selected, acidfree_get_vocab_id(), t('description'), true, false);
946 if ($all_albums) {
947 $fields['acidfree_block_2_random_albums']['#attributes'] = array('disabled' => 'disabled');
948 }
949 }
950 return $fields;
951 }
952 case 'save':
953 if ($delta == 3)
954 break;
955 variable_set("acidfree_block_{$delta}_items", $edit["acidfree_block_{$delta}_items"]);
956 if ($delta == 2) {
957 variable_set('acidfree_block_2_random_albums', $edit['acidfree_block_2_random_albums']);
958 variable_set('acidfree_block_2_all_albums', $edit['acidfree_block_2_all_albums'] == 1);
959 }
960 break;
961 }
962 }
963
964 function _acidfree_form_element($item) {
965 $el = '#acidfree_form';
966 $item = (array) $item;
967 return isset($item['#acidfree_form']);
968 }
969 function acidfree_form_elements($arr) {
970 return array_filter($arr, '_acidfree_form_element');
971 }
972
973 function acidfree_node_form_validate($form_id, &$edit, &$form) {
974 if ($form_id != 'acidfree_node_form')
975 return;
976 // FIXME: should we do this sort of checking on the file?
977 // and is this the right place to do it?
978 return;
979 if ($form['acidfreeupload'] && !file_check_upload('acidfreeupload'))
980 form_error($form['acidfreeupload'], t('No file supplied'));
981 }
982
983 function acidfree_test() {
984 $errors = 0;
985 $output .= "<ol>\n";
986 if (module_exists('image')) {
987 if (_image_check_settings()) {
988 $output .= '<li class="testok">'.t('Image module sanity check passed.').'</li>';
989 } else {
990 $output .= '<li class="testfail">'.t('Image module sanity check failed. Check the settings at !imgurl and !fsurl.', array('!imgurl'=>'<a href="'.url('admin/settings/image').'">admin/settings/image</a>', '!fsurl'=>'<a href="'.url('admin/settings/file-system').'">admin/settings/file-system</a>')).'</li>';
991 $errors++;
992 }
993 }
994 if (module_exists('video_upload')) {
995 if (_video_upload_check_settings()) {
996 $output .= '<li class="testok">'.t('Video Upload module sanity check passed.').'</li>';
997 } else {
998 $output .= '<li class="testfail">'.t('Video Upload module sanity check failed. Check the settings at !fsurl.', array('!fsurl'=>'<a href="'.url('admin/settings/file-system').'">admin/settings/file-system</a>')).'</li>';
999 $errors++;
1000 }
1001 }
1002 if (file_check_directory(file_directory_temp(), FILE_CREATE_DIRECTORY)) {
1003 $output .= '<li class="testok">'.t('Temporary path okay.').'</li>';
1004 } else {
1005 $output .= '<li class="testfail">'.t('Temporary path does not exist. Check the settings at !fsurl.', array('!fsurl'=>'<a href="'.url('admin/settings/file-system').'">admin/settings/file-system</a>')).'</li>';
1006 $errors++;
1007 }
1008 $modules = array(
1009 "'acidfree'",
1010 "'image'",
1011 "'taxonomy'",
1012 "'video'",
1013 "'video_image'",
1014 "'video_upload'",
1015 );
1016 $results = db_query('SELECT name,weight FROM {system} WHERE name IN ('.implode(',', $modules).')');
1017 while (($row = db_fetch_array($results))) {
1018 $weights[$row['name']] = $row['weight'];
1019 }
1020 $query = "UPDATE {system} SET weight=%d WHERE name='%s'";
1021 if ($weights['video_image'] < $weights['video_upload']) {
1022 db_query($query, ++$weights['video_upload'], 'video_image');
1023 $output .= '<li class="testfail">'.t('Updated %mod module weight.', array('%mod' => 'video_image')).'</li>';
1024 $errors++;
1025 } else {
1026 $output .= '<li class="testok">'.t('%mod module weight okay.', array('%mod' => 'video_image')).'</li>';
1027 }
1028 if ($weights['acidfree'] < $weights['image'] ||
1029 $weights['acidfree'] < $weights['taxonomy'] ||
1030 $weights['acidfree'] < $weights['video'] ||
1031 $weights['acidfree'] < $weights['video_image'] ||
1032 $weights['acidfree'] < $weights['video_upload']) {
1033 db_query($query, max($weights)+1, 'acidfree');
1034 $output .= '<li class="testfail">'.t('Updated %mod module weight.', array('%mod' => 'acidfree')).'</li>';
1035 $errors++;
1036 } else {
1037 $output .= '<li class="testok">'.t('%mod module weight okay.', array('%mod' => 'acidfree')).'</li>';
1038 }
1039 if (($itk = image_get_toolkit()) && image_toolkit_invoke('check_settings')) {
1040 $output .= '<li class="testok">'.t('%itk image toolkit installed and properly configured', array('%itk' => $itk)).'</li>';
1041 } else {
1042 $output .= '<li class="testfail">'.t('Image toolkit not properly installed or configured. Go to %url and configure the image toolkit properly.', array('%url' => '<a href="%url">admin/settings</a>', array('%url' => url('admin/settings')))).'</li>';
1043 $errors++;
1044 }
1045 $output .= "</ol>\n";
1046 if ($errors) {
1047 $output .= '<p>'.t<