App-SD
view release on metacpan or search on metacpan
lib/App/SD/Replica/trac/PushEncoder.pm view on Meta::CPAN
package App::SD::Replica::trac::PushEncoder;
use Any::Moose;
use Params::Validate;
use Time::HiRes qw/usleep/;
has sync_source =>
( isa => 'App::SD::Replica::trac',
is => 'rw');
extends 'App::SD::ForeignReplica::PushEncoder';
sub after_integrate_change {
usleep(1100); # trac only accepts one ticket update per second. Yes.
}
sub integrate_ticket_update {
my $self = shift;
my ( $change, $changeset ) = validate_pos(
@_,
{ isa => 'Prophet::Change' },
{ isa => 'Prophet::ChangeSet' }
);
# Figure out the remote site's ticket ID for this change's record
my $remote_ticket_id =
$self->sync_source->remote_id_for_uuid( $change->record_uuid );
my $ticket = Net::Trac::Ticket->new( connection => $self->sync_source->trac);
$ticket->load($remote_ticket_id) or
die "couldn't load remote track ticket $remote_ticket_id\n";
$ticket->update( %{ $self->_recode_props_for_integrate($change) } ) or
die "couldn't update remote track ticket $remote_ticket_id\n";
return $remote_ticket_id;
}
sub integrate_ticket_create {
my $self = shift;
my ( $change, $changeset ) = validate_pos(
@_,
{ isa => 'Prophet::Change' },
{ isa => 'Prophet::ChangeSet' }
);
# Build up a ticket object out of all the record's attributes
my $ticket = Net::Trac::Ticket->new(
connection => $self->sync_source->trac);
my $id = $ticket->create( %{ $self->_recode_props_for_integrate($change) });
return $id
}
sub integrate_comment {
my $self = shift;
my ($change, $changeset) = validate_pos( @_,
{ isa => 'Prophet::Change' }, {isa => 'Prophet::ChangeSet'} );
# Figure out the remote site's ticket ID for this change's record
my %props = map { $_->name => $_->new_value } $change->prop_changes;
my $ticket_id = $self->sync_source->remote_id_for_uuid( $props{'ticket'} );
my $ticket = Net::Trac::Ticket->new( connection => $self->sync_source->trac);
$ticket->load($ticket_id);
$ticket->comment( $props{content});
return $ticket_id;
}
sub integrate_attachment {
my ($self, $change, $changeset ) = validate_pos( @_,
{ isa => 'App::SD::Replica::trac::PushEncoder'},
{ isa => 'Prophet::Change' },
{ isa => 'Prophet::ChangeSet' });
my %props = map { $_->name => $_->new_value } $change->prop_changes;
my $ticket_id = $self->sync_source->remote_id_for_uuid( $props{'ticket'} );
my $ticket = Net::Trac::Ticket->new( connection => $self->sync_source->trac);
$ticket->load($ticket_id);
my $tempdir = File::Temp::tempdir( CLEANUP => 1 );
my $file = File::Spec->catfile( $tempdir, ( $props{'name'} || 'unnamed' ) );
open my $fh, '>', $file or die $!;
print $fh $props{content};
close $fh;
$ticket->attach( file => $file) || die "Could not attach file for ticket $ticket_id";
return $ticket_id;
}
sub _recode_props_for_integrate {
my $self = shift;
my ($change) = validate_pos( @_, { isa => 'Prophet::Change' } );
my %props = map { $_->name => $_->new_value } $change->prop_changes;
my %attr;
for my $key ( keys %props ) {
next unless ( $key =~ /^(summary|status|owner)/ );
if ( $key eq 'status' ) {
my $active_statuses =
$self->sync_source->database_settings->{active_statuses};
if ( grep { $props{$key} eq $_ } @$active_statuses, 'closed' ) {
$attr{$key} = $props{$key};
}
else {
$attr{$key} = 'closed';
$attr{resolution} = $props{$key};
}
}
else {
$attr{$key} = $props{$key};
}
}
return \%attr;
}
__PACKAGE__->meta->make_immutable;
no Any::Moose;
1;
( run in 0.500 second using v1.01-cache-2.11-cpan-39bf76dae61 )