rt 4.2.16
[freeside.git] / rt / lib / RT / Topic.pm
1 # BEGIN BPS TAGGED BLOCK {{{
2 #
3 # COPYRIGHT:
4 #
5 # This software is Copyright (c) 1996-2019 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 use warnings;
50 use strict;
51
52 package RT::Topic;
53 use base 'RT::Record';
54
55 sub Table {'Topics'}
56
57 # {{{ Create
58
59 =head2 Create PARAMHASH
60
61 Create takes a hash of values and creates a row in the database:
62
63   int(11) 'Parent'.
64   varchar(255) 'Name'.
65   varchar(255) 'Description'.
66   varchar(64) 'ObjectType'.
67   int(11) 'ObjectId'.
68
69 =cut
70
71 sub Create {
72     my $self = shift;
73     my %args = (
74                 Parent => '',
75                 Name => '',
76                 Description => '',
77                 ObjectType => '',
78                 ObjectId => '0',
79                 @_);
80
81     my $obj = $RT::System;
82     if ($args{ObjectId}) {
83         $obj = $args{ObjectType}->new($self->CurrentUser);
84         $obj->Load($args{ObjectId});
85         $obj = $RT::System unless $obj->id;
86     }
87
88     return ( 0, $self->loc("Permission Denied"))
89       unless ( $self->CurrentUser->HasRight(
90                                             Right        => "AdminTopics",
91                                             Object       => $obj,
92                                             EquivObjects => [ $RT::System, $obj ],
93                                            ) );
94
95     $self->SUPER::Create(@_);
96 }
97
98 # }}}
99
100
101 # {{{ Delete
102
103 =head2 Delete
104
105 Deletes this topic, reparenting all sub-topics to this one's parent.
106
107 =cut
108
109 sub Delete {
110     my $self = shift;
111     
112     unless ( $self->CurrentUserHasRight('AdminTopics') ) {
113         return ( 0, $self->loc("Permission Denied") );
114     }
115
116     my $kids = RT::Topics->new($self->CurrentUser);
117     $kids->LimitToKids($self->Id);
118     while (my $topic = $kids->Next) {
119         $topic->setParent($self->Parent);
120     }
121
122     $self->SUPER::Delete(@_);
123     return (0, "Topic deleted");
124 }
125
126 # }}}
127
128
129 # {{{ DeleteAll
130
131 =head2 DeleteAll
132
133 Deletes this topic, and all of its descendants.
134
135 =cut
136
137 sub DeleteAll {
138     my $self = shift;
139     
140     unless ( $self->CurrentUserHasRight('AdminTopics') ) {
141         return ( 0, $self->loc("Permission Denied") );
142     }
143
144     $self->SUPER::Delete(@_);
145     my $kids = RT::Topics->new($self->CurrentUser);
146     $kids->LimitToKids($self->Id);
147     while (my $topic = $kids->Next) {
148         $topic->DeleteAll;
149     }
150
151     return (0, "Topic tree deleted");
152 }
153
154 # }}}
155
156
157 # {{{ ParentObj
158
159 =head2 ParentObj
160
161 Returns the parent Topic of this one.
162
163 =cut
164
165 sub ParentObj {
166   my $self = shift;
167   my $id = $self->Parent;
168   my $obj = RT::Topic->new($self->CurrentUser);
169   $obj->Load($id);
170   return $obj;
171 }
172
173 # }}}
174
175 # {{{ Children
176
177 =head2 Children
178
179 Returns a Topics object containing this topic's children,
180 sorted by Topic.Name.
181
182 =cut
183
184 sub Children {
185     my $self = shift;
186     unless ($self->{'Children'}) {
187         $self->{'Children'} = RT::Topics->new($self->CurrentUser);
188         $self->{'Children'}->Limit('FIELD' => 'Parent',
189                                    'VALUE' => $self->Id);
190         $self->{'Children'}->OrderBy('FIELD' => 'Name');
191     }
192     return $self->{'Children'};
193 }
194
195 # {{{ _Set
196
197 =head2 _Set
198
199 Intercept attempts to modify the Topic so we can apply ACLs
200
201 =cut
202
203 sub _Set {
204     my $self = shift;
205     
206     unless ( $self->CurrentUserHasRight('AdminTopics') ) {
207         return ( 0, $self->loc("Permission Denied") );
208     }
209     $self->SUPER::_Set(@_);
210 }
211
212 # }}}
213
214
215 =head2 ACLEquivalenceObjects
216
217 Rights on the topic are inherited from the object it is a topic on.
218
219 =cut
220
221 sub ACLEquivalenceObjects {
222     my $self  = shift;
223     return unless $self->id and $self->ObjectId;
224
225     return $self->Object;
226 }
227
228
229 sub Object {
230     my $self  = shift;
231     my $Object = $self->__Value('ObjectType')->new( $self->CurrentUser );
232     $Object->Load( $self->__Value('ObjectId') );
233     return $Object;
234 }
235
236 =head2 id
237
238 Returns the current value of id. 
239 (In the database, id is stored as int(11).)
240
241
242 =cut
243
244
245 =head2 Parent
246
247 Returns the current value of Parent. 
248 (In the database, Parent is stored as int(11).)
249
250
251
252 =head2 SetParent VALUE
253
254
255 Set Parent to VALUE. 
256 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
257 (In the database, Parent will be stored as a int(11).)
258
259
260 =cut
261
262
263 =head2 Name
264
265 Returns the current value of Name. 
266 (In the database, Name is stored as varchar(255).)
267
268
269
270 =head2 SetName VALUE
271
272
273 Set Name to VALUE. 
274 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
275 (In the database, Name will be stored as a varchar(255).)
276
277
278 =cut
279
280
281 =head2 Description
282
283 Returns the current value of Description. 
284 (In the database, Description is stored as varchar(255).)
285
286
287
288 =head2 SetDescription VALUE
289
290
291 Set Description to VALUE. 
292 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
293 (In the database, Description will be stored as a varchar(255).)
294
295
296 =cut
297
298
299 =head2 ObjectType
300
301 Returns the current value of ObjectType. 
302 (In the database, ObjectType is stored as varchar(64).)
303
304
305
306 =head2 SetObjectType VALUE
307
308
309 Set ObjectType to VALUE. 
310 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
311 (In the database, ObjectType will be stored as a varchar(64).)
312
313
314 =cut
315
316
317 =head2 ObjectId
318
319 Returns the current value of ObjectId. 
320 (In the database, ObjectId is stored as int(11).)
321
322
323
324 =head2 SetObjectId VALUE
325
326
327 Set ObjectId to VALUE. 
328 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
329 (In the database, ObjectId will be stored as a int(11).)
330
331
332 =cut
333
334
335
336 sub _CoreAccessible {
337     {
338      
339         id =>
340                 {read => 1, type => 'int(11)', default => ''},
341         Parent => 
342                 {read => 1, write => 1, type => 'int(11)', default => ''},
343         Name => 
344                 {read => 1, write => 1, type => 'varchar(255)', default => ''},
345         Description => 
346                 {read => 1, write => 1, type => 'varchar(255)', default => ''},
347         ObjectType => 
348                 {read => 1, write => 1, type => 'varchar(64)', default => ''},
349         ObjectId => 
350                 {read => 1, write => 1, type => 'int(11)', default => '0'},
351
352  }
353 };
354
355 sub FindDependencies {
356     my $self = shift;
357     my ($walker, $deps) = @_;
358
359     $self->SUPER::FindDependencies($walker, $deps);
360     $deps->Add( out => $self->ParentObj ) if $self->ParentObj->Id;
361     $deps->Add( in  => $self->Children );
362     $deps->Add( out => $self->Object );
363 }
364
365 RT::Base->_ImportOverlays();
366 1;