Group
Extension

WebService-JotForm/lib/WebService/JotForm.pm

package WebService::JotForm;

use strict;
use warnings FATAL => 'all';
use Moo;
use JSON::MaybeXS;
use LWP::UserAgent;
use URI::Escape qw(uri_escape);
use Carp qw(croak);

=head1 NAME

WebService::JotForm - Perl interface to JotForm's API -- currently only the read operations are fully supported.

Support for create, update, and delete operations are beginning to be added in this and future releases.

=head1 VERSION

Version 0.020

=head1 SYNOPSIS
	
	my $jotform = WebService::JotForm->new( apiKey => $apiKey);

	my $forms = $jotform->get_user_forms();

	# Show form details associated with our account

	foreach my $form (@{$forms->{content}}) {
		print "Form $form->{id} - $form->{title} - $form->{url} - $form->{last_submission}\n";
	}

	my $form_id = "42";

	my $submissions = $jotform->get_form_submissions($form_id);

	# Loop through all submissions to our form and print out submission created_at and ip

	foreach my $sub(@{$submissions->{content}}) {
		print "$sub->{created_at} $sub->{ip}\n";
	}

=head1 DESCRIPTION

This is a thin wrapper around the JotForm API.  All results are what's returned by the JotForm API, 
with the JSON being converted into Perl data structures.

You need a JotForm API key to use this module.  The easiest way to get an apiKey is just to
login to L<JotForm|http://jotform.com/> and then go to L<http://www.jotform.com/myaccount/api>.
From there create a token (or use an existing one).  You can set whether it's a read-only or full-access token.

More information on tokens is available in the L<JotForm API Documentation|http://api.jotform.com/docs/>

=cut

our $VERSION = '0.020';

has 'apiKey'  		=> ( is => 'ro', required => 1);
has 'apiBase' 		=> ( is => 'ro', default => 'https://api.jotform.com');
has 'apiVersion'	=> ( is => 'ro', default => 'v1');
has 'agent'   		=> ( is => 'rw'); # Must act like LWP::UserAgent

my $json = JSON::MaybeXS->new;

sub BUILD {
	my ($self) = @_;
	
	if(not $self->agent) {
		$self->agent(LWP::UserAgent->new(agent => "perl/$], WebService::JotForm/" . $self->VERSION));
	}

	my $resp = $self->agent->get($self->apiBase . "/" . $self->apiVersion . "/user?apiKey=" . $self->apiKey);

	return;
}

=head1 METHODS

=head2 new(%params)

Create a new WebService::JotForm object with hash parameter

	my $jotform = WebService::JotForm->new(
		apiKey => '1234567890abcdef'
	);

Accepts the following parameters:

=over 4

=item * apiKey

Required parameter.  JotForm apiKey

=item * apiBase

Optional parameter - defaults to: 'https://api.jotform.com'

=item * apiVersion

Optional parameter - defaults to 'v1'

=item * agent

Agent that acts like LWP::UserAgent used for making requests -- module defaults to creating its own if none is provide

=back

=cut

=head2 get_user()

	$jotform->get_user();

Get user account details for this JotForm user. Including user account type, avatar URL, name, email, website URL and account limits.

	my $user = $jotform->get_user();

=cut


sub get_user {
	my $self = shift;
	return $self->_get("user");
}

=head2 get_user_usage()

	$jotform->get_user_usage();

Get number of form submissions received this month. Also, get number of SSL form submissions, payment form submissions and upload space used by user.

=cut

sub get_user_usage {
	my $self = shift;
	return $self->_get("user/usage");
}


=head2 get_user_submissions($params)

	$jotform->get_user_submissions($params);

Get a list of all submissions for all forms on this account. The answers array has the submission data. Created_at is the date of the submission.
Optional paramaters

=over 4

=item offset

	Example: 20

=item limit

	Example: 20

=item filter

	Example: {"new":"1"} or {"created_at:gt":"2013-01-01 00:00:00"}

=item orderby

	Example: created_at

=back

=cut

sub get_user_submissions {
	my ($self, $params) = @_;
	$params ||= {};
	return $self->_get("user/submissions", $params);
}

=head2 get_user_subusers()

	$jotform->get_user_subusers();

Get a list of sub users for this accounts and list of forms and form folders with access privileges.
=cut

sub get_user_subusers {
	my $self = shift;
	return $self->_get("user/subusers");
}

=head2 get_user_folders()

	$jotform->get_user_folders();

