[Rt-commit] rt 02/02: Clean up lifecycles on save when possible
sunnavy
sunnavy at bestpractical.com
Wed Jul 21 21:39:14 UTC 2021
This is an automated email from the git hooks/post-receive script.
sunnavy pushed a commit to branch 5.0/cleanup-lifecycles
in repository rt.
commit 265ea8f4aee2fe723d30a3d3244a9be69a4f5ab3
Author: sunnavy <sunnavy at bestpractical.com>
AuthorDate: Thu Jul 22 04:00:57 2021 +0800
Clean up lifecycles on save when possible
Here we just clean up obvious errors like nonexistent lifecycles,
statuses, etc. This is initially to sync __maps__ when statuses are
deleted from lifecycles.
---
lib/RT/Lifecycle.pm | 162 +++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 130 insertions(+), 32 deletions(-)
diff --git a/lib/RT/Lifecycle.pm b/lib/RT/Lifecycle.pm
index eee78d2499..e03c0816d5 100644
--- a/lib/RT/Lifecycle.pm
+++ b/lib/RT/Lifecycle.pm
@@ -799,6 +799,22 @@ sub _SaveLifecycles {
my $lifecycles = shift;
my $CurrentUser = shift;
+ for my $key ( keys %$lifecycles ) {
+ next if $key eq '__maps__';
+ my ( $ret, @warnings )
+ = $class->ValidateLifecycle( Lifecycle => $lifecycles->{$key}, Name => $key, Cleanup => 1 );
+ unless ($ret) {
+ RT->Logger->warning($_) for @warnings;
+ }
+ }
+
+ if ( $lifecycles->{__maps__} ) {
+ my ( $ret, @warnings ) = $class->ValidateLifecycleMaps( Lifecycles => $lifecycles, Cleanup => 1 );
+ unless ($ret) {
+ RT->Logger->warning($_) for @warnings;
+ }
+ }
+
my $setting = RT::Configuration->new($CurrentUser);
$setting->LoadByCols(Name => 'Lifecycles', Disabled => 0);
if ($setting->Id) {
@@ -953,10 +969,13 @@ sub UpdateMaps {
return (1, $CurrentUser->loc("Lifecycle mappings updated"));
}
-=head2 ValidateLifecycle( CurrentUser => undef, Lifecycle => undef, Name => undef )
+=head2 ValidateLifecycle( CurrentUser => undef, Lifecycle => undef, Name => undef, Cleanup => undef )
Validate passed Lifecycle data structure.
+If Cleanup is true, clean up passed Lifecycle data structure, e.g. removing
+nonexistent statuses.
+
Returns (STATUS, MESSAGE). STATUS is true if succeeded, otherwise false.
=cut
@@ -967,6 +986,7 @@ sub ValidateLifecycle {
CurrentUser => undef,
Lifecycle => undef,
Name => undef,
+ Cleanup => undef,
@_,
);
my $current_user = $args{CurrentUser} || RT->SystemUser;
@@ -994,39 +1014,75 @@ sub ValidateLifecycle {
# ->{actions} are handled below
for my $state ( keys %{ $lifecycle->{defaults} || {} } ) {
my $status = $lifecycle->{defaults}{$state};
- push @warnings, $current_user->loc( "Nonexistent status [_1] in default states in [_2] lifecycle", lc $status, $name )
- unless $lifecycle->{canonical_case}{ lc $status };
+ unless ( $lifecycle->{canonical_case}{ lc $status } ) {
+ push @warnings,
+ $current_user->loc( "Nonexistent status [_1] in default states in [_2] lifecycle", lc $status, $name );
+ if ( $args{Cleanup} ) {
+ delete $lifecycle->{defaults}{$state};
+ }
+ }
}
for my $from ( keys %{ $lifecycle->{transitions} || {} } ) {
- push @warnings, $current_user->loc( "Nonexistent status [_1] in transitions in [_2] lifecycle", lc $from, $name )
- unless $from eq '' || $lifecycle->{canonical_case}{ lc $from };
+ unless ( $from eq '' || $lifecycle->{canonical_case}{ lc $from } ) {
+ push @warnings,
+ $current_user->loc( "Nonexistent status [_1] in transitions in [_2] lifecycle", lc $from, $name );
+ if ( $args{Cleanup} ) {
+ delete $lifecycle->{transitions}{$from};
+ next;
+ }
+ }
for my $status ( @{ ( $lifecycle->{transitions}{$from} ) || [] } ) {
push @warnings, $current_user->loc( "Nonexistent status [_1] in transitions in [_2] lifecycle", lc $status, $name )
unless $lifecycle->{canonical_case}{ lc $status };
}
+
+ if ( $args{Cleanup} ) {
+ $lifecycle->{transitions}{$from}
+ = [ grep { $lifecycle->{canonical_case}{ lc $_ } } @{ ( $lifecycle->{transitions}{$from} ) || [] } ];
+ }
}
for my $schema ( keys %{ $lifecycle->{rights} || {} } ) {
my ( $from, $to ) = split /\s*->\s*/, $schema, 2;
unless ( $from and $to ) {
push @warnings, $current_user->loc( "Invalid right transition [_1] in [_2] lifecycle", $schema, $name );
+ if ( $args{Cleanup} ) {
+ delete $lifecycle->{rights}{$schema};
+ }
next;
}
- push @warnings, $current_user->loc( "Nonexistent status [_1] in right transition in [_2] lifecycle", lc $from, $name )
- unless $from eq '*'
- or $lifecycle->{canonical_case}{ lc $from };
- push @warnings, $current_user->loc( "Nonexistent status [_1] in right transition in [_2] lifecycle", lc $to, $name )
- unless $to eq '*' || $lifecycle->{canonical_case}{ lc $to };
-
- push @warnings,
- $current_user->loc( "Invalid right name ([_1]) in [_2] lifecycle; right names must be ASCII", $lifecycle->{rights}{$schema}, $name )
- if $lifecycle->{rights}{$schema} =~ /\P{ASCII}/;
-
- push @warnings,
- $current_user
- ->loc( "Invalid right name ([_1]) in [_2] lifecycle; right names must be <= 25 characters", $lifecycle->{rights}{$schema}, $name )
- if length( $lifecycle->{rights}{$schema} ) > 25;
+
+ my $invalid;
+ unless ( $from eq '*' or $lifecycle->{canonical_case}{ lc $from } ) {
+ push @warnings,
+ $current_user->loc( "Nonexistent status [_1] in right transition in [_2] lifecycle", lc $from, $name );
+ $invalid = 1;
+ }
+
+ unless ( $to eq '*' || $lifecycle->{canonical_case}{ lc $to } ) {
+ push @warnings,
+ $current_user->loc( "Nonexistent status [_1] in right transition in [_2] lifecycle", lc $to, $name );
+ $invalid = 1;
+ }
+
+ if ( $lifecycle->{rights}{$schema} =~ /\P{ASCII}/ ) {
+ push @warnings,
+ $current_user->loc( "Invalid right name ([_1]) in [_2] lifecycle; right names must be ASCII",
+ $lifecycle->{rights}{$schema}, $name );
+ $invalid = 1;
+ }
+
+ if ( length( $lifecycle->{rights}{$schema} ) > 25 ) {
+ push @warnings,
+ $current_user->loc( "Invalid right name ([_1]) in [_2] lifecycle; right names must be <= 25 characters",
+ $lifecycle->{rights}{$schema}, $name );
+ $invalid = 1;
+ }
+
+ if ( $args{Cleanup} && $invalid ) {
+ delete $lifecycle->{rights}{$schema};
+ }
}
my @actions;
@@ -1039,27 +1095,44 @@ sub ValidateLifecycle {
@actions = @{ $lifecycle->{'actions'} };
}
+ my @valid_actions;
while ( my ( $transition, $info ) = splice @actions, 0, 2 ) {
my ( $from, $to ) = split /\s*->\s*/, $transition, 2;
unless ( $from and $to ) {
push @warnings, $current_user->loc( "Invalid action status change [_1], in [_2] lifecycle", $transition, $name );
next;
}
- push @warnings, $current_user->loc( "Nonexistent status [_1] in action in [_2] lifecycle", lc $from, $name )
- unless $from eq '*'
- or $lifecycle->{canonical_case}{ lc $from };
- push @warnings, $current_user->loc( "Nonexistent status [_1] in action in [_2] lifecycle", lc $to, $name )
- unless $to eq '*'
- or $lifecycle->{canonical_case}{ lc $to };
+
+ my $invalid;
+ unless ( $from eq '*' or $lifecycle->{canonical_case}{ lc $from } ) {
+ push @warnings, $current_user->loc( "Nonexistent status [_1] in action in [_2] lifecycle", lc $from, $name );
+ $invalid = 1;
+ }
+
+ unless ( $to eq '*' or $lifecycle->{canonical_case}{ lc $to } ) {
+ push @warnings, $current_user->loc( "Nonexistent status [_1] in action in [_2] lifecycle", lc $to, $name );
+ $invalid = 1;
+ }
+
+ if ( $args{Cleanup} && !$invalid ) {
+ push @valid_actions, $transition, $info;
+ }
+ }
+
+ if ( $args{Cleanup} ) {
+ $lifecycle->{'actions'} = \@valid_actions;
}
return @warnings ? ( 0, uniq @warnings ) : 1;
}
-=head2 ValidateLifecycleMaps( CurrentUser => undef )
+=head2 ValidateLifecycleMaps( CurrentUser => undef, Lifecycles => undef, Maps => undef, Cleanup => undef )
Validate lifecycle Maps.
+If Cleanup is true, clean up maps structure, e.g. removing nonexistent
+statuses.
+
Returns (STATUS, MESSAGES). STATUS is true if succeeded, otherwise false.
=cut
@@ -1068,28 +1141,53 @@ sub ValidateLifecycleMaps {
my $self = shift;
my %args = (
CurrentUser => undef,
+ Lifecycles => undef,
+ Maps => undef,
+ Cleanup => undef,
@_,
);
my $current_user = $args{CurrentUser} || RT->SystemUser;
my @warnings;
- for my $mapname ( keys %{ $LIFECYCLES_CACHE{'__maps__'} || {} } ) {
+ my $lifecycles = $args{Lifecycles} || \%LIFECYCLES_CACHE;
+ my $maps = $args{Maps} || $lifecycles->{__maps__} || $LIFECYCLES_CACHE{__maps__} || {};
+
+ for my $mapname ( keys %$maps ) {
my ( $from, $to ) = split /\s*->\s*/, $mapname, 2;
unless ( $from and $to ) {
push @warnings, $current_user->loc( "Invalid lifecycle mapping [_1]", $mapname );
+ if ( $args{Cleanup} ) {
+ delete $maps->{$mapname};
+ }
next;
}
push @warnings, $current_user->loc( "Nonexistent lifecycle [_1] in [_2] lifecycle map", $from, $mapname )
- unless $LIFECYCLES_CACHE{$from};
+ unless $lifecycles->{$from};
push @warnings, $current_user->loc( "Nonexistent lifecycle [_1] in [_2] lifecycle map", $to, $mapname )
- unless $LIFECYCLES_CACHE{$to};
+ unless $lifecycles->{$to};
- my $map = $LIFECYCLES_CACHE{'__maps__'}{$mapname};
+ if ( $args{Cleanup} && ( !$lifecycles->{$from} || !$lifecycles->{$to} ) ) {
+ delete $maps->{$mapname};
+ next;
+ }
+
+ my $map = $maps->{$mapname};
+ my $new_map = {};
for my $status ( keys %{$map} ) {
push @warnings, $current_user->loc( "Nonexistent status [_1] in [_2] in [_3] lifecycle map", lc $status, $from, $mapname )
- if $LIFECYCLES_CACHE{$from} && !$LIFECYCLES_CACHE{$from}{canonical_case}{ lc $status };
+ if $lifecycles->{$from} && !$lifecycles->{$from}{canonical_case}{ lc $status };
push @warnings, $current_user->loc( "Nonexistent status [_1] in [_2] in [_3] lifecycle map", lc $map->{$status}, $to, $mapname )
- if $LIFECYCLES_CACHE{$to} && !$LIFECYCLES_CACHE{$to}{canonical_case}{ lc $map->{$status} };
+ if $lifecycles->{$to} && !$lifecycles->{$to}{canonical_case}{ lc $map->{$status} };
+ $new_map->{$status} = $map->{$status}
+ if $args{Cleanup}
+ && $lifecycles->{$from}
+ && $lifecycles->{$from}{canonical_case}{ lc $status }
+ && $lifecycles->{$to}
+ && $lifecycles->{$to}{canonical_case}{ lc $map->{$status} };
+ }
+
+ if ( $args{Cleanup} ) {
+ $maps->{$mapname} = $new_map;
}
}
--
To stop receiving notification emails like this one, please contact
sysadmin at bestpractical.com.
More information about the rt-commit
mailing list