+sub FindDependencies {
+ my $self = shift;
+ my ($walker, $deps) = @_;
+
+ $self->SUPER::FindDependencies($walker, $deps);
+
+ $deps->Add( out => $self->BaseObj ) if $self->BaseObj and $self->BaseObj->id;
+ $deps->Add( out => $self->TargetObj ) if $self->TargetObj and $self->TargetObj->id;
+}
+
+sub __DependsOn {
+ my $self = shift;
+ my %args = (
+ Shredder => undef,
+ Dependencies => undef,
+ @_,
+ );
+ my $deps = $args{'Dependencies'};
+ my $list = [];
+
+# AddLink transactions
+ my $map = { %RT::Link::TYPEMAP };
+ my $link_meta = $map->{ $self->Type };
+ unless ( $link_meta && $link_meta->{'Mode'} && $link_meta->{'Type'} ) {
+ RT::Shredder::Exception->throw( 'Wrong link link_meta, no record for '. $self->Type );
+ }
+ if ( $self->BaseURI->IsLocal ) {
+ my $objs = $self->BaseObj->Transactions;
+ $objs->Limit(
+ FIELD => 'Type',
+ OPERATOR => '=',
+ VALUE => 'AddLink',
+ );
+ $objs->Limit( FIELD => 'NewValue', VALUE => $self->Target );
+ while ( my ($k, $v) = each %$map ) {
+ next unless $v->{'Type'} eq $link_meta->{'Type'};
+ next unless $v->{'Mode'} eq $link_meta->{'Mode'};
+ $objs->Limit( FIELD => 'Field', VALUE => $k );
+ }
+ push( @$list, $objs );
+ }
+
+ my %reverse = ( Base => 'Target', Target => 'Base' );
+ if ( $self->TargetURI->IsLocal ) {
+ my $objs = $self->TargetObj->Transactions;
+ $objs->Limit(
+ FIELD => 'Type',
+ OPERATOR => '=',
+ VALUE => 'AddLink',
+ );
+ $objs->Limit( FIELD => 'NewValue', VALUE => $self->Base );
+ while ( my ($k, $v) = each %$map ) {
+ next unless $v->{'Type'} eq $link_meta->{'Type'};
+ next unless $v->{'Mode'} eq $reverse{ $link_meta->{'Mode'} };
+ $objs->Limit( FIELD => 'Field', VALUE => $k );
+ }
+ push( @$list, $objs );
+ }
+
+ $deps->_PushDependencies(
+ BaseObject => $self,
+ Flags => RT::Shredder::Constants::DEPENDS_ON|RT::Shredder::Constants::WIPE_AFTER,
+ TargetObjects => $list,
+ Shredder => $args{'Shredder'}
+ );
+ return $self->SUPER::__DependsOn( %args );
+}
+
+sub Serialize {
+ my $self = shift;
+ my %args = (@_);
+ my %store = $self->SUPER::Serialize(@_);
+
+ delete $store{LocalBase} if $store{Base};
+ delete $store{LocalTarget} if $store{Target};
+
+ for my $dir (qw/Base Target/) {
+ my $uri = $self->${\($dir.'URI')};
+ my $object = $self->${\($dir.'Obj')};
+
+ if ($uri->IsLocal) {
+ if ($args{serializer}->Observe(object => $object)) {
+ # no action needed; the object is being migrated
+ }
+ elsif ($args{serializer}{HyperlinkUnmigrated}) {
+ # object is not being migrated; hyperlinkify
+ $store{$dir} = $uri->AsHREF;
+ }
+ else {
+ # object is not being migrated and hyperlinks not desired,
+ # so drop this RT::Link altogether
+ return;
+ }
+ }
+ }
+
+ return %store;
+}
+
+
+sub PreInflate {
+ my $class = shift;
+ my ($importer, $uid, $data) = @_;
+
+ for my $dir (qw/Base Target/) {
+ my $uid_ref = $data->{$dir};
+ next unless $uid_ref and ref $uid_ref;
+
+ my $to_uid = ${ $uid_ref };
+ my $obj = $importer->LookupObj( $to_uid );
+ if ($obj) {
+ $data->{$dir} = $obj->URI;
+ $data->{"Local$dir"} = $obj->Id if $obj->isa("RT::Ticket");
+ } else {
+ $data->{$dir} = "";
+ $importer->Postpone(
+ for => $to_uid,
+ uid => $uid,
+ uri => $dir,
+ column => ($to_uid =~ /RT::Ticket/ ? "Local$dir" : undef),
+ );
+ }
+
+ }
+
+ return $class->SUPER::PreInflate( $importer, $uid, $data );
+}
+