You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
6.6 KiB
228 lines
6.6 KiB
package NGCP::Panel::Utils::RedisLocationResultSet;
|
|
|
|
use Moose;
|
|
|
|
use TryCatch;
|
|
use NGCP::Panel::Utils::RedisLocationResultSource;
|
|
|
|
use Data::Dumper;
|
|
|
|
has _c => (
|
|
is => 'ro',
|
|
isa => 'NGCP::Panel',
|
|
);
|
|
|
|
has _redis => (
|
|
is => 'ro',
|
|
isa => 'Redis',
|
|
);
|
|
|
|
has _rows => (
|
|
is => 'rw',
|
|
isa => 'ArrayRef',
|
|
default => sub {[]}
|
|
);
|
|
|
|
has _query_done => (
|
|
is => 'rw',
|
|
isa => 'Int',
|
|
default => 0,
|
|
);
|
|
|
|
has _domain_resellers => (
|
|
is => 'rw',
|
|
isa => 'HashRef',
|
|
lazy => 1,
|
|
default => sub {
|
|
my $self = shift;
|
|
my $h = {};
|
|
my $domres_rs = $self->_c->model('DB')->resultset('domain_resellers')->search(undef, {
|
|
join => 'domain'
|
|
});
|
|
while ((my $res = $domres_rs->next)) {
|
|
$h->{$res->domain->domain} = $res->reseller_id;
|
|
}
|
|
return $h;
|
|
},
|
|
);
|
|
|
|
sub count {
|
|
my ($self) = @_;
|
|
|
|
my $count = @{ $self->_rows };
|
|
return $count;
|
|
}
|
|
|
|
sub first {
|
|
my ($self) = @_;
|
|
return $self->_rows->[0];
|
|
}
|
|
|
|
sub all {
|
|
my ($self) = @_;
|
|
return @{ $self->_rows };
|
|
}
|
|
|
|
sub find {
|
|
my ($self, $filter) = @_;
|
|
my $id;
|
|
|
|
if (ref $filter eq "") {
|
|
$id = $filter;
|
|
$filter = { id => $id };
|
|
} elsif(ref $filter eq "HASH" && exists $filter->{id}) {
|
|
$id = $filter->{id};
|
|
} else {
|
|
$self->_c->log->error("id filter is mandatory for redis find()");
|
|
return;
|
|
}
|
|
|
|
my %entry = $self->_redis->hgetall("location:entry::$id");
|
|
$entry{id} = $entry{ruid};
|
|
if (exists $filter->{reseller_id} && $filter->{reseller_id} != $self->_domain_resellers->{$entry{domain}}) {
|
|
return;
|
|
}
|
|
return NGCP::Panel::Utils::RedisLocationResultSource->new(_data => \%entry);
|
|
}
|
|
|
|
sub search {
|
|
my ($self, $filter, $opt) = @_;
|
|
$filter //= {};
|
|
|
|
my $new_rs = $self->meta->clone_object($self);
|
|
unless ($new_rs->_query_done) {
|
|
if ($filter->{id}) {
|
|
push @{ $new_rs->_rows }, $new_rs->find($filter);
|
|
} elsif ($filter->{username} && $filter->{domain}) {
|
|
push @{ $new_rs->_rows },
|
|
@{ $new_rs->_rows_from_mapkey("location:usrdom::" .
|
|
$filter->{username} . ":" . $filter->{domain}, $filter) };
|
|
} else {
|
|
$new_rs->_scan($filter);
|
|
}
|
|
$new_rs->_query_done(1);
|
|
}
|
|
$new_rs->_filter($filter);
|
|
|
|
if ($opt->{order_by}->{'-desc'}) {
|
|
my $f = $opt->{order_by}->{'-desc'};
|
|
$f =~ s/^me\.//;
|
|
$new_rs->_rows([sort { $b->$f cmp $a->$f } @{ $new_rs->_rows }]);
|
|
} elsif ($opt->{order_by}->{'-asc'} || ref $opt->{order_by} eq "") {
|
|
my $f = $opt->{order_by}->{'-asc'} // $opt->{order_by};
|
|
$f =~ s/^me\.//;
|
|
$new_rs->_rows([sort { $a->$f cmp $b->$f } @{ $new_rs->_rows }]);
|
|
}
|
|
|
|
$opt->{rows} //= -1;
|
|
$opt->{offset} //= 0;
|
|
if (!defined $opt->{page} && $opt->{rows} > -1 || $opt->{offset} > 0) {
|
|
$new_rs->_rows([ splice @{ $new_rs->_rows }, $opt->{offset}, $opt->{rows} ]);
|
|
}
|
|
|
|
if (defined $opt->{page} && $opt->{rows} > 0) {
|
|
$new_rs->_rows([ splice(@{ $new_rs->_rows }, ($opt->{page} - 1 )*$opt->{rows}, $opt->{rows}) ]);
|
|
}
|
|
return $new_rs;
|
|
}
|
|
|
|
sub _rows_from_mapkey {
|
|
my ($self, $mapkey, $filter) = @_;
|
|
my @rows = ();
|
|
my $keys = $self->_redis->smembers($mapkey);
|
|
foreach my $key (@{ $keys }) {
|
|
my %entry = $self->_redis->hgetall($key);
|
|
$entry{id} = $entry{ruid};
|
|
if (exists $filter->{reseller_id} && $filter->{reseller_id} != $self->_domain_resellers->{$entry{domain}}) {
|
|
next;
|
|
}
|
|
my $res = NGCP::Panel::Utils::RedisLocationResultSource->new(_data => \%entry);
|
|
push @rows, $res;
|
|
}
|
|
return \@rows;
|
|
}
|
|
|
|
sub _filter {
|
|
my ($self, $filter) = @_;
|
|
my @newrows = ();
|
|
my $i = 0;
|
|
foreach my $row (@{ $self->_rows }) {
|
|
my $match = 0;
|
|
my $filter_applied = 0;
|
|
my %attr = map { $_->name => 1 } $row->meta->get_all_attributes;
|
|
foreach my $f (keys %{ $filter }) {
|
|
if ($f eq "-and" && ref $filter->{$f} eq "ARRAY") {
|
|
foreach my $col (@{ $filter->{$f} }) {
|
|
next unless (ref $col eq "ARRAY");
|
|
foreach my $innercol (@{ $col }) {
|
|
if (ref $innercol eq "HASH") {
|
|
foreach my $colname (keys %{ $innercol }) {
|
|
my $searchname = $colname;
|
|
$colname =~ s/^me\.//;
|
|
next if ($colname =~ /\./); # we don't support joined table columns
|
|
$filter_applied = 1;
|
|
if (ref $innercol->{$searchname} eq "") {
|
|
if (!exists $attr{$colname} || lc($row->$colname) ne lc($innercol->{$searchname})) {
|
|
} else {
|
|
$match = 1;
|
|
last;
|
|
}
|
|
} elsif (ref $innercol->{$searchname} eq "HASH" && exists $innercol->{$searchname}->{like}) {
|
|
my $fil = $innercol->{$searchname}->{like};
|
|
$fil =~ s/^\%//;
|
|
$fil =~ s/\%$//;
|
|
if (!exists $attr{$colname} || $row->$colname !~ /$fil/i) {
|
|
} else {
|
|
$match = 1;
|
|
last;
|
|
}
|
|
}
|
|
}
|
|
last if ($match);
|
|
}
|
|
}
|
|
}
|
|
last if ($match);
|
|
}
|
|
|
|
}
|
|
next if ($filter_applied && !$match);
|
|
push @newrows, $row;
|
|
}
|
|
$self->_rows(\@newrows);
|
|
}
|
|
|
|
sub _scan {
|
|
my ($self, $filter) = @_;
|
|
$filter //= {};
|
|
my $match = ($filter->{username} // "") . ":" . ($filter->{domain} // "");
|
|
if ($match eq ":") {
|
|
$match = "*";
|
|
} elsif ($match =~ /:$/) {
|
|
$match .= '*';
|
|
}
|
|
|
|
$self->_rows([]);
|
|
my $cursor = 0;
|
|
do {
|
|
my $res = $self->_redis->scan($cursor, MATCH => "location:usrdom::$match", COUNT => 1000);
|
|
$cursor = shift @{ $res };
|
|
my $mapkeys = shift @{ $res };
|
|
foreach my $mapkey (@{ $mapkeys }) {
|
|
push @{ $self->_rows }, @{ $self->_rows_from_mapkey($mapkey, $filter) };
|
|
}
|
|
} while ($cursor);
|
|
|
|
return 1;
|
|
}
|
|
|
|
sub result_class {
|
|
"dummy";
|
|
}
|
|
|
|
sub result_source {
|
|
NGCP::Panel::Utils::RedisLocationResultSource->new;
|
|
}
|
|
|
|
1;
|