]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/PhotoAlbum.php
fixed gettext strings
[SourceForge/phpwiki.git] / lib / plugin / PhotoAlbum.php
1 <?php // -*-php-*-
2 rcs_id('$Id: PhotoAlbum.php,v 1.7 2004-05-03 20:44:55 rurban Exp $');
3 /*
4  Copyright 2003, 2004 $ThePhpWikiProgrammingTeam
5  
6  This file is part of PhpWiki.
7
8  PhpWiki 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  PhpWiki 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 PhpWiki; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 /**
24  * WikiPlugin which makes an 'album' of a set of photos with optional
25  * descriptions.
26  *
27  * @author: Ted Vinke <teddy@jouwfeestje.com>
28  *          local fs by Reini Urban
29  *
30  * Usage:
31  * <?plugin PhotoAlbum
32  *          src="http://server/textfile" or localfile or localdir or nothing
33  *          mode=[column|row]
34  *          desc=true
35  *          sort=false
36  *          height=50%
37  *          width=50%
38  * ?>
39
40  * (1) No src specified. Means [wikipagename].jpg from fixed albumlocation
41  *     will be displayed e.g. "Sandbox.jpg".
42  *
43  *     You can set the following constants:
44  */
45
46 define('allow_album_location', true);
47 define('album_location', 'http://kw.jouwfeestje.com/foto/redactie');
48 define('album_default_extension', '.jpg');
49
50 /**
51  * (2) Textfile. Local or remote e.g. http://myserver/images/MyPhotos.txt
52  *     E.g. possible content of a valid textfile:
53  *
54  *      photo-01.jpg; Me and my girlfriend
55  *      photo-02.jpg
56  *      christmas.gif; Merry Christmas!
57
58  *     Inside textfile, filenames and optional descriptions are seperated by
59  *     constant 'desc_separator' (default is semi-colon) on each line. Listed
60  *     files must be in same directory as textfile itself, so don't use
61  *     relative paths inside textfile.
62  */
63
64 define('desc_separator', ';');
65
66 /**
67  * (3) Directory. 
68  *     Need weblocation="" the webpath to the srcdir
69  *
70  * Other parameters that need explaining:
71  * "parameter"  "value"
72  *
73  * "mode"       "normal" - Normal table which shows photos full-size
74  *              "thumbs" - WinXP thumbnail style
75  *              "tiles"  - WinXP tiles style
76  *              "list"   - WinXP list style
77  *              "slide"  - Not yet implemented
78  *
79  * "numcols"    Amount of columns per row in table
80  *
81  * "showdesc"   "none"   - No descriptions next to photos
82  *              "name"   - Only filename shown
83  *              "desc"   - Only description (from textfile) shown
84  *              "both"   - If no description found, then filename will be used
85  *
86  * "link"       If true, each image will be hyperlink to page where only that
87  *              photo will be shown full-size. Only works when mode != 'normal'
88  *
89  * "attrib"     Array which can hold:
90  *              "sort"   - sort shown photos alphabetically
91  *              "nowrap" - descriptions won't be wrapped
92  *              "alt"    - descs instead of filenames are used in image ALT-tags
93  *
94  * "bgcolor"
95  * "hlcolor"    Cell background and highlight color
96  *
97  * "align"      Aligment of cell: "left", "center", "right"
98  *
99  * "height"
100  * "width"      Size of shown photos. Either absolute value (e.g. "50") or
101  *              HTML style percentage (e.g. "75%") or "auto" for no special
102  *              action.
103  *
104  * "cellwidth"  Width of cells in table. Either absolute value in pixels, HTML
105  *              style percentage, "auto" (no special action), "equal" (where
106  *              all columns are equally sized) or "image" (take height and
107  *              width of the photo in that cell).
108  *
109  * "tablewidth" Guess what.
110  */
111
112 define('default_mode', 'normal');       // normal|thumbs|tiles|list
113 define('default_numcols', 3);           // photos per row
114 define('default_showdesc', 'both');     // none|name|desc|both
115 define('default_link', true);           // show link to original sized photo
116 define('default_attrib', '');           // 'sort, nowrap, alt'
117 define('default_bgcolor', '#eae8e8');   // cell bgcolor (lightgrey)
118 define('default_hlcolor', '#c0c0ff');   // highlight color (lightblue)
119 define('default_align', 'center');      // alignment of all
120 define('default_height', 'auto');       // image height (auto|75|100%)
121 define('default_width', 'auto');        // image width (auto|75|100%)
122 define('default_cellwidth', 'image');   // cell (auto|equal|image|75|100%)
123 define('default_tablewidth', 1);        // table (75|100%)
124
125 /**
126  * TODO:
127  *
128  * - parse any local directory for pictures
129  * - implement WinXP style 'slide' mode
130  * - specify picture(s) as parameter(s)
131  * - limit amount of pictures on one page
132  * - use PHP to really resize or greyscale images (only where GD library
133  *   supports it)
134  *
135  * KNOWN ISSUES:
136  *
137  * - reading height and width, from images with spaces in their names, fails
138  *
139  * Fixed album location idea by Philip J. Hollenback. Thanks!
140  */
141
142 class WikiPlugin_PhotoAlbum
143 extends WikiPlugin
144 {
145     function getName () {
146         return _("PhotoAlbum");
147     }
148
149     function getDescription () {
150         return _("Displays a set of photos listed in a text file with optional descriptions");
151     }
152
153     function getVersion() {
154         return preg_replace("/[Revision: $]/", '',
155                             "\$Revision: 1.7 $");
156     }
157
158     function getDefaultArguments() {
159         return array('src'      => '',          // textfile
160                      'mode'     => default_mode,
161                      'numcols'  => default_numcols,
162                      'showdesc' => default_showdesc,
163                      'link'     => default_link,
164                      'attrib'   => default_attrib,
165                      'bgcolor'  => default_bgcolor,
166                      'hlcolor'  => default_hlcolor,
167                      'align'    => default_align,
168                      'height'   => default_height,
169                      'width'    => default_width,
170                      'cellwidth'=> default_cellwidth,
171                      'tablewidth'=> default_tablewidth,
172                      'p'        => false, // "displaythissinglephoto.jpg"
173                      'h'        => false, // "highlightcolorofthisphoto.jpg"
174                      'weblocation'  => false, // if src = localfs the web location
175                      );
176     }
177     // attrib arg allows multiple attributes attrib=sort,nowrap,alt
178     // 'sort' sorts alphabetically, 'nowrap' for cells, 'alt' to use
179     // descriptions (instead of filenames) for image alt-tags
180
181     function run($dbi, $argstr, $request) {
182         extract($this->getArgs($argstr, $request));
183
184         $attributes = $attrib ? explode(",", $attrib) : array();
185
186         $photos = array();
187         $html = HTML();
188
189         // check all parameters
190
191         // what type do we have?
192         if (!$src) {
193             $showdesc  = 'none';
194             $src   = $request->getArg('pagename');
195             $error = $this->fromLocation($src, $photos);
196         } else {
197             $error = $this->fromFile($src, $photos, $weblocation);
198         }
199         if ($error) {
200             return $this->error($error);
201         }
202
203         if ($numcols < 1) $numcols = 1;
204         if ($align != 'left' && $align != 'center' && $align != 'right') {
205             $align = default_align;
206         }
207
208         if (count($photos) == 0) return;
209
210         if (in_array("sort", $attributes))
211             sort($photos);
212
213         if ($p) {
214             $mode = "normal";
215         }
216
217         // set some fixed properties for each $mode
218         if ($mode == 'thumbs' || $mode == 'tiles') {
219             $attributes = array_merge($attributes, "alt");
220             $attributes = array_merge($attributes, "nowrap");
221             $cellwidth  = 'auto'; // else cell won't nowrap
222             $showdesc   = 'name';
223             $width      = 50;
224         } elseif ($mode == 'list') {
225             $numcols    = 1;
226             $cellwidth  = "auto";
227             if ($showdesc != "none") {
228                 $showdesc = "desc";
229             }
230         }
231
232         $row = HTML();
233         while (list($key, $value) = each($photos))  {
234             if ($p && basename($value["name"]) != "$p") {
235                 continue;
236             }
237             if ($h && basename($value["name"]) == "$h") {
238                 $color = $hlcolor ? $hlcolor : $bgcolor;
239             } else {
240                 $color = $bgcolor;
241             }
242             // $params will be used for each <img > tag
243             $params = array('src'    => $value["name"],
244                             'border' => "0",
245                             'alt'    => ($value["desc"] != "" &&
246                                          in_array("alt", $attributes)) ?
247                                          $value["desc"] :
248                                          basename($value["name"])
249                             );
250
251             // check description
252             switch ($showdesc) {
253                 case 'none':
254                     $value["desc"] = '';
255                     break;
256                 case 'name':
257                     $value["desc"] = basename($value["name"]);
258                     break;
259                 case 'desc':
260                     break;
261                 default: // 'both'
262                     $value["desc"] = ($value["desc"] != "") ?
263                                       $value["desc"] :
264                                       basename($value["name"]);
265                     break;
266             }
267
268             // FIXME: get getimagesize to work with names with spaces in it.
269             // convert $value["name"] from webpath to local path
270             $size = @getimagesize($value["name"]); // try " " => "\\ "
271             if (!$size and !empty($value["src"])) {
272                 $size = @getimagesize($value["src"]);
273                 if (!$size) {
274                     trigger_error("Unable to getimagesize(".$value["name"].")",E_USER_NOTICE);
275                 }
276             }
277
278             $newwidth = $this->newSize($size[0], $width);
279             $newheight = $this->newSize($size[1], $height);
280
281             if ($width != 'auto' && $newwidth > 0) {
282                 $params = array_merge($params, array("width" => $newwidth));
283             }
284             if ($height != 'auto' && $newheight > 0) {
285                 $params = array_merge($params, array("height" => $newheight));
286             }
287
288             // cell operations
289             $cell = array('align'   => "center",
290                           'valign'  => "top",
291                           'bgcolor' => "$color",
292                           );
293             if ($cellwidth != 'auto') {
294                 if ($cellwidth == 'equal') {
295                     $newcellwidth = round(100/$numcols)."%";
296                 } else if ($cellwidth == 'image') {
297                     $newcellwidth = $newwidth;
298                 } else {
299                     $newcellwidth = $cellwidth;
300                 }
301                 $cell = array_merge($cell, array("width" => $newcellwidth));
302             }
303             if (in_array("nowrap", $attributes)) {
304                 $cell = array_merge($cell, array("nowrap" => ""));
305             }
306             //create url to display single larger version of image on page
307             $url        = WikiURL($request->getPage(),
308                           array("p" => basename($value["name"])));
309             $b_url      = WikiURL($request->getPage(),
310                           array("h" => basename($value["name"]))).
311                                                 "#".
312                                                 basename($value["name"]);
313             $url_text   = $link ? HTML::a(array("href" => "$url"),
314                                                 basename($value["name"])) :
315                                                 basename($value["name"]);
316             if (! $p) {
317                 $url_image = $link ? HTML::a(array("href" => "$url"),
318                                                    HTML::img($params)) :
319                                                    HTML::img($params);
320             } else {
321                 $url_image = $link ? HTML::a(array("href" => "$b_url"),
322                                                    HTML::img($params)) :
323                                                    HTML::img($params);
324             }
325             $url_text = HTML::a(array("name" => basename($value["name"])),
326                                       $url_text);
327             // here we use different modes
328             if ($mode == 'tiles') {
329                 $row->pushContent(HTML::td($cell,
330                      HTML::table(array("cellpadding" => 1, "border" => 0),
331                      HTML::tr(
332                            HTML::td(array("valign" => "top", "rowspan" => 2),
333                                            $url_image),
334                            HTML::td(array("valign" => "top", "nowrap" => 0),
335                                           HTML::small(HTML::strong($url_text)),
336                                           HTML::br(),
337                                           HTML::small($size[0].
338                                                       " x ".
339                                                       $size[1].
340                                                       " pixels"))
341                               ))));
342             } else if ($mode == 'list') {
343                 $desc = ($showdesc != 'none') ? $value["desc"] : '';
344                 $row->pushContent(
345                     HTML::td(array("valign"  => "top",
346                                    "nowrap"  => 0,
347                                    "bgcolor" => $color),
348                                    HTML::small(HTML::strong($url_text))));
349                 $row->pushContent(
350                     HTML::td(array("valign"  => "top",
351                                    "nowrap"  => 0,
352                                    "bgcolor" => $color),
353                                    HTML::small($size[0].
354                                                " x ".
355                                                $size[1].
356                                                " pixels")));
357
358                 if ($desc != '') {
359                     $row->pushContent(HTML::td(array("valign"  => "top",
360                                                      "nowrap"  => 0,
361                                                      "bgcolor" => $color),
362                                                      HTML::small($desc)));
363                 }
364             } else if ($mode == 'thumbs') {
365                 $desc = ($showdesc != 'none') ?
366                         HTML::p(HTML::a(array("href" => "$url"),
367                                         $url_text)) :
368                                         '';
369                 $row->pushContent(
370                     (HTML::td($cell,
371                               $url_image,
372                               // FIXME: no HtmlElement for fontsizes?
373                               // rurban: use ->setAttr("style","font-size:small;")
374                               //         but better use a css class
375                               HTML::span(array('class'=>'gensmall'),$desc)
376                               )));
377             } else /* 'normal' mode */ {
378                 $desc = ($showdesc != 'none') ? HTML::p($value["desc"]) : '';
379                 $row->pushContent(
380                     (HTML::td($cell,
381                               $url_image,
382                               // FIXME: no HtmlElement for fontsizes?
383                               HTML::span(array('class'=>'gensmall'),$desc)
384                               )));
385             }
386
387             // no more images in one row as defined by $numcols
388             if ( ($key + 1) % $numcols == 0 ||
389                  ($key + 1) == count($photos) ||
390                   $p) {
391                 $html->pushcontent(HTML::tr($row));
392                 $row->setContent('');
393             }
394         }
395
396         //create main table
397         $html = HTML::table(array("border"      => 0,
398                                   "cellpadding" => 5,
399                                   "cellspacing" => 2,
400                                   "width"       => $tablewidth),
401                                   $html);
402         // align all
403         $html = HTML::div(array("align" => $align), $html);
404         return $html;
405     }
406
407     /**
408      * Calculate the new size in pixels when the original size
409      * with a value is given.
410      *
411      * @param integer $oldSize Absolute no. of pixels
412      * @param mixed $value Either absolute no. or HTML percentage e.g. '50%'
413      * @return integer New size in pixels
414      */
415     function newSize($oldSize, $value) {
416         if (substr($value, strlen($value) - 1) != "%") {
417             return $value;
418         }
419         substr_replace($value, "%", "");
420         return round(($oldSize*$value)/100);
421     }
422
423     /**
424     * fromLocation - read only one picture from fixed album_location
425     * and return it in array $photos
426     *
427     * @param string $src Name of page
428     * @param array $photos
429     * @return string Error if fixed location is not allowed
430     */
431     function fromLocation($src, &$photos) {
432         if (!allow_album_location) {
433             return $this->error(_("Fixed album location is not allowed. Please specify parameter src."));
434         }
435         $photos[count($photos)] =
436           array ("name" => album_location."/$src".album_default_extension,
437                  "desc" => ""
438                  );
439     }
440
441     /**
442      * fromFile - read pictures & descriptions (separated by desc_sep)
443      * from file $src and return it in array $photos
444      *
445      * @param string $src Full path and filename of textfile
446      * @param array $photos
447      * @return string Error when bad url or file couldn't be opened
448      */
449     function fromFile($src, &$photos, $webpath = false) {
450         if (! IsSafeURL($src)) {
451             return $this->error(_("Bad url in src: remove all of <, >, \""));
452         }
453         if (!preg_match('/^(http|ftp|https):\/\//i',$src)) {
454             // check if src is a directory
455             if (file_exists($src) and filetype($src) == 'dir') {
456                 //all images
457                 $list = array();
458                 foreach (array('jpeg','jpg','png','gif') as $ext) {
459                     $fileset = new fileSet($src, "*.$ext");
460                     $list = array_merge($list,$fileset->getFiles());
461                 }
462                 // convert dirname($src) (local fs path) to web path
463                 natcasesort($list);
464                 if (! $webpath ) {
465                     // assume relative src. default: "themes/Hawaiian/images/pictures"
466                     $webpath = DATA_PATH . '/' . $src;
467                 }
468                 foreach ($list as $file) {
469                     // convert local path to webpath
470                     $photos[] = array ("name" => $webpath . "/$file",
471                                        "src"  => $src . "/$file",
472                                        "desc" => "",
473                                        );
474                 }
475                 return;
476             }
477         } else {
478             // fixed: get current value, not stored value.
479             // todo: use lib/HttpClient.php
480             if (! get_cfg_var('allow_url_fopen')) {
481                 return $this->error(fmt("Wrong server setting: allow_url_fopen set to Off"));
482             }
483         }
484         @$fp = fopen ($src,"r");
485         if (!$fp) {
486             return $this->error(fmt("Unable to read %s ", $src));
487         }
488         while ($data = fgetcsv ($fp, 1024, desc_separator)) {
489             if (count($data) == 0 || empty($data[0]))
490                 continue;
491             // otherwise when empty 'undefined index 1' PHP warning appears
492             if (empty($data[1]))
493                 $data[1] = '';
494             $photos[count($photos)] = array ("name" => dirname($src).
495                                                        "/".
496                                                        trim("$data[0]"),
497                                              "desc" => trim("$data[1]"),
498                                              );
499         }
500         fclose ($fp);
501     }
502 };
503
504 // $Log: not supported by cvs2svn $
505 // Revision 1.6  2004/04/18 00:19:30  rurban
506 // better default example with local src, don't require weblocation for
507 // the default setup, better docs, fixed ini_get => get_cfg_var("allow_url_fopen"),
508 // no HttpClient lib yet.
509 //
510 // Revision 1.5  2004/03/09 12:10:23  rurban
511 // fixed getimagesize problem with local dir.
512 //
513 // Revision 1.4  2004/02/28 21:14:08  rurban
514 // generally more PHPDOC docs
515 //   see http://xarch.tu-graz.ac.at/home/rurban/phpwiki/xref/
516 // fxied WikiUserNew pref handling: empty theme not stored, save only
517 //   changed prefs, sql prefs improved, fixed password update,
518 //   removed REPLACE sql (dangerous)
519 // moved gettext init after the locale was guessed
520 // + some minor changes
521 //
522 // Revision 1.3  2004/02/27 08:03:35  rurban
523 // Update from version 1.2 by Ted Vinke
524 // implemented the localdir support
525 //
526 // Revision 1.2  2004/02/17 12:11:36  rurban
527 // added missing 4th basepage arg at plugin->run() to almost all plugins. This caused no harm so far, because it was silently dropped on normal usage. However on plugin internal ->run invocations it failed. (InterWikiSearch, IncludeSiteMap, ...)
528 //
529 // Revision 1.1  2003/01/05 04:21:06  carstenklapp
530 // New plugin by Ted Vinke (sf tracker patch #661189)
531 //
532
533 // For emacs users
534 // Local Variables:
535 // mode: php
536 // tab-width: 8
537 // c-basic-offset: 4
538 // c-hanging-comment-ender-p: nil
539 // indent-tabs-mode: nil
540 // End:
541 ?>