properly handle unicode in upper/lowercase types
[gitmo/MooseX-Types-Common.git] / lib / MooseX / Types / Common / String.pm
index 708f666..218b826 100644 (file)
@@ -1,12 +1,20 @@
 package MooseX::Types::Common::String;
+# ABSTRACT:  Commonly used string types
 
 use strict;
 use warnings;
 
-our $VERSION = '0.001000';
-
 use MooseX::Types -declare => [
-  qw(SimpleStr NonEmptySimpleStr Password StrongPassword NonEmptyStr)
+  qw(SimpleStr
+     NonEmptySimpleStr
+     NumericCode
+     LowerCaseSimpleStr
+     UpperCaseSimpleStr
+     Password
+     StrongPassword
+     NonEmptyStr
+     LowerCaseStr
+     UpperCaseStr)
 ];
 
 use MooseX::Types::Moose qw/Str/;
@@ -14,35 +22,143 @@ use MooseX::Types::Moose qw/Str/;
 subtype SimpleStr,
   as Str,
   where { (length($_) <= 255) && ($_ !~ m/\n/) },
-  message { "Must be a single line of no more than 255 chars" };
+  message { "Must be a single line of no more than 255 chars" },
+    ( $Moose::VERSION >= 2.0200
+        ? inline_as {
+            $_[0]->parent()->_inline_check( $_[1] ) . ' && '
+                . qq{ ( (length($_[1]) <= 255) && ($_[1] !~ m/\n/) ) };
+        }
+        : ()
+    );
 
 subtype NonEmptySimpleStr,
   as SimpleStr,
   where { length($_) > 0 },
