File Coverage

blib/lib/Tags/HTML/Login/Request.pm
Criterion Covered Total %
statement 55 72 76.3
branch 8 12 66.6
condition n/a
subroutine 12 15 80.0
pod 1 1 100.0
total 76 100 76.0


line stmt bran cond sub pod time code
1             package Tags::HTML::Login::Request;
2              
3 3     3   161563 use base qw(Tags::HTML);
  3         5  
  3         1652  
4 3     3   27862 use strict;
  3         5  
  3         76  
5 3     3   1610 use warnings;
  3         8  
  3         203  
6              
7 3     3   14 use Class::Utils qw(set_params split_params);
  3         7  
  3         138  
8 3     3   14 use Error::Pure qw(err);
  3         9  
  3         156  
9 3     3   18 use List::Util 1.33 qw(none);
  3         51  
  3         294  
10 3     3   1828 use Mo::utils::CSS 0.07 qw(check_css_unit);
  3         28005  
  3         63  
11 3     3   1513 use Mo::utils::Language 0.05 qw(check_language_639_2);
  3         897289  
  3         89  
12 3     3   310 use Readonly;
  3         8  
  3         146  
13 3     3   3970 use Tags::HTML::Messages;
  3         8821  
  3         4542  
14              
15             Readonly::Array our @FORM_METHODS => qw(post get);
16              
17             our $VERSION = 0.03;
18              
19             # Constructor.
20             sub new {
21 13     13 1 405530 my ($class, @params) = @_;
22              
23             # Create object.
24 13         109 my ($object_params_ar, $other_params_ar) = split_params(
25             ['css_class', 'form_method', 'lang', 'logo_image_url',
26             'text', 'width'], @params);
27 13         531 my $self = $class->SUPER::new(@{$other_params_ar});
  13         95  
28              
29             # CSS style.
30 10         400 $self->{'css_class'} = 'form-request';
31              
32             # Form method.
33 10         54 $self->{'form_method'} = 'post';
34              
35             # Language.
36 10         31 $self->{'lang'} = 'eng';
37              
38             # Logo.
39 10         27 $self->{'logo_image_url'} = undef;
40              
41             # Language texts.
42 10         67 $self->{'text'} = {
43             'eng' => {
44             'login_request' => 'Login request',
45             'email_label' => 'Email',
46             'submit' => 'Request',
47             },
48             };
49              
50             # Login box width.
51 10         41 $self->{'width'} = '300px';
52              
53             # Process params.
54 10         22 set_params($self, @{$object_params_ar});
  10         47  
55              
56             # Check form method.
57 10 100   11   275 if (none { $self->{'form_method'} eq $_ } @FORM_METHODS) {
  11         129  
58 1         13 err "Parameter 'form_method' has bad value.";
59             }
60              
61             # Check lang.
62 9         158 check_language_639_2($self, 'lang');
63              
64             # Check text for lang
65 8 100       98072 if (! defined $self->{'text'}) {
66 1         7 err "Parameter 'text' is required.";
67             }
68 7 100       40 if (ref $self->{'text'} ne 'HASH') {
69 1         12 err "Parameter 'text' must be a hash with language texts.";
70             }
71 6 100       32 if (! exists $self->{'text'}->{$self->{'lang'}}) {
72 1         10 err "Texts for language '$self->{'lang'}' doesn't exist.";
73             }
74              
75 5         35 check_css_unit($self, 'width');
76              
77             $self->{'_tags_messages'} = Tags::HTML::Messages->new(
78             'css' => $self->{'css'},
79             'flag_no_messages' => 0,
80 2         245 'tags' => $self->{'tags'},
81             );
82              
83             # Object.
84 2         23984 return $self;
85             }
86              
87             # Process 'Tags'.
88             sub _process {
89 0     0     my ($self, $messages_ar) = @_;
90              
91 0           my $email_id = 'email';
92              
93             $self->{'tags'}->put(
94             ['b', 'form'],
95             ['a', 'class', $self->{'css_class'}],
96 0           ['a', 'method', $self->{'form_method'}],
97              
98             ['b', 'fieldset'],
99             ['b', 'legend'],
100             ['d', $self->_text('login_request')],
101             ['e', 'legend'],
102             );
103              
104 0 0         if (defined $self->{'logo_image_url'}) {
105             $self->{'tags'}->put(
106             ['b', 'div'],
107             ['a', 'class', 'logo'],
108             ['b', 'img'],
109 0           ['a', 'src', $self->{'logo_image_url'}],
110             ['a', 'alt', 'logo'],
111             ['e', 'img'],
112             ['e', 'div'],
113             );
114             }
115              
116 0           $self->{'tags'}->put(
117              
118             ['b', 'p'],
119             ['b', 'label'],
120             ['a', 'for', $email_id],
121             ['e', 'label'],
122             ['d', $self->_text('email_label')],
123             ['b', 'input'],
124             ['a', 'type', 'email'],
125             ['a', 'name', $email_id],
126             ['a', 'id', $email_id],
127             ['a', 'autofocus', 'autofocus'],
128             ['e', 'input'],
129             ['e', 'p'],
130              
131             ['b', 'p'],
132             ['b', 'button'],
133             ['a', 'type', 'submit'],
134             ['a', 'name', 'login_request'],
135             ['a', 'value', 'login_request'],
136             ['d', $self->_text('submit')],
137             ['e', 'button'],
138             ['e', 'p'],
139              
140             ['e', 'fieldset'],
141             );
142              
143 0           $self->{'_tags_messages'}->process($messages_ar);
144              
145 0           $self->{'tags'}->put(
146             ['e', 'form'],
147             );
148              
149 0           return;
150             }
151              
152             # Process 'CSS::Struct'.
153             sub _process_css {
154 0     0     my ($self, $message_types_hr) = @_;
155              
156             $self->{'css'}->put(
157             ['s', '.'.$self->{'css_class'}],
158             ['d', 'width', $self->{'width'}],
159             ['d', 'background-color', '#f2f2f2'],
160             ['d', 'padding', '20px'],
161             ['d', 'border-radius', '5px'],
162             ['d', 'box-shadow', '0 0 10px rgba(0, 0, 0, 0.2)'],
163             ['e'],
164              
165             ['s', '.'.$self->{'css_class'}.' .logo'],
166             ['d', 'height', '5em'],
167             ['d', 'width', '100%'],
168             ['e'],
169              
170             ['s', '.'.$self->{'css_class'}.' img'],
171             ['d', 'margin', 'auto'],
172             ['d', 'display', 'block'],
173             ['d', 'max-width', '100%'],
174             ['d', 'max-height', '5em'],
175             ['e'],
176              
177             ['s', '.'.$self->{'css_class'}.' fieldset'],
178             ['d', 'border', 'none'],
179             ['d', 'padding', 0],
180             ['d', 'margin-bottom', '20px'],
181             ['e'],
182              
183             ['s', '.'.$self->{'css_class'}.' legend'],
184             ['d', 'font-weight', 'bold'],
185             ['d', 'margin-bottom', '10px'],
186             ['e'],
187              
188             ['s', '.'.$self->{'css_class'}.' p'],
189             ['d', 'margin', 0],
190             ['d', 'padding', '10px 0'],
191             ['e'],
192              
193             ['s', '.'.$self->{'css_class'}.' label'],
194             ['d', 'display', 'block'],
195             ['d', 'font-weight', 'bold'],
196             ['d', 'margin-bottom', '5px'],
197             ['e'],
198              
199             ['s', '.'.$self->{'css_class'}.' input[type="email"]'],
200             ['d', 'width', '100%'],
201             ['d', 'padding', '8px'],
202             ['d', 'border', '1px solid #ccc'],
203             ['d', 'border-radius', '3px'],
204             ['e'],
205              
206             ['s', '.'.$self->{'css_class'}.' button[type="submit"]'],
207             ['d', 'width', '100%'],
208             ['d', 'padding', '10px'],
209             ['d', 'background-color', '#4CAF50'],
210             ['d', 'color', '#fff'],
211             ['d', 'border', 'none'],
212             ['d', 'border-radius', '3px'],
213             ['d', 'cursor', 'pointer'],
214             ['e'],
215              
216             ['s', '.'.$self->{'css_class'}.' button[type="submit"]:hover'],
217             ['d', 'background-color', '#45a049'],
218             ['e'],
219              
220 0           ['s', '.'.$self->{'css_class'}.' .messages'],
221             ['d', 'text-align', 'center'],
222             ['e'],
223             );
224              
225 0           $self->{'_tags_messages'}->process_css($message_types_hr);
226              
227 0           return;
228             }
229              
230             sub _text {
231 0     0     my ($self, $key) = @_;
232              
233 0 0         if (! exists $self->{'text'}->{$self->{'lang'}}->{$key}) {
234 0           err "Text for lang '$self->{'lang'}' and key '$key' doesn't exist.";
235             }
236              
237 0           return $self->{'text'}->{$self->{'lang'}}->{$key};
238             }
239              
240             1;
241              
242             __END__
243              
244             =pod
245              
246             =encoding utf8
247              
248             =head1 NAME
249              
250             Tags::HTML::Login::Request - Tags helper for login request.
251              
252             =head1 SYNOPSIS
253              
254             use Tags::HTML::Login::Request;
255              
256             my $obj = Tags::HTML::Login::Request->new(%params);
257             $obj->process($message_ar);
258             $obj->process_css($message_types_hr);
259              
260             =head1 METHODS
261              
262             =head2 C<new>
263              
264             my $obj = Tags::HTML::Login::Request->new(%params);
265              
266             Constructor.
267              
268             Returns instance of object.
269              
270             =over 8
271              
272             =item * C<css>
273              
274             'CSS::Struct::Output' object for L<process_css> processing.
275              
276             Default value is undef.
277              
278             =item * C<css_class>
279              
280             CSS class.
281              
282             Default value is 'form-request'.
283              
284             =item * C<form_method>
285              
286             Form method.
287              
288             Possible values are 'post' and 'get'.
289              
290             Default value is 'post'.
291              
292             =item * C<lang>
293              
294             Language in ISO 639-2 code.
295              
296             Default value is 'eng'.
297              
298             =item * C<logo_image_url>
299              
300             URL to logo image.
301              
302             Default value is undef.
303              
304             =item * C<tags>
305              
306             'Tags::Output' object.
307              
308             Default value is undef.
309              
310             =item * C<text>
311              
312             Hash reference with keys defined language in ISO 639-2 code and value with hash
313             reference with texts.
314              
315             Required keys are 'login_request', 'email_label' and 'submit'.
316              
317             Default value is:
318              
319             {
320             'eng' => {
321             'login_request' => 'Login request',
322             'email_label' => 'Email',
323             'submit' => 'Request',
324             },
325             }
326              
327             =back
328              
329             =head2 C<process>
330              
331             $obj->process($message_ar);
332              
333             Process Tags structure for login box.
334              
335             Reference to array with message objects C<$message_ar> must be a instance of
336             L<Data::Message::Simple> object.
337              
338             Returns undef.
339              
340             =head2 C<process_css>
341              
342             $obj->process_css($message_types_hr);
343              
344             Process CSS::Struct structure for login box.
345              
346             Variable C<$message_type_hr> is reference to hash with keys for message type and value for color in CSS style.
347             Possible message types are info and error now. Types are defined in L<Data::Message::Simple>.
348              
349             Returns undef.
350              
351             =head1 ERRORS
352              
353             new():
354             From Class::Utils::set_params():
355             Unknown parameter '%s'.
356             From Mo::utils::CSS::check_css_unit():
357             Parameter 'width' doesn't contain unit number.
358             Value: %s
359             Parameter 'width' doesn't contain unit name.
360             Value: %s
361             Parameter 'width' contain bad unit.
362             Unit: %s
363             Value: %s
364             From Mo::utils::Language::check_language_639_2():
365             Parameter 'lang' doesn't contain valid ISO 639-2 code.
366             Codeset: %s
367             Value: %s
368             From Tags::HTML::new():
369             Parameter 'css' must be a 'CSS::Struct::Output::*' class.
370             Parameter 'tags' must be a 'Tags::Output::*' class.
371              
372             process():
373             From Tags::HTML::process():
374             Parameter 'tags' isn't defined.
375              
376             process_css():
377             From Tags::HTML::process_css():
378             Parameter 'css' isn't defined.
379              
380             =head1 EXAMPLE1
381              
382             =for comment filename=print_block_html_and_css.pl
383              
384             use strict;
385             use warnings;
386              
387             use CSS::Struct::Output::Indent;
388             use Tags::HTML::Login::Request;
389             use Tags::Output::Indent;
390              
391             # Object.
392             my $css = CSS::Struct::Output::Indent->new;
393             my $tags = Tags::Output::Indent->new;
394             my $obj = Tags::HTML::Login::Request->new(
395             'css' => $css,
396             'tags' => $tags,
397             );
398              
399             # Process login button.
400             $obj->process_css;
401             $obj->process;
402              
403             # Print out.
404             print "CSS\n";
405             print $css->flush."\n\n";
406             print "HTML\n";
407             print $tags->flush."\n";
408              
409             # Output:
410             # CSS
411             # .form-request {
412             # width: 300px;
413             # background-color: #f2f2f2;
414             # padding: 20px;
415             # border-radius: 5px;
416             # box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
417             # }
418             # .form-request .logo {
419             # height: 5em;
420             # width: 100%;
421             # }
422             # .form-request img {
423             # margin: auto;
424             # display: block;
425             # max-width: 100%;
426             # max-height: 5em;
427             # }
428             # .form-request fieldset {
429             # border: none;
430             # padding: 0;
431             # margin-bottom: 20px;
432             # }
433             # .form-request legend {
434             # font-weight: bold;
435             # margin-bottom: 10px;
436             # }
437             # .form-request p {
438             # margin: 0;
439             # padding: 10px 0;
440             # }
441             # .form-request label {
442             # display: block;
443             # font-weight: bold;
444             # margin-bottom: 5px;
445             # }
446             # .form-request input[type="email"] {
447             # width: 100%;
448             # padding: 8px;
449             # border: 1px solid #ccc;
450             # border-radius: 3px;
451             # }
452             # .form-request button[type="submit"] {
453             # width: 100%;
454             # padding: 10px;
455             # background-color: #4CAF50;
456             # color: #fff;
457             # border: none;
458             # border-radius: 3px;
459             # cursor: pointer;
460             # }
461             # .form-request button[type="submit"]:hover {
462             # background-color: #45a049;
463             # }
464             # .form-request .messages {
465             # text-align: center;
466             # }
467             #
468             # HTML
469             # <form class="form-request" method="post">
470             # <fieldset>
471             # <legend>
472             # Login request
473             # </legend>
474             # <p>
475             # <label for="email">
476             # </label>
477             # Email
478             # <input type="email" name="email" id="email" autofocus="autofocus">
479             # </input>
480             # </p>
481             # <p>
482             # <button type="submit" name="login_request" value="login_request">
483             # Request
484             # </button>
485             # </p>
486             # </fieldset>
487             # </form>
488              
489             =head1 EXAMPLE2
490              
491             =for comment filename=plack_app_login_request.pl
492              
493             use strict;
494             use warnings;
495            
496             use CSS::Struct::Output::Indent;
497             use Plack::App::Tags::HTML;
498             use Plack::Runner;
499             use Tags::HTML::Login::Request;
500             use Tags::Output::Indent;
501             use Unicode::UTF8 qw(decode_utf8);
502            
503             my $css = CSS::Struct::Output::Indent->new;
504             my $tags = Tags::Output::Indent->new(
505             'xml' => 1,
506             'preserved' => ['style'],
507             );
508             my $login_request = Tags::HTML::Login::Request->new(
509             'css' => $css,
510             'tags' => $tags,
511             );
512             $login_request->process_css;
513             my $app = Plack::App::Tags::HTML->new(
514             'component' => 'Tags::HTML::Container',
515             'data' => [sub {
516             my $self = shift;
517             $login_request->process;
518             $login_request->process_css;
519             return;
520             }],
521             'css' => $css,
522             'tags' => $tags,
523             'title' => 'Login and password',
524             )->to_app;
525             Plack::Runner->new->run($app);
526              
527             # Output screenshot is in images/ directory.
528              
529             =begin html
530              
531             <a href="https://raw.githubusercontent.com/michal-josef-spacek/Tags-HTML-Login-Request/master/images/plack_app_login_request.png">
532             <img src="https://raw.githubusercontent.com/michal-josef-spacek/Tags-HTML-Login-Request/master/images/plack_app_login_request.png" alt="Web app example" width="300px" height="300px" />
533             </a>
534              
535             =end html
536              
537             =head1 DEPENDENCIES
538              
539             L<Class::Utils>,
540             L<Error::Pure>,
541             L<List::Util>,
542             L<Mo::utils::Language>,
543             L<Readonly>,
544             L<Tags::HTML>,
545             L<Tags::HTML::Messages>.
546              
547             =head1 SEE ALSO
548              
549             =over
550              
551             =item L<Tags::HTML::Login::Button>
552              
553             Tags helper for login button.
554              
555             =item L<Tags::HTML::Login::Register>
556              
557             Tags helper for login register.
558              
559             =back
560              
561             =head1 REPOSITORY
562              
563             L<https://github.com/michal-josef-spacek/Tags-HTML-Login-Request>
564              
565             =head1 AUTHOR
566              
567             Michal Josef Špaček L<mailto:skim@cpan.org>
568              
569             L<http://skim.cz>
570              
571             =head1 LICENSE AND COPYRIGHT
572              
573             © 2024 Michal Josef Špaček
574              
575             BSD 2-Clause License
576              
577             =head1 VERSION
578              
579             0.03
580              
581             =cut