Get a list of form folders for this account. Returns name of the folder and owner of the folder for shared folders.

=cut

sub get_user_folders {
	my $self = shift;
	return $self->_get("user/folders");
}

=head2 get_user_reports()
	
	$jotform->get_user_reports();

List of URLS for reports in this account. Includes reports for all of the forms. ie. Excel, CSV, printable charts, embeddable HTML tables.

=cut
sub get_user_reports {
	my $self = shift;
	return $self->_get("user/reports");
}

=head2 register_user()

	$jotform->register_user($params);

	$jotform->register_user({ username => $username, password => $pw, email => $email });

Register a new JotForm account with username, password and email

=cut

sub register_user {
	my $self = shift;
	my $params = shift;
	$params ||= {};
	return $self->_post("user/register", $params);
}

=head2 login_user()

	$jotform->register_user($params);

	$jotform->register_user({ username => $username, password => $pw });

Login user with given credentials - accepts username, password, and optionally appName, and access

=cut



sub login_user {
	my $self = shift;
	my $params = shift;
	$params ||= {};
	return $self->_post("user/login", $params);
}

=head2 get_user_logout()

	$jotform->get_user_logout();

Logout user

=cut
sub get_user_logout {
	my $self = shift;
	return $self->_get("user/logout");
}

=head2 get_user_settings()

	$jotform->get_user_settings();

Get user's time zone and language.

=cut
sub get_user_settings {
	my $self = shift;
	return $self->_get("user/settings");
}

=head2 update_user_settings()

	$jotform->update_user_settings($params);
	
	$jotform->update_user_settings({ email => $updated_email });

Update user's settings like time zone and language.  Optional fields: name, email, website, time_zone, company, securityQuestion, securityAnswer, industry

=cut
sub update_user_settings {
	my $self = shift;
	my $params = shift;
	$params ||= {};
	
	return $self->_post("user/settings", $params);
}








=head2 get_user_history()

	$jotform->get_user_history();

User activity log about things like forms created/modified/deleted, account logins and other operations.


=cut

sub get_user_history {
	my ($self, $params) = @_;
	return $self->_get("user/history", $params);
}

=head2 get_user_forms($params)

	$jotform->get_user_forms($params);


Get a list of forms for this account. Includes basic details such as title of the form, when it was created, number of new and total submissions.

TODO -- document additionsal optional params

=cut

sub get_user_forms {
	my ($self, $params) = @_;
	return $self->_get("user/forms", $params);
}

=head2 create_forms($params);

	$jotform->create_forms($params);

Add new forms with questions, properties and email settings.


=cut

sub create_forms {
	my $self = shift;
	my $params = shift;
	$params ||= {};

	return $self->_post("user/forms", $params);
}

=head2 create_form($params);

	$jotform->create_form($params);

Add new form with questions, properties and email settings.


=cut

sub create_form {
	my $self = shift;
	my $params = shift;
	$params ||= {};

	return $self->_post("/form", $params);
}


=head2 get_form($id)

	$jotform->get_form($id);

Get basic information about a form. Use get_form_questions($id) to get the list of questions.

=cut

sub get_form {
	my ($self, $form_id) = @_;
	croak "No form id provided to get_form" if !$form_id;
	return $self->_get("form/$form_id");
}

=head2 clone_form($id)
	
	$jotform->clone_form($id);

Clone a given form
=cut

sub clone_form {
	my ($self, $form_id) = @_;
	croak "No form id provided to clone_form" if !$form_id;
	return $self->_post("/form/$form_id/clone");
}

=head2 create_form_question($id, $question)

	$jotform->create_form_question($id, $question)

	Add a new question to a form, takes an id for the form as a parameter, and then a hasref of key/values for the question fields

=cut

sub create_form_question {
	my ($self, $form_id, $question) = @_;
	
	croak "No form id provided to create_form_question" if !$form_id;
	
	$question ||= {};
	my $params = {};

	foreach (keys %$question) {
		$params->{"question[$_]"} = $question->{$_};
	}

	return $self->_post("/form/$form_id/questions", $params);
}


=head2 edit_form_question($form_id, $qid, $question);

	$jotform->edit_form_question($form_id, $qid, $question);

Edit a question property or add a new one. Form questions might have various properties. Examples: Is it required? Are there any validations such as 'numeric only'?

=cut

