File Coverage

blib/lib/User/Identity.pm
Criterion Covered Total %
statement 87 96 90.6
branch 37 58 63.7
condition 8 18 44.4
subroutine 23 24 95.8
pod 18 19 94.7
total 173 215 80.4


line stmt bran cond sub pod time code
1             # This code is part of Perl distribution User-Identity version 4.00.
2             # The POD got stripped from this file by OODoc version 3.05.
3             # For contributors see file ChangeLog.
4              
5             # This software is copyright (c) 2003-2025 by Mark Overmeer.
6              
7             # This is free software; you can redistribute it and/or modify it under
8             # the same terms as the Perl 5 programming language system itself.
9             # SPDX-License-Identifier: Artistic-1.0-Perl OR GPL-1.0-or-later
10              
11              
12             package User::Identity;{
13             our $VERSION = '4.00';
14             }
15              
16 3     3   385963 use parent 'User::Identity::Item';
  3         7  
  3         23  
17              
18 3     3   239 use strict;
  3         7  
  3         97  
19 3     3   16 use warnings;
  3         12  
  3         167  
20              
21 3     3   17 use Log::Report 'user-identity';
  3         17  
  3         18  
22              
23             #--------------------
24              
25 3     3   891 use overload '""' => 'fullName';
  3         12  
  3         23  
26              
27             #--------------------
28              
29             my @attributes = qw/charset courtesy birth full_name formal_name firstname
30             gender initials language nickname prefix surname titles/;
31              
32             sub init($)
33 7     7 0 17 { my ($self, $args) = @_;
34              
35             exists $args->{$_} && ($self->{'UI_'.$_} = delete $args->{$_})
36 7   100     262 for @attributes;
37              
38 7         40 $self->SUPER::init($args);
39             }
40              
41             sub type() { 'user' }
42 4     4 1 16 sub user() { $_[0] }
43              
44             #--------------------
45              
46 1 50   1 1 9 sub charset() { $_[0]->{UI_charset} || $ENV{LC_CTYPE} }
47              
48              
49             sub nickname()
50 5     5 1 1285 { my $self = shift;
51 5 50       29 $self->{UI_nickname} || $self->name;
52             # TBI: If OS-specific info exists, then username
53             }
54              
55              
56             sub firstname()
57 9     9 1 19 { my $self = shift;
58 9 100       54 $self->{UI_firstname} || ucfirst $self->nickname;
59             }
60              
61              
62             sub initials()
63 6     6 1 228 { my $self = shift;
64 6 100       26 return $self->{UI_initials} if defined $self->{UI_initials};
65              
66 4 50       10 if(my $firstname = $self->firstname)
67 4         8 { my $i = '';
68 4         31 while( $firstname =~ m/(\w+)(\-)?/g )
69 12         28 { my ($part, $connect) = ($1,$2);
70 12   100     35 $connect ||= '.';
71 12         27 $part =~ m/^(chr|th|\w)/i;
72 12         70 $i .= ucfirst(lc $1).$connect;
73             }
74 4         21 return $i;
75             }
76             }
77              
78              
79 1     1 1 4 sub prefix() { $_[0]->{UI_prefix} }
80              
81              
82 1     1 1 3 sub surname() { $_[0]->{UI_surname} }
83              
84              
85             sub fullName()
86 10     10 1 34 { my $self = shift;
87 10 50       44 return $self->{UI_full_name} if defined $self->{UI_full_name};
88              
89 10         28 my ($first, $prefix, $surname) = @$self{ qw/UI_firstname UI_prefix UI_surname/};
90              
91 10 100 33     61 $surname //= ucfirst $self->nickname if defined $first;
92 10 100 33     24 $first //= $self->firstname if defined $surname;
93              
94 10         39 my $full = join ' ', grep defined, ($first, $prefix, $surname);
95 10 100       23 $full = $self->firstname unless length $full;
96              
97             # TBI: if OS-specific knowledge, then unix GCOS?
98              
99 10         41 $full;
100             }
101              
102              
103             sub formalName()
104 3     3 1 8 { my $self = shift;
105 3 50       12 return $self->{UI_formal_name} if defined $self->{UI_formal_name};
106              
107 3         8 my $initials = $self->initials;
108              
109 3         7 my $firstname = $self->{UI_firstname};
110 3 50       13 $firstname = "($firstname)" if defined $firstname;
111              
112             join ' ', grep defined,
113 3         11 $self->courtesy, $initials, @$self{ qw/UI_prefix UI_surname UI_titles/ };
114             }
115              
116              
117             my %male_courtesy= (
118             mister => 'en',
119             mr => 'en',
120             sir => 'en',
121             'de heer' => 'nl',
122             mijnheer => 'nl',
123             dhr => 'nl',
124             herr => 'de',
125             );
126              
127             my %male_courtesy_default = (
128             en => 'Mr.',
129             nl => 'De heer',
130             de => 'Herr',
131             );
132              
133             my %female_courtesy = (
134             miss => 'en',
135             ms => 'en',
136             mrs => 'en',
137             madam => 'en',
138             mevr => 'nl',
139             mevrouw => 'nl',
140             frau => 'de',
141             );
142              
143             my %female_courtesy_default = (
144             en => 'Madam',
145             nl => 'Mevrouw',
146             de => 'Frau',
147             );
148              
149             sub courtesy()
150 3     3 1 6 { my $self = shift;
151 3 50       9 return $self->{UI_courtesy} if defined $self->{UI_courtesy};
152              
153 3 50       11 my $table
    100          
154             = $self->isMale ? \%male_courtesy_default
155             : $self->isFemale ? \%female_courtesy_default
156             : return undef;
157              
158 3         16 my $lang = lc $self->language;
159 3 100       33 return $table->{$lang} if exists $table->{$lang};
160              
161 1         4 $lang =~ s/\..*//; # "en_GB.utf8" --> "en-GB" and retry
162 1 50       5 return $table->{$lang} if exists $table->{$lang};
163              
164 1         6 $lang =~ s/[-_].*//; # "en_GB.utf8" --> "en" and retry
165 1         13 $table->{$lang};
166             }
167              
168              
169             # TBI: if we have a courtesy, we may detect the language.
170             # TBI: when we have a postal address, we may derive the language from
171             # the country.
172             # TBI: if we have an e-mail addres, we may derive the language from
173             # that.
174              
175 3 100   3 1 34 sub language() { $_[0]->{UI_language} || 'en' }
176              
177              
178 3     3 1 427 sub gender() { $_[0]->{UI_gender} }
179              
180              
181             sub isMale()
182 6     6 1 31 { my $self = shift;
183              
184 6 100       20 if(my $gender = $self->{UI_gender})
185 5         29 { return $gender =~ m/^[mh]/i;
186             }
187              
188 1 50       4 if(my $courtesy = $self->{UI_courtesy})
189 0         0 { $courtesy = lc $courtesy;
190 0         0 $courtesy =~ s/[^\s\w]//g;
191 0 0       0 return 1 if exists $male_courtesy{$courtesy};
192             }
193              
194 1         6 undef;
195             }
196              
197              
198             sub isFemale()
199 4     4 1 9 { my $self = shift;
200              
201 4 100       13 if(my $gender = $self->{UI_gender})
202 3         901 { return $gender =~ m/^[vf]/i;
203             }
204              
205 1 50       3 if(my $courtesy = $self->{UI_courtesy})
206 0         0 { $courtesy = lc $courtesy;
207 0         0 $courtesy =~ s/[^\s\w]//g;
208 0 0       0 return 1 if exists $female_courtesy{$courtesy};
209             }
210              
211 1         5 undef;
212             }
213              
214              
215 3     3 1 10 sub dateOfBirth() { $_[0]->{UI_birth} }
216              
217              
218             sub birth()
219 2     2 1 18 { my $birth = shift->dateOfBirth;
220 2         3 my $time;
221              
222 2 50       10 if($birth =~ m/^\s*(\d{4})[-\s]*(\d{2})[-\s]*(\d{2})\s*$/)
223             { # Pre-formatted.
224 0         0 return sprintf "%04d%02d%02d", $1, $2, $3;
225             }
226              
227 2         113 eval "require Date::Parse";
228 2 50       8 unless($@)
229 2         32 { my ($day,$month,$year) = (Date::Parse::strptime($birth))[3,4,5];
230 2 50       535 if(defined $year)
231 2 50 50     17 { return sprintf "%04d%02d%02d",
232             ($year + 1900),
233             (defined $month ? $month+1 : 0),
234             ($day || 0);
235             }
236             }
237              
238             # TBI: Other date parsers
239              
240 0         0 undef;
241             }
242              
243              
244             sub age()
245 1 50   1 1 4 { my $birth = shift->birth or return;
246              
247 1         5 my ($year, $month, $day) = $birth =~ m/^(\d{4})(\d\d)(\d\d)$/;
248 1         45 my ($today, $tomonth, $toyear) = (localtime)[3,4,5];
249 1         2 $tomonth++;
250              
251 1         4 my $age = $toyear+1900 - $year;
252 1 50 0     4 $age-- if $month > $tomonth || ($month == $tomonth && $day >= $today);
      33        
253 1         5 $age;
254             }
255              
256              
257 0     0 1   sub titles() { $_[0]->{UI_titles} }
258              
259             1;