From: Niclas Zimmermann Date: Fri, 8 Mar 2013 16:29:18 +0000 (+0100) Subject: Merge branch 'acc_trans' X-Git-Tag: release-3.1.0beta1~539 X-Git-Url: http://wagnertech.de/gitweb/gitweb.cgi/mfinanz.git/commitdiff_plain/0347cf10772dfc42e8cffb0b593b7a7780b00043?hp=a8da95826e357e75f78ccfc6b8f2c2523c52723f Merge branch 'acc_trans' --- diff --git a/SL/Locale.pm b/SL/Locale.pm index 5503c1b95..3216cd270 100644 --- a/SL/Locale.pm +++ b/SL/Locale.pm @@ -539,7 +539,20 @@ sub get_local_time_zone { return $self->{local_time_zone}; } +sub language_join { + my ($self, $items, %params) = @_; + + $items ||= []; + $params{conjunction} ||= $::locale->text('and'); + my $num = scalar @{ $items }; + + return 0 == $num ? '' + : 1 == $num ? $items->[0] + : join(', ', @{ $items }[0..$num - 2]) . ' ' . $params{conjunction} . ' ' . $items->[$num - 1]; +} + 1; + __END__ =pod diff --git a/SL/Presenter.pm b/SL/Presenter.pm index 36acc73dd..abfd561fa 100644 --- a/SL/Presenter.pm +++ b/SL/Presenter.pm @@ -14,6 +14,7 @@ use SL::Presenter::Invoice; use SL::Presenter::Order; use SL::Presenter::Project; use SL::Presenter::Record; +use SL::Presenter::Text; sub get { return $::request->presenter; diff --git a/SL/Presenter/Text.pm b/SL/Presenter/Text.pm new file mode 100644 index 000000000..bcae2f96f --- /dev/null +++ b/SL/Presenter/Text.pm @@ -0,0 +1,84 @@ +package SL::Presenter::Text; + +use strict; + +use parent qw(Exporter); + +use Exporter qw(import); +our @EXPORT = qw(simple_format truncate); + +use Carp; + +sub truncate { + my ($self, $text, %params) = @_; + + $params{at} ||= 50; + $params{at} = 3 if 3 > $params{at}; + $params{at} -= 3; + + return $text if length($text) < $params{at}; + return substr($text, 0, $params{at}) . '...'; +} + +sub simple_format { + my ($self, $text, %params) = @_; + + $text = $::locale->quote_special_chars('HTML', $text || ''); + + $text =~ s{\r\n?}{\n}g; # \r\n and \r -> \n + $text =~ s{\n\n+}{

\n\n

}g; # 2+ newline -> paragraph + $text =~ s{([^\n]\n)(?=[^\n])}{$1
}g; # 1 newline -> br + + return '