sub edit_form_question { 
	my ($self, $form_id, $qid, $question) = @_;
	croak "edit_form_question requires both a form_id and question id" if !$form_id && $qid;

	$question ||= {};
	my $params = {};
	
	foreach (keys %$question) {
		$params->{"question[$_]"} = $question->{$_};
	}
	
	return $self->_post("form/$form_id/question/$qid", $params);
}

=head2 set_form_properties($form_id, $params)

	$jotform->set_form_properties($form_id, $params);
	
	$jotform->set_form_properties($form_id, { formWidth => 555 });

Add or edit properties of a specific form

=cut 
sub set_form_properties {
	my($self, $form_id, $params) = @_;
	croak "set_form_properties requires a form_id" if !$form_id;
	$params ||= {};

	my $props = {};

	foreach(keys %$params) {
		$props->{"properties[$_]"} = $params->{$_};
	}
	return $self->_post("/form/$form_id/properties", $props);
}

=head2 get_form_questions($id)
	
	$jotform->get_form_questions($id);

	Get a list of all questions on a form. Type describes question field type. Order is the question order in the form. Text field is the question label.

=cut

sub get_form_questions {
	my ($self, $form_id) = @_;
	croak "No form id provided to get_form_questions" if !$form_id;
	return $self->_get("form/$form_id/questions");
}

=head2 get_form_question($form_id, $qid)
	
	$jotform->get_form_question($form_id, $qid);

	Get Details About a Question

=cut

sub get_form_question {
	my ($self, $form_id, $qid) = @_;
	croak "Get_form_question requires both a form_id and question id" if !$form_id && $qid;
	return $self->_get("form/$form_id/question/$qid");
}

=head2 get_form_properties($id,$key)

	$jotform->get_form_properties($id);
	
	$jotform->get_form_properties($id,$key);

	Get a list of all properties on a form.

=cut

sub get_form_properties {
	my ($self, $form_id, $key) = @_;
	croak "Get_form_properties requires a form_id" if !$form_id;
	
	if($key) {
		return $self->_get("form/$form_id/properties/$key"); 
	} else {
		return $self->_get("form/$form_id/properties"); 
	}
}

=head2 get_form_reports($id)

	$jotform->getFormReports($id);

	Get all the reports of a specific form.

=cut

sub get_form_reports {
	my ($self, $form_id) = @_;
	croak "No form id provided to get_form_reports" if !$form_id;
	return $self->_get("form/$form_id/reports"); 
}

=head2 create_form_report($form_id, { title => $title, list_type => $list_type });

	$jotform->create_form_report($form_id, { title => $title, list_type => "csv" });
	$jotform->create_form_report($form_id, { title => $title, list_type => "csv", "fields=ip,dt,1" });

	Create new report of a form with intended fields, type and title.

=cut 

sub create_form_report{
	my($self, $form_id, $params) = @_;
	$params ||= {};
	croak "No form id provided to create_form_report" if !$form_id;
	croak "title and list_type required parameters to create_form_report" if !$params->{title} || !$params->{list_type};

	return $self->_post("form/$form_id/reports", $params);
}

=head2 get_form_files($id)

	$jotform->get_form_files($id);

	List of files uploaded on a form. Here is how you can access a particular file: http://www.jotform.com/uploads/{username}/{form-id}/{submission-id}/{file-name}. Size and file type is also included.

=cut


sub get_form_files {
	my ($self, $form_id) = @_;
	croak "No form id provided to get_form_files" if !$form_id;
	return $self->_get("form/$form_id/files"); 
}

=head2 get_form_webhooks($id)

	$jotform->get_form_webhooks($id)

	Webhooks can be used to send form submission data as an instant notification. Returns list of webhooks for this form.

=cut


sub get_form_webhooks {
	my ($self, $form_id) = @_;
	croak "No form id provided to get_form_webhooks" if !$form_id;
	return $self->_get("form/$form_id/webhooks"); 
}

=head2 create_form_webhook($form_id, $url)

	$jotform->create_form_webhook($form_id, $url);

	Webhooks can be used to send form submission data as an instant notification.  Add a new webhook that receives submission data for a given form

=cut

sub create_form_webhook {
	my($self, $form_id, $url) = @_;
	croak "No form id provided to create_form_webhook" if !$form_id;
	croak "No url provided to create_form_webhook" if !$url;

	return $self->_post("/form/$form_id/webhooks", { webhookURL => $url });
}

