view lib/Benzin/Bugzilla/XmlWriter.pm @ 12:52b34ea50eff default tip

sync: work time projection doesn't seem to be working anyway
author cin
date Sun, 13 Sep 2015 19:37:16 +0300
parents 4eb9fdf4efa9
children
line wrap: on
line source

package Benzin::Bugzilla::XmlWriter;

our %Transform = (
	'Benzin::Bugzilla::Bug'        => 'WriteBug',
	'Benzin::Bugzilla::BugComment' => 'WriteBugComment',
	'HASH'                         => 'WriteHash',
	'DateTime'                     => 'WriteTJ3DateTime',
	-plain                         => 'WriteValue',
	-default                       => 'WriteValue'
);

use IMPL::lang qw(coarsen coarsen_dt is);
use IMPL::Const qw(:prop);
use IMPL::declare {
	require => {
		XMLWriter  => 'XML::Writer',
		Bug        => 'Benzin::Bugzilla::Bug',
		BugComment => 'Benzin::Bugzilla::BugComment',
		Duration   => 'DateTime::Duration',
	},
	base => [
		'IMPL::Transform' => sub { %Transform }
	],
	props => [
		_writer        => PROP_RW,
		timereports    => PROP_RW,
		timeresolution => PROP_RW
	]
};

use fields qw(_writer);

sub CTOR {
	my SELF $this = shift;

	$this->_writer( XMLWriter->new(@_) );
}

sub WriteBugList {
	my SELF $this = shift;
	my $bugs = shift || [];
	my $writer = $this->_writer;

	$writer->xmlDecl("UTF-8");
	$writer->startTag("bugzilla");

	my %timesheets;

	foreach my $bug (@$bugs) {
		$writer->startTag("bug");
		$this->WriteBug($bug);

		if ( $this->timereports ) {
			my $time = $bug->GetTimeReports( $this->timeresolution );

			my $prevReportDate = $bug->{creation_time};

			foreach my $item ( @{ $time->{report} || [] } ) {
				$timesheets{ $item->{who} }{bugs}{ $bug->{id} }{work} +=
				  $item->{work_time};
				$timesheets{ $item->{who} }{bugs}{ $bug->{id} }{remaining} =
				  $time->{remaining};

				$timesheets{ $item->{who} }{start} = $prevReportDate
				  unless $timesheets{ $item->{who} }{start}
				  and $timesheets{ $item->{who} }{start} <= $prevReportDate;
				$timesheets{ $item->{who} }{end} = $item->{when}
				  unless $timesheets{ $item->{who} }{end}
				  and $timesheets{ $item->{who} }{end} >= $item->{when};

				$prevReportDate = $item->{when};
			}

			$this->WriteElement( 'time', $time );
		}

		$writer->endTag();
	}

	while ( my ( $who, $sheet ) = each %timesheets ) {

		$writer->startTag(
			'timesheet',
			resource => $who,
			start    => $this->FormatTJ3DateTime( $sheet->{start} ),
			end      => $this->FormatTJ3DateTime( $sheet->{end} )
		);

		while ( my ( $bug, $info ) = each %{ $sheet->{bugs} } ) {
			$writer->startTag( 'bug', id => $bug );
			$this->WriteElement( 'work', $info->{work} );
			$this->WriteElement( 'remaining', $info->{remaining} );
			$writer->endTag();
		}

		$writer->endTag();
	}

	$writer->endTag();

}

sub WriteBug {
	my SELF $this = shift;
	my $value     = shift;
	my $writer    = $this->_writer;

	foreach my $field ( @{ Bug->BUG_FIELDS } ) {
		next unless $value->{$field};
		$this->WriteElement( $field, $value->{$field} );
	}
}

sub WriteBugComment {
	my SELF $this = shift;
	my $value     = shift;
	my $writer    = $this->_writer;

	foreach my $field ( @{ BugComment->COMMENT_FIELDS } ) {
		next unless $value->{$field};
		$this->WriteElement( $field, $value->{$field} );
	}
}

sub WriteHash {
	my SELF $this = shift;
	my $value = shift;

	while ( my ( $k, $v ) = each %$value ) {
		$this->WriteElement( $k, $v );
	}
}

sub WriteElement {
	my SELF $this = shift;
	my ( $name, $data ) = @_;
	my $writer = $this->_writer;

	my @values =
	     ref($data)
	  && ref($data) eq 'ARRAY'
	  ? @{$data}
	  : $data;

	foreach my $v (@values) {
		$writer->startTag($name);
		$this->Transform($v);
		$writer->endTag;
	}
}

sub WriteValue {
	my SELF $this = shift;
	my $value = shift;

	$this->_writer->characters($value) if defined $value;
}

sub WriteTJ3DateTime {
	my SELF $this = shift;
	my $value = shift;

	$this->_writer->characters( $this->FormatTJ3DateTime($value) )
	  if defined $value;
}

sub FormatTJ3DateTime {
	my SELF $this = shift;
	my $value = shift;

	my $duration =
	  is( $this->timeresolution, Duration )
	  ? $this->timeresolution
	  : Duration->new( %{ $this->timeresolution } );

	return coarsen_dt( $value, $duration )->strftime('%F-%T');
}

1;