]> git.uio.no Git - usit-rt.git/blobdiff - lib/RT/Link.pm
Upgrade to 4.2.8
[usit-rt.git] / lib / RT / Link.pm
index 7a277473f38f30708648904121511263755bcd73..0418b8fb909d09e22cc93babf864f7f9779592eb 100644 (file)
@@ -2,7 +2,7 @@
 #
 # COPYRIGHT:
 #
-# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
 #                                          <sales@bestpractical.com>
 #
 # (Except where explicitly superseded by other copyright notices)
 This module should never be called directly by client code. it's an internal module which
 should only be accessed through exported APIs in Ticket other similar objects.
 
-=head1 METHODS
-
-
-
 =cut
 
 
@@ -78,8 +74,67 @@ use base 'RT::Record';
 sub Table {'Links'}
 use Carp;
 use RT::URI;
+use List::Util 'first';
+use List::MoreUtils 'uniq';
+
+# Helper tables for links mapping to make it easier
+# to build and parse links between objects.
+our %TYPEMAP = (
+    MemberOf        => { Type => 'MemberOf',    Mode => 'Target',   Display => 0 },
+    Parents         => { Type => 'MemberOf',    Mode => 'Target',   Display => 1 },
+    Parent          => { Type => 'MemberOf',    Mode => 'Target',   Display => 0 },
+    Members         => { Type => 'MemberOf',    Mode => 'Base',     Display => 0 },
+    Member          => { Type => 'MemberOf',    Mode => 'Base',     Display => 0 },
+    Children        => { Type => 'MemberOf',    Mode => 'Base',     Display => 1 },
+    Child           => { Type => 'MemberOf',    Mode => 'Base',     Display => 0 },
+    HasMember       => { Type => 'MemberOf',    Mode => 'Base',     Display => 0 },
+    RefersTo        => { Type => 'RefersTo',    Mode => 'Target',   Display => 1 },
+    ReferredToBy    => { Type => 'RefersTo',    Mode => 'Base',     Display => 1 },
+    DependsOn       => { Type => 'DependsOn',   Mode => 'Target',   Display => 1 },
+    DependedOnBy    => { Type => 'DependsOn',   Mode => 'Base',     Display => 1 },
+    MergedInto      => { Type => 'MergedInto',  Mode => 'Target',   Display => 1 },
+);
+our %DIRMAP = (
+    MemberOf    => { Base => 'MemberOf',    Target => 'HasMember'    },
+    RefersTo    => { Base => 'RefersTo',    Target => 'ReferredToBy' },
+    DependsOn   => { Base => 'DependsOn',   Target => 'DependedOnBy' },
+    MergedInto  => { Base => 'MergedInto',  Target => 'MergedInto'   },
+);
+
+__PACKAGE__->_BuildDisplayAs;
+
+my %DISPLAY_AS;
+sub _BuildDisplayAs {
+    %DISPLAY_AS = ();
+    foreach my $in_db ( uniq map { $_->{Type} } values %TYPEMAP ) {
+        foreach my $mode (qw(Base Target)) {
+            $DISPLAY_AS{$in_db}{$mode} = first {
+                   $TYPEMAP{$_}{Display}
+                && $TYPEMAP{$_}{Type} eq $in_db
+                && $TYPEMAP{$_}{Mode} eq $mode
+            } keys %TYPEMAP;
+        }
+    }
+}
+
+=head1 CLASS METHODS
 
+=head2 DisplayTypes
 
+Returns a list of the standard link Types for display, including directional
+variants but not aliases.
+
+=cut
+
+sub DisplayTypes {
+    sort { $a cmp $b }
+    uniq
+    grep { defined }
+     map { values %$_ }
+  values %DISPLAY_AS
+}
+
+=head1 METHODS
 
 =head2 Create PARAMHASH
 
@@ -171,20 +226,20 @@ sub LoadByParams {
 
     my $base = RT::URI->new($self->CurrentUser);
     $base->FromURI( $args{'Base'} )
-        or return (0, $self->loc("Couldn't parse Base URI: [_1]", $args{Base}));
+        or return wantarray ? (0, $self->loc("Couldn't parse Base URI: [_1]", $args{Base})) : 0;
 
     my $target = RT::URI->new($self->CurrentUser);
     $target->FromURI( $args{'Target'} )
-        or return (0, $self->loc("Couldn't parse Target URI: [_1]", $args{Target}));
+        or return wantarray ? (0, $self->loc("Couldn't parse Target URI: [_1]", $args{Target})) : 0;
 
     my ( $id, $msg ) = $self->LoadByCols( Base   => $base->URI,
                                           Type   => $args{'Type'},
                                           Target => $target->URI );
 
     unless ($id) {
-        return ( 0, $self->loc("Couldn't load link: [_1]", $msg) );
+        return wantarray ? ( 0, $self->loc("Couldn't load link: [_1]", $msg) ) : 0;
     } else {
-        return ($id, $msg);
+        return wantarray ? ($id, $msg) : $id;
     }
 }
 
@@ -204,14 +259,14 @@ sub Load {
 
 
     if ( $identifier !~ /^\d+$/ ) {
-        return ( 0, $self->loc("That's not a numerical id") );
+        return wantarray ? ( 0, $self->loc("That's not a numerical id") ) : 0;
     }
     else {
         my ( $id, $msg ) = $self->LoadById($identifier);
         unless ( $self->Id ) {
-            return ( 0, $self->loc("Couldn't load link") );
+            return wantarray ? ( 0, $self->loc("Couldn't load link") ) : 0;
         }
-        return ( $id, $msg );
+        return wantarray ? ( $id, $msg ) : $id;
     }
 }
 
@@ -265,7 +320,6 @@ sub BaseObj {
   return $self->BaseURI->Object;
 }
 
-
 =head2 id
 
 Returns the current value of id.
@@ -406,29 +460,78 @@ sub _CoreAccessible {
     {
 
         id =>
-               {read => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => ''},
+                {read => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => ''},
         Base =>
-               {read => 1, write => 1, sql_type => 12, length => 240,  is_blob => 0,  is_numeric => 0,  type => 'varchar(240)', default => ''},
+                {read => 1, write => 1, sql_type => 12, length => 240,  is_blob => 0,  is_numeric => 0,  type => 'varchar(240)', default => ''},
         Target =>
-               {read => 1, write => 1, sql_type => 12, length => 240,  is_blob => 0,  is_numeric => 0,  type => 'varchar(240)', default => ''},
+                {read => 1, write => 1, sql_type => 12, length => 240,  is_blob => 0,  is_numeric => 0,  type => 'varchar(240)', default => ''},
         Type =>
-               {read => 1, write => 1, sql_type => 12, length => 20,  is_blob => 0,  is_numeric => 0,  type => 'varchar(20)', default => ''},
+                {read => 1, write => 1, sql_type => 12, length => 20,  is_blob => 0,  is_numeric => 0,  type => 'varchar(20)', default => ''},
         LocalTarget =>
-               {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
+                {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
         LocalBase =>
-               {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
+                {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
         LastUpdatedBy =>
-               {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
+                {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
         LastUpdated =>
-               {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
+                {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
         Creator =>
-               {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
+                {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
         Created =>
-               {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
+                {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
 
  }
 };
 
+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 Serialize {
+    my $self = shift;
+    my %args = (@_);
+    my %store = $self->SUPER::Serialize(@_);
+
+    delete $store{LocalBase}   if $store{Base};
+    delete $store{LocalTarget} if $store{Target};
+    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 );
+}
+
 RT::Base->_ImportOverlays();
 
 1;