--- /dev/null
+This software is licensed under the GPL version 2 or higher, or the Perl
+Artistic License, at your choice. The text of these two licenses can be
+found in /usr/share/common-licenses/ on a Debian system, or at:
+ GPL: http://www.gnu.org/licenses/gpl.txt
+ Areistic: http://www.perl.com/pub/a/language/misc/Artistic.html
+
+1.2 - Tue Jan 3 12:50:39 GMT 2006
+
+ - Slight calendar fix
+ - Tidy up display of large datasets.
+ - Rejig tag searching.
+ - Edit/delete photos
+ - Tag hierarchy computed over whole dataset, not just current page.
+ - RSS feeds available on most pages
+
1.1 - Mon Oct 31 23:59:52 GMT 2005
- RSS feeds available from [%base%]/recent.rss
--- /dev/null
+Memories/Photo.pm
+Memories/Tag.pm
+Memories/DBI.pm
+Memories/User.pm
+Memories/Album.pm
+Memories/Comment.pm
+Memories/Config.pm
+Memories/SystemTag.pm
+Memories.pm
+README
+COPYING
+templates/login_box
+templates/nav
+templates/macros
+templates/frontpage
+templates/static/memories.png
+templates/static/memories.css
+templates/static/1-s.gif
+templates/static/1.gif
+templates/static/2.gif
+templates/static/3.gif
+templates/static/4.gif
+templates/static/5.gif
+templates/static/6.gif
+templates/static/7.gif
+templates/static/8.gif
+templates/static/9.gif
+templates/static/2-s.gif
+templates/static/3-s.gif
+templates/static/4-s.gif
+templates/static/5-s.gif
+templates/static/6-s.gif
+templates/static/7-s.gif
+templates/static/8-s.gif
+templates/static/9-s.gif
+templates/static/upload.js
+templates/header
+templates/photo/recent
+templates/photo/tagedit
+templates/photo/comment
+templates/photo/upload
+templates/photo/view
+templates/photo/exif
+templates/rhs
+templates/footer
+templates/pager
+templates/album_adder
+templates/album/denied
+templates/album/view
+templates/album/list
+templates/tagcloud
+templates/custom/list
+templates/tag/view
+templates/tag/list
+templates/tag/list_js
+templates/user/view
+templates/user/list
+templates/user/album_list
+templates/calendar
+templates/memories.css
+templates/memories.png
+templates/picture/view
+templates/systemtag/view
+templates/systemtag/list
+templates/recent.rss
+memories.sql
+MANIFEST
+tag_dates
+Changes
+META.yml Module meta-data (added by MakeMaker)
--- /dev/null
+# http://module-build.sourceforge.net/META-spec.html
+#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX#
+name: Memories
+version: 1.2
+version_from: Memories.pm
+installdirs: site
+requires:
+ Cache::MemoryCache: 0
+ Calendar::Simple: 0
+ Class::DBI::Plugin::AbstractCount: 0
+ Class::DBI::Plugin::Pager: 0
+ File::Path: 0
+ HTML::TagCloud: 0
+ Image::ExifTool: 0
+ Image::Imlib2: 0
+ Image::Info: 0
+ Maypole: 1.1
+ Text::Balanced: 0
+ Time::Piece: 0
+ URI::Escape: 0
+ XML::RSS: 0
+
+distribution_type: module
+generated_by: ExtUtils::MakeMaker version 6.17
package Memories;
use strict;
+our $VERSION = "1.2";
+use Maypole::Application qw(Upload Authentication::UserSessionCookie);
use HTML::TagCloud;
use URI;
-use Maypole::Application qw(Upload Authentication::UserSessionCookie
--Debug);
use Memories::Config;
use Memories::DBI;
use Memories::Photo;
use Memories::Album;
use URI::Escape;
use Calendar::Simple;
+use XML::RSS;
Memories->config->auth->{ user_field } = "name";
Memories->config->model("Maypole::Model::CDBI::Plain");
push @{$self->{template_args}{messages}}, $message;
}
+sub do_rss {
+ my $r = shift;
+ $r->model_class->process($r);
+ my $rss = XML::RSS->new(version => "2.0");
+ $rss->channel(
+ title => ($r->config->{application_name}. " : ".ucfirst($r->action)." ".ucfirst($r->table)." ".($r->objects||[])->[0]) ,
+ link => $r->config->{uri_base}."/".$r->path
+ );
+ my $maybe_photos = $r->{objects}||[];
+ my $photos =
+ (@$maybe_photos && $maybe_photos->[0]->isa("Memories::Photo"))
+ ? $maybe_photos :
+ ($r->{template_args}->{photos} || []);
+ for my $item (@$photos) {
+ my $link = $r->config->{uri_base}."photo/view/".$item->id;
+ $rss->add_item( title => $item->title, link => $link,
+ description =>
+ "<a href=\"$link\">
+ <img src=\"". $item->thumb_url."\" alt=\"".$item->title."\"></a>",
+ dc => { subject => join " ", $item->tags },
+ pubDate => $item->uploaded->strftime("%a, %d %b %Y %H:%M:%S %z")
+ )
+ }
+ $r->output($rss->as_string);
+ $r->content_type("application/rss+xml");
+ return
+}
+
sub additional_data {
my $r = shift;
if ($r->params->{view_cal}) {
- $r->{template_args}{view_cal} = eval {
+ $r->{template_args}{view_cal} = eval {
Time::Piece->strptime($r->{params}{view_cal}, "%Y-%m-%d") };
}
$r->{template_args}{now} = Time::Piece->new;
+ return $r->do_rss if ($r->params->{format} =~ /rss/)
}
use Maypole::Constants;
sub tag_select {
- my ($r, $tags, $photos) = @_;
- # XXX only affects current page
+ my ($r, $tags) = @_;
my %counter;
- for (map {$_->tags} @$photos) {
+ my @photos = Memories::Photo->sth_to_objects(Memories::Tag->multi_search(@$tags));
+ for (map {$_->tags} @photos) {
$counter{$_->name}++;
}
delete $counter{$_->name} for @$tags;
my $base = $r->config->uri_base.$r->path."/";
my $tags;
for my $name (sort {$a cmp $b} keys %counter) {
- if ($counter{$name} == @$photos) {
+ if ($counter{$name} == @photos) {
push @super, $name;
} else {
$cloud->add($name, $base.uri_escape($name), $counter{$name});
package Memories::DBI;
+#use base qw(Class::DBI::Sweet Class::DBI::mysql);
use base qw(Class::DBI::mysql);
Memories::DBI->connection(Memories->config->{dsn});
Memories::DBI->autoupdate(1);
use Time::Piece;
use constant PAGER_SYNTAX => "LimitXY";
__PACKAGE__->columns(Essential => qw(id title uploader uploaded x y));
+__PACKAGE__->untaint_columns(printable => [qw/title/]);
__PACKAGE__->columns(TEMP => qw/exif_object/);
__PACKAGE__->set_sql(recent => q{
SELECT __ESSENTIAL__
my $pager = Class::DBI::Pager::_pager("Memories::Photo",
Memories->config->{photos_per_page}, $page);
$r->{template_args}{pager} = $pager;
+ my @tags = map { $self->search(name => $_)->first } @{$r->args};
if (@{$r->args} > 1) { # This is actually an n-level search
- $self->multi_search($r);
+ my $sth = $self->multi_search(@tags);
+ $r->{template_args}{photos} = [ $r->{template_args}{pager}->sth_to_objects($sth) ];
+ $sth->finish;
+ $r->{template_args}{tags} = \@tags;
} else {
if (!$r->objects) {
- $tag = $self->search(name => $r->{args}->[0])->first;
+ $tag = $tags[0];
} else {
- $tag = $r->objects->[0]; # Should hardly happen
+ $tag = $r->objects->[0];
}
$r->{template_args}{tag} = $tag;
$r->{template_args}{tags} = [$tag]; # For selector
}
sub multi_search {
- my ($self, $r) = @_;
+ my ($self, @tags) = @_;
my $counter = "tagaaa";
- my @tags;
- for (@{$r->{args}}) {
- my $tag = $self->search(name => $_)->first;
+ my @stuff;
+ for my $tag (@tags) {
if (!$tag) { return }
- push @tags, { tag => $tag, id => $tag-> id, counter => $counter++ };
+ push @stuff, { tag => $tag, id => $tag->id, counter => $counter++ };
}
my $sql = "select photo.id as id, photo.title as title, uploader, uploaded, x, y
-from photo, ". (join ",", map{ "tagging ".$_->{counter} } @tags).
-" where ". (join " AND ", map { "$_->{counter}.tag=$_->{id} and photo.id = $_->{counter}.photo" } @tags);
+from photo, ". (join ",", map{ "tagging ".$_->{counter} } @stuff).
+" where ". (join " AND ", map { "$_->{counter}.tag=$_->{id} and photo.id
+= $_->{counter}.photo" } @stuff);
$sql .= " order by photo.uploaded desc";
my $sth = $self->db_Main->prepare($sql);
- $r->{template_args}{photos} = [ $r->{template_args}{pager}->sth_to_objects($sth) ];
- $sth->finish;
- $r->{template_args}{tags} = [ map { $_->{tag} } @tags ];
}
sub list :Exported {
FROM tagging
GROUP BY tag
ORDER BY count DESC
-LIMIT 50
+LIMIT 75
/);
__PACKAGE__->set_sql(all => qq/
SELECT id, tag, count(*) AS count
Maypole::Plugin::Upload
Maypole::Plugin::Authentication::UserSessionCookie
HTML::TagCloud
+ XML::RSS
Apache mod_perl is recommended. Memories can also be run as a CGI
application, but you're on your own.
2) Run the tag_dates script.
+Updating Memories 1.1 to 1.2
+----------------------------
+
+No changes.
[% SET calendar = request.calendar(date.ymd) %]
<table class="calendar">
<tr>
- <th> <a href="?view_cal=[%prev.ymd%]">« </a></th>
+ <th> <a href="[%base%]/[%request.path%]?view_cal=[%prev.ymd%]">« </a></th>
<th colspan="5">
[% date.strftime("%Y-%m") %]
</th>
<th> [% IF next %]
- <a href="?view_cal=[%next.ymd%]">» </a>
+ <a href="[%base%]/[%request.path%]?view_cal=[%next.ymd%]">» </a>
[% END %]
</th>
</tr>
<head>
<title> Memories - Photo Sharing </title>
<link title="Maypole" href="[%base%]/static/memories.css" type="text/css" rel="stylesheet"/>
+ [% IF photos %]
+<link rel="alternate" type="application/rdf+xml" title="RSS"
+href="[%base%]/[%path%]?format=rss" />
+[% END %]
[% IF request.params.active == "tagedit" %]
<script type="text/javascript" src="[%base%]/tag/list_js"></script>
<script type="text/javascript" src="[%base%]/static/upload.js"></script>
-[% IF pager.last_page > 1 %]
- [% FOREACH num = [pager.first_page .. pager.last_page] %]
+[% MACRO link_page(num) BLOCK; %]
[% IF num == pager.current_page %]
[% IF num < 10 %]
<img src="[%base%]/static/[%num%]-s.gif">
</a>
[% END %]
[% END %]
-[% END %]
+[% IF pager.last_page > 1;
+ SET begin_page = pager.current_page - 5;
+ IF begin_page < 1;
+ SET begin_page = pager.first_page;
+ END;
+ SET end_page = pager.current_page + 5;
+ IF pager.last_page < end_page;
+ SET end_page = pager.last_page;
+ END;
+ IF begin_page != 1; link_page(1); " ... "; END;
+ FOREACH num = [begin_page .. end_page];
+ link_page(num);
+ END;
+ IF end_page != pager.last_page; "..."; link_page(pager.last_page); END;
+END %]
<tr valign="top">
<td width="70%">
<h1>[% photo.title %]</h1>
+[% IF request.user == photo.uploader %]
+ <p><a href="[%base%]/photo/delete/[%photo.id%]">Delete this
+ photo</a></p>
+ <form action="[%base%]/photo/do_edit/[%photo.id%]">
+ <input name="title" value="[%photo.title |html%]">
+ <input type="submit" name="Rename" value="Rename">
+ </form>
+[% END %]
</td>
<td align="right" class="tagbrowse">
[% FOR tag = photo.tags;
[% END %]
</table>
[% INCLUDE calendar %]
+[% IF photos %]
+<p align="center">
+<A HREF="?format=rss">
+<span style="font-family: verdana, sans-serif;
+font-size: 10px;
+font-weight:bold;
+text-decoration:none;
+color: white;
+background-color: #F60;
+border:1px solid;
+border-color: #FC9 #630 #330 #F96;
+padding:0px 3px 0px 3px;
+margin:0px;">RSS</span>
+</A>
+</p>
+[% END %]
[% INCLUDE tagcloud %]
[% END %]
</h1>
<div class="related">
-[% SET stuff = request.tag_select(tags,photos) %]
+[% SET stuff = request.tag_select(tags) %]
[% IF stuff.super %]
Enclosing tags:
[% FOR tag = stuff.super %]
<p align="center" style="border: 1px solid black; background: #eee"> Popular tags </p>
<div class="htmltagcloud">
-[% request.tagcloud.html(75) %]
+[% request.tagcloud.html(100) %]
</div>
+++ /dev/null
-[% INCLUDE header %]
-[% INCLUDE footer %]