File Coverage

blib/lib/Tags/HTML/Login/Register.pm
Criterion Covered Total %
statement 65 65 100.0
branch 10 10 100.0
condition n/a
subroutine 14 14 100.0
pod 1 1 100.0
total 90 90 100.0


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