' . $text; +} + +1; +__END__ + +=pod + +=encoding utf8 + +=head1 NAME + +SL::Presenter::Text - Presenter module for assorted text helpers + +=head1 SYNOPSIS + + my $long_text = "This is very, very long. Need shorter, surely."; + my $truncated = $::request->presenter->truncate($long_text, at => 10); + # Result: "This is..." + +=head1 FUNCTIONS + +=over 4 + +=item C + +Returns the C<$text> truncated after a certain number of +characters. + +The number of characters to truncate at is determined by the parameter +C which defaults to 50. If the text is longer than C<$params{at}> +then it will be truncated and postfixed with '...'. Otherwise it will +be returned unmodified. + +=item C + +Applies simple formatting rules to C<$text>: The text is put into +paragraph HTML tags. Two consecutive newlines are interpreted as a +paragraph change: they close the current paragraph tag and start a new +one. Single newlines are converted to line breaks. Carriage returns +are removed. + +=back + +=head1 BUGS + +Nothing here yet. + +=head1 AUTHOR + +Moritz Bunkus Em.bunkus@linet-services.deE + +=cut diff --git a/SL/Template/Plugin/L.pm b/SL/Template/Plugin/L.pm index bac6f7f12..8de38ab17 100644 --- a/SL/Template/Plugin/L.pm +++ b/SL/Template/Plugin/L.pm @@ -52,6 +52,18 @@ sub _context { return $_[0]->{CONTEXT}; } +sub _call_presenter { + my ($method, @args) = @_; + + my $presenter = $::request->presenter; + + return '' unless $presenter->can($method); + + splice @args, -1, 1, %{ $args[-1] } if @args && (ref($args[-1]) eq 'HASH'); + + $presenter->$method(@args); +} + sub name_to_id { my $self = shift; my $name = shift; @@ -116,6 +128,8 @@ sub select_tag { my $with_empty = delete($attributes{with_empty}); my $empty_title = delete($attributes{empty_title}); + my $with_optgroups = delete($attributes{with_optgroups}); + my %selected; if ( ref($attributes{default}) eq 'ARRAY' ) { @@ -130,91 +144,71 @@ sub select_tag { delete($attributes{default}); - my @options; - - if ( $with_empty ) { - push(@options, [undef, $empty_title || '']); - } + my @all_options; + push @all_options, [undef, $empty_title || ''] if $with_empty; my $normalize_entry = sub { - my ($type, $entry, $sub, $key) = @_; - if ( $sub ) { - return $sub->($entry); - } + return $sub->($entry) if $sub; my $ref = ref($entry); if ( !$ref ) { - - if ( $type eq 'value' || $type eq 'title' ) { - return $entry; - } - + return $entry if $type eq 'value' || $type eq 'title'; return 0; } if ( $ref eq 'ARRAY' ) { - - if ( $type eq 'value' ) { - return $entry->[0]; - } - - if ( $type eq 'title' ) { - return $entry->[1]; - } - - return $entry->[2]; - } - - if ( $ref eq 'HASH' ) { - return $entry->{$key}; - } - - if ( $type ne 'default' || $entry->can($key) ) { - return $entry->$key; + return $entry->[ $type eq 'value' ? 0 : $type eq 'title' ? 1 : 2 ]; } + return $entry->{$key} if $ref eq 'HASH'; + return $entry->$key if $type ne 'default' || $entry->can($key); return undef; }; - foreach my $entry ( @{ $collection } ) { - my $value; - my $title; + my $list_to_code = sub { + my ($sub_collection) = @_; - if ( $value_title_sub ) { - ($value, $title) = @{ $value_title_sub->($entry) }; - } else { + my @options; + foreach my $entry ( @{ $sub_collection } ) { + my $value; + my $title; - $value = $normalize_entry->('value', $entry, $value_sub, $value_key); - $title = $normalize_entry->('title', $entry, $title_sub, $title_key); - } + if ( $value_title_sub ) { + ($value, $title) = @{ $value_title_sub->($entry) }; + } else { - my $default = $normalize_entry->('default', $entry, $default_sub, $default_key); + $value = $normalize_entry->('value', $entry, $value_sub, $value_key); + $title = $normalize_entry->('title', $entry, $title_sub, $title_key); + } - push(@options, [$value, $title, $default]); - } + my $default = $normalize_entry->('default', $entry, $default_sub, $default_key); - foreach my $entry (@options) { - if ( exists($selected{$entry->[0]}) ) { - $entry->[2] = 1; + push(@options, [$value, $title, $default]); } - } - my $code = ''; + foreach my $entry (@options) { + $entry->[2] = 1 if $selected{$entry->[0]}; + } - foreach my $entry (@options) { - my %args = (value => $entry->[0]); + return join '', map { $self->html_tag('option', _H($_->[1]), value => $_->[0], selected => $_->[2]) } @options; + }; - $args{selected} = $entry->[2]; + my $code; - $code .= $self->html_tag('option', _H($entry->[1]), %args); - } + if (!$with_optgroups) { + $code = $list_to_code->($collection); - $code = $self->html_tag('select', $code, %attributes, name => $name); + } else { + $code = join '', map { + my ($optgroup_title, $sub_collection) = @{ $_ }; + $self->html_tag('optgroup', $list_to_code->($sub_collection), label => $optgroup_title) + } @{ $collection }; + } - return $code; + return $self->html_tag('select', $code, %attributes, name => $name); } sub textarea_tag { @@ -596,15 +590,8 @@ sub dump { } sub truncate { - my ($self, $text, @slurp) = @_; - my %params = _hashify(@slurp); - - $params{at} ||= 50; - $params{at} = 3 if 3 > $params{at}; - $params{at} -= 3; - - return $text if length($text) < $params{at}; - return substr($text, 0, $params{at}) . '...'; + my $self = shift; + return _call_presenter('truncate', @_); } sub sortable_table_header { @@ -651,6 +638,11 @@ sub paginate_controls { return SL::Presenter->get->render('common/paginate', %template_params); } +sub simple_format { + my $self = shift; + return _call_presenter('simple_format', @_); +} + 1; __END__ @@ -761,6 +753,37 @@ selected. The tag's C defaults to C. +If the option C is set then this function expects +C<\@collection> to be one level deeper. The upper-most level is +translated into a HTML C tag. So the structure becomes: + +=over 4 + +=item 1. Array of array references. Each element in the +C<\@collection> is converted into an optgroup. + +=item 2. The optgroup's C