-  message { "Must be a non-empty single line of no more than 255 chars" };
+  message { "Must be a non-empty single line of no more than 255 chars" },
+    ( $Moose::VERSION >= 2.0200
+        ? inline_as {
+            $_[0]->parent()->_inline_check( $_[1] ) . ' && '
+                . qq{ (length($_[1]) > 0) };
+        }
+        : ()
+    );
+
+subtype NumericCode,
+  as NonEmptySimpleStr,
+  where { $_ =~ m/^[0-9]+$/ },
+  message {
+    'Must be a non-empty single line of no more than 255 chars that consists '
+       . 'of numeric characters only'
+  };
+
+coerce NumericCode,
+  from NonEmptySimpleStr,
+  via { my $code = $_; $code =~ s/[[:punct:]]//g; return $code };
 
-# XXX duplicating constraint msges since moose only uses last message
 subtype Password,
   as NonEmptySimpleStr,
   where { length($_) > 3 },
-  message { "Must be between 4 and 255 chars" };
+  message { "Must be between 4 and 255 chars" },
+    ( $Moose::VERSION >= 2.0200
+        ? inline_as {
+            $_[0]->parent()->_inline_check( $_[1] ) . ' && '
+                . qq{ (length($_[1]) > 3) };
+        }
+        : ()
+    );
 
 subtype StrongPassword,
   as Password,
   where { (length($_) > 7) && (m/[^a-zA-Z]/) },
-  message {"Must be between 8 and 255 chars, and contain a non-alpha char" };
+  message {"Must be between 8 and 255 chars, and contain a non-alpha char" },
+    ( $Moose::VERSION >= 2.0200
+        ? inline_as {
+            $_[0]->parent()->_inline_check( $_[1] ) . ' && '
+                . qq{ ( (length($_[1]) > 7) && ($_[1] =~ m/[^a-zA-Z]/) ) };
+        }
+        : ()
+    );
 
 subtype NonEmptyStr,
   as Str,
   where { length($_) > 0 },
-  message { "Must not be empty" };
-
+  message { "Must not be empty" },
+    ( $Moose::VERSION >= 2.0200
+        ? inline_as {
+            $_[0]->parent()->_inline_check( $_[1] ) . ' && '
+                . qq{ (length($_[1]) > 0) };
+        }
+        : ()
+    );
+
+subtype LowerCaseStr,
+  as NonEmptyStr,
+  where { !/\p{Upper}/ms },
+  message { "Must not contain upper case letters" },
+    ( $Moose::VERSION >= 2.0200
+        ? inline_as {
+            $_[0]->parent()->_inline_check( $_[1] ) . ' && '
+                . qq{ ( $_[1] !~ /\\p{Upper}/ms ) };
+        }
+        : ()
+    );
+
+coerce LowerCaseStr,
+  from NonEmptyStr,
+  via { lc };
+
+subtype UpperCaseStr,
+  as NonEmptyStr,
+  where { !/\p{Lower}/ms },
+  message { "Must not contain lower case letters" },
+    ( $Moose::VERSION >= 2.0200
+        ? inline_as {
+            $_[0]->parent()->_inline_check( $_[1] ) . ' && '
+                . qq{ ( $_[1] !~ /\\p{Lower}/ms ) };
+        }
+        : ()
+    );
+
+coerce UpperCaseStr,
+  from NonEmptyStr,
+  via { uc };
+
+subtype LowerCaseSimpleStr,
+  as NonEmptySimpleStr,
+  where { !/\p{Upper}/ },
+  message { "Must not contain upper case letters" },
+    ( $Moose::VERSION >= 2.0200
+        ? inline_as {
+            $_[0]->parent()->_inline_check( $_[1] ) . ' && '
+                . qq{ ( $_[1] !~ /\\p{Upper}/ ) };
+        }
+        : ()
+    );
+
+coerce LowerCaseSimpleStr,
+  from NonEmptySimpleStr,
+  via { lc };
+
+subtype UpperCaseSimpleStr,
+  as NonEmptySimpleStr,
+  where { !/\p{Lower}/ },
+  message { "Must not contain lower case letters" },
+    ( $Moose::VERSION >= 2.0200
+        ? inline_as {
+            $_[0]->parent()->_inline_check( $_[1] ) . ' && '
+                . qq{ ( $_[1] !~ /\\p{Lower}/ ) };
+        }
+        : ()
+    );
+
+coerce UpperCaseSimpleStr,
+  from NonEmptySimpleStr,
+  via { uc };
 
 1;
+__END__
 
-=head1 NAME
-
-MooseX::Types::Common::String
+=pod
 
 =head1 SYNOPSIS
 
@@ -60,19 +176,48 @@ default.
 
 =over
 
-=item * SimpleStr
+=item * C<SimpleStr>
+
+A C<Str> with no new-line characters.
+
+=item * C<NonEmptySimpleStr>
+
+A C<Str> with no new-line characters and length > 0
 
-A Str with no new-line characters.
+=item * C<LowerCaseSimpleStr>
 
-=item * NonEmptySimpleStr
+A C<Str> with no new-line characters, length > 0 and no uppercase characters
+A coercion exists via C<lc> from C<NonEmptySimpleStr>
 
-Does what it says on the tin.
+=item * C<UpperCaseSimpleStr>
 
-=item * Password
+A C<Str> with no new-line characters, length > 0 and no lowercase characters
+A coercion exists via C<uc> from C<NonEmptySimpleStr>
 
-=item * StrongPassword
+=item * C<Password>
 
-=item * NonEmptyStr
+=item * C<StrongPassword>
+
+=item * C<NonEmptyStr>
+
+A C<Str> with length > 0
+
+=item * C<LowerCaseStr>
+
+A C<Str> with length > 0 and no uppercase characters.
+A coercion exists via C<lc> from C<NonEmptyStr>
+
+=item * C<UpperCaseStr>
+
+A C<Str> with length > 0 and no lowercase characters.
+A coercion exists via C<uc> from C<NonEmptyStr>
+
+=item * C<NumericCode>
+
+A C<Str> with no new-line characters that consists of only Numeric characters.
+Examples include, Social Security Numbers, Personal Identification Numbers, Postal Codes, HTTP Status
+Codes, etc. Supports attempting to coerce from a string that has punctuation
+in it ( e.g credit card number 4111-1111-1111-1111 ).
 
 =back
 
@@ -84,8 +229,4 @@ Does what it says on the tin.
 
 =back
 
-=head1 AUTHORS
-
-Please see:: L<MooseX::Types::Common>
-
 =cut