Changeset 68 in bookmarks


Ignore:
Timestamp:
02/08/14 18:23:22 (10 years ago)
Author:
peter
Message:
  • added a "view" class, BookmarksList
  • moved the code to render the various formats of the list of bookmarks from and if statement in BookmarkController::list() to a set of as_$format() methods in BookmarksList
  • moved the _get_list_links() method from BookmarkController to BookmarksList
  • Bookmarks::get_bookmarks() returns a BookmarksList instead of an array
  • the ?format parameter accepts "atom" to render arbitrary sets of results as Atom feeds; the BookmarkController::feed() method just calls as_atom() on a BookmarksList search result object
Location:
trunk
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/BookmarkController.pm

    r67 r68  
    4343    $url .= '/' unless $url =~ m{/$}; 
    4444    return URI->new($url); 
    45 } 
    46  
    47 sub _get_list_links { 
    48     my $self = shift; 
    49     my ($self_type, $query) = @_; 
    50     my @links = ( 
    51         { 
    52             text => 'JSON', 
    53             type => 'application/json', 
    54             query => { 
    55                 %$query, 
    56                 format => 'json', 
    57             }, 
    58         }, 
    59         { 
    60             text => 'XBEL', 
    61             type => 'application/xml', 
    62             query => { 
    63                 %$query, 
    64                 format => 'xbel', 
    65             }, 
    66         }, 
    67         { 
    68             text => 'Atom', 
    69             type => 'application/atom+xml', 
    70             path => 'feed', 
    71             query => { 
    72                 %$query, 
    73             }, 
    74         }, 
    75         { 
    76             text => 'CSV', 
    77             type => 'text/csv', 
    78             query => { 
    79                 %$query, 
    80                 format => 'csv', 
    81             }, 
    82         }, 
    83         { 
    84             text => 'URI List', 
    85             type => 'text/uri-list', 
    86             query => { 
    87                 %$query, 
    88                 format => 'text', 
    89             }, 
    90         }, 
    91         { 
    92             text => 'HTML', 
    93             type => 'text/html', 
    94             query => { 
    95                 %$query, 
    96             }, 
    97         }, 
    98     ); 
    99  
    100     for my $link (@links) { 
    101         $link->{rel}  = $link->{type} eq $self_type ? 'self' : 'alternate'; 
    102         $link->{href} = URI->new_abs($link->{path} || '', $self->base_uri); 
    103         $link->{href}->query_form($link->{query}); 
    104     } 
    105  
    106     return @links; 
    10745} 
    10846 
     
    14381    my $limit = $self->request->param('limit'); 
    14482    my $offset = $self->request->param('offset'); 
    145     my @resources = $self->bookmarks->get_bookmarks({ 
     83 
     84    my $list = $self->bookmarks->get_bookmarks({ 
    14685        query  => $query, 
    14786        tag    => \@tags, 
     
    14988        offset => $offset, 
    15089    }); 
    151     my @all_tags = $self->bookmarks->get_tags({ selected => $tags[0] }); 
    152     my @cotags = $self->bookmarks->get_cotags({ 
    153         query  => $query, 
    154         tag    => \@tags, 
    155     }); 
    156      
    157     my $title = 'Bookmarks' . (@tags ? " tagged as " . join(' & ', @tags) : '') . ($query ? " matching '$query'" : ''); 
    158  
    159     if ($format eq 'json') { 
    160         my $json = decode_utf8( 
    161             JSON->new->utf8->convert_blessed->encode({ 
    162                 bookmarks => \@resources, 
    163             }) 
    164         ); 
    165         return [200, ['Content-Type' => 'application/json; charset=UTF-8'], [$json]]; 
    166     } elsif ($format eq 'xbel') { 
    167         require XML::XBEL; 
    168         #TODO: conditional support; if XML::XBEL is not present, return a 5xx response 
    169  
    170         my $xbel = XML::XBEL->new; 
    171  
    172         $xbel->new_document({ 
    173             title => $title, 
    174         }); 
    175  
    176         for my $bookmark (@resources) { 
    177             my $cdatetime = time2isoz $bookmark->ctime; 
    178             my $mdatetime = time2isoz $bookmark->mtime; 
    179             # make the timestamps W3C-correct 
    180             s/ /T/ foreach ($cdatetime, $mdatetime); 
    181  
    182             $xbel->add_bookmark({ 
    183                 href     => $bookmark->uri, 
    184                 title    => $bookmark->title, 
    185                 desc     => 'Tags: ' . join(', ', @{ $bookmark->tags }), 
    186                 added    => $cdatetime, 
    187                 #XXX: are we sure that modified is the mtime of the bookmark or the resource? 
    188                 modified => $mdatetime, 
    189             }); 
    190         } 
    191  
    192         return [200, ['Content-Type' => 'application/xml; charset=UTF-8'], [$xbel->toString]]; 
    193     } elsif ($format eq 'text') { 
    194         my $text = join '',  
    195             map { 
    196                 sprintf "# %s\n# Tags: %s\n%s\n", 
    197                 $_->title, 
    198                 join(', ', @{ $_->tags }),  
    199                 $_->uri 
    200             } @resources; 
    201         return [200, ['Content-Type' => 'text/uri-list; charset=UTF-8'], [$text]]; 
    202     } elsif ($format eq 'csv') { 
    203         require Text::CSV::Encoded; 
    204         my $csv = Text::CSV::Encoded->new({ encoding_out => 'utf8' }); 
    205         my $text = qq{id,uri,title,tags,ctime,mtime\n}; 
    206         for my $bookmark (@resources) { 
    207             my $success = $csv->combine( 
    208                 $bookmark->id, 
    209                 $bookmark->uri, 
    210                 $bookmark->title, 
    211                 join(' ', @{ $bookmark->tags }), 
    212                 $bookmark->ctime, 
    213                 $bookmark->mtime, 
    214             ); 
    215             $text .= $csv->string . "\n" if $success; 
    216         } 
    217  
    218         # include the local timestamp in the attchment filename 
    219         my $dt = time2iso; 
    220         $dt =~ s/[^\d]//g; 
    221  
    222         my $filename = sprintf( 
    223             'bookmarks-%s-%s.csv', 
    224             join('_', @tags), 
    225             $dt, 
    226         ); 
    227  
    228         return [200, ['Content-Type' => 'text/csv; charset=UTF-8', 'Content-Disposition' => sprintf('attachement; filename="%s"', $filename)], [$text]]; 
    229     } else { 
    230         my $template = Template->new; 
    231  
    232         $template->process( 
    233             'list.tt', 
    234             { 
    235                 base_url     => $self->base_uri, 
    236                 title        => $title, 
    237                 query        => $query, 
    238                 selected_tag => $tags[0], 
    239                 search_tags  => \@tags, 
    240                 links        => [ $self->_get_list_links('text/html', { q => $query, tag => \@tags }) ], 
    241                 all_tags     => \@all_tags, 
    242                 cotags       => \@cotags, 
    243                 resources    => \@resources, 
    244             }, 
    245             \my $output, 
    246         ); 
    247         return [200, ['Content-Type' => 'text/html; charset=UTF-8'], [$output]]; 
    248     } 
     90 
     91    my $as_format = "as_$format"; 
     92    if (!$list->meta->has_method($as_format)) { 
     93        return [406, ['Content-Type' => 'text/plain; charset=UTF-8'], [qq{"$format" is not a supported format}]]; 
     94    } 
     95    return $list->$as_format; 
    24996} 
    25097 
     
    254101    my $query = $self->request->param('q'); 
    255102    my @tags = grep { $_ ne '' } $self->request->param('tag'); 
    256     my $title = 'Bookmarks' . (@tags ? " tagged as " . join(' & ', @tags) : ''); 
    257  
    258     require XML::Atom; 
    259     $XML::Atom::DefaultVersion = "1.0"; 
    260  
    261     require XML::Atom::Feed; 
    262     require XML::Atom::Entry; 
    263     require XML::Atom::Link; 
    264     require XML::Atom::Category; 
    265  
    266     my $feed = XML::Atom::Feed->new; 
    267     $feed->title($title); 
    268  
    269     for my $link ($self->_get_list_links('application/atom+xml', { q => $query, tag => \@tags })) { 
    270         my $atom_link = XML::Atom::Link->new; 
    271         $atom_link->type($link->{type}); 
    272         $atom_link->rel($link->{rel}); 
    273         $atom_link->href($link->{href}->canonical); 
    274         $feed->add_link($atom_link); 
    275     } 
    276103 
    277104    # construct a feed from the most recent 12 bookmarks 
    278     for my $bookmark ($self->bookmarks->get_bookmarks({ query => $query, tag => \@tags, limit => 12 })) { 
    279         my $entry = XML::Atom::Entry->new; 
    280         $entry->id($bookmark->bookmark_uri->canonical); 
    281         $entry->title($bookmark->title); 
    282          
    283         my $link = XML::Atom::Link->new; 
    284         $link->href($bookmark->uri); 
    285         $entry->add_link($link); 
    286          
    287         $entry->summary('Tags: ' . join(', ', @{ $bookmark->tags })); 
    288  
    289         my $cdatetime = time2isoz $bookmark->ctime; 
    290         my $mdatetime = time2isoz $bookmark->mtime; 
    291         # make the timestamp W3C-correct 
    292         s/ /T/ foreach ($cdatetime, $mdatetime); 
    293         $entry->published($cdatetime); 
    294         $entry->updated($mdatetime); 
    295          
    296         for my $tag (@{ $bookmark->tags }) { 
    297             my $category = XML::Atom::Category->new; 
    298             $category->term($tag); 
    299             $entry->add_category($category); 
    300         } 
    301  
    302         $feed->add_entry($entry); 
    303     } 
    304  
    305     return [200, ['Content-Type' => 'application/atom+xml; charset=UTF-8'], [$feed->as_xml]]; 
     105    my $list = $self->bookmarks->get_bookmarks({ query => $query, tag => \@tags, limit => 12 }); 
     106    return $list->as_atom; 
    306107} 
    307108 
  • trunk/Bookmarks.pm

    r66 r68  
    55use URI; 
    66use Bookmark; 
     7use BookmarksList; 
    78 
    89has dbh      => ( is => 'rw' ); 
     
    116117        }); 
    117118    } 
    118     return @resources; 
     119    return BookmarksList->new({ 
     120        bookmarks => $self, 
     121        tags      => $tags, 
     122        query     => $query, 
     123        limit     => $limit, 
     124        offset    => $offset, 
     125        results   => \@resources, 
     126    }); 
    119127} 
    120128 
Note: See TracChangeset for help on using the changeset viewer.