=head2 get_form_submissions($id)

	$jotform->get_form_submissions($id, $params);

	List of form reponses. Fields array has the submitted data. Created_at is the date of the submission.

=cut


sub get_form_submissions {
	my ($self, $form_id, $params) = @_;
	croak "No form id provided to get_form_submissions" if !$form_id;
	return $self->_get("form/$form_id/submissions"); 
}

=head2 get_submission($id)

	$jotform->get_submission($id);

	Similar to get_form_submissions($id) But only get a single submission, based on submission id

=cut


sub get_submission {
	my ($self, $sub_id) = @_;
	croak "No submission id provided to get_submission" if !$sub_id;
	return $self->_get("submission/$sub_id");
}

=head2 get_report($id)

	$jotform->get_report($id);

	Get more information about a data report.
=cut


sub get_report {
	my ($self, $rep_id) = @_;
	croak "No report id provided to get_report" if !$rep_id;
	return $self->_get("report/$rep_id"); 
}

=head2 get_folder($id)

	$jotform->get_folder($id)

	Get a list of forms in a folder, and other details about the form such as folder color.
=cut


sub get_folder {
	my ($self, $fol_id) = @_;
	croak "No folder id provided to get_folder" if !$fol_id;
	return $self->_get("folder/$fol_id"); 
}

=head2 get_system_plan($plan_name)

	$jotform->get_system_plan($plan_name)

	Get limit and prices of a plan.
=cut


sub get_system_plan {
	my ($self, $plan_name) = @_;
	croak "No plan name provided to get_system_plan" if !$plan_name;
	return $self->_get("system/plan/$plan_name"); 

}


sub _get {
	my ($self, $path, $params) = @_;
	my $url = $self->_gen_request_url($path, $params);
	my $resp = $self->agent->get($url);

	unless ($resp->is_success) {
		croak "Failed to fetch $url - ".$resp->status_line;
	}
	return $json->decode($resp->content);
}

sub _post {
	my ($self, $path, $params) = @_;
	$params ||= {};
	my $url = join("/", $self->apiBase, $self->apiVersion, $path) . "?apiKey=" .$self->apiKey;
	my $resp = $self->agent->post($url, $params);
	unless ($resp->is_success) {
		croak "Failed to fetch $url - ".$resp->status_line;
	}
	return $json->decode($resp->content);
}

sub _gen_request_url {
	my ($self, $path, $params) = @_;
	my $url = join("/", $self->apiBase, $self->apiVersion, $path) . "?apiKey=" .$self->apiKey;
	foreach my $param (keys %$params) {
		$url .= "&".uri_escape($param) ."=". uri_escape($params->{$param});
	}
	return $url;
} 


=head1 AUTHOR

Tim Vroom, C<< <vroom at blockstackers.com> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-webservice-jotform at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=WebService-JotForm>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.




=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc WebService::JotForm


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker (report bugs here)

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=WebService-JotForm>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/WebService-JotForm>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/WebService-JotForm>

=item * Search CPAN

L<http://search.cpan.org/dist/WebService-JotForm/>

=back


=head1 ACKNOWLEDGEMENTS


=head1 LICENSE AND COPYRIGHT

Copyright 2014 Tim Vroom.

This program is free software; you can redistribute it and/or modify it
under the terms of the the Artistic License (2.0). You may obtain a
copy of the full license at:

L<http://www.perlfoundation.org/artistic_license_2_0>

Any use, modification, and distribution of the Standard or Modified
Versions is governed by this Artistic License. By using, modifying or
distributing the Package, you accept this license. Do not use, modify,
or distribute the Package, if you do not accept this license.

If your Modified Version has been derived from a Modified Version made
by someone other than you, you are nevertheless required to ensure that
your Modified Version complies with the requirements of this license.

This license does not grant you the right to use any trademark, service
mark, tradename, or logo of the Copyright Holder.

This license includes the non-exclusive, worldwide, free-of-charge
patent license to make, have made, use, offer to sell, sell, import and
otherwise transfer the Package with respect to any patent claims
licensable by the Copyright Holder that are necessarily infringed by the
Package. If you institute patent litigation (including a cross-claim or
counterclaim) against any party alleging that the Package constitutes
direct or contributory patent infringement, then this Artistic License
to you shall terminate on the date that such litigation is filed.

Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


=cut

1; # End of WebService::JotForm


Powered by Groonga
Maintained by Kenichi Ishigaki <ishigaki@cpan.org>. If you find anything, submit it on GitHub.