Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial release

  • Loading branch information...
commit 23fdfaed7513c43b943e00807d03f757b423a5a7 1 parent 72b10ea
@rshadow rshadow authored
View
1  .gitignore
@@ -14,3 +14,4 @@ META.yml
MYMETA.yml
nytprof.out
pm_to_blib
+.project
View
18 Makefile.PL
@@ -0,0 +1,18 @@
+use ExtUtils::MakeMaker;
+
+WriteMakefile(
+ NAME => "Mojolicious::Plugin::Human",
+ VERSION_FROM => "lib/Mojolicious/Plugin/Human.pm",
+ ABSTRACT_FROM => "lib/Mojolicious/Plugin/Human.pm",
+ MAKEFILE => 'Makefile',
+ LICENSE => 'Perl',
+ AUTHOR => [
+ 'Dmitry E. Oboukhov <unera@debian.org>,',
+ 'Roman V. Nikolaev <rshadow@rambler.ru>',
+ ],
+ PREREQ_PM => {
+ 'Mojo::Base' => 0,
+ 'DateTime' => 0,
+ 'DateTime::Format::DateParse' => 0,
+ }
+);
View
338 lib/Mojolicious/Plugin/Human.pm
@@ -0,0 +1,338 @@
+package Mojolicious::Plugin::Human;
+
+use strict;
+use warnings;
+use utf8;
+
+use Mojo::Base 'Mojolicious::Plugin';
+use Carp;
+
+use DateTime;
+use DateTime::Format::DateParse;
+
+our $VERSION = '0.1';
+
+=encoding utf-8
+
+=head1 NAME
+
+Mojolicious::Plugin::Human - Helpers to print values as human readable form.
+
+=head1 SYNOPSIS
+
+ $self->plugin('Human', {
+
+ # Set money parameters if you need
+ money_delim => ",",
+ money_digit => " ",
+
+ # Or change date and time strings
+ datetime => '%d.%m.%Y %H:%M',
+ time => '%H:%M:%S',
+ date => '%d.%m.%Y',
+ });
+
+=head1 DESCRIPTION
+
+You can use this module in Mojo template engine to make you users happy.
+
+=head1 CONFIGURATION
+
+=over
+
+=item money_delim
+
+Set format for human readable delimiter of money. Default: <.>
+
+=item money_digit
+
+Set format for human readable digits of money. Default: <,>
+
+=item datetime
+
+Set format for human readable date and time. Default: %F %H:%M
+
+=item time
+
+Set format for human readable time. Default: %H:%M:%S
+
+=item date
+
+=item time
+
+Set format for human readable date. Default: %F
+
+=back
+
+=head1 DATE AND TIME HELPERS
+
+=head2 str2time
+
+Get string, return timestamp
+
+=head2 strftime
+
+Get string, return formatted string
+
+=head2 human_datetime
+
+Get string, return date and time string in human readable form.
+
+=head2 human_time
+
+Get string, return time string in human readable form.
+
+=head2 human_date
+
+Get string, return date string in human readable form.
+
+=head1 MONEY HELPERS
+
+=head2 human_money
+
+Get number, return money string in human readable form with levels.
+
+=head1 PHONE HELPERS
+
+=head2 human_phones
+
+Get srtring, return phones (if many) string in human readable form.
+
+=head2 yandex_phone
+
+Get srtring, return just numbers phone string without country code.
+
+=head1 TEXT HELPERS
+
+=head2 human_suffix $str, $count, $one, $two, $many
+
+Get word base form and add some of suffix ($one, $two, $many) depends of $count
+
+=cut
+
+# Compiled regexp for placement level in the money functions
+my $REGEXP_DIGIT = qr{^(-?\d+)(\d{3})};
+
+sub clean_phone($);
+sub human_phone($);
+sub date_parse($);
+
+sub register {
+ my ($self, $app, $conf) = @_;
+
+ # Configuration
+ $conf ||= {};
+ $conf->{money_delim} //= '.';
+ $conf->{money_digit} //= ',';
+
+ $conf->{datetime} //= '%F %H:%M';
+ $conf->{time} //= '%H:%M:%S';
+ $conf->{date} //= '%F';
+
+ # Datetime
+
+ $app->helper(str2time => sub {
+ my ($self, $str) = @_;
+ my $datetime = date_parse( $str );
+ return $str unless $datetime;
+ return $datetime->epoch;
+ });
+
+ $app->helper(strftime => sub {
+ my ($self, $format, $str) = @_;
+ return unless defined $str;
+ my $datetime = date_parse( $str );
+ return $str unless $datetime;
+ return $datetime->strftime( $format );
+ });
+
+ $app->helper(human_datetime => sub {
+ my ($self, $str) = @_;
+ my $datetime = date_parse( $str );
+ return $str unless $datetime;
+ return $datetime->strftime($conf->{datetime});
+ });
+
+ $app->helper(human_time => sub {
+ my ($self, $str) = @_;
+ my $datetime = date_parse( $str );
+ return $str unless $datetime;
+ return $datetime->strftime($conf->{time});
+ });
+
+ $app->helper(human_date => sub {
+ my ($self, $str) = @_;
+ my $datetime = date_parse( $str );
+ return $str unless $datetime;
+ return $datetime->strftime($conf->{date});
+ });
+
+ # Money
+
+ $app->helper(human_money => sub {
+ my ($self, $str) = @_;
+ my $delim = $conf->{money_delim};
+ my $digit = $conf->{money_digit};
+ $str = sprintf '%.2f', $str;
+ $str =~ s{\.}{$delim};
+ 1 while $str =~ s{$REGEXP_DIGIT}{$1$digit$2};
+ return $str;
+ });
+
+ # Phones
+
+ $app->helper(human_phones => sub {
+ my ($self, $str) = @_;
+ return '' unless $str;
+ my @phones = split /[\s,;:]+/, $str;
+ return join ', ' => grep { $_ } map { human_phone $_ } @phones;
+ });
+
+ $app->helper(yandex_phone => sub {
+ my ($self, $phone) = @_;
+ return clean_phone($phone) || '';
+ });
+
+ # Text
+
+ $app->helper(human_suffix => sub {
+ my ($self, $str, $count, $one, $two, $many) = @_;
+
+ # Last digit
+ my $tail = abs( $count ) % 10;
+
+ # Default suffix
+ $one //= $str;
+ $two //= $str . 'a';
+ $many //= $str . 'ов';
+
+ # Get right suffix
+ my $result =
+ ( $tail == 0 ) ?$many :
+ ( $tail == 1 ) ?$one :
+ ( $tail >= 2 and $tail < 5 ) ?$two :$many;
+
+ # For 10 - 20 get special suffix
+ $tail = abs( $count ) % 100;
+ $result =
+ ( $tail >= 10 and $tail < 21 ) ?$many :$result;
+
+ return $result;
+ });
+}
+
+=head1 INTERNAL FUNCIONS
+
+=head2 clean_phone
+
+Clear phones. Fix first local digit 8 problem.
+
+Return <undef> if phome not correct
+
+=cut
+
+sub clean_phone($) {
+ my ($phone) = @_;
+ return undef unless $phone;
+ for ($phone) {
+ s/\D+//g;
+
+ $_ = '495' . $_ if 7 == length;
+
+ return undef unless 10 <= length $phone;
+
+ if (11 == length $_) { # have a country code
+ s/^8/7/;
+ } elsif (10 == length $_) { # havn`t country code
+ s/^/7/;
+ }
+
+ s/^/+/;
+ }
+ return $phone;
+}
+
+=head2 human_phone
+
+Make phone string in human readable form.
+
+=cut
+
+sub human_phone($) {
+ my ($phone) = @_;
+ $phone = clean_phone $phone;
+ return $phone unless $phone;
+ $phone =~ s/(...)(...)(....)$/-$1-$2-$3/;
+ return $phone;
+}
+
+=head2 date_parse $str
+
+Get a string and return DateTime or undef. Have a hack for parse Russian data
+and time.
+
+=cut
+
+sub date_parse($) {
+ my ($str) = @_;
+
+ return unless $str;
+
+ my $dt;
+
+ my $tzone = DateTime::TimeZone->new( name => 'local' );
+
+ # Take a russian date if possible
+ my ($day, $month, $year, $hour, $minute, $second, $tz) =
+ $str =~ m{^
+ (\d{2})\.(\d{2})\.(\d{4})
+ (?:
+ \s+
+ (\d{2}):(\d{2}):(\d{2})?(?:\.\d+)?
+ )?
+ (?:
+ \s+
+ (.*)
+ )?
+ $}xs;
+ if( $day and $month and $year ) {
+ $dt = eval {
+ DateTime->new(
+ year => $year,
+ month => $month,
+ day => $day,
+ hour => $hour || 0,
+ minute => $minute || 0,
+ second => $second || 0,
+ time_zone => ($tz)
+ ?DateTime::TimeZone->new( name => $tz )
+ :$tzone,
+ );
+ };
+ return if !$dt or $@;
+ } else {
+ $dt = eval {
+ DateTime::Format::DateParse->parse_datetime( $str, $tzone->name );
+ };
+ return if !$dt or $@;
+ }
+
+ return $dt;
+}
+
+1;
+
+=head1 AUTHORS
+
+Dmitry E. Oboukhov <unera@debian.org>
+Roman V. Nikolaev <rshadow@rambler.ru>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2011 Dmitry E. Oboukhov <unera@debian.org>
+Copyright (C) 2011 Roman V. Nikolaev <rshadow@rambler.ru>
+
+This program is free software, you can redistribute it and/or
+modify it under the terms of the Artistic License.
+
+=cut
View
41 t/001_use_ok.t
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+use utf8;
+use open qw(:std :utf8);
+use lib qw(lib ../lib);
+
+use Test::More tests => 5;
+use Encode qw(decode encode);
+
+use DateTime;
+use DateTime::Format::DateParse;
+use Mail::RFC822::Address;
+use List::MoreUtils qw(any);
+
+BEGIN {
+ my $builder = Test::More->builder;
+ binmode $builder->output, ":utf8";
+ binmode $builder->failure_output, ":utf8";
+ binmode $builder->todo_output, ":utf8";
+
+ require_ok 'Mojolicious';
+ require_ok 'DateTime';
+ require_ok 'DateTime::Format::DateParse';
+ require_ok 'Test::Compile';
+}
+
+ok $Mojolicious::VERSION >= 2.23, 'Mojolicious version >= 2.23';
+
+
+=head1 COPYRIGHT
+
+Copyright (C) 2011 Dmitry E. Oboukhov <unera@debian.org>
+Copyright (C) 2011 Roman V. Nikolaev <rshadow@rambler.ru>
+
+All rights reserved. If You want to use the code You
+MUST have permissions from Dmitry E. Oboukhov AND
+Roman V Nikolaev.
+
+=cut
View
21 t/005_compile.t
@@ -0,0 +1,21 @@
+use warnings;
+use strict;
+use utf8;
+use open qw(:std :utf8);
+use lib qw(lib ../lib);
+
+use Test::More;
+plan tests => 1;
+use Test::Compile;
+
+BEGIN {
+ # Подготовка объекта тестирования для работы с utf8
+ my $builder = Test::More->builder;
+ binmode $builder->output, ":utf8";
+ binmode $builder->failure_output, ":utf8";
+ binmode $builder->todo_output, ":utf8";
+}
+
+subtest 'Perl modules' => sub {
+ all_pm_files_ok();
+};
View
97 t/010_human.t
@@ -0,0 +1,97 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+use utf8;
+use open qw(:std :utf8);
+use lib qw(lib ../lib ../../lib);
+
+use Test::More tests => 21;
+use Encode qw(decode encode);
+
+
+BEGIN {
+ # Подготовка объекта тестирования для работы с utf8
+ my $builder = Test::More->builder;
+ binmode $builder->output, ":utf8";
+ binmode $builder->failure_output, ":utf8";
+ binmode $builder->todo_output, ":utf8";
+
+ use_ok 'Test::Mojo';
+ use_ok 'Mojolicious::Plugin::Human';
+ use_ok 'DateTime';
+}
+
+{
+ package MyApp;
+ use Mojo::Base 'Mojolicious';
+
+ sub startup {
+ my ($self) = @_;
+ $self->plugin('Human');
+ }
+ 1;
+}
+
+my $t = Test::Mojo->new('MyApp');
+ok $t, 'Test Mojo created';
+
+$t->app->routes->post("/test/human")->to( cb => sub {
+ my ($self) = @_;
+
+ my $dt = DateTime->from_epoch( epoch => time, time_zone => 'local');
+ my $dstr = $dt->strftime('%F %T %z');
+
+ ok $self->str2time( $dstr ) == $dt->epoch, 'str2time';
+ ok $self->strftime( '%T', $dstr ) eq $dt->strftime('%T'),
+ 'strftime';
+ ok $self->human_datetime( $dstr ) eq $dt->strftime('%F %H:%M'),
+ 'human_datetime';
+ ok $self->human_time( $dstr ) eq $dt->strftime('%H:%M:%S'),
+ 'human_time';
+ ok $self->human_date( $dstr ) eq $dt->strftime('%F'),
+ 'human_date';
+
+
+ ok $self->human_money('12345678.00') eq '12,345,678.00',
+ 'human_money';
+
+ ok $self->human_phones('1234567890') eq '+7-123-456-7890',
+ 'human_phones';
+ ok $self->human_phones('1234567890,0987654321')
+ eq '+7-123-456-7890, +7-098-765-4321',
+ 'human_phones many';
+ ok $self->yandex_phone('1234567890') eq '+71234567890',
+ 'yandex_phone';
+
+
+ ok $self->human_suffix('', 0, '1','2','100500') eq '100500',
+ 'human_suffix 0';
+ ok $self->human_suffix('', 1, '1','2','100500') eq '1',
+ 'human_suffix 1';
+ for my $count (2..4) {
+ ok $self->human_suffix('', $count, '1','2','100500') eq '2',
+ "human_suffix $count";
+ }
+ ok $self->human_suffix('', 6, '1','2','100500') eq '100500',
+ 'human_suffix 6';
+
+ $self->render(text => 'OK.');
+});
+
+$t->post_form_ok("/test/human" => {})-> status_is( 200 );
+
+diag decode utf8 => $t->tx->res->body unless $t->tx->success;
+
+=head1 COPYRIGHT
+
+Copyright (C) 2011 Dmitry E. Oboukhov <unera@debian.org>
+
+Copyright (C) 2011 Roman V. Nikolaev <rshadow@rambler.ru>
+
+All rights reserved. If You want to use the code You
+MUST have permissions from Dmitry E. Oboukhov AND
+Roman V Nikolaev.
+
+=cut
+
Please sign in to comment.
Something went wrong with that request. Please try again.