Skip to content

Instantly share code, notes, and snippets.

@Getty
Created May 17, 2017 13:50
Show Gist options
  • Save Getty/8e60512a4e8b317f3e5f9028e724ad8a to your computer and use it in GitHub Desktop.
Save Getty/8e60512a4e8b317f3e5f9028e724ad8a to your computer and use it in GitHub Desktop.
has xslate => (
isa => 'Text::Xslate',
is => 'ro',
lazy_build => 1,
);
sub _build_xslate {
my ( $self ) = @_;
my $xslate;
my $obj2dir = sub {
my $obj = shift;
if (blessed $obj && $obj->can('i')) {
return $obj->i;
}
my $class = ref $obj;
# we might not want singletonrows in the end after all - i still leave it in for the case of the cases
if ($class =~ m/^(DBIx::Class::SingletonRows::Cached::XXX|XXX)::(DB::Result|DB::ResultSet|Admin::Model::DB)::(.*)$/) {
my $dir = $3;
$dir =~ s/::/_/g;
$dir = decamelize($dir);
$dir = lc($dir);
$dir .= '_rs' if $2 eq 'DB::ResultSet';
return $dir;
} elsif ($class =~ m/^(DBIx::Class::SingletonRows::Cached::XXX|XXX)::(.*)$/) {
my $dir = $1;
$dir =~ s/::/_/g;
$dir = decamelize($dir);
$dir = lc($dir);
return $dir;
}
$class =~ s/::/_/g;
$class = decamelize($class);
$class = lc($class);
return $class;
};
my $i_template_and_vars = sub {
my $object = shift;
my $subtemplate;
my $no_templatedir;
my $vars;
if (ref $object) {
$subtemplate = shift;
$vars = shift;
} elsif (!defined $object) {
return '';
} else {
$no_templatedir = 1;
$subtemplate = $object;
my $next = shift;
if (ref $next eq 'HASH') {
$object = undef;
$vars = $next;
} else {
$object = $next;
$vars = shift;
}
}
my $main_object;
my @objects;
push @objects, $object if $object;
if (ref $object eq 'ARRAY') {
$main_object = $object->[0];
@objects = @{$object};
} else {
$main_object = $object;
}
my %current_vars = %{$xslate->current_vars};
my $no_caller = delete $vars->{no_caller} ? 1 : 0;
if (defined $current_vars{_} && !$no_caller) {
$current_vars{caller} = $current_vars{_};
}
$current_vars{_} = $main_object;
my $ref_main_object = ref $main_object;
if ($main_object && $ref_main_object) {
if (blessed $main_object && $main_object->can('meta')) {
for my $method ( $main_object->meta->get_all_methods ) {
if ($method->name =~ m/^i_(.*)$/) {
my $name = $1;
my $var_name = '_'.$name;
my $func = 'i_'.$name;
$current_vars{$var_name} = $main_object->$func;
}
}
}
}
my @template = ('i');
unless ($no_templatedir) {
push @template, $obj2dir->($main_object);
}
push @template, $subtemplate ? $subtemplate : 'label';
my %new_vars;
for (@objects) {
my $obj_dir = $obj2dir->($_);
if (defined $new_vars{$obj_dir}) {
if (ref $new_vars{$obj_dir} eq 'ARRAY') {
push @{$new_vars{$obj_dir}}, $_;
} else {
$new_vars{$obj_dir} = [
$new_vars{$obj_dir}, $_,
];
}
} else {
$new_vars{$obj_dir} = $_;
}
}
for (keys %new_vars) {
$current_vars{$_} = $new_vars{$_};
}
if ($vars) {
for (keys %{$vars}) {
$current_vars{$_} = $vars->{$_};
}
}
return join('/',@template).".tx",\%current_vars;
};
$xslate = Text::Xslate->new({
path => [ path(__FILE__)->parent->parent->child('root/templates')->realpath->absolute ],
suffix => '.tx',
function => {
# Mark text as raw HTML
r => sub { mark_raw(@_) },
v => sub { $xslate->current_vars->{join('',@_)} if @_ },
dump => sub { return p($_[0]) },
pf => sub { sprintf(shift,@_) },
sprintf => sub { sprintf(shift,@_) },
js => sub { js(shift) },
url_encode => sub { url_encode(@_) },
# trick function for DBIx::Class::ResultSet
results => sub {
my ( $rs, $sorting ) = @_;
my @results = $rs->all;
$sorting
? [ sort { $a->$sorting <=> $b->$sorting } @results ]
: [ @results ];
},
columns => sub {
my ( $result ) = @_;
my %columns = $result->get_columns();
return [ sort { $a cmp $b } keys %columns ];
},
# general functions avoiding xslates problems
call => sub {
my $thing = shift;
my $func = shift;
$thing->$func;
},
call_if => sub {
my $thing = shift;
my $func = shift;
$thing->$func if $thing;
},
replace => sub {
my $source = shift;
my $from = shift;
my $to = shift;
$source =~ s/$from/$to/g;
return $source;
},
rounded => sub {
my $minutes = shift;
my $return = sprintf("%.1f",$minutes);
$return =~ s/\.0$//;
return $return;
},
lines => sub {
my $text = shift;
my @lines = split /^/, $text;
return [ grep { length($_) > 0 } map { s/^\s+//; s/\s$//; s/\s+/ /g; $_; } @lines ];
},
urify => sub {
my $value = shift;
$value = lc $value;
$value =~ s/[^a-zA-Z]+/-/g;
return $value;
},
ref => sub { ref($_[0]) },
defined => sub { defined($_[0]) },
floor => sub { floor($_[0]) },
ceil => sub { ceil($_[0]) },
length => sub { length($_[0]) },
lc => sub { lc($_[0]) },
uc => sub { uc($_[0]) },
join => sub { join(shift,@_) },
jointrue => sub { join(shift,map { $_ ? ($_) : () } @_) },
i_template_and_vars => $i_template_and_vars,
i => sub { mark_raw($xslate->render($i_template_and_vars->(@_))) },
i_template => sub {
my ( $template, $vars ) = $i_template_and_vars->(@_);
return $template
},
datetime => sub {
my ( $date ) = @_;
$date = DateTime->from_epoch( epoch => $date ) unless ref $date;
return $date;
},
time => sub { time() },
ordinate => sub {
return ordinate($_[0]);
},
dur_precise => sub {
my ( $date ) = @_;
$date = DateTime->from_epoch( epoch => $date ) unless ref $date;
return DateTime::Format::Human::Duration->new->format_duration(
ref $date eq 'DateTime::Duration' ? $date : (DateTime->now( time_zone => $self->time_zone ) - $date),
'units' => [qw/years months days hours minutes/],
'past' => '%s ago',
'future' => 'in %s',
'no_time' => 'just now',
);
},
nl2br => sub {
my $t = shift || return;
$t =~ s/([\r])/<br>/g;
return $t;
},
n => sub {
my ( $singular, $plural, @args ) = @_;
if ($args[0] == 1) {
return $singular =~ m/%/
? sprintf($singular,@args)
: sprintf($singular);
} else {
return $plural =~ m/%/
? sprintf($plural,@args)
: sprintf($plural);
}
},
before_now => sub {
return 0 unless $_[0];
DateTime->compare( DateTime->now( time_zone => $self->time_zone ), $_[0] ) == 1 ? 0 : 1;
},
make_data => sub {
my ( $data ) = @_;
my $text = ' ';
for my $key (keys %{$data}) {
$text .= 'data-'.$key.'="'.html_escape($data->{$key} || "").'" ';
}
return mark_raw($text);
},
alphapos => sub {
my ( $pos ) = @_;
my @alphas = 'a'..'zz';
return $alphas[$pos-1];
},
style => sub {
my %style;
my @styles = @_;
while (@styles) {
my $t_style = $self->template_styles->{shift @styles};
if (ref $t_style eq 'HASH') {
$style{$_} = $t_style->{$_} for keys %{$t_style};
} elsif (ref $t_style eq 'ARRAY') {
unshift @styles, @{$t_style};
}
}
my $return = 'style="';
$return .= $_.':'.$style{$_}.';' for (sort { length($a) <=> length($b) } keys %style);
$return .= '"';
return mark_raw($return);
},
},
});
return $xslate;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment