File Coverage

blib/lib/Magrathea/API/Emergency.pm
Criterion Covered Total %
statement 29 114 25.4
branch 0 38 0.0
condition 0 8 0.0
subroutine 10 22 45.4
pod 8 10 80.0
total 47 192 24.4


line stmt bran cond sub pod time code
1             package Magrathea::API::Emergency;
2              
3 1     1   7 use strict;
  1         2  
  1         31  
4 1     1   6 use warnings;
  1         2  
  1         25  
5 1     1   11 use 5.10.0;
  1         4  
6 1     1   5 use utf8;
  1         2  
  1         5  
7              
8 1     1   28 use Scalar::Util qw{ dualvar };
  1         2  
  1         56  
9 1     1   6 use Attribute::Boolean;
  1         3  
  1         5  
10 1     1   88 use Carp;
  1         3  
  1         60  
11 1     1   619 use Data::Dumper;
  1         6670  
  1         70  
12              
13 1     1   421 use Magrathea::API::Abbreviation qw{abbreviate};
  1         3  
  1         156  
14              
15 1     1   9 use constant POSTCODE_RE => qr/^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$/;
  1         2  
  1         1176  
16              
17             =encoding utf8
18              
19             =head2 NAME
20              
21             Magrathea::API::Emergency - Access to the Magrathea 999 Interface
22              
23             =head2 EXAMPLE
24              
25             use Magrathea::API;
26             my $mt = new Magrathea::API($username, $password);
27             my $emerg = $mt->emergency_info($phone_number);
28             # Get the status, print it and check it
29             my $status = $emerg->status;
30             say "Status is: $status" if $status != 0;
31             # Print the thoroughfare, update it and print it again
32             say "Thoroughfare is currently: ", $emerg->thoroughfare;
33             $emerg->thoroughfare("He is a justice of the peace and in accommodation.");
34             say "Thoroughfare is now ", $emerg->thoroughfare;
35             # prints: He is a J.P. & in Accom.
36             # Update the changes
37             $emerge->update
38              
39             =cut
40              
41             =head2 DESCRIPTION
42              
43             This module represents the
44             L.
45              
46             It should not be constructed by user code; it is only avalible through
47             the main L code as follows:
48              
49             my $mt = new Magrathea::API($username, $password);
50             my $emerg = $mt->emergency_info($phone_number);
51              
52             =cut
53              
54             #################################################################
55             ##
56             ## Local Prototyped Functions
57             ##
58             #################################################################
59              
60              
61             #################################################################
62             ##
63             ## Private Instance Functions
64             ##
65             #################################################################
66              
67             sub sendline
68             {
69 0     0 0   my $self = shift;
70 0   0       my $message = shift // '';
71 0 0 0       say ">> $message" if $self->{debug} && $message;
72 0 0         $self->{telnet}->print($message) if $message;
73 0           my $response = $self->{telnet}->getline;
74 0           chomp $response;
75 0           my ($val, $msg) = $response =~ /^(\d)\s+(.*)/;
76 0 0         croak qq(Unknown response: "$response") unless defined $val;
77 0 0         say "<<$val $msg" if $self->{debug};
78 0           return dualvar $val, $msg;
79             }
80              
81             #################################################################
82             ##
83             ## Class Functions
84             ##
85             #################################################################
86              
87             =head2 METHODS
88              
89             =cut
90              
91             sub new
92             {
93 0     0 0   my $class = shift;
94 0           my $api = shift;
95 0           my $number = shift;
96 0           local $_;
97 0 0         croak "This package must not be called directly" unless ref $api eq 'Magrathea::API';
98             my $self = {
99             telnet => $api->{telnet},
100             debug => $api->{params}{debug},
101 0           number => $number,
102             };
103 0           bless $self, $class;
104 0           my %info;
105 0           my $response = $self->DATA;
106 0           while ($response == 0) {
107 0           chomp $response;
108 0           my ($key, $value) = split / /, $response, 2;
109 0           $info{lc $key} = $value;
110 0           $response = $self->sendline;
111             }
112 0           $self->{info} = \%info;
113 0           my $exists : Boolean = keys(%info) > 0;
114 0           $self->{exists} = $exists;
115 0           $self;
116             }
117              
118             =head2 create
119              
120             This is used the first time a number is put onto the database and
121             then only if the owner changes. It needs to be followed by an
122             L after entering all the data.
123              
124             =cut
125              
126             sub create
127             {
128 0     0 1   my $self = shift;
129 0           my $result = $self->CREATE;
130 0 0         croak "$result" unless $result == 0;
131 0           $self->{exists} = true;
132             }
133              
134             =head3 number
135              
136             This returns the number currently being worked on as a L.
137              
138             =cut
139              
140             sub number
141             {
142 0     0 1   my $self = shift;
143 0           return $self->{number};
144             }
145              
146             =head3 exists
147              
148             This is a boolean which can be tested to find out if the number
149             already exists on the Magrathea database. It is set during
150             the call to L and updated after
151             a successful call to L.
152              
153             =cut
154              
155             sub exists
156             {
157 0     0 1   my $self = shift;
158 0           return $self->{exists};
159             }
160              
161             =head3 info
162              
163             This returns all the fields in a hash or as a pointer to a hash
164             depending on list or scalar context. The fields are as documented for
165             methods below.
166              
167             =cut
168              
169             sub info
170             {
171 0     0 1   my $self = shift;
172 0           my %info = %{$self->{info}}; # Copy it so it can't be changed
  0            
173 0 0         return wantarray ? %info : \%info;
174             }
175              
176             =head3 status
177              
178             This returns a single value for status. The valuse returned can be
179             used as a string and returns the message or as a number which returns
180             the status code. The possible statuses are curently as below but they
181             are returned from Magrathea so the
182             L<999 Appendix|https://www.magrathea-telecom.co.uk/assets/Client-Downloads/Magrathea-NTSAPI-999-Appendix.pdf>
183             should be treated as authoritive.
184              
185             =over
186              
187             =item 0 Accepted
188              
189             =item 1 Info received
190              
191             =item 2 Info awaiting further validation
192              
193             =item 3 Info submitted
194              
195             =item 6 Submitted – Awaiting manual processing
196              
197             =item 8 Rejected
198              
199             =item 9 No record found
200              
201             =back
202              
203             =cut
204              
205             sub status
206             {
207 0     0 1   my $self = shift;
208 0           my $status = eval {
209 0           $self->STATUS;
210             };
211 0           return $status;
212             }
213              
214              
215             =head3 title
216              
217             =head3 forename
218              
219             =head3 name
220              
221             =head3 honours
222              
223             =head3 bussuffix
224              
225             =head3 premises
226              
227             =head3 thoroughfare
228              
229             =head3 locality
230              
231             =head3 postcode
232              
233             The above methods will get or set a field in the 999 record.
234              
235             Abbreviations are substituted and they are then checked for
236             maximum length. These routines will croak if an invalid length
237             (or invalid postcode) is passed
238              
239             To get the data, simply call the method, to change the data, pass
240             it as a parameter.
241              
242             Nothing is sent to Magrathea until L is called.
243              
244             =cut
245              
246             sub postcode
247             {
248 0     0 1   my $self = shift;
249 0           my $postcode = shift;
250 0 0         if ($postcode) {
251 0 0         if ($postcode ne "") {
252 0 0         croak "Invalid postcode" unless $postcode =~ POSTCODE_RE;
253             }
254 0           $self->{info}{postcode} = $postcode;
255 0           $self->POSTCODE($postcode);
256             }
257 0           return $self->{info}{postcode};
258             }
259              
260             =head3 ported
261              
262             This is a boolean value showing whether or not the number has been
263             ported in from another provider. It will always evaluate to C
264             though unless set by this method as there is no way to store the
265             information on the Magrathea database.
266              
267              
268             $emerge->ported(true); # Assuming true is set to 1
269             my $ported = $emerg->ported;
270              
271             =cut
272              
273             sub ported
274             {
275 0     0 1   my $self = shift;
276 0           my $value : Boolean = shift;
277 0 0         $self->{ported} = $value if defined $value;
278 0           $value = $self->{ported};
279 0           return $value;
280             }
281              
282             =head3 update
283              
284             This will take the current data and send it to Magrathea. The possible
285             valid responses are C (0 in numeric context) or
286             C (1 in numeric context).
287              
288             If Magrathea's validation fails, the update will croak.
289              
290             =cut
291              
292             sub update
293             {
294 0     0 1   my $self = shift;
295 0           my $info = $self->info;
296 0 0 0       unless ($self->postcode and $self->name) {
297 0           croak "Name and postcode are mandatory";
298             }
299 0           my $response = $self->VALIDATE;
300 0 0         croak "Update failed: $response" if $response >= 2;
301 0           return $response;
302             }
303              
304             sub AUTOLOAD
305             {
306 0     0     my $self = shift;
307 0           my $commands = qr{^(?:
308             CREATE|VALIDATE|STATUS|DATA|
309             TITLE|FORENAME|NAME|HONOURS|BUSSUFFIX|
310             PREMISES|THOROUGHFARE|LOCALITY|POSTCODE
311             )$}x;
312 0           my %fields = (
313             title => 20,
314             forename => 20,
315             name => 50,
316             honours => 30,
317             bussuffix => 50,
318             premises => 60,
319             thoroughfare => 55,
320             locality => 30
321             );
322 0           (my $name = our $AUTOLOAD) =~ s/.*://;
323 0 0         if ($name =~ /^[A-Z]+$/) {
324 0 0         croak "Unknown Command: $name" unless $name =~ $commands;
325 0           my $number = $self->number->packed;
326 0 0         $number =~ s/^0/P/ if $self->ported;
327 0           my @cmd = ('INFO', $number, 999, $name, @_);
328 0           return $self->sendline("@cmd");
329             }
330             else {
331 0           my $value = shift;
332 0 0         croak "Unknown method: $name" unless exists $fields{$name};
333 0 0         if (defined $value) {
334 0           my $abbr = abbreviate $value;
335 0           my $len = length $abbr;
336 0           my $max = $fields{$name};
337 0 0         croak "$abbr ($len charancters abbreviated)\n" .
338             "is longer than the max. length of $max" .
339             "for field $name" if $len > $max;
340 0           $self->{info}{$name} = $abbr;
341 0           my $cmd = uc $name;
342 0           $self->$cmd($abbr);
343             }
344 0           return $self->{info}{$name};
345             }
346             }
347              
348       0     sub DESTROY {
349             # Avoid AUTOLOAD
350             }
351              
352             =head2 AUTHOR
353              
354             Cliff Stanford, Ecliff@may.beE
355              
356             =head2 ISSUES
357              
358             Please open any issues with this code on the
359             L.
360              
361             =head2 COPYRIGHT AND LICENCE
362              
363             Copyright (C) 2012 - 2018 by Cliff Stanford
364              
365             This library is free software; you can redistribute it and/or modify
366             it under the same terms as Perl itself, either Perl version 5.10.1 or,
367             at your option, any later version of Perl 5 you may have available.
368              
369             =cut
370              
371             1;