package Maypole::Plugin::LinkTools; use warnings; use strict; our $VERSION = '0.21'; =head1 NAME Maypole::Plugin::LinkTools - convenient link construction =head1 SYNOPSIS use Maypole::Application qw( LinkTools ); #... print $request->maybe_link_view( $thing ); print $request->maybe_many_link_views( @things ); print $request->link( table => $table, action => $action, # called 'command' in the original link template additional => $additional, # optional - generally an object ID label => $label, ); print $request->make_path( table => $table, action => $action, # called 'command' in the original link template additional => $additional, # optional - generally an object ID ); =head1 DESCRIPTION Provides convenient replacements for the C and C templates, and a new C method. Centralises all path manipulation, so that a new URI scheme can be implemented site-wide by overriding just two methods (C and C). For ease of use with the Template Toolkit, C, C and C will also accept a hashref of arguments. For example: print $request->make_path({ table => $table, action => $action, additional => $additional, }); =head1 METHODS =over 4 =item make_path( %args or \%args ) This is the counterpart to C. It generates a path to use in links, form actions etc. To implement your own path scheme, just override this method and C. %args = ( table => $table, action => $action, # called 'command' in the original link template additional => $additional, # optional - generally an object ID ); C can be used as an alternative key to C. =cut # TODO: # C<$additional> can be a string, an arrayref, or a hashref. An arrayref is expanded into extra # path elements, whereas a hashref is translated into a query string. sub make_path { my $r = shift; my %args = (@_ == 1 && ref $_[0] && ref $_[0] eq 'HASH') ? %{$_[0]} : @_; do { die "no $_" unless $args{ $_ } } for qw( table action ); my $base = $r->config->uri_base; $base = '' if $base eq '/'; $args{additional} ||= $args{id}; my $add = $args{additional} ? "/$args{additional}" : ''; return sprintf '%s/%s/%s%s', $base, $args{table}, $args{action}, $add; } =item link( %args or \%args ) Returns a link, calling C to generate the path. %args = ( table => $table, action => $action, # called 'command' in the original link template additional => $additional, # optional - generally an object ID label => $label, ); The table can be omitted and defaults to that of the request's model. C can be used as an alternative key to C. =cut sub link { my $r = shift; my %args = (@_ == 1 && ref $_[0] && ref $_[0] eq 'HASH') ? %{$_[0]} : @_; $args{table} ||= $r->model_class->table; $args{label} ||= '...'; # in case a stringify column is left empty foreach my $key ( qw( table action ) ) { die sprintf "link: no %s (got table: %s action: %s label: %s)", $key, $args{table} || '', $args{action} || '', $args{label} || '' unless $args{ $key }; } my $path = $r->make_path( %args ); return sprintf '%s', $path, $args{label}; } =item link_view( $thing or %args or \%args ) Build a link to the C action of the given item. If passed a Maypole request object, builds a link to its C action. print $request->link_view( $maypole_request ); print $request->link_view( table => $table, label => $label, additional => $id, ); =cut sub link_view { my $r = shift; my %args; if ( @_ == 1 ) { die "single argument to link_view() must be a reference (got $_[0])" unless ref $_[0]; if ( ref $_[0] eq 'HASH' ) { %args = %{ $_[0] }; } elsif ( UNIVERSAL::isa( $_[0], 'Maypole::Model::Base' ) ) { my $object = shift; my $str = ''.$object; warn sprintf "%s (id: %s) object has no data for stringification", ref($object), $object->id unless $str; $str ||= '...'; %args = ( table => $object->table, additional => $object->id, label => $str, ); } else { die "unsuitable single argument to link_view (got $_[0]) - need hashref or Maypole/CDBI object"; } } else { %args = @_; } return $r->link( %args, action => 'view' ); } =item maybe_link_view( $thing ) Returns stringified C<$thing> unless it isa C object, in which case a link to the view template for the object is returned. =cut sub maybe_link_view { my ( $r, $thing ) = @_; if ( ref $thing and UNIVERSAL::isa( $thing, 'Maypole::Model::Base' ) ) { return $r->link_view( $thing ); } else { return ''.$thing; } } =item maybe_many_link_views Runs multiple items through C, returning a list. =cut # if the accessor is for a has_many relationship, it might return multiple items, which # would each be passed individually to maybe_link_view(), and then each would go in its # own column. Instead, we want a list of items to put in a single cell. sub maybe_many_link_views { my ( $r, @values ) = @_; return map { $r->maybe_link_view( $_ ) } @values; } =back =head1 AUTHOR David Baird, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 ACKNOWLEDGEMENTS =head1 COPYRIGHT & LICENSE Copyright 2005 David Baird, All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; # End of Maypole::Plugin::LinkTools