X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=lib%2FMojoFacets%2FData.pm;h=cd78d26333143d17fdfe3cd9ce4641b5ba5049bf;hb=448b052be000b337f18e761886aca87f3fddaedf;hp=0cdb77b61ee4e9a8ce800772699297f0c10d1c49;hpb=3e1ecb5815eb15e076a82ccf9e64cd7e03011162;p=MojoFacets.git diff --git a/lib/MojoFacets/Data.pm b/lib/MojoFacets/Data.pm index 0cdb77b..cd78d26 100644 --- a/lib/MojoFacets/Data.pm +++ b/lib/MojoFacets/Data.pm @@ -5,7 +5,11 @@ use warnings; use base 'Mojolicious::Controller'; -use Data::Dump qw(dump); +#use Data::Dump qw(dump); # broken with Mojo::JSON, see https://rt.cpan.org/Public/Bug/Display.html?id=86592 +use Data::Dumper; +use subs 'dump'; +sub dump { Dumper(@_) }; + use File::Slurp; use Encode; use locale; @@ -17,11 +21,39 @@ use Text::Unaccent::PurePerl; use Digest::MD5; use Statistics::Descriptive; -use MojoFacets::Import::File; -use MojoFacets::Import::HTMLTable; -use MojoFacets::Import::CSV; -use MojoFacets::Import::CouchDB; -use MojoFacets::Import::SQL; +our $imports; +foreach my $module ( glob('lib/MojoFacets/Import/*.pm') ) { + $module =~ s{lib/(\w+)/(\w+)/(.*)\.pm}{$1::$2::$3}; + eval "use $module"; + die "$module: $!" if $!; + my ( $ext, $priority ) = $module->ext; + $imports->{$priority || 'file'}->{$ext} = $module; + warn "# import $ext $module\n"; +} + +warn "# import loaded ",dump( $imports ); + +sub import_module { + my $full_path = shift; + +# warn "# import_module $full_path\n"; + + return if $full_path =~ m/\.columns$/; + + foreach my $ext ( keys %{ $imports->{file} } ) { + if ( -f $full_path && $full_path =~ m/$ext/i ) { + return $imports->{file}->{$ext}; + last; + } + } + + foreach my $ext ( keys %{ $imports->{directory} } ) { + if ( -f $full_path && $full_path =~ m/$ext/i ) { + return $imports->{directory}->{$ext}; + last; + } + } +} our $loaded; our $filters; @@ -29,22 +61,17 @@ our $filters; sub index { my $self = shift; - my $data_dir = $self->app->home->rel_dir('data'); + my $data_dir = $self->app->home->rel_file('data'); die "no data dir $data_dir" unless -d $data_dir; my @files; my $changes; + find( sub { my $file = $File::Find::name; - if ( -f $file && $file =~ m/\.(js(on)?|txt)$/ ) { - $file =~ s/$data_dir\/*//; - push @files, $file; - } elsif ( -f $file && $file =~ m/([^\/]+)\.changes\/(\d+\.\d+.+)/ ) { + if ( -f $file && $file =~ m/([^\/]+)\.changes\/(\d+[\.,]\d+.+)/ ) { push @{ $changes->{$1} }, $2 - } elsif ( -d $file && $file =~ m/\.html$/ ) { - $file =~ s/$data_dir\/*//; - push @files, $file; - } elsif ( -f $file && $file =~ m/\.(csv|storable|couchdb|sql)$/i ) { + } elsif ( import_module( $file ) ) { $file =~ s/$data_dir\/*//; push @files, $file; } else { @@ -71,7 +98,7 @@ sub index { sub _dump_path { my ( $self, $name ) = @_; - my $dir = $self->app->home->rel_dir('data'); + my $dir = $self->app->home->rel_file('data'); $name =~ s/^$dir//; $name =~ s/\/+/_/g; return '/tmp/mojo_facets.' . $name . '.storable'; @@ -196,37 +223,8 @@ sub _load_path { } my $data; - if ( -f $full_path ) { - if ( $full_path =~ m/.storable$/ ) { # check storable first to catch files copied from /tmp/ - $data->{generated}++; - warn "open $full_path ", -s $full_path, " bytes"; - open(my $pipe, "<", $full_path) || die $!; - while ( my $o = eval { Storable::fd_retrieve $pipe } ) { - if ( exists $o->{item} ) { - # stream of storable objects - push @{ $data->{items} }, $o->{item}; - } elsif ( exists $o->{data}->{items} ) { - # /tmp/mojofacets.*.storable - $data->{items} = $o->{data}->{items}; - $data->{header} = $o->{header}; - delete $data->{generated}; - } else { - warn "SKIP ",dump($o); - } - } - close($pipe); - warn "loaded ", $#{ $data->{items} } + 1, " items from $full_path\n"; - } elsif ( $full_path =~ m/.csv/i ) { - $data = MojoFacets::Import::CSV->new( full_path => $full_path )->data; - } elsif ( $full_path =~ m/.sql/i ) { - $data = MojoFacets::Import::SQL->new( full_path => $full_path )->data; - } elsif ( $full_path =~ m/.couchdb/i ) { - $data = MojoFacets::Import::CouchDB->new( full_path => $full_path )->data; - } else { - $data = MojoFacets::Import::File->new( full_path => $full_path, path => $path )->data; - } - } elsif ( -d $full_path && $full_path =~ m/.html/ ) { - $data = MojoFacets::Import::HTMLTable->new( dir => $full_path )->data; + if ( my $module = import_module( $full_path ) ) { + $data = $module->new( full_path => $full_path )->data; } else { die "can't load $full_path"; } @@ -267,9 +265,7 @@ sub _load_path { sub load { my $self = shift; - my $path = $self->param('path') || return $self->redirect_to( '/data/index' ); - - my @paths = $self->param('paths'); + my @paths = @{ $self->every_param('paths') }; warn "# paths ", dump @paths; foreach my $p ( keys %$loaded ) { @@ -280,6 +276,8 @@ sub load { $self->_load_path( $_ ) foreach @paths; + my $path = $self->param('path') || $self->session('path') || $paths[0] || $self->redirect_to('/data/index'); + warn "# path $path\n"; $self->_load_path( $path ); @@ -359,12 +357,12 @@ sub _checked { sub _permanent_path { my $self = shift; my $path = $self->_param_or_session('path'); - $self->app->home->rel_dir('data') . '/' . join('.', $path, @_); + $self->app->home->rel_file('data') . '/' . join('.', $path, @_); } sub __unac { my $n = shift; - $n = unac_string($n); + $n = unac_string('utf-8',$n); $n =~ s/\W+/_/g; return $n; } @@ -385,7 +383,7 @@ sub _export_path { warn "no path in param or session"; return; } - my $dir = $self->app->home->rel_dir('public') . "/export/$path"; + my $dir = $self->app->home->rel_file('public') . "/export/$path"; mkpath $dir unless -e $dir; my $name = __export_path_name( $path, @_ ); my $full = $dir . '/' . $name; @@ -461,7 +459,7 @@ sub columns { sub _param_array { my ($self,$name) = @_; - my @array = $self->param($name); + my @array = @{ $self->every_param($name) }; my $path = $self->session('path'); if ( @array ) { @@ -491,8 +489,11 @@ sub _param_scalar { if ( ! defined $scalar ) { $scalar = $default; - die "no default for $name" unless defined $scalar; - $self->session($name => $scalar); + if ( defined $scalar ) { + $self->session($name => $scalar); + } else { + warn "no default for $name"; + } } warn "# _param_scalar $name ",dump $scalar; @@ -503,7 +504,7 @@ sub filter { my $self = shift; my $name = $self->param('filter_name') || die "name?"; - my @vals = $self->param('filter_vals'); + my @vals = @{ $self->every_param('filter_vals') }; $self->_remove_filter( $name ); if ( @vals ) { @@ -814,7 +815,7 @@ sub items { $code =~ s{\n+$}{\n}s; # XXX convert @row->{foo} into @{$row->{foo}} - $code =~ s|\@(row->{[^}]+})|\@{\$$1}|gs; + $code =~ s|\@(row->\{[^}]+\})|\@{\$$1}|gs; my $commit = $self->param('commit'); my $test = $self->param('test'); @@ -825,7 +826,7 @@ sub items { if ( $code && ( $test || $commit ) ) { # XXX find columns used in code snippet and show them to user my $order = 0; - foreach my $column ( $code =~ m/\$row->{([^}]+)}/g ) { + foreach my $column ( $code =~ m/\$row->\{([^}]+)\}/g ) { if ( $column =~ s/^(['"])// ) { $column =~ s/$1$//; } @@ -834,9 +835,11 @@ sub items { } } - my $code_path = $self->app->home->rel_dir('public') . "/code"; + my $code_path = $self->app->home->rel_file('public') . "/code"; if ( $commit ) { + __path_modified( $path, 'commit' ); + warn "# commit on ", $#$filtered + 1, " items:\n$code\n"; ( $key, $value, $out ) = ( 'key', 'value' ); foreach ( 0 .. $#$filtered ) { @@ -989,7 +992,7 @@ sub items { warn "# sorted_items ", $#$sorted_items + 1, " offset $offset limit $limit order $sort"; my $depends_on; - my $tmp = $code; $tmp =~ s/\$row->{(['"]?)([\w\s]+)\1/$depends_on->{$2}++/gse; + my $tmp = $code; $tmp =~ s/\$row->\{(['"]?)([\w\s]+)\1/$depends_on->{$2}++/gse; warn "# depends_on ",dump $depends_on; my $test_added = Storable::dclone $test_changed; @@ -1292,7 +1295,7 @@ sub save { sub export { my $self = shift; - my $dir = $self->app->home->rel_dir('public'); + my $dir = $self->app->home->rel_file('public'); if ( my $import = $self->param('import') ) { @@ -1332,6 +1335,14 @@ sub __loaded_paths { keys %$loaded; } +sub reload { + my $self = shift; + $self->stash( reload => 1 ); + $self->remove; +# $self->_load_path( $self->param('path') ); + $self->redirect_to('/data/load?path=' . $self->param('path') ); +} + sub remove { my $self = shift; my $path = $self->param('path'); @@ -1345,6 +1356,7 @@ sub remove { } else { warn "WARNING: $path unlink ignored"; } + return if $self->stash('reload'); return $self->redirect_to( '/data/load' ); }