From: Robert 'phaylon' Sedlacek Date: Mon, 23 Jul 2012 21:49:08 +0000 (+0000) Subject: mediawiki merging, row identification, tests X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=21e7cc982388da1a487ade2274bc0bae52944286;p=scpubgit%2FSystem-Introspector-Report.git mediawiki merging, row identification, tests --- diff --git a/lib/System/Introspector/Report/Builder/Packages/Apt/ByHost.pm b/lib/System/Introspector/Report/Builder/Packages/Apt/ByHost.pm index 5c9a088..9398c98 100644 --- a/lib/System/Introspector/Report/Builder/Packages/Apt/ByHost.pm +++ b/lib/System/Introspector/Report/Builder/Packages/Apt/ByHost.pm @@ -40,6 +40,7 @@ sub render_reports { columns => \@columns, title => "Packages on $remote", id => ['packages-apt-by-remote', $remote], + rowid => [qw( package )], meta => { remote => $remote }, rows => [map { my $package = $_; diff --git a/lib/System/Introspector/Report/Builder/Packages/Apt/ByPackage.pm b/lib/System/Introspector/Report/Builder/Packages/Apt/ByPackage.pm index 12c8b80..8d03722 100644 --- a/lib/System/Introspector/Report/Builder/Packages/Apt/ByPackage.pm +++ b/lib/System/Introspector/Report/Builder/Packages/Apt/ByPackage.pm @@ -43,6 +43,7 @@ sub render_reports { columns => \@columns, title => "$package Installations", id => ['packages-apt-by-package', $package], + rowid => [qw( remote )], meta => { package => $package }, rows => [ map { my $remote = $_; diff --git a/lib/System/Introspector/Report/Builder/Perls.pm b/lib/System/Introspector/Report/Builder/Perls.pm index 041e33a..ce3e03c 100644 --- a/lib/System/Introspector/Report/Builder/Perls.pm +++ b/lib/System/Introspector/Report/Builder/Perls.pm @@ -47,6 +47,7 @@ sub render_reports { return +{ title => 'Perl Installations', id => 'perls', + rowid => [qw( remote location )], columns => [ { key => 'remote', label => 'Remote' }, { key => 'hostname', label => 'Hostname' }, diff --git a/lib/System/Introspector/Report/Publish/MediaWiki.pm b/lib/System/Introspector/Report/Publish/MediaWiki.pm index 839a2e3..edbead7 100644 --- a/lib/System/Introspector/Report/Publish/MediaWiki.pm +++ b/lib/System/Introspector/Report/Publish/MediaWiki.pm @@ -1,6 +1,5 @@ package System::Introspector::Report::Publish::MediaWiki; use Moo; -use aliased 'System::Introspector::Report::Publish::MediaWiki::Producer'; use aliased 'System::Introspector::Report::Publish::MediaWiki::Connection'; has page_options => ( @@ -9,10 +8,6 @@ has page_options => ( init_arg => 'page', ); -has producer => (is => 'lazy', handles => { - _render_page => 'render', -}); - has connection => (is => 'ro', lazy => 1, builder => 1, handles => { get_page => 'get', put_page => 'put', @@ -48,11 +43,11 @@ sub _sort_reports { } sub _publish_page { - my ($self, $reports, $page, $options) = @_; + my ($self, $reports, $page_name, $options) = @_; my $sorted = $self->_sort_reports($reports, $options->{report} || []); - print $self->_render_page($sorted); -# print $self->render_report($_) -# for @$sorted; + my $page = $self->get_page($page_name); + $page->update($sorted); + $self->put_page($page); return 1; } diff --git a/lib/System/Introspector/Report/Publish/MediaWiki/Connection.pm b/lib/System/Introspector/Report/Publish/MediaWiki/Connection.pm index e0f19d6..8871f64 100644 --- a/lib/System/Introspector/Report/Publish/MediaWiki/Connection.pm +++ b/lib/System/Introspector/Report/Publish/MediaWiki/Connection.pm @@ -1,8 +1,12 @@ package System::Introspector::Report::Publish::MediaWiki::Connection; use Moo; -sub get { } +sub get { + my ($self, $page_name) = @_; +} -sub put { } +sub put { + my ($self, $page) = @_; +} 1; diff --git a/lib/System/Introspector/Report/Publish/MediaWiki/Page.pm b/lib/System/Introspector/Report/Publish/MediaWiki/Page.pm index 0244eef..b39b6c7 100644 --- a/lib/System/Introspector/Report/Publish/MediaWiki/Page.pm +++ b/lib/System/Introspector/Report/Publish/MediaWiki/Page.pm @@ -1,11 +1,24 @@ package System::Introspector::Report::Publish::MediaWiki::Page; use Moo; +use aliased 'System::Introspector::Report::Publish::MediaWiki::Parser'; +use aliased 'System::Introspector::Report::Publish::MediaWiki::Producer'; +use aliased 'System::Introspector::Report::Updater'; + +has name => (is => 'ro', required => 1); has timestamp => (is => 'ro', required => 1); -has content => (is => 'ro', required => 1); +has content => (is => 'rwp', required => 1); + +my $_producer = Producer->new; +my $_parser = Parser->new; +my $_updater = Updater->new; sub update { my ($self, $update_stream) = @_; + my $original_stream = $_parser->parse($self->content); + my $merged_stream = $_updater->merge($original_stream, $update_stream); + $self->_set_content($_producer->render($merged_stream)); + return 1; } 1; diff --git a/lib/System/Introspector/Report/Publish/MediaWiki/Producer.pm b/lib/System/Introspector/Report/Publish/MediaWiki/Producer.pm index fa43a43..f6c252c 100644 --- a/lib/System/Introspector/Report/Publish/MediaWiki/Producer.pm +++ b/lib/System/Introspector/Report/Publish/MediaWiki/Producer.pm @@ -4,9 +4,15 @@ use HTML::Zoom; sub render { my ($self, $stream) = @_; - return join "\n", map { + return $self->_clear_body(join "\n", map { ref($_) ? $self->_render_table($_) : $_; - } @$stream; + } @$stream); +} + +sub _clear_body { + my ($self, $string) = @_; + $string =~ s{\n\n+}{\n\n}g; + return $string; } sub _wrap { @@ -23,7 +29,6 @@ sub _render_table { my $id = $report->{id}; my $str_id = ref($id) ? join(':', @$id) : $id; my $markup = $self->_load_markup; - $markup = $self->_apply_identity($markup, $report); $markup = $self->_apply_table_head($markup, $report); $markup = $self->_apply_table_body($markup, $report); my $description = $report->{description} || ['']; @@ -39,16 +44,6 @@ sub _render_title { return sprintf '== %s ==', $report->{title}; } -sub _apply_identity { - my ($self, $markup, $report) = @_; - my $id = $report->{id}; - return $markup - ->select('table') - ->set_attribute(id => 'si-id-' . join '__', - ref($id) ? @$id : $id, - ); -} - sub _apply_table_body { my ($self, $markup, $report) = @_; my $index = 0; @@ -77,9 +72,15 @@ sub _apply_table_body { }; }, }); - }); + })->memoize; } +my $_trim = sub { + my $string = shift; + $string =~ s{(?:^\s+|\s+$)}{}g; + return $string; +}; + sub _apply_table_head { my ($self, $markup, $report) = @_; my @cols = @{$report->{columns}}; @@ -87,23 +88,27 @@ sub _apply_table_head { ->repeat('th', [map { my $col_idx = $_; my $col = $cols[$_]; + my $label = $col->{label}; sub { $_->apply_if($col->{key} !~ m{^__}, sub { $_->add_to_attribute('th', class => 'si-colhead-' . $col->{key}); }) - ->replace_content('th', $col->{label}) + ->replace_content('th', defined($label) ? $label->$_trim : 'Unnamed') ->apply_if($col_idx != $#cols, sub { $_->add_after('th', "\n "); }); }; } 0 .. $#cols ]) + ->memoize; } +my $_template = do { + local $/; + scalar ; +}; + sub _load_markup { - return HTML::Zoom->from_html(do { - local $/; - scalar ; - }); + return HTML::Zoom->from_html($_template); } 1; diff --git a/lib/System/Introspector/Report/Updater.pm b/lib/System/Introspector/Report/Updater.pm new file mode 100644 index 0000000..a2c96d7 --- /dev/null +++ b/lib/System/Introspector/Report/Updater.pm @@ -0,0 +1,102 @@ +package System::Introspector::Report::Updater; +use Moo; + +my $_flatten_id = sub { + my $value = $_[0]; + return ref($value) ? join("\0", @$value) : $value; +}; + +sub merge { + my ($self, $original, $update) = @_; + my $old = $self->_map_reports_by_id($original); + my $new = $self->_map_reports_by_id($update); + my %add = map { ($_ => $new->{$_}) } grep { not($old->{$_}) } keys %$new; + return $self->_weave_additional([ map { + (ref($_) eq 'HASH') ? do { + my $report = $_; + my $id = $report->{id}->$_flatten_id; + $new->{$id} + ? $self->_merge_reports($report, $new->{$id}) + : $report; + } : $_; + } @$original ], \%add, $self->_calc_sequence($update)); +} + +sub _weave_additional { + my ($self, $stream, $additional, $sequence) = @_; + my @items = @$stream; + if (my $begin = $sequence->{''}) { + if (my $item = delete $additional->{$begin}) { + unshift @items, $item; + } + } + my @done; + while (defined( my $item = shift @items )) { + if (ref($item) eq 'HASH') { + my $item_id = $item->{id}->$_flatten_id; + if (my $after = $sequence->{$item_id}) { + if (my $insert = $additional->{$after}) { + unshift @items, $insert; + } + } + } + push @done, $item; + } + return \@done; +} + +sub _calc_sequence { + my ($self, $stream) = @_; + my @ids = map { + $_->{id}->$_flatten_id; + } grep { + ref($_) eq 'HASH'; + } @$stream; + my %sequence; + for my $index (0 .. $#ids) { + $sequence{ $index ? $ids[$index - 1] : '' } = $ids[$index]; + } + return \%sequence; +} + +sub _merge_reports { + my ($self, $original, $update) = @_; + my $rowid = $update->{rowid}; + my $ident = sub { + my $row = shift; + join "\0", map $row->{$_}, @$rowid; + }; + my %current; + $current{$_->$ident} = $_ + for @{$original->{rows}}; + return { + title => $update->{title}, + id => $update->{id}, + rowid => $update->{rowid}, + meta => $update->{meta} || {}, + columns => [ + @{$update->{columns}}, + (grep { + $_->{key} =~ m{^__}; + } @{$original->{columns}}), + ], + rows => [ map { + my $row = $_; + my $id = $row->$ident; + +{ %{$current{$id}||{}}, %$row }; + } @{$update->{rows}} ], + }; +} + +sub _map_reports_by_id { + my ($self, $stream) = @_; + return { + map { + ($_->{id}->$_flatten_id, $_); + } grep { + ref($_) eq 'HASH'; + } @$stream, + }; +} + +1; diff --git a/t/data/foo.txt b/t/data/foo.txt new file mode 100644 index 0000000..2f3a68b --- /dev/null +++ b/t/data/foo.txt @@ -0,0 +1,63 @@ +Previous text. + + +== Foo X == + + +User description. + + + + + + + + + + + + + + + + + + + +
BarBaz + Qux +
231421171
232422172173
+ + +More text. + + +== Foo Y == + + +User description. + + + + + + + + + + + + + + + + + + + +
BarBaz + Qux +
231421171
232422172173
+ + +End Text diff --git a/t/data/result/foo.txt b/t/data/result/foo.txt new file mode 100644 index 0000000..a75fa43 --- /dev/null +++ b/t/data/result/foo.txt @@ -0,0 +1,82 @@ +Previous text. + + +== Foo A == + + + + + + + + + + + + + + + + + + + + + + + + + + +
BarBazQuxUnnamed
231421171
232884172173
332784
+ + + +== Foo B == + + + + + + + + + + + + + + + +
BarBaz
231421
332784
+ + +More text. + + +== Foo C == + + + + + + + + + + + + + + + + + + + + + +
New BarNew BazQuxUnnamed
232884172173
332784
+ + +End Text \ No newline at end of file diff --git a/t/publish_mediawiki.t b/t/publish_mediawiki.t new file mode 100644 index 0000000..8d5f7d3 --- /dev/null +++ b/t/publish_mediawiki.t @@ -0,0 +1,94 @@ +use strictures 1; +use Test::More; +use IO::All; +use FindBin; + +use aliased 'System::Introspector::Report::Publish::MediaWiki'; + +my %result; + +do { + package TestConnection; + use Moo; + use IO::All; + use aliased 'System::Introspector::Report::Publish::MediaWiki::Page'; + + sub get { + my ($self, $name) = @_; + return Page->new( + name => $name, + timestamp => 23, + content => scalar(io("$FindBin::Bin/data/$name.txt")->slurp), + ); + } + + sub put { + my ($self, $page) = @_; + $result{$page->name} = $page->content; + } +}; + +my $conn = TestConnection->new; +my $wiki = MediaWiki->new( + connection => $conn, + page => { + foo => { + report => ['foo:*'], + }, + }, +); + +ok $wiki->publish([ + { id => [qw( foo a )], + title => "Foo A", + rowid => ['bar'], + columns => [ + { key => 'bar', label => 'Bar' }, + { key => 'baz', label => 'Baz' }, + ], + rows => [ + { bar => 231, baz => 421 }, + { bar => 232, baz => 884 }, + { bar => 332, baz => 784 }, + ], + }, + { id => [qw( foo b )], + title => "Foo B", + rowid => ['bar'], + columns => [ + { key => 'bar', label => 'Bar' }, + { key => 'baz', label => 'Baz' }, + ], + rows => [ + { bar => 231, baz => 421 }, + { bar => 332, baz => 784 }, + ], + }, + { id => [qw( foo c )], + title => "Foo C", + rowid => ['bar'], + columns => [ + { key => 'bar', label => 'New Bar' }, + { key => 'baz', label => 'New Baz' }, + ], + rows => [ + { bar => 232, baz => 884 }, + { bar => 332, baz => 784 }, + ], + }, +]), 'publish ok'; + +my $_despace = sub { + my $string = shift; + $string =~ s{[\s\n]+}{}g; + return $string; +}; + +## uncomment to regenerate result file +# do { no warnings; $result{foo} > io("$FindBin::Bin/data/result/foo.txt") }; + +is $result{foo}->$_despace, + scalar(io("$FindBin::Bin/data/result/foo.txt")->slurp)->$_despace, + 'resulting page looks correct'; + +done_testing;