package HTML::FormFu::Element::reCAPTCHA; use Moose; extends 'HTML::FormFu::Element::Multi'; use HTML::FormFu::Util qw( process_attrs _merge_hashes ); use Captcha::reCAPTCHA; use Clone (); use Scalar::Util qw( blessed ); has public_key => ( is => 'rw', traits => ['Chained'] ); has private_key => ( is => 'rw', traits => ['Chained'] ); has ssl => ( is => 'rw', default => 'auto', lazy => 1, traits => ['Chained'], ); has recaptcha_options => ( is => 'rw', default => sub { {} }, lazy => 1, traits => ['Chained'], ); after BUILD => sub { my $self = shift; $self->filename('recaptcha'); $self->constraint_args( { type => 'reCAPTCHA' } ); $self->constraint( $self->constraint_args ); return; }; sub constraint_args { my ( $self, $args ) = @_; $self->{constraint_args} ||= {}; if ( @_ > 1 ) { $self->{constraint_args} = _merge_hashes( $self->{constraint_args}, $args, ); my $constraint = $self->get_constraint( { type => 'reCAPTCHA' } ); if ( defined $constraint ) { $constraint->populate( $self->{constraint_args} ); } } return $self->{constraint_args}; } sub render_data_non_recursive { my $self = shift; my $pubkey = $self->public_key || $ENV{RECAPTCHA_PUBLIC_KEY}; my $error = undef; # prefer catalyst methods to %ENV vars my $query = $self->form->query; my $catalyst_compatible = blessed($query) && $query->can('secure') && $query->can('address'); my $use_ssl = $self->ssl eq 'auto' ? $catalyst_compatible : $query->secure ? $ENV{HTTPS} : $self->ssl; my $recaptcha_options = $self->recaptcha_options; my $recaptcha = Captcha::reCAPTCHA->new; my $recaptcha_html = $recaptcha->get_html( $pubkey, $error, $use_ssl, $recaptcha_options, ); my $render = $self->SUPER::render_data_non_recursive( { recaptcha_html => $recaptcha_html, @_ ? %{ $_[0] } : () } ); return $render; } sub string { my ( $self, $args ) = @_; $args ||= {}; my $render = exists $args->{render_data} ? $args->{render_data} : $self->render_data_non_recursive; # field wrapper template - start my $html = $self->_string_field_start($render); # reaptcha template $html .= sprintf "\n", process_attrs( $render->{attributes} ); $html .= $render->{recaptcha_html}; $html .= ""; # field wrapper template - end $html .= $self->_string_field_end($render); return $html; } sub clone { my $self = shift; my $clone = $self->SUPER::clone(@_); $clone->recaptcha_options( Clone::clone( $self->recaptcha_options ) ); return $clone; } __PACKAGE__->meta->make_immutable; 1; __END__ =head1 NAME HTML::FormFu::Element::reCAPTCHA - "Are you human" tester! =head1 SYNOPSIS --- elements: - type: reCAPTCHA name: recaptcha public_key: $recaptcha_net_public_key private_key: $recaptcha_net_private_key =head1 DESCRIPTION A wrapper around L. The reCAPTCHA fields aren't added to the form as "real" FormFu fields - so the values are never available via L, etc. You can check that the reCAPTCHA verified correctly, by the usual methods: L or L This element automatically adds L to itself - you should never add it yourself. Although this is a subclass of L, you should not call C or C to try to add other fields - consider the reCAPTCHA element a black box. =head1 METHODS =head2 name Required. Although not visibly used for anything, you must give this field a name for the L to work correctly. =head2 public_key Arguments: $public_key Required. Obtained from L. =head2 private_key Arguments: $private_key Required. Obtained from L. =head2 ssl Default Value: 'auto'. Valid Values: '1', '0' or 'auto' Whether to load the recaptcha.net files via C or C. If set to C, it will use C urls if the current page is running under ssl, otherwise it will use C urls. =head2 recaptcha_options Arguments: \%options See the recaptcha.net API for details of valid options. recaptcha_options: lang: de theme: white =head2 constraint_args Arguments: \%constraint_args Options that will be passed to the L that is automatically added for you. --- elements: - type: reCAPTCHA name: recaptcha constraint_args: message: 'custom error message' =head1 SEE ALSO Is a sub-class of, and inherits methods from L, L, L, L L =head1 AUTHOR Carl Franks, C =head1 LICENSE This library is free software, you can redistribute it and/or modify it under the same terms as Perl itself. =cut