package # hide from PAUSE MyBlog::Controller::EntryCollection; use strict; use warnings; use Atompub::DateTime qw(datetime); use Atompub::MediaType qw(media_type); use HTTP::Status; use POSIX qw(strftime); use String::CamelCase qw(camelize); use Time::HiRes qw(gettimeofday); use base qw(Catalyst::Controller::Atompub::Collection); my $ENTRIES_PER_PAGE = 10; my $TABLE_NAME = 'entries'; my $MODEL = join '::', 'DBIC', camelize($TABLE_NAME); sub get_feed :Atompub(list) { my($self, $c) = @_; ## URI without parameters my $uri = $self->collection_resource->uri; my $feed = $self->collection_resource->body; my $page = $c->req->param('page') || 1; my $attr = { offset => ($page - 1) * $ENTRIES_PER_PAGE, rows => $ENTRIES_PER_PAGE, order_by => 'edited desc', }; my $rs = $c->model($MODEL)->search({}, $attr); while (my $resource = $rs->next) { my $entry = XML::Atom::Entry->new(\$resource->body); $feed->add_entry($entry); } $feed->alternate_link($c->req->base.'html'); $feed->first_link($uri); $feed->previous_link("$uri?page=".($page-1)) if $page > 1; $feed->next_link("$uri?page=".($page+1)) if $rs->count >= $ENTRIES_PER_PAGE; 1; } sub create_resource :Atompub(create) { my($self, $c) = @_; # URI of the new Entry, which was determined by C::C::Atompub my $uri = $self->entry_resource->uri; return $self->error($c, RC_CONFLICT, "Resource name is used (change Slug): $uri") if $c->model($MODEL)->find({ uri => $uri }); my $entry = $self->entry_resource->body; # Edit $entry if needed my $vals = { edited => $self->edited->epoch, uri => $uri, etag => $self->calculate_new_etag($c, $uri), body => $entry->as_xml, }; $c->model($MODEL)->create($vals) or return $self->error($c, RC_INTERNAL_SERVER_ERROR, 'Cannot create new resource'); 1; } sub get_resource :Atompub(read) { my($self, $c) = @_; my $uri = $c->req->uri; my $rs = $c->model($MODEL)->find({ uri => $uri }) or return $self->error($c, RC_NOT_FOUND); $self->entry_resource->body(XML::Atom::Entry->new(\$rs->body)); 1; } sub update_resource :Atompub(update) { my($self, $c) = @_; my $uri = $c->req->uri; # Edit $entry if needed my $rs = $c->model($MODEL)->find({ uri => $uri }) or return $self->error($c, RC_NOT_FOUND); my $vals = { edited => $self->edited->epoch, uri => $uri, etag => $self->calculate_new_etag($c, $uri), body => $self->entry_resource->body->as_xml, }; $rs->update($vals) or return $self->error($c, RC_INTERNAL_SERVER_ERROR, "Cannot update resource: $uri"); 1; } sub delete_resource :Atompub(delete) { my($self, $c) = @_; my $uri = $c->req->uri; my $rs = $c->model($MODEL)->find({ uri => $uri }) or return $self->error($c, RC_NOT_FOUND); $rs->delete or return $self->error($c, RC_INTERNAL_SERVER_ERROR, "Cannot delete resource: $uri"); 1; } sub make_edit_uri { my($self, $c, @args) = @_; my @uris = $self->SUPER::make_edit_uri($c, @args); # return, if $uris[0] is not used return wantarray ? @uris : $uris[0] unless $c->model($MODEL)->find({ uri => $uris[0] }); my($sec, $usec) = gettimeofday; my $dt = strftime '%Y%m%d-%H%M%S', localtime($sec); $usec = sprintf '%06d', $usec; # insert $dt-$usec before extension $_ =~ s{(\.[^./?]+)$}{-$dt-$usec$1} for @uris; @uris; } sub find_version { my($self, $c, $uri) = @_; my $rs = $c->model($MODEL)->find({ uri => $uri }) or return; return (etag => $rs->etag); # return (etag => $rs->etag, last_modified => datetime($rs->edited)->str); } sub calculate_new_etag { my($self, $c, $uri) = @_; my($sec, $usec) = gettimeofday; my $dt = join '-', strftime('%Y%m%d-%H%M%S', localtime($sec)), sprintf('%06d', $usec); join '/', $uri, $dt; } 1;