App-PhotoDB
view release on metacpan or search on metacpan
lib/App/PhotoDB/funcs.pm view on Meta::CPAN
package App::PhotoDB::funcs;
=head1 Functions
This package provides reusable functions to be consumed by the rest of the PhotoDB application.
Note that some of these functions take traditional argument lists which must
be in order, while the more complex functions take a hashref of arguments
which can be passed in any order. Examples of each function are given.
=cut
use strict;
use warnings;
use experimental 'smartmatch';
use DBI;
use DBD::mysql;
use SQL::Abstract;
use Exporter qw(import);
use Config::IniHash;
use YAML;
use Image::ExifTool;
use Term::ReadLine;
use Term::ReadLine::Perl;
use File::Basename;
use Time::Piece;
use Text::TabularDisplay;
our @EXPORT_OK = qw(prompt db updaterecord deleterecord newrecord notimplemented nocommand nosubcommand listchoices lookupval lookuplist today validate ini printlist round pad lookupcol thin resolvenegid chooseneg annotatefilm keyword parselensmodel ...
=head2 prompt
Prompt the user for an arbitrary value. Has various options for data validation and customisation of the prompt.
If the provided input fails validation, or if a blank string is given when required=1 then the prompt is repeated.
=head4 Usage
my $camera = &prompt({prompt=>'What model is the camera?', required=>1, default=>$$defaults{model}, type=>'text'});
would give a prompt like
What model is the camera? (text) []:
=head4 Arguments
=item * C<$default> Default value that will be used if no input from user. Default empty string.
=item * C<$prompt> Prompt message for the user
=item * C<$type> Data type that this input expects, out of C<text>, C<integer>, C<boolean>, C<date>, C<decimal>, C<time>
=item * C<$required> Whether this input is required, or whether it can return an empty value. Default C<0>
=item * C<$showtype> Whether to show the user what data type is expected, in parentheses. Default C<1>
=item * C<$showdefault> Whether to show the user what the default value is set to, in square brackets. Default C<1>
=item * C<$char> Character to print at the end of the prompt. Defaults to C<:>
=head4 Returns
The value the user provided
=cut
sub prompt {
# Pass in a hashref of arguments
my $href = shift;
# Unpack the hashref and set default values
my $default = $href->{default} // ''; # Default value that will be used if no input from user
my $prompt = $href->{prompt}; # Prompt message for the user
my $type = $href->{type} || 'text'; # Data type that this input expects, out of text, integer, boolean, date, decimal, time
my $required = $href->{required} // 0; # Whether this input is required, or whether it can return an empty value
my $showtype = $href->{showtype} // 1; # Whether to show the user what data type is expected
my $showdefault = $href->{showdefault} // 1; # Whether to show the user what the default value is
my $char = $href->{char} // ':'; # Character to print at the end of the prompt
die "Must provide value for \$prompt\n" if !($prompt);
# Rewrite binary bools as strings
if ($type eq 'boolean' && $default ne '') {
$default = &printbool($default);
}
# Assemble prompt text
my $msg = $prompt;
$msg .= " ($type)" if $showtype;
$msg .= " [$default]" if $showdefault;
$msg .= "$char ";
# Create terminal handler
my $term = $App::PhotoDB::term;
my $rv;
# Repeatedly prompt user until we get a response of the correct type
do {
my $input = $term->readline($msg);
# Use default value if user gave blank input
$rv = ($input eq "") ? $default:$input;
# Prompt again if the input doesn't pass validation, or if it's a required field that was blank
} while (!&validate({val => $rv, type => $type}) || ($rv eq '' && $required == 1));
# Rewrite friendly bools and then return the value
if ($type eq 'boolean') {
return friendlybool($rv);
} else {
return $rv;
}
}
=head2 term
Set up a terminal object for use by PhotoDB
=head4 Usage
my $term = &term;
=head4 Arguments
None
=head4 Returns
Terminal object
=cut
sub term {
my $term = Term::ReadLine->new('PhotoDB');
$term->ornaments(0);
$term->MinLine(7);
return $term;
}
=head2 validate
Validate that a value is a certain data type
=head4 Usage
my $result = &validate({val => 'hello', type => 'text'});
=head4 Arguments
=item * C<$val> The value to be validated
=item * C<$type> Data type to validate as, out of C<text>, C<integer>, C<boolean>, C<date>, C<decimal>, C<time>. Defaults to C<text>.
=head4 Returns
Returns C<1> if the value passes validation as the requested type, and C<0> if it doesn't.
=cut
sub validate {
# Pass in a hashref of arguments
my $href = shift;
# Unpack the hashref and set default values
my $val = $href->{val}; # The value to be validated
my $type = $href->{type} || 'text'; # Data type to validate as, out of text, integer, boolean, date, decimal, time
die "Must provide value for \$val\n" if !defined($val);
# Empty string always passes validation
if ($val eq '') {
return 1;
}
elsif ($type eq 'boolean') {
if ($val =~ m/^(y(es)?|no?|false|true|1|0)$/i) {
return 1;
} else {
return 0;
}
} elsif ($type eq 'integer') {
if ($val =~ m/^-?\d+$/) {
return 1;
} else {
return 0;
}
} elsif ($type eq 'text') {
if ($val =~ m/^.+$/) {
return 1;
} else {
return 0;
}
} elsif ($type eq 'date') {
if ($val =~ m/^\d{4}-\d{2}-\d{2}$/) {
return 1;
} else {
return 0;
}
} elsif ($type eq 'decimal') {
if ($val =~ m/^\d+(\.\d+)?$/) {
return 1;
} else {
return 0;
}
} elsif ($type eq 'time') {
if ($val =~ m/^\d\d?:\d\d?:\d\d?$/) {
return 1;
} else {
return 0;
}
} else {
die "$type is not a valid data type\n";
}
}
=head2 ini
Find PhotoDB config ini file
=head4 Usage
my $ini = &ini;
=head4 Arguments
None
( run in 1.138 second using v1.01-cache-2.11-cpan-39bf76dae61 )