package Bookmark; use Moose; has id => ( is => 'ro' ); has uri => ( is => 'rw' ); has title => ( is => 'rw' ); has ctime => ( is => 'ro' ); has mtime => ( is => 'ro', # mtime defaults to ctime default => sub { $_[0]->ctime }, lazy => 1, ); has tags => ( is => 'rw' ); has bookmark_uri => ( is => 'rw' ); sub BUILD { my $self = shift; my $args = shift; if ($args->{base_uri}) { $self->bookmark_uri(URI->new_abs($self->id, $args->{base_uri})); } } sub TO_JSON { my $self = shift; return { id => $self->id, uri => $self->uri, title => $self->title, ctime => $self->ctime, mtime => $self->mtime, tags => $self->tags, ($self->bookmark_uri ? (bookmark_uri => $self->bookmark_uri->canonical->as_string) : ()), }; } sub update { my $self = shift; # TODO: store the dbh somewhere better, or use a more generic "Bookmark Store" object my $dbh = shift; my $mtime = time; my $changed_uri = 0; my $sth_current = $dbh->prepare('select uri from bookmarks where id = ?'); $sth_current->execute($self->id); my ($stored_uri) = $sth_current->fetchrow_array; if ($stored_uri ne $self->uri) { # the URI has changed my $sth_update_uri = $dbh->prepare('update resources set uri = ? where uri = ?'); $sth_update_uri->execute($self->uri, $stored_uri); $changed_uri++; } # update the title # TODO: only do this if the title has changed # TODO: should we update mtime if the title changes? my $sth_update = $dbh->prepare('update resources set title = ? where uri = ?'); $sth_update->execute($self->title, $self->uri); # update the tags my $changed_tags = 0; my %new_tags = map { $_ => 1 } @{ $self->tags }; my $sth_delete_tag = $dbh->prepare('delete from tags where uri = ? and tag = ?'); my $sth_insert_tag = $dbh->prepare('insert into tags (uri, tag) values (?, ?)'); my $sth_current_tags = $dbh->prepare('select tag from tags where uri = ?'); $sth_current_tags->execute($self->uri); while (my ($tag) = $sth_current_tags->fetchrow_array) { if (!$new_tags{$tag}) { # if a current tag is not in the new tags, remove it from the database $sth_delete_tag->execute($self->uri, $tag); $changed_tags++; } else { # if a new tag is already in the database, remove it from the list of tags to add delete $new_tags{$tag}; } } for my $tag (keys %new_tags) { $sth_insert_tag->execute($self->uri, $tag); $changed_tags++; } if ($changed_uri or $changed_tags) { # update the mtime if the bookmark already existed but the tags were changed my $sth_update = $dbh->prepare('update bookmarks set mtime = ? where uri = ?'); $sth_update->execute($mtime, $self->uri); } # return the bookmark return $self; } # module return 1;