--- /dev/null
+<?php
+// vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4:
+// +--------------------------------------------------------------------+
+// | Hooks |
+// +--------------------------------------------------------------------+
+// | This file is part of Hooks. |
+// | |
+// | Hooks is free software; you can redistribute it and/or modify it |
+// | under the terms of the GNU General Public License as published by |
+// | the Free Software Foundation; either version 2 of the License, or |
+// | (at your option) any later version. |
+// | |
+// | Hooks is distributed in the hope that it will be useful, but |
+// | WITHOUT ANY WARRANTY; without even the implied warranty of |
+// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
+// | General Public License for more details. |
+// | |
+// | You should have received a copy of the GNU General Public License |
+// | along with Hooks; if not, write to the Free Software Foundation, |
+// | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
+// +--------------------------------------------------------------------+
+// | Created: 2000 |
+// | Authors: Harpo Maxx <harpo@lugmen.org.ar> |
+// | Groucho Marx <groucho@lugmen.org.ar> |
+// | Leandro Lucarella <luca@lugmen.org.ar> |
+// +--------------------------------------------------------------------+
+//
+// $Id$
+//
+
+require_once 'PEAR.php';
+require_once 'Util.php';
+require_once 'Image/Transform.php';
+require_once 'HTML/Template/Sigma.php';
+
+/**
+ * Generates a photo album.
+ *
+ * This library generates a photo album dinamically.
+ *
+ * @package Hooks
+ * @subpackage Album
+ * @author Harpo Maxx <harpo@lugmen.org.ar>
+ * @author Groucho Marx <groucho@lugmen.org.ar>
+ * @author Leandro Lucarella <luca@lugmen.org.ar>
+ * @version $Rev$
+ * @since rev 130
+ * @access public
+ */
+class Hook_Album {
+
+ var $root;
+ var $recursive;
+ var $thumbsdir;
+ var $thumbsformat;
+ var $exts;
+
+ /**
+ * Constructor.
+ *
+ * @param string $root Root directory.
+ * same row.
+ * @param bool $recursive True if subdirectories must be
+ * proccessed.
+ * @param string $thumbsdir Directory where the thumbnails are (or
+ * will be generated).
+ * @param array $exts Comma separated extensions of photo files.
+ *
+ * @access public
+ */
+ function Hook_Album($root = '.', $recursive = true, $thumbsformat = 'jpeg', $thumbsdir = '.thumbs', $exts = 'png,jpg,jpeg,gif') {
+ $this->root = $root ? $root : '.';
+ $this->recursive = $recursive;
+ $this->thumbsdir = $thumbsdir;
+ $this->thumbsformat = $thumbsformat;
+ $this->exts = preg_split('/\s*,\s*/', $exts);
+ }
+
+ /**
+ * Shows the photo album.
+ *
+ * Shows the photo album.
+ *
+ * @param string $photo Selected photo.
+ * @param int $max Maximum quantity of thumbnails to show. 0 for
+ * unlimited.
+ * @param int $cols How many thumbnails are shown in the
+ *
+ * @access public
+ * @todo Implement the 'max' feature!
+ * @todo Make the thumbs cache before showing the images so the
+ * browser can find the with having to refresh.
+ */
+ function album(&$tpl, $photo = '', $max = 0, $cols = 4) {
+ $tpl->loadTemplateFile('bife_album.html');
+ $tpl->addBlockFile('ITEMS', 'ITEM', 'bife_album_item.html');
+
+ $root = $this->root;
+ $list = $this->getList();
+ $tot = count($list);
+ $rows = ceil($tot / $cols);
+
+ for ($row = 0; $row < $rows; $row++) {
+ for ($col = 0; $col < $cols; $col++) {
+ $cur = $row*$cols+$col;
+ if ($photo = @$list[$cur]) {
+ $selected = ($photo['file'] === $photo);
+ if (is_null($photo['thumb'])) {
+ $photo['thumb'] = $this->makeThumb($photo['file']);
+ }
+ $tpl->setVariable(
+ array(
+ 'PHOTO' => $photo['file'],
+ 'DESC' => $photo['desc'],
+ 'THUMB' => $photo['thumb'],
+ )
+ );
+ $tpl->parse('ITEM');
+ } else {
+ if (!@$empty) {
+ $tpl->replaceBlockFile('ITEM',
+ 'bife_album_emptyitem.html', true);
+ $empty = true;
+ }
+ $tpl->touchBlock('ITEM');
+ $tpl->parse('ITEM');
+ }
+ }
+ $tpl->parse('FILA');
+ }
+ $tpl->setVariable('DESC', $this->getDescription());
+ return $tpl->get();
+ }
+
+ /**
+ * Shows a photo.
+ *
+ * Shows a photo.
+ *
+ * @param string $photo Photo to show.
+ *
+ * @access public
+ * @since rev 131
+ */
+ function photo($photo) {
+ list($path, $name, $ext) = File_Util::splitFilename($photo);
+ $tpl =& new HTML_Template_Sigma('.');
+ $tpl->loadTemplateFile('photo.html');
+ $tpl->setVariable(
+ array(
+ 'DESC' => $name,
+ 'PHOTO' => $photo,
+ )
+ );
+ $tpl->show();
+ }
+
+ /**
+ * Makes a photo thumbnail.
+ *
+ * @param string $photo Source photo to create the thumbnail.
+ * @param int $size Maximum thumbnail size.
+ *
+ * @return bool True on success, false on failure.
+ *
+ * @access public
+ * @since rev 131
+ */
+ function makeThumb($photo, $size = 100) {
+ $format = $this->thumbsformat;
+ $thumb = $this->getThumbName($photo);
+ list($path, $name, $ext) = File_Util::splitFilename($thumb);
+
+ $img =& Image_Transform::factory('GD');
+
+ $img->load($photo);
+ // If image is larger than the maximum size, we resize it.
+ if ($img->img_x > $size or $img->img_y > $size ) {
+ if (!is_dir($path) and !mkdir($path)) {
+ return false;
+ }
+ if (PEAR::isError($img)) {
+ return false;
+ }
+ if (!$img->scale($size)) {
+ return false;
+ }
+ }
+ $img->save("$path/$name.$format", $format);
+ $img->free();
+
+ return true;
+ }
+
+ /**
+ * Gets a list of photos with their descriptions and thumbnails.
+ *
+ * Returns an array of associative arrays with this keys:
+ * <ul>
+ * <li><b>file:</b> Photo filename.</li>
+ * <li><b>desc:</b> Photo Description.</li>
+ * <li><b>thumb:</b> Photo thumbnail filename.</li>
+ * </ul>
+ *
+ * @return array Array of associative arrays with file, desc and
+ * thumb.
+ *
+ * @access public
+ */
+ function getList() {
+ $root = $this->root;
+ $exts = $this->exts;
+ $format = $this->thumbsformat;
+ $return = array();
+
+ $d = dir($root);
+ while (($file = $d->read()) !== false) {
+ list($path, $name, $ext) = File_Util::splitFilename("$root/$file");
+ if (is_readable("$root/$file") and in_array($ext, $exts)) {
+ $thumb = $this->getThumbName("$root/$file");
+ $return[] = array(
+ 'file' => "$root/$file",
+ 'desc' => $name,
+ 'thumb' => is_readable($thumb) ? $thumb : null,
+ );
+ }
+ }
+ $d->close();
+
+ return $return;
+ }
+
+ /**
+ * Gets a photo thumbnail name.
+ *
+ * @param string $photo Source photo to create the thumbnail.
+ *
+ * @return string Thumbnail name.
+ *
+ * @access public
+ * @since rev 131
+ */
+ function getThumbName($photo) {
+ $root = $this->root;
+ $format = $this->thumbsformat;
+ $thumbsdir = $this->thumbsdir;
+
+ list($path, $name, $ext) = File_Util::splitFilename($photo);
+
+ return "$root/$thumbsdir/$name.$format";
+ }
+
+ /**
+ * Creates album thumbnails.
+ *
+ * @since rev 147
+ * @access public
+ */
+ function createThumbs() {
+ foreach ($this->getList() as $photo) {
+ if (is_null($photo['thumb'])) {
+ $photo['thumb'] = $this->makeThumb($photo['file']);
+ }
+ }
+ }
+
+ /**
+ * Sets the album description.
+ *
+ * @param string $desc New album description.
+ *
+ * @returns bool True on success, false on failure.
+ *
+ * @since rev 147
+ * @access public
+ */
+ function setDescription($desc) {
+ $root = $this->root;
+ $out = fopen("$root/.album", 'w');
+ $ret = fputs($out, $desc);
+ fclose($out);
+ return $ret ? true : false;
+ }
+
+ /**
+ * Gets the album description.
+ *
+ * @returns string Album description.
+ *
+ * @since rev 149
+ * @access public
+ */
+ function getDescription() {
+ $root = $this->root;
+ return file_get_contents("$root/.album");
+ }
+
+}
+
+// $Id$
+?>
--- /dev/null
+<?php
+// vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4:
+// +--------------------------------------------------------------------+
+// | Hooks |
+// +--------------------------------------------------------------------+
+// | This file is part of Hooks. |
+// | |
+// | Hooks is free software; you can redistribute it and/or modify it |
+// | under the terms of the GNU General Public License as published by |
+// | the Free Software Foundation; either version 2 of the License, or |
+// | (at your option) any later version. |
+// | |
+// | Hooks is distributed in the hope that it will be useful, but |
+// | WITHOUT ANY WARRANTY; without even the implied warranty of |
+// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
+// | General Public License for more details. |
+// | |
+// | You should have received a copy of the GNU General Public License |
+// | along with Hooks; if not, write to the Free Software Foundation, |
+// | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
+// +--------------------------------------------------------------------+
+// | Created: lun ene 6 17:22:31 ART 2003 |
+// | Authors: Leandro Lucarella <luca@lugmen.org.ar> |
+// +--------------------------------------------------------------------+
+//
+// $Id$
+//
+
+/**
+ * General file utilities functions.
+ *
+ * This is a group of static functions for getting file info and other
+ * stuff.
+ *
+ * @package Hooks
+ * @author Leandro Lucarella <luca@lugmen.org.ar>
+ * @version $Rev$
+ * @since rev 122
+ * @access public
+ */
+class File_Util {
+
+ /**
+ * Splits a filename into path, filename and extension.
+ *
+ * @param string $file Filename to split.
+ *
+ * @return array Array where the first element (index 0) is the
+ * path, the second is the name and the third is the
+ * extension.
+ *
+ * @access public
+ * @since rev 122
+ */
+ function splitFilename($file)
+ {
+ $path = preg_split('|/|', $file);
+ $file = array_pop($path);
+ $ext = '';
+ if (strstr($file, '.')) {
+ preg_match('|([^/]+?)(\.([^\.]*))?$|', $file, $m);
+ $file = @$m[1] . ((@$m[2] == '.' ) ? '.' : '');
+ $ext = @$m[3];
+ }
+ $dir = count($path) ? join('/', $path) : '';
+ return array($dir, $file, $ext);
+ }
+
+ /**
+ * Tells if a file is readable looking in the include path.
+ *
+ * @param string $file Name of the file to look for.
+ *
+ * @return bool True if file is readable, false if not.
+ *
+ * @access public
+ * @since rev 122
+ */
+ function isReadableInclude($file)
+ {
+ list($dir, $page, $ext) = File_Util::splitFilename($file);
+ if (is_readable($file)) {
+ return true;
+ }
+ $include_path = array_unique(preg_split('/:/', ini_get('include_path')));
+ foreach ($include_path as $path) {
+ if (is_readable("$path/$file")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Gets the last modification date/time for a file.
+ *
+ * @param string $file Name of the file to get the last modification
+ * date/time.
+ * @param string $format Format (see strftime).
+ *
+ * @return string Formated string with the last modification
+ * date/time.
+ *
+ * @see strftime()
+ * @access public
+ * @since rev 142
+ */
+ function lastModified($file, $format = '%c')
+ {
+ return strftime($format, filemtime($file));
+ }
+
+}
+
+// This is a workarround to live until PHP 4.3 is out and we can use the
+// native get_file_contents() function. We don't care about
+// $use_include_file option.
+function file_get_contents($file, $use_include_file = false)
+{
+ if (@is_readable($file)) {
+ $var = join('', file($file));
+ } else {
+ $var = '';
+ }
+ return $var;
+}
+
+?>
--- /dev/null
+<H3 class="album">{DESC}</H3>
+<DIV class="center">
+ <TABLE class="album">
+ <TBODY>
+ <!-- BEGIN FILA -->
+ <TR>
+ {ITEMS}
+ </TR>
+ <!-- END FILA -->
+ </TBODY>
+ </TABLE>
+</DIV>
--- /dev/null
+<TD class="albumitem">VACIO</TD>
--- /dev/null
+<TD class="albumitem">
+ <A class="albumitem" href="photo?photo={PHOTO}" title="{DESC}"><IMG alt="{DESC}" src="{THUMB}" class="albumitem"></A>
+</TD>
--- /dev/null
+<HTML>
+ <HEAD>
+ <TITLE>{TITLE}</TITLE>
+ </HEAD>
+ <BODY>
+ <H1>{TITLE}</H1>
+ {CONTENTS}
+ </BODY>
+</HTML>
--- /dev/null
+<H2>{CONTENTS}</H2>
<?
-// BIFE: Build It FastEr - draft 1
+// BIFE: Build It FastEr - draft 2
-define('TAB', ' ');
+require_once 'HTML/Template/Sigma.php';
+require_once 'Album.php';
-$file = "data.xml";
-$depth = array();
+$file = "simple.xml";
+
+$template =& new HTML_Template_Sigma('.');
+$template->setErrorHandling(PEAR_ERROR_PRINT);
+
+$output = '';
$stack = array();
function startElement($parser, $name, $attrs) {
- global $depth, $stack;
- $stack[] = $name;
- echo str_repeat(TAB, @$depth[$parser]);
- echo "<$name> ";
- foreach ($attrs as $attr => $val) {
- echo "$attr: '$val' ";
+ global $stack;
+ $class = "BIFE_$name";
+ if (class_exists($class)) {
+ $obj =& new $class($attrs);
+ if (!is_a($obj, 'bife_base')) {
+ trigger_error("Class '$class' is not a BIFE_Base.", E_USER_WARNING);
+ }
+ $stack[] =& $obj;
+ } else {
+ trigger_error("Class not found '$class'.", E_USER_ERROR);
}
- echo "\n";
- @$depth[$parser]++;
}
function endElement($parser, $name) {
- global $depth, $stack;
+ global $stack, $template, $output;
+ end($stack);
+ $current =& $stack[key($stack)];
array_pop($stack);
- $depth[$parser]--;
+ end($stack);
+ $parent =& $stack[key($stack)];
+ if ($parent) {
+ $parent->addContents($current->process($template));
+ } else {
+ $output = $current->process($template);
+ }
}
function characterData($parser, $data) {
- static $last = '';
- global $depth, $stack;
- $current = join('/', $stack);
- $data = trim($data);
- if ($data) {
- echo str_repeat(TAB, @$depth[$parser]);
- if ($current !== $last) {
- $last = $current;
- echo "En $current: ";
- } else {
- echo " ";
- }
- echo "'$data'\n";
- }
+ global $stack;
+ end($stack);
+ $current =& $stack[key($stack)];
+ $current->addContents($data);
}
$xml_parser = xml_parser_create();
}
xml_parser_free($xml_parser);
+class BIFE_Base {
+
+ function BIFE_Base() {
+ trigger_error('Can\'t instanciate abstract class BIFE_Base.',
+ E_USER_ERROR);
+ }
+
+ function addContents($contents) {
+ trigger_error('Method not implemented '.get_class($this).
+ '::addContents().', E_USER_ERROR);
+ }
+
+ function process(&$template) {
+ trigger_error('Method not implemented '.get_class($this).
+ '::addContents().', E_USER_ERROR);
+ }
+
+}
+
+class BIFE_Common extends BIFE_Base {
+
+ var $attrs;
+ var $contents;
+
+ function BIFE_Common($attrs) {
+ $this->attrs = $attrs;
+ $this->contents = '';
+ }
+
+ function addContents($contents) {
+ $this->contents .= trim($contents);
+ }
+
+ function process(&$template) {
+ $template->loadTemplateFile(get_class($this).'.html');
+ $template->setVariable($this->attrs);
+ $template->setVariable('CONTENTS', $this->contents);
+ return $template->get();
+ }
+
+}
+
+class BIFE_Page extends BIFE_Common {
+ function BIFE_Page($attrs) {
+ $this->BIFE_Common($attrs);
+ }
+}
+
+class BIFE_Title extends BIFE_Common {
+ function BIFE_Title($attrs) {
+ $this->BIFE_Common($attrs);
+ }
+}
+
+class BIFE_Album extends BIFE_Base {
+ var $attrs;
+ function BIFE_Album($attrs) {
+ $defaults = array(
+ 'DIR' => '.',
+ 'RECURSIVE' => true,
+ 'THUMBSFORMAT' => 'jpeg',
+ 'THUMBSDIR' => '.thumbs',
+ 'EXTENSIONS' => 'png,jpg,jpeg,gif',
+ 'SELECTED' => '',
+ 'MAXROWS' => 0,
+ 'COLUMNS' => 4,
+ );
+ $this->attrs = array_merge($defaults, $attrs);
+ }
+ function addContents($contents) {
+ trigger_error('BIFE_Album is not a container, you can\'t add contents.',
+ E_USER_ERROR);
+ }
+ function process(&$template) {
+ extract($this->attrs, EXTR_SKIP);
+ $album =& new Hook_Album($DIR, $RECURSIVE, $THUMBSFORMAT, $THUMBSDIR, $EXTENSIONS);
+ return $album->album($template, $SELECTED, $MAXROWS, $COLUMNS);
+ }
+}
+
+echo $output;
+
?>
--- /dev/null
+<IMG class="albumphoto" alt="{DESC}" src="{PHOTO}"/>
+<DIV class="albumphoto">{DESC}</DIV>
--- /dev/null
+<Page title="Hola mundo!" menu="true" use="Album:Perfil">
+ <Title>Datos!</Title>
+ <Album dir=".." columns="8"/>
+</Page>