package Mojolicious::Plugin::DefaultHelpers; use Mojo::Base 'Mojolicious::Plugin'; use Mojo::ByteStream; use Mojo::Collection; use Mojo::IOLoop; use Mojo::Util qw(dumper sha1_sum steady_time); sub register { my ($self, $app) = @_; # Controller alias helpers for my $name (qw(app flash param stash session url_for validation)) { $app->helper($name => sub { shift->$name(@_) }); } # Stash key shortcuts (should not generate log messages) for my $name (qw(extends layout title)) { $app->helper( $name => sub { my $c = shift; my $stash = $c->stash; $stash->{$name} = shift if @_; $c->stash(@_) if @_; return $stash->{$name}; } ); } $app->helper($_ => $self->can("_$_")) for qw(accepts content content_for csrf_token current_route delay), qw(inactivity_timeout url_with); $app->helper(b => sub { shift; Mojo::ByteStream->new(@_) }); $app->helper(c => sub { shift; Mojo::Collection->new(@_) }); $app->helper(config => sub { shift->app->config(@_) }); $app->helper(dumper => sub { shift; dumper(@_) }); $app->helper(include => sub { shift->render_to_string(@_) }); $app->helper(ua => sub { shift->app->ua }); } sub _accepts { my $c = shift; return $c->app->renderer->accepts($c, @_); } sub _content { my ($c, $name, $content) = @_; $name ||= 'content'; # Set (first come) my $hash = $c->stash->{'mojo.content'} ||= {}; $hash->{$name} //= ref $content eq 'CODE' ? $content->() : $content if defined $content; # Get return Mojo::ByteStream->new($hash->{$name} // ''); } sub _content_for { my ($c, $name, $content) = @_; return _content($c, $name) unless defined $content; my $hash = $c->stash->{'mojo.content'} ||= {}; return $hash->{$name} .= ref $content eq 'CODE' ? $content->() : $content; } sub _csrf_token { my $c = shift; $c->session->{csrf_token} ||= sha1_sum($c->app->secrets->[0] . steady_time . rand 999); } sub _current_route { return '' unless my $endpoint = shift->match->endpoint; return $endpoint->name unless @_; return $endpoint->name eq shift; } sub _delay { my $c = shift; my $tx = $c->render_later->tx; my $delay = Mojo::IOLoop->delay(@_); $delay->catch(sub { $c->render_exception(pop) and undef $tx })->wait; } sub _inactivity_timeout { return unless my $stream = Mojo::IOLoop->stream(shift->tx->connection // ''); $stream->timeout(shift); } sub _url_with { my $c = shift; return $c->url_for(@_)->query($c->req->url->query->clone); } 1; =encoding utf8 =head1 NAME Mojolicious::Plugin::DefaultHelpers - Default helpers plugin =head1 SYNOPSIS # Mojolicious $self->plugin('DefaultHelpers'); # Mojolicious::Lite plugin 'DefaultHelpers'; =head1 DESCRIPTION L is a collection of renderer helpers for L. This is a core plugin, that means it is always enabled and its code a good example for learning to build new plugins, you're welcome to fork it. See L for a list of plugins that are available by default. =head1 HELPERS L implements the following helpers. =head2 accepts my $formats = $c->accepts; my $format = $c->accepts('html', 'json', 'txt'); Select best possible representation for resource from C request header, C stash value or C C/C parameter with L, defaults to returning the first extension if no preference could be detected. # Check if JSON is acceptable $c->render(json => {hello => 'world'}) if $c->accepts('json'); # Check if JSON was specifically requested $c->render(json => {hello => 'world'}) if $c->accepts('', 'json'); # Unsupported representation $c->render(data => '', status => 204) unless my $format = $c->accepts('html', 'json'); # Detected representations to select from my @formats = @{$c->accepts}; =head2 app %= app->secrets->[0] Alias for L. =head2 b %= b('test 123')->b64_encode Turn string into a L object. =head2 c %= c(qw(a b c))->shuffle->join Turn list into a L object. =head2 config %= config 'something' Alias for L. =head2 content %= content foo => begin test % end %= content bar => 'Hello World!' %= content 'foo' %= content 'bar' %= content Store partial rendered content in named buffer and retrieve it, defaults to retrieving the named buffer C, which is commonly used for the renderers C and C features. Note that new content will be ignored if the named buffer is already in use. =head2 content_for % content_for foo => begin test % end %= content_for 'foo' Append partial rendered content to named buffer and retrieve it. Note that named buffers are shared with the L helper. % content_for message => begin Hello % end % content_for message => begin world! % end %= content_for 'message' =head2 csrf_token %= csrf_token Get CSRF token from L, and generate one if none exists. =head2 current_route % if (current_route 'login') { Welcome to Mojolicious! % } %= current_route Check or get name of current route. =head2 delay $c->delay(sub {...}, sub {...}); Disable automatic rendering and use L to manage callbacks and control the flow of events, which can help you avoid deep nested closures and memory leaks that often result from continuation-passing style. Calls L if an error occured in one of the steps, breaking the chain. # Longer version $c->render_later; my $delay = Mojo::IOLoop->delay(sub {...}, sub {...}); $delay->catch(sub { $c->render_exception(pop) })->wait; =head2 dumper %= dumper {some => 'data'} Dump a Perl data structure with L. =head2 extends % extends 'blue'; % extends 'blue', title => 'Blue!'; Set C stash value, all additional pairs get merged into the L. =head2 flash %= flash 'foo' Alias for L. =head2 inactivity_timeout $c->inactivity_timeout(3600); Use L to find the current connection and increase timeout if possible. # Longer version Mojo::IOLoop->stream($c->tx->connection)->timeout(3600); =head2 include %= include 'menubar' %= include 'menubar', format => 'txt' Alias for C. =head2 layout % layout 'green'; % layout 'green', title => 'Green!'; Set C stash value, all additional pairs get merged into the L. =head2 param %= param 'foo' Alias for L. =head2 session %= session 'foo' Alias for L. =head2 stash %= stash 'foo' % stash foo => 'bar'; Alias for L. %= stash('name') // 'Somebody' =head2 title % title 'Welcome!'; % title 'Welcome!', foo => 'bar'; %= title Set C stash value, all additional pairs get merged into the L</"stash">. =head2 ua %= ua->get('mojolicio.us')->res->dom->at('title')->text Alias for L<Mojo/"ua">. =head2 url_for %= url_for 'named', controller => 'bar', action => 'baz' Alias for L<Mojolicious::Controller/"url_for">. =head2 url_with %= url_with 'named', controller => 'bar', action => 'baz' Does the same as L</"url_for">, but inherits query parameters from the current request. %= url_with->query([page => 2]) =head2 validation %= validation->param('foo') Alias for L<Mojolicious::Controller/"validation">. =head1 METHODS L<Mojolicious::Plugin::DefaultHelpers> inherits all methods from L<Mojolicious::Plugin> and implements the following new ones. =head2 register $plugin->register(Mojolicious->new); Register helpers in L<Mojolicious> application. =head1 SEE ALSO L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>. =cut