File Coverage

lib/Mojolicious/Plugin/UrlWith.pm
Criterion Covered Total %
statement 57 57 100.0
branch 24 24 100.0
condition 10 14 71.4
subroutine 9 9 100.0
pod 3 3 100.0
total 103 107 96.2


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::UrlWith;
2              
3             =head1 NAME
4              
5             Mojolicious::Plugin::UrlWith - Preserve parts of the url
6              
7             =head1 VERSION
8              
9             0.0502
10              
11             =head1 DESCRIPTION
12              
13             This helper provides the same method as L
14             with the difference that it keeps the query string.
15              
16             =head1 SYNOPSIS
17              
18             package MyApp;
19             sub startup {
20             my $self = shift;
21              
22             $self->plugin('Mojolicious::Plugin::UrlWith' => {
23             parse_fragment => 1,
24             current_page_class => 'current-page',
25             });
26              
27             # ...
28             }
29              
30             =cut
31              
32 3     3   7862 use Mojo::Base 'Mojolicious::Plugin';
  3         10  
  3         28  
33 3     3   842 use Mojo::Util qw/ xml_escape /;
  3         9  
  3         217  
34 3     3   19 use Mojolicious::Plugin::TagHelpers;
  3         6  
  3         55  
35              
36             our $VERSION = eval '0.0502';
37              
38             =head1 ATTRIBUTES
39              
40             =head2 parse_fragment
41              
42             Will remove the '#fragment' part from the first arugment to L,
43             and use it use it for L.
44              
45             =cut
46              
47             __PACKAGE__->attr(parse_fragment => sub { 0 });
48              
49             =head2 current_page_class
50              
51             $self->current_page_class($classname);
52             $classname = $self->current_page_class;
53              
54             Will add the C<$classname> to the link in L if the path part
55             of the link match the currently requested path. You need to set this
56             attribute when registering the plugin, since the default value is empty
57             string, cancelling the behavior.
58              
59             This attribute is EXPERIMENTAL and may be removed/changed without warning.
60              
61             =cut
62              
63             __PACKAGE__->attr(current_page_class => sub { '' });
64              
65             =head1 HELPERS
66              
67             =head2 url_with
68              
69             The examples below has this current request url:
70             C.
71              
72             =over 4
73              
74             =item $controller->url_with({ name => 'bob' });
75              
76             Will result in C.
77              
78             =item $controller->url_with({ page => undef });
79              
80             Will result in C.
81              
82             =item $controller->url_with('named', { age => 42 });
83              
84             Will result in C.
85              
86             =item $controller->url_with('/path', { random => 24 });
87              
88             Will result in C.
89              
90             =item $controller->url_with('/path', [ c => 313 ]);
91              
92             Will result in C.
93              
94             =back
95              
96             Summary: A hash-ref will be merged with existing query params, while
97             an array-ref will create a new set of query params.
98              
99             =cut
100              
101             sub url_with {
102 23     23 1 57 my $self = shift;
103 23         42 my $controller = shift;
104 23 100       175 my $args = ref($_[-1]) =~ /^(?:HASH|ARRAY)$/ ? pop : undef;
105 23         54 my @args = @_;
106 23         117 my $query = $controller->req->url->query->clone;
107 23         4546 my $url;
108              
109 23 100       600 if($self->parse_fragment) {
110 8 100 66     112 if(defined $_[0] and ref $_[0] eq '') {
111 6         32 $args[0] =~ s/#(.*)$//;
112 6         33 $url = $controller->url_for(@args);
113 6         26860 $url->fragment($1);
114             }
115             }
116 23 100       258 if(!$url) {
117 17 100       128 $url = @args ? $controller->url_for(@args) : $controller->req->url->clone;
118             }
119              
120 23 100       9596 if(ref $args eq 'HASH') { # merge
    100          
121 18         105 for my $key (keys %$args) {
122 16 100       47 if(defined $args->{$key}) {
123 15         90 $query->param($key => $args->{$key});
124             }
125             else {
126 1         13 $query->remove($key);
127             }
128             }
129             }
130             elsif(ref $args eq 'ARRAY') { # replace
131 2         12 $query = Mojo::Parameters->new(@$args);
132             }
133              
134 23         5849 $url->query($query);
135              
136 23         666 return $url;
137             }
138              
139             =head2 link_with
140              
141             Same as L, but use L
142             instead of L to construct the hyper
143             reference.
144              
145             =cut
146              
147             sub link_with {
148 10     10 1 29 my $self = shift;
149 10         25 my $controller = shift;
150 10         18 my($url, @url_args, @tag_args);
151              
152             # Pretty much copy/paste from Plugin::TagHelpers
153 10 100 66     115 unless(defined $_[-1] and ref $_[-1] eq 'CODE') {
154 4         10 my $content = shift;
155 4         30 xml_escape $content;
156 4     4   44 push @tag_args, sub { $content };
  4         3347  
157             }
158              
159 10         50 for my $i (reverse 0..@_-1) {
160 15 100       98 if(ref($_[$i]) =~ /^(?:HASH|ARRAY)/) {
161 9         37 push @url_args, @_[0..$i];
162 9         36 unshift @tag_args, @_[$i+1..@_-1];
163 9         25 last;
164             }
165             }
166              
167 10         42 $url = $self->url_with($controller, @url_args);
168              
169 10 100       293 if(my $class = $self->current_page_class) {
170 2 100       38 if($url->path eq $controller->req->url->path) {
171 1         317 unshift @tag_args, class => $class;
172             }
173             }
174              
175 10         496 return Mojolicious::Plugin::TagHelpers::_tag(a => href => $url, @tag_args);
176             }
177              
178             =head1 METHODS
179              
180             =head2 register
181              
182             Will register the methods under L.
183              
184             =cut
185              
186             sub register {
187 3     3 1 143 my($self, $app, $config) = @_;
188              
189 3   50     36 $config->{'url_with_alias'} ||= 'url_with';
190 3   50     20 $config->{'link_with_alias'} ||= 'link_with';
191 3   100     145 $self->parse_fragment($config->{'parse_fragment'} || 0);
192 3   100     124 $self->current_page_class($config->{'current_page_class'} || '');
193              
194 3     13   149 $app->helper($config->{'url_with_alias'} => sub { $self->url_with(@_) });
  13         391962  
195 3     10   879 $app->helper($config->{'link_with_alias'} => sub { $self->link_with(@_) });
  10         358348  
196             }
197              
198             =head1 COPYRIGHT & LICENSE
199              
200             This library is free software. You can redistribute it and/or modify
201             it under the same terms as Perl itself.
202              
203             =head1 AUTHOR
204              
205             Jan Henning Thorsen
206              
207             =cut
208              
209             1;