Skip to content

Commit

Permalink
added support for multiple static/template classes and fixed port gen…
Browse files Browse the repository at this point in the history
…eration bug (closes #302)
  • Loading branch information
kraih committed Mar 17, 2012
1 parent f34fc89 commit 9940a7d
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 127 deletions.
6 changes: 5 additions & 1 deletion Changes
@@ -1,6 +1,10 @@
This file documents the revision history for Perl extension Mojolicious.

2.62 2012-03-17 00:00:00
- Deprecated Mojolicious::Renderer->default_template_class in favor
of Mojolicious::Renderer->classes.
- Deprecated Mojolicious::Static->default_static_class in favor of
Mojolicious::Static->classes.
- Added options function to Mojolicious::Lite.
- Added options method to Mojolicious::Routes.
- Added options method to Mojo::UserAgent.
Expand Down Expand Up @@ -60,11 +64,11 @@ This file documents the revision history for Perl extension Mojolicious.
Mojo::Content::Single.
- Removed experimental status from is_dynamic, is_limit_exceeded and
max_line_size methods in Mojo::Message.
- Improved port range and address used for testing.
- Improved Mojo::IOWatcher exception handling a little.
- Improved Mojolicious::Routes logging.
- Improved documentation.
- Improved tests.
- Fixed port generation bug. (xaka)
- Fixed IPv6 listen value bug in Mojo::Server::Daemon.

2.61 2012-03-14 00:00:00
Expand Down
3 changes: 1 addition & 2 deletions lib/Mojo/IOLoop.pm
Expand Up @@ -491,8 +491,7 @@ them to finish writing all data in their write buffers.
my $port = Mojo::IOLoop->generate_port;
my $port = $loop->generate_port;
Find a free private TCP port in the range from C<49152> to C<65535>, this is
a utility function primarily used for tests.
Find a free TCP port, this is a utility function primarily used for tests.
=head2 C<is_running>
Expand Down
20 changes: 6 additions & 14 deletions lib/Mojo/IOLoop/Server.pm
Expand Up @@ -145,18 +145,11 @@ sub listen {
}

sub generate_port {

# Try private ports
for my $port ((49152 + int(rand 16000)) .. 65535) {
IO::Socket::INET->new(
Listen => 5,
LocalAddr => '127.0.0.1',
LocalPort => $port,
Proto => 'tcp'
) and return $port;
}

return;
IO::Socket::INET->new(
Listen => 5,
LocalAddr => '127.0.0.1',
Proto => 'tcp'
)->sockport;
}

sub start {
Expand Down Expand Up @@ -338,8 +331,7 @@ Path to the TLS key file, defaults to a built-in test key.
my $port = $server->generate_port;
Find a free private TCP port in the range from C<49152> to C<65535>, this is
a utility function primarily used for tests.
Find a free TCP port, this is a utility function primarily used for tests.
=head2 C<start>
Expand Down
10 changes: 8 additions & 2 deletions lib/Mojolicious/Command/inflate.pm
Expand Up @@ -10,8 +10,14 @@ has usage => "usage: $0 inflate\n";
sub run {
my $self = shift;

# Find and turn all embedded files into real files
my $all = $self->get_all_data($self->app->renderer->default_template_class);
# Find all embedded files
my $all = {};
my $app = $self->app;
for my $class (@{$app->renderer->classes}, @{$app->static->classes}) {
$all = {%$all, %{$self->get_all_data($class)}};
}

# Turn them into real files
for my $file (keys %$all) {
my $prefix = $file =~ /\.\w+\.\w+$/ ? 'templates' : 'public';
my $path = $self->rel_file("$prefix/$file");
Expand Down
4 changes: 2 additions & 2 deletions lib/Mojolicious/Controller.pm
Expand Up @@ -964,8 +964,8 @@ Non persistent data storage and exchange, application wide default values can
be set with L<Mojolicious/"defaults">. Many stash value have a special
meaning and are reserved, the full list is currently C<action>, C<app>,
C<cb>, C<controller>, C<data>, C<extends>, C<format>, C<handler>, C<json>,
C<layout>, C<namespace>, C<partial>, C<path>, C<static_class>, C<status>,
C<template>, C<template_class> and C<text>.
C<layout>, C<namespace>, C<partial>, C<path>, C<status>, C<template> and
C<text>.
# Manipulate stash
$c->stash->{foo} = 'bar';
Expand Down
4 changes: 2 additions & 2 deletions lib/Mojolicious/Lite.pm
Expand Up @@ -29,8 +29,8 @@ sub import {
$routes->namespace('');

# Default static and template class
$app->static->default_static_class($caller);
$app->renderer->default_template_class($caller);
$app->static->classes->[0] = $caller;
$app->renderer->classes->[0] = $caller;

# Export
no warnings 'redefine';
Expand Down
120 changes: 54 additions & 66 deletions lib/Mojolicious/Renderer.pm
Expand Up @@ -8,16 +8,14 @@ use Mojo::Home;
use Mojo::JSON;
use Mojo::Util 'encode';

has cache => sub { Mojo::Cache->new };
has cache => sub { Mojo::Cache->new };
has classes => sub { ['main'] };
has default_format => 'html';
has 'default_handler';
has default_template_class => 'main';
has detect_templates => 1;
has encoding => 'UTF-8';
has handlers => sub { {} };
has helpers => sub { {} };
has layout_prefix => 'layouts';
has paths => sub { [] };
has encoding => 'UTF-8';
has handlers => sub { {} };
has helpers => sub { {} };
has paths => sub { [] };

# "This is not how Xmas is supposed to be.
# In my day Xmas was about bringing people together,
Expand Down Expand Up @@ -64,10 +62,22 @@ sub add_helper {
return $self;
}

# DEPRECATED in Leaf Fluttering In Wind!
sub default_template_class {
warn <<EOF;
Mojolicious::Renderer->default_template_class is DEPRECATED in favor of
Mojolicious::Renderer->classes!
EOF
my $self = shift;
return $self->classes->[0] unless @_;
$self->classes->[0] = shift;
return $self;
}

sub get_data_template {
my ($self, $options, $template) = @_;
return Mojo::Command->new->get_data($template,
$self->_detect_template_class($options));
$self->_data_templates->{$template});
}

# "Bodies are for hookers and fat people."
Expand Down Expand Up @@ -96,12 +106,11 @@ sub render {
my $handler = $stash->{handler};
$handler = $self->default_handler if defined $inline && !defined $handler;
my $options = {
template => $template,
format => $format,
handler => $handler,
encoding => $self->encoding,
inline => $inline,
template_class => $stash->{template_class}
template => $template,
format => $format,
handler => $handler,
encoding => $self->encoding,
inline => $inline
};

# Text
Expand Down Expand Up @@ -140,10 +149,9 @@ sub render {

# Extends
while ((my $extends = $self->_extends($c)) && !defined $inline) {
$options->{template_class} = $stash->{template_class};
$options->{handler} = $stash->{handler};
$options->{format} = $stash->{format} || $self->default_format;
$options->{template} = $extends;
$options->{handler} = $stash->{handler};
$options->{format} = $stash->{format} || $self->default_format;
$options->{template} = $extends;
$self->_render_template($c, \$output, $options);
$content->{content} = $output
if $content->{content} !~ /\S/ && $output =~ /\S/;
Expand Down Expand Up @@ -197,44 +205,40 @@ sub template_path {
return catfile($self->paths->[0], split '/', $name);
}

sub _detect_handler {
my ($self, $options) = @_;

# Disabled
return unless $self->detect_templates;
sub _data_templates {
my $self = shift;

# Templates
my $templates = $self->{templates};
unless ($templates) {
$templates = $self->{templates} =
[map { @{Mojo::Home->new($_)->list_files} } @{$self->paths}];
# Index DATA templates
return $self->{data_templates} if $self->{data_templates};
for my $class (@{$self->classes}) {
$self->{data_templates}->{$_} = $class
for keys %{Mojo::Command->new->get_all_data($class) || {}};
}

# DATA templates
my $class = $self->_detect_template_class($options);
my $inline = $self->{data_templates}->{$class}
||= [keys %{Mojo::Command->new->get_all_data($class) || {}}];
return $self->{data_templates} ||= {};
}

# Detect
sub _detect_handler {
my ($self, $options) = @_;

# Templates
return unless my $file = $self->template_name($options);
$file = quotemeta $file;
for my $template (@$templates, @$inline) {
if ($template =~ /^$file\.(\w+)$/) { return $1 }
}
my $templates = $self->{templates} =
[map { @{Mojo::Home->new($_)->list_files} } @{$self->paths}];
/^$file\.(\w+)$/ and return $1 for @$templates;

return;
}
# DATA templates
/^$file\.(\w+)$/ and return $1 for keys %{$self->_data_templates};

sub _detect_template_class {
my ($self, $options) = @_;
return $options->{template_class} || $self->default_template_class;
return;
}

sub _extends {
my ($self, $c) = @_;
my $stash = $c->stash;
if (my $layout = delete $stash->{layout}) {
$stash->{extends} ||= $self->layout_prefix . '/' . $layout;
$stash->{extends} ||= 'layouts' . '/' . $layout;
}
return delete $stash->{extends};
}
Expand Down Expand Up @@ -291,6 +295,13 @@ L<Mojolicious::Renderer> implements the following attributes.
Renderer cache, defaults to a L<Mojo::Cache> object.
=head2 C<classes>
my $classes = $renderer->classes;
$renderer = $renderer->classes(['main']);
Classes to use for finding templates in C<DATA> section, defaults to C<main>.
=head2 C<default_format>
my $default = $renderer->default_format;
Expand Down Expand Up @@ -319,21 +330,6 @@ C<Embedded Perl> handled by L<Mojolicious::Plugin::EPRenderer>.
=back
=head2 C<default_template_class>
my $default = $renderer->default_template_class;
$renderer = $renderer->default_template_class('main');
Class to use for finding templates in C<DATA> section, defaults to C<main>.
=head2 C<detect_templates>
my $detect = $renderer->detect_templates;
$renderer = $renderer->detect_templates(1);
Template auto detection, the renderer will try to select the right template
and renderer automatically.
=head2 C<encoding>
my $encoding = $renderer->encoding;
Expand All @@ -355,13 +351,6 @@ Registered handlers.
Registered helpers.
=head2 C<layout_prefix>
my $prefix = $renderer->layout_prefix;
$renderer = $renderer->layout_prefix('layouts');
Directory to look for layouts in, defaults to C<layouts>.
=head2 C<paths>
my $paths = $renderer->paths;
Expand Down Expand Up @@ -403,7 +392,6 @@ sample helpers.
template => 'foo/bar',
format => 'html',
handler => 'epl'
template_class => 'main'
}, 'foo.html.ep');
Get a DATA template by name, usually used by handlers.
Expand Down
42 changes: 27 additions & 15 deletions lib/Mojolicious/Static.pm
Expand Up @@ -9,8 +9,20 @@ use Mojo::Content::Single;
use Mojo::Home;
use Mojo::Path;

has default_static_class => 'main';
has paths => sub { [] };
has classes => sub { ['main'] };
has paths => sub { [] };

# DEPRECATED in Leaf Fluttering In Wind!
sub default_static_class {
warn <<EOF;
Mojolicious::Static->default_static_class is DEPRECATED in favor of
Mojolicious::Static->classes!
EOF
my $self = shift;
return $self->classes->[0] unless @_;
$self->classes->[0] = shift;
return $self;
}

# "Valentine's Day's coming? Aw crap! I forgot to get a girlfriend again!"
sub dispatch {
Expand Down Expand Up @@ -142,17 +154,17 @@ sub _get_data_file {
# Protect templates
return if $rel =~ /\.\w+\.\w+$/;

# Detect DATA class
my $class = $c->stash->{static_class} || $self->default_static_class;

# Find DATA file
my $data = $self->{data_files}->{$class}
||= [keys %{Mojo::Command->new->get_all_data($class) || {}}];
for my $path (@$data) {
return Mojo::Command->new->get_data($path, $class) if $path eq $rel;
# Index DATA files
unless ($self->{data_files}) {
$self->{data_files} = {};
for my $class (@{$self->classes}) {
$self->{data_files}->{$_} = $class
for keys %{Mojo::Command->new->get_all_data($class) || {}};
}
}

return;
# Find file
return Mojo::Command->new->get_data($rel, $self->{data_files}->{$rel});
}

sub _get_file {
Expand Down Expand Up @@ -184,12 +196,12 @@ C<If-Modified-Since> support.
L<Mojolicious::Static> implements the following attributes.
=head2 C<default_static_class>
=head2 C<classes>
my $class = $static->default_static_class;
$static = $static->default_static_class('main');
my $classes = $static->classes;
$static = $static->classes(['main']);
Class to use for finding files in C<DATA> section, defaults to C<main>.
Classes to use for finding files in C<DATA> section, defaults to C<main>.
=head2 C<paths>
Expand Down
12 changes: 5 additions & 7 deletions t/mojolicious/lib/PluginWithTemplate.pm
Expand Up @@ -4,16 +4,14 @@ use Mojo::Base 'Mojolicious::Plugin';
# "Good news, everyone! I've taught the toaster to feel love!"
sub register {
my ($self, $app) = @_;
$app->routes->route('/plugin_with_template')->to(
cb => sub {
shift->render('template', template_class => __PACKAGE__);
}
);
push @{$app->renderer->classes}, __PACKAGE__;
$app->routes->route('/plugin_with_template')
->to(cb => sub { shift->render('plugin_with_template') });
}

1;
__DATA__
@@ template.html.ep
% layout plugin_with_template => (template_class => 'main');
@@ plugin_with_template.html.ep
% layout 'plugin_with_template';
with template

0 comments on commit 9940a7d

Please sign in to comment.