NAME
WebService::Redmine - Wrapper for RedMine REST API (http://www.redmine.org/projects/redmine/wiki/Rest_api).
SYNOPSIS
use WebService::Redmine;
my $redminer = WebService::Redmine->new(
host => 'example.com/redmine',
key => 'xxx',
);
# password-based auth is also supported:
#my $redminer = WebService::Redmine->new(
# host => 'example.com/redmine',
# user => 'redminer',
# pass => 'p@s$w0rD',
#);
my $project = $redminer->createProject({ project => {
identifier => 'my-project',
name => 'My Project',
description => 'My project, created with *WebService::Redmine*',
}});
if (!$project) {
say STDERR 'Error(s) creating project: ', join("\n", map { $_ } @{ $redminer->errorDetails->{errors} });
exit 1;
}
my $project_id = $project->{project}{id};
$redminer->updateProject($project_id, { project => {
parent_id => 42, # Make a project with numeric ID 42 parent for $project_id
inherit_members => 1, # Inherit all members and their permissions from the parent
}});
my $issue = $redminer->createIssue({ issue => {
project_id => $project_id,
subject => 'Test issue for WebService::Redmine',
description => 'Issue description',
}});
$redminer->deleteProject($project_id);
DESCRIPTION
This module is a client for RedMine REST API. Please note that although RedMine API is designed to support both JSON and XML, this module is JSON only.
METHODS NAMING AND OTHER CALL CONVENTIONS
All methods are dynamically converted to actual HTTP requests using following conventions.
Getting a Collection of Objects
$redminer->projects; # ->users, ->issues, ->timeEntries ...
$redminer->getProjects; # ->getUsers, ->getIssues, ->getTimeEntries ...
$redminer->readProjects; # ->readUsers, ->readIssues, ->readTimeEntries ...
# Second page when displaying 10 items per page:
$redminer->projects({ offset => 9, limit => 10 });
# Filtering issues:
$redminer->issues({ project_id => 42, assigned_to_id => 'me' });
Getting an Object
$redminer->project(1); # ->user(1), ->issue(1), ->timeEntry(1) ...
$redminer->getProject(1); # ->getUser(1), ->getIssue(1), ->getTimeEntry(1) ...
$redminer->readProject(1); # ->readUsers(1), ->readIssue(1), ->readTimeEntry(1) ...
# Showing an object with additional metadata:
$redminer->issue(1, { include => 'relations,changesets' });
Creating an Object
$redminer->createProject({
# ...
}); # ->createUser, ->createIssue, ->createTimeEntry ...
Updating an Object
$redminer->updateProject(1, {
# ...
}); # ->updateUser(...), ->updateIssue(...), ->updateTimeEntry(...) ...
Deleting an Object
$redminer->deleteProject(1); # ->deleteUser(1), ->deleteIssue(1), ->deleteTimeEntry(1) ...
Objects Belonging to Other Objects
#
# Example for project membership(s)
#
my $project_id = 42;
my $membership_id = 42;
# Listing *project* memberships and creating a membership within a *project*
# require identifying a project and thus have to be spelled like this:
$redminer->projectMemberships($project_id, { limit => 50 });
$redminer->createProjectMembership($project_id, { ... });
# Viewing/Updating/Deleting a membership is performed directly by its ID, thus:
my $membership = $redminer->membership($membership_id);
$redminer->updateMembership($membership_id, { ... });
$redminer->deleteMembership($membership_id);
Complex Object Names
Such complex names as TimeEntry
which should be dispatched to time_entries
are recognized and thus can be spelled in CamelCase (see examples above). If this is not the case, please report bugs.
Return Values
All successfull calls return hash references. For update*
and delete*
calls hash references are empty.
If a call fails, undef
is returned. In this case detailed error information can be retrieved using errorDetails
method:
if (!$redminer->deleteIssue(42)) {
my $details = $redminer->errorDetails;
# Process $details here...
}
METHODS
new
my $redminer = WebService::Redmine->new(%options);
Following options are recognized:
host: RedMine host. Beside host name, may include port, path and/or URL scheme (
http
is used by default).key: API key. For details, please refer to http://www.redmine.org/projects/redmine/wiki/Rest_api#Authentication
user, pass: User name and password for password-based authentication
work_as: User login for impersonation. For details, please refer to http://www.redmine.org/projects/redmine/wiki/Rest_api#User-Impersonation.
no_wrapper_object: Automatically add/remove wrapper object for data. See below.
no_wrapper_object
By default RedMine API requires you to wrap you object data:
my $project = $redminer->createProject({
project => {
identifier => 'some-id',
name => 'Some Name',
}
});
# $project contains something like
# { project => { id => 42, identifier => 'some-id', name => 'Some Name' ... } }
By default this module follows this convention. However, if you turn on the no_wrapper_object
flag
my $redminer = WebService::Redmine->new(
host => 'example.com/redmine',
key => 'xxx',
no_wrapper_object => 1,
);
you can skip "wrapping" object data, which results in simpler data structures:
my $project = $redminer->createProject({
identifier => 'some-id',
name => 'Some Name',
});
# $project contains something like
# { id => 42, identifier => 'some-id', name => 'Some Name' ... }
Please note that wrapping can be skipped only while operating on single objects, i.e. this flag is honored for create*
and update*
requests as well as for get
ting individual objects. This flag is ignored for delete*
calls and calls like issues
.
error
Error during the last call. This is an empty string for successfull calls, otherwise it contains an HTTP status line.
If the call failed before sending an actual request (e.g. method name could not be dispatched into an HTTP request), contains description of the client error.
errorDetails
Contains detailed error messages from the last call. This is an empty hash reference for successfull calls, otherwise please see http://www.redmine.org/projects/redmine/wiki/Rest_api#Validation-errors.
If the call failed before sending an actual request (e.g. method name could not be dispatched into an HTTP request), return value is
{
client_error => 1
}
SEE ALSO
Redmine::API (https://metacpan.org/pod/Redmine::API). Major differences between this module and Redmine::API are:
Dependencies. Redmine::API depends on Moo and REST::Client which in turn depends on LWP::UserAgent, URI and possibly others. WebService::Redmine uses pure Perl OOP and depends directly on LWP::UserAgent and URI.
Call conventions. Although both modules use dynamic dispatching for building actual HTTP requests, they do it in a different manner. In particular, WebService::Redmine tries to dispatch a single method name without using chains of interrim objects as Redmine::API does.
Fork this project on GitHub: https://github.com/igelhaus/redminer
AUTHOR
Anton Soldatov, <igelhaus@gmail.com>
COPYRIGHT AND LICENSE
Copyright (C) 2014 by Anton Soldatov
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.10.0 or, at your option, any later version of Perl 5 you may have available.