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.
252 lines
8.6 KiB
252 lines
8.6 KiB
#!/usr/bin/perl
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Data::Dumper;
|
|
use NGCP::Schema;
|
|
use NGCP::Panel::Utils::Subscriber;
|
|
use NGCP::Panel::Utils::Preferences;
|
|
use Test::More;
|
|
use Data::HAL qw();
|
|
use Data::HAL::Link qw();
|
|
use Safe::Isa qw($_isa);
|
|
use NGCP::Panel::Form::CFSimpleAPI;
|
|
|
|
my $schema = NGCP::Schema->connect();
|
|
my $ql_exists = 0;
|
|
my ($ql,$ana);
|
|
|
|
if($ql_exists){
|
|
#use DBIx::Class::QueryLog;
|
|
#use DBIx::Class::QueryLog::Analyzer;
|
|
my $ql = DBIx::Class::QueryLog->new;
|
|
$schema->storage->debugobj($ql);
|
|
$schema->storage->debug(1);
|
|
my $ana = DBIx::Class::QueryLog::Analyzer->new({ querylog => $ql });
|
|
$ql->bucket('origin');
|
|
}
|
|
|
|
my $time = time();
|
|
print "start;\n";
|
|
#print Dumper($schema);
|
|
|
|
my $item_rs = $schema->resultset('voip_subscribers')->search( {
|
|
'me.status' => { '!=' => 'terminated' }
|
|
},{
|
|
prefetch => { 'provisioning_voip_subscriber'=>'voip_cf_mappings'},
|
|
#prefetch => 'provisioning_voip_subscriber',
|
|
rows => 200,
|
|
},
|
|
);
|
|
my (@arr_orig,@arr_opt);
|
|
for my $item ($item_rs->all) {
|
|
# print Dumper({$item->get_inflated_columns});
|
|
my %resource = ();
|
|
my $prov_subs = $item->provisioning_voip_subscriber;
|
|
for my $cf_type (qw/cfu cfb cft cfna cfs/) {
|
|
my $mapping = $schema->resultset('voip_cf_mappings')->search({
|
|
subscriber_id => $prov_subs->id,
|
|
type => $cf_type,
|
|
})->first;
|
|
if ($mapping) {
|
|
$resource{$cf_type} = _contents_from_cfm($mapping, $item);
|
|
} else {
|
|
$resource{$cf_type} = {};
|
|
}
|
|
}
|
|
if(keys %{$resource{cft}}){
|
|
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
|
|
c => undef, attribute => 'ringtimeout', prov_subscriber => $prov_subs, schema => $schema )->first;
|
|
$ringtimeout_preference = $ringtimeout_preference ? $ringtimeout_preference->value : undef;
|
|
$resource{cft}{ringtimeout} = $ringtimeout_preference;
|
|
}
|
|
additional_processing($item, \%resource);
|
|
push @arr_orig, \%resource;
|
|
}
|
|
print "1.time=".(time()-$time).";\n";
|
|
#exit;
|
|
if($ql_exists){
|
|
$ql->bucket('optimized');
|
|
}
|
|
$time = time();
|
|
|
|
for my $item ($item_rs->all) {
|
|
my %resource = ();
|
|
my $prov_subs = $item->provisioning_voip_subscriber;
|
|
@resource{qw/cfu cfb cft cfna cfs/} = ({}) x 5;
|
|
for my $item_cf ($item->provisioning_voip_subscriber->voip_cf_mappings->all){
|
|
$resource{$item_cf->type} = _contents_from_cfm($item_cf, $item);
|
|
}
|
|
if(keys %{$resource{cft}}){
|
|
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
|
|
c => undef, attribute => 'ringtimeout', prov_subscriber => $prov_subs, schema => $schema )->first;
|
|
$ringtimeout_preference = $ringtimeout_preference ? $ringtimeout_preference->value : undef;
|
|
$resource{cft}{ringtimeout} = $ringtimeout_preference;
|
|
}
|
|
additional_processing($item, \%resource);
|
|
push @arr_opt, \%resource;
|
|
}
|
|
print "2.time=".(time()-$time).";\n";
|
|
|
|
is_deeply(\@arr_orig, \@arr_opt, "check that arrays are equiv");
|
|
#print Dumper[\@arr_orig, \@arr_opt];
|
|
if($ql_exists){
|
|
print Dumper $ana->get_totaled_queries_by_bucket;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sub additional_processing{
|
|
my($item,$resource) = @_;
|
|
my $type='';
|
|
my %resource=%$resource;
|
|
my $hal = Data::HAL->new(
|
|
links => [
|
|
Data::HAL::Link->new(
|
|
relation => 'curies',
|
|
href => 'http://purl.org/sipwise/ngcp-api/#rel-{rel}',
|
|
name => 'ngcp',
|
|
templated => 1,
|
|
),
|
|
Data::HAL::Link->new(relation => 'collection', href => sprintf("%s", '')),
|
|
Data::HAL::Link->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'),
|
|
Data::HAL::Link->new(relation => 'self', href => sprintf("%s%s", '', $item->id)),
|
|
Data::HAL::Link->new(relation => "ngcp:$type", href => sprintf("/api/%s/%s", $type, $item->id)),
|
|
Data::HAL::Link->new(relation => 'ngcp:subscribers', href => sprintf("/api/subscribers/%d", $item->id)),
|
|
],
|
|
relation => 'ngcp:callforwards',
|
|
);
|
|
my $form=NGCP::Panel::Form::CFSimpleAPI->new();
|
|
|
|
validate_form(
|
|
form => $form,
|
|
resource => \%resource,
|
|
run => 0,
|
|
);
|
|
|
|
$hal->resource(\%resource);
|
|
|
|
}
|
|
sub _contents_from_cfm {
|
|
my ($cfm_item, $sub) = @_;
|
|
my (@times, @destinations);
|
|
my $timeset_item = $cfm_item->time_set;
|
|
my $dset_item = $cfm_item->destination_set;
|
|
for my $time ($timeset_item ? $timeset_item->voip_cf_periods->all : () ) {
|
|
push @times, {$time->get_inflated_columns};
|
|
delete @{$times[-1]}{'time_set_id', 'id'};
|
|
}
|
|
for my $dest ($dset_item ? $dset_item->voip_cf_destinations->all : () ) {
|
|
my ($d, $duri) = NGCP::Panel::Utils::Subscriber::destination_to_field($dest->destination);
|
|
my $deflated;
|
|
if($d eq "uri") {
|
|
$deflated = NGCP::Panel::Utils::Subscriber::uri_deflate(undef, $duri,$sub) if $d eq "uri";
|
|
$d = $dest->destination;
|
|
}
|
|
push @destinations, {$dest->get_inflated_columns,
|
|
destination => $d,
|
|
$deflated ? (simple_destination => $deflated) : (),
|
|
};
|
|
delete @{$destinations[-1]}{'destination_set_id', 'id'};
|
|
}
|
|
return {times => \@times, destinations => \@destinations};
|
|
}
|
|
sub validate_form {
|
|
my (%params) = @_;
|
|
|
|
my $resource = $params{resource};
|
|
my $form = $params{form};
|
|
my $run = $params{run} // 1;
|
|
my $exceptions = $params{exceptions} // [];
|
|
my $form_params = $params{form_params} // {};
|
|
push @{ $exceptions }, "external_id";
|
|
|
|
my @normalized = ();
|
|
|
|
# move {xxx_id} into {xxx}{id} for FormHandler
|
|
foreach my $key(keys %{ $resource } ) {
|
|
my $skip_normalize = grep {/^$key$/} @{ $exceptions };
|
|
if($key =~ /^(.+)_id$/ && !$skip_normalize && !exists $resource->{$1}) {
|
|
push @normalized, $1;
|
|
$resource->{$1}{id} = delete $resource->{$key};
|
|
}
|
|
}
|
|
|
|
# remove unknown keys
|
|
my %fields = map { $_->name => $_ } $form->fields;
|
|
validate_fields($resource, \%fields, $run);
|
|
|
|
if($run) {
|
|
# check keys/vals
|
|
$form->process(params => $resource, posted => 1, %{$form_params} );
|
|
unless($form->validated) {
|
|
my $e = join '; ', map {
|
|
sprintf 'field=\'%s\', input=\'%s\', errors=\'%s\'',
|
|
($_->parent->$_isa('HTML::FormHandler::Field') ? $_->parent->name . '_' : '') . $_->name,
|
|
$_->input // '',
|
|
join('', @{ $_->errors })
|
|
} $form->error_fields;
|
|
return;
|
|
}
|
|
}
|
|
|
|
# move {xxx}{id} back into {xxx_id} for DB
|
|
foreach my $key(@normalized) {
|
|
next unless(exists $resource->{$key});
|
|
$resource->{$key . '_id'} = defined($resource->{$key}{id}) ?
|
|
int($resource->{$key}{id}) :
|
|
$resource->{$key}{id};
|
|
delete $resource->{$key};
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
sub validate_fields {
|
|
my ($resource, $fields, $run) = @_;
|
|
|
|
for my $k (keys %{ $resource }) {
|
|
#if($resource->{$k}->$_isa('JSON::XS::Boolean') || $resource->{$k}->$_isa('JSON::PP::Boolean')) {
|
|
if($resource->{$k}->$_isa('JSON::PP::Boolean')) {
|
|
$resource->{$k} = $resource->{$k} ? 1 : 0;
|
|
}
|
|
unless(exists $fields->{$k}) {
|
|
delete $resource->{$k};
|
|
}
|
|
$resource->{$k} = DateTime::Format::RFC3339->format_datetime($resource->{$k})
|
|
if $resource->{$k}->$_isa('DateTime');
|
|
$resource->{$k} = $resource->{$k} + 0
|
|
if(defined $resource->{$k} && (
|
|
$fields->{$k}->$_isa('HTML::FormHandler::Field::Integer') ||
|
|
$fields->{$k}->$_isa('HTML::FormHandler::Field::Money') ||
|
|
$fields->{$k}->$_isa('HTML::FormHandler::Field::Float')) &&
|
|
(is_int($resource->{$k}) || is_decimal($resource->{$k})));
|
|
|
|
if (defined $resource->{$k} &&
|
|
$fields->{$k}->$_isa('HTML::FormHandler::Field::Repeatable') &&
|
|
"ARRAY" eq ref $resource->{$k} ) {
|
|
for my $elem (@{ $resource->{$k} }) {
|
|
my ($subfield_instance) = $fields->{$k}->fields;
|
|
my %subfields = map { $_->name => $_ } $subfield_instance->fields;
|
|
validate_fields($elem, \%subfields, $run);
|
|
}
|
|
}
|
|
|
|
# only do this for converting back from obj to hal
|
|
# otherwise it breaks db fields with the \0 and \1 notation
|
|
unless($run) {
|
|
$resource->{$k} = $resource->{$k} ? JSON::true : JSON::false
|
|
if(defined $resource->{$k} &&
|
|
$fields->{$k}->$_isa('HTML::FormHandler::Field::Boolean'));
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
1;
|