source: bookmarks/trunk/Bookmarks.pm @ 7

Last change on this file since 7 was 7, checked in by peter, 12 years ago
  • added a base_uri property to the Bookmarks class; if present, it adds a bookmark_uri key to bookmarks returned by get_bookmark() and get_resources()
  • an individual bookmark can be returned as JSON by passing a "?format=json" parameter to the individual bookmark GET request
File size: 5.9 KB
Line 
1package Bookmarks;
2
3use Class::Accessor 'antlers';
4use Bookmark;
5
6has dbh      => ( is => 'ro' );
7has base_uri => ( is => 'ro' );
8
9sub get_bookmark {
10    my $self = shift;
11    my $params = shift;
12    my $sth;
13    if ($params->{id}) {
14        $sth = $self->dbh->prepare('select id,resources.uri,title,ctime,mtime from bookmarks join resources on bookmarks.uri=resources.uri where id=?');
15        $sth->execute($params->{id});
16    } elsif ($params->{uri}) {
17        $sth = $self->dbh->prepare('select id,resources.uri,title,ctime,mtime from bookmarks join resources on bookmarks.uri=resources.uri where resources.uri=?');
18        $sth->execute($params->{uri});
19    } else {
20        die "Must specify either id or uri";
21    }
22    my $bookmark = $sth->fetchrow_hashref;
23    if ($bookmark) {
24        my $sth_tag = $self->dbh->prepare('select tag from tags where uri = ? order by tag');
25        $sth_tag->execute($bookmark->{uri});
26        $bookmark->{tags} = [ map { $$_[0] } @{ $sth_tag->fetchall_arrayref } ];
27        if ($self->base_uri) {
28            $bookmark->{bookmark_uri} = $self->base_uri . $bookmark->{id};
29        }
30    }
31    return $bookmark;
32}
33
34sub get_resources {
35    my $self = shift;
36    my $params = shift;
37    my $tag = $params->{tag};
38    my $sth_resource;
39    if ($tag) {
40        $sth_resource = $self->dbh->prepare('select * from resources join tags on resources.uri = tags.uri join bookmarks on resources.uri = bookmarks.uri where tags.tag = ? order by ctime desc');
41        $sth_resource->execute($tag);
42    } else {
43        $sth_resource = $self->dbh->prepare('select * from resources join bookmarks on resources.uri = bookmarks.uri order by ctime desc');
44        $sth_resource->execute;
45    }
46
47    my $sth_tag = $self->dbh->prepare('select tag from tags where uri = ? order by tag');
48    my @resources;
49    while (my $resource = $sth_resource->fetchrow_hashref) {
50        $sth_tag->execute($resource->{uri});
51        $resource->{tags} = [ map { $$_[0] } @{ $sth_tag->fetchall_arrayref } ];
52        if ($self->base_uri) {
53            $resource->{bookmark_uri} = $self->base_uri . $resource->{id};
54        }
55        push @resources, $resource;
56    }
57    return @resources;
58}
59
60sub get_tags {
61    my $self = shift;
62    my $params = shift;
63    my $tag = $params->{selected};
64    my $sth_all_tags = $self->dbh->prepare('select tag, count(tag) as count, tag = ? as selected from tags group by tag order by tag');
65    $sth_all_tags->execute($tag);
66    my $all_tags = $sth_all_tags->fetchall_arrayref({});
67    return @{ $all_tags };
68}
69
70sub get_cotags {
71    my $self = shift;
72    my $params = shift;
73    my $tag = $params->{tag};
74    my $sth = $self->dbh->prepare('select tag, count(tag) as count from tags where tag != ? and uri in (select uri from tags where tag = ?) group by tag order by tag');
75    $sth->execute($tag, $tag);
76    return @{ $sth->fetchall_arrayref({}) };
77}
78
79sub add {
80    my $self = shift;
81    my $bookmark = shift;
82
83    my $uri = $bookmark->{uri};
84    my $title = $bookmark->{title};
85    #TODO: accept a ctime or mtime
86    my $mtime = my $ctime = $bookmark->{ctime} || time;
87
88    # create an entry for the resource
89    my $sth_resource = $self->dbh->prepare('insert into resources (uri, title) values (?, ?)');
90    eval {
91        $sth_resource->execute($uri, $title);
92    };
93    if ($@) {
94        if ($@ =~ /column uri is not unique/) {
95            # this is not truly an error condition; the resource is already listed
96            # update the title instead
97            my $sth_update = $self->dbh->prepare('update resources set title = ? where uri = ?');
98            $sth_update->execute($title, $uri);
99        } else {
100            die $@;
101        }
102    }
103
104    # create the bookmark
105    my $sth_bookmark = $self->dbh->prepare('insert into bookmarks (uri, ctime, mtime) values (?, ?, ?)');
106    eval {
107        $sth_bookmark->execute($uri, $ctime, $mtime);
108    };
109    if ($@) {
110        if ($@ =~ /column uri is not unique/) {
111            # this is not truly an error condition; the bookmark was already there
112            # update the mtime instead
113            # TODO: only update mtime if the tag list is changed?
114            my $sth_update = $self->dbh->prepare('update bookmarks set mtime = ? where uri = ?');
115            $sth_update->execute($mtime, $uri);
116        } else {
117            die $@;
118        }
119    }
120
121    my %new_tags = map { $_ => 1 } @{ $bookmark->{tags} };
122    my $sth_delete_tag = $self->dbh->prepare('delete from tags where uri = ? and tag = ?');
123    my $sth_insert_tag = $self->dbh->prepare('insert into tags (uri, tag) values (?, ?)');
124    my $sth_current_tags = $self->dbh->prepare('select tag from tags where uri = ?');
125    $sth_current_tags->execute($uri);
126    while (my ($tag) = $sth_current_tags->fetchrow_array) {
127        if (!$new_tags{$tag}) {
128            # if a current tag is not in the new tags, remove it from the database
129            $sth_delete_tag->execute($uri, $tag);
130        } else {
131            # if a new tag is already in the database, remove it from the list of tags to add
132            delete $new_tags{$tag};
133        }
134    }
135    for my $tag (keys %new_tags) {
136        $sth_insert_tag->execute($uri, $tag);
137    }
138
139=begin
140
141    # clear all tags
142    my $sth_delete_tag = $self->dbh->prepare('delete from tags where uri = ?');
143    $sth_delete_tag->execute($uri);
144    my $sth_tag = $self->dbh->prepare('insert into tags (uri, tag) values (?, ?)');
145    for my $tag (@{ $bookmark->{tags} }) {
146        #print $tag, "\n";
147        # prevent duplicate (uri,tag) pairs in the database
148        # TODO: should POST with a set of tags ever remove tags?
149        eval {
150            $sth_tag->execute($uri, $tag);
151        };
152        if ($@) {
153            if ($@ =~ /columns uri, tag are not unique/) {
154                # this is not truly an error condition; the tag was already there
155            } else {
156                die $@;
157            }
158        }
159    }
160
161=cut
162
163    # return the newly created or updated bookmark
164    return $self->get_bookmark({ uri => $uri });
165}
166
167# module returns true
1681;
Note: See TracBrowser for help on using the repository browser.