305c345037b1e605adb70c1cf201924b94040e64
[freeside.git] / rt / lib / RT / Link.pm
1 # BEGIN BPS TAGGED BLOCK {{{
2 #
3 # COPYRIGHT:
4 #
5 # This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
6 #                                          <sales@bestpractical.com>
7 #
8 # (Except where explicitly superseded by other copyright notices)
9 #
10 #
11 # LICENSE:
12 #
13 # This work is made available to you under the terms of Version 2 of
14 # the GNU General Public License. A copy of that license should have
15 # been provided with this software, but in any event can be snarfed
16 # from www.gnu.org.
17 #
18 # This work is distributed in the hope that it will be useful, but
19 # WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 # General Public License for more details.
22 #
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 # 02110-1301 or visit their web page on the internet at
27 # http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
28 #
29 #
30 # CONTRIBUTION SUBMISSION POLICY:
31 #
32 # (The following paragraph is not intended to limit the rights granted
33 # to you to modify and distribute this software under the terms of
34 # the GNU General Public License and is only of importance to you if
35 # you choose to contribute your changes and enhancements to the
36 # community by submitting them to Best Practical Solutions, LLC.)
37 #
38 # By intentionally submitting any modifications, corrections or
39 # derivatives to this work, or any other work intended for use with
40 # Request Tracker, to Best Practical Solutions, LLC, you confirm that
41 # you are the copyright holder for those contributions and you grant
42 # Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
43 # royalty-free, perpetual, license to use, copy, create derivative
44 # works based on those contributions, and sublicense and distribute
45 # those contributions and any derivatives thereof.
46 #
47 # END BPS TAGGED BLOCK }}}
48
49 =head1 NAME
50
51   RT::Link - an RT Link object
52
53 =head1 SYNOPSIS
54
55   use RT::Link;
56
57 =head1 DESCRIPTION
58
59 This module should never be called directly by client code. it's an internal module which
60 should only be accessed through exported APIs in Ticket other similar objects.
61
62 =head1 METHODS
63
64
65
66 =cut
67
68
69 package RT::Link;
70
71 use strict;
72 use warnings;
73
74
75
76 use base 'RT::Record';
77
78 sub Table {'Links'}
79 use Carp;
80 use RT::URI;
81
82
83
84 =head2 Create PARAMHASH
85
86 Create a new link object. Takes 'Base', 'Target' and 'Type'.
87 Returns undef on failure or a Link Id on success.
88
89 =cut
90
91 sub Create {
92     my $self = shift;
93     my %args = ( Base   => undef,
94                  Target => undef,
95                  Type   => undef,
96                  @_ );
97
98     my $base = RT::URI->new( $self->CurrentUser );
99     unless ($base->FromURI( $args{'Base'} )) {
100         my $msg = $self->loc("Couldn't resolve base '[_1]' into a URI.", $args{'Base'});
101         $RT::Logger->warning( "$self $msg" );
102         return wantarray ? (undef, $msg) : undef;
103     }
104
105     my $target = RT::URI->new( $self->CurrentUser );
106     unless ($target->FromURI( $args{'Target'} )) {
107         my $msg = $self->loc("Couldn't resolve target '[_1]' into a URI.", $args{'Target'});
108         $RT::Logger->warning( "$self $msg" );
109         return wantarray ? (undef, $msg) : undef;
110     }
111
112     my $base_id   = 0;
113     my $target_id = 0;
114
115
116
117
118     if ( $base->IsLocal ) {
119         my $object = $base->Object;
120         unless (UNIVERSAL::can($object, 'Id')) {
121             return (undef, $self->loc("[_1] appears to be a local object, but can't be found in the database", $args{'Base'}));
122         
123         }
124         $base_id = $object->Id if UNIVERSAL::isa($object, 'RT::Ticket');
125     }
126     if ( $target->IsLocal ) {
127         my $object = $target->Object;
128         unless (UNIVERSAL::can($object, 'Id')) {
129             return (undef, $self->loc("[_1] appears to be a local object, but can't be found in the database", $args{'Target'}));
130         
131         }
132         $target_id = $object->Id if UNIVERSAL::isa($object, 'RT::Ticket');
133     }
134
135     # We don't want references to ourself
136     if ( $base->URI eq $target->URI ) {
137         return ( 0, $self->loc("Can't link a ticket to itself") );
138     }
139
140     # }}}
141
142     my ( $id, $msg ) = $self->SUPER::Create( Base        => $base->URI,
143                                              Target      => $target->URI,
144                                              LocalBase   => $base_id,
145                                              LocalTarget => $target_id,
146                                              Type        => $args{'Type'} );
147     return ( $id, $msg );
148 }
149
150  # sub LoadByParams
151
152 =head2 LoadByParams
153
154   Load an RT::Link object from the database.  Takes three parameters
155   
156   Base => undef,
157   Target => undef,
158   Type =>undef
159  
160   Base and Target are expected to be integers which refer to Tickets or URIs
161   Type is the link type
162
163 =cut
164
165 sub LoadByParams {
166     my $self = shift;
167     my %args = ( Base   => undef,
168                  Target => undef,
169                  Type   => undef,
170                  @_ );
171
172     my $base = RT::URI->new($self->CurrentUser);
173     $base->FromURI( $args{'Base'} )
174         or return (0, $self->loc("Couldn't parse Base URI: [_1]", $args{Base}));
175
176     my $target = RT::URI->new($self->CurrentUser);
177     $target->FromURI( $args{'Target'} )
178         or return (0, $self->loc("Couldn't parse Target URI: [_1]", $args{Target}));
179
180     my ( $id, $msg ) = $self->LoadByCols( Base   => $base->URI,
181                                           Type   => $args{'Type'},
182                                           Target => $target->URI );
183
184     unless ($id) {
185         return ( 0, $self->loc("Couldn't load link: [_1]", $msg) );
186     } else {
187         return ($id, $msg);
188     }
189 }
190
191
192 =head2 Load
193
194   Load an RT::Link object from the database.  Takes one parameter, the id of an entry in the links table.
195
196
197 =cut
198
199 sub Load {
200     my $self       = shift;
201     my $identifier = shift;
202
203
204
205
206     if ( $identifier !~ /^\d+$/ ) {
207         return ( 0, $self->loc("That's not a numerical id") );
208     }
209     else {
210         my ( $id, $msg ) = $self->LoadById($identifier);
211         unless ( $self->Id ) {
212             return ( 0, $self->loc("Couldn't load link") );
213         }
214         return ( $id, $msg );
215     }
216 }
217
218
219
220
221 =head2 TargetURI
222
223 returns an RT::URI object for the "Target" of this link.
224
225 =cut
226
227 sub TargetURI {
228     my $self = shift;
229     my $URI = RT::URI->new($self->CurrentUser);
230     $URI->FromURI($self->Target);
231     return ($URI);
232 }
233
234
235 =head2 TargetObj
236
237 =cut
238
239 sub TargetObj {
240     my $self = shift;
241     return $self->TargetURI->Object;
242 }
243
244
245 =head2 BaseURI
246
247 returns an RT::URI object for the "Base" of this link.
248
249 =cut
250
251 sub BaseURI {
252     my $self = shift;
253     my $URI = RT::URI->new($self->CurrentUser);
254     $URI->FromURI($self->Base);
255     return ($URI);
256 }
257
258
259 =head2 BaseObj
260
261 =cut
262
263 sub BaseObj {
264   my $self = shift;
265   return $self->BaseURI->Object;
266 }
267
268
269 =head2 id
270
271 Returns the current value of id.
272 (In the database, id is stored as int(11).)
273
274
275 =cut
276
277
278 =head2 Base
279
280 Returns the current value of Base.
281 (In the database, Base is stored as varchar(240).)
282
283
284
285 =head2 SetBase VALUE
286
287
288 Set Base to VALUE.
289 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
290 (In the database, Base will be stored as a varchar(240).)
291
292
293 =cut
294
295
296 =head2 Target
297
298 Returns the current value of Target.
299 (In the database, Target is stored as varchar(240).)
300
301
302
303 =head2 SetTarget VALUE
304
305
306 Set Target to VALUE.
307 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
308 (In the database, Target will be stored as a varchar(240).)
309
310
311 =cut
312
313
314 =head2 Type
315
316 Returns the current value of Type.
317 (In the database, Type is stored as varchar(20).)
318
319
320
321 =head2 SetType VALUE
322
323
324 Set Type to VALUE.
325 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
326 (In the database, Type will be stored as a varchar(20).)
327
328
329 =cut
330
331
332 =head2 LocalTarget
333
334 Returns the current value of LocalTarget.
335 (In the database, LocalTarget is stored as int(11).)
336
337
338
339 =head2 SetLocalTarget VALUE
340
341
342 Set LocalTarget to VALUE.
343 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
344 (In the database, LocalTarget will be stored as a int(11).)
345
346
347 =cut
348
349
350 =head2 LocalBase
351
352 Returns the current value of LocalBase.
353 (In the database, LocalBase is stored as int(11).)
354
355
356
357 =head2 SetLocalBase VALUE
358
359
360 Set LocalBase to VALUE.
361 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
362 (In the database, LocalBase will be stored as a int(11).)
363
364
365 =cut
366
367
368 =head2 LastUpdatedBy
369
370 Returns the current value of LastUpdatedBy.
371 (In the database, LastUpdatedBy is stored as int(11).)
372
373
374 =cut
375
376
377 =head2 LastUpdated
378
379 Returns the current value of LastUpdated.
380 (In the database, LastUpdated is stored as datetime.)
381
382
383 =cut
384
385
386 =head2 Creator
387
388 Returns the current value of Creator.
389 (In the database, Creator is stored as int(11).)
390
391
392 =cut
393
394
395 =head2 Created
396
397 Returns the current value of Created.
398 (In the database, Created is stored as datetime.)
399
400
401 =cut
402
403
404
405 sub _CoreAccessible {
406     {
407
408         id =>
409                 {read => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => ''},
410         Base =>
411                 {read => 1, write => 1, sql_type => 12, length => 240,  is_blob => 0,  is_numeric => 0,  type => 'varchar(240)', default => ''},
412         Target =>
413                 {read => 1, write => 1, sql_type => 12, length => 240,  is_blob => 0,  is_numeric => 0,  type => 'varchar(240)', default => ''},
414         Type =>
415                 {read => 1, write => 1, sql_type => 12, length => 20,  is_blob => 0,  is_numeric => 0,  type => 'varchar(20)', default => ''},
416         LocalTarget =>
417                 {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
418         LocalBase =>
419                 {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
420         LastUpdatedBy =>
421                 {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
422         LastUpdated =>
423                 {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
424         Creator =>
425                 {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
426         Created =>
427                 {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
428
429  }
430 };
431
432 RT::Base->_ImportOverlays();
433
434 1;