eliminate some noisy warnings so we can see anything important
[freeside.git] / rt / lib / RT / Topic.pm
1 # BEGIN BPS TAGGED BLOCK {{{
2 #
3 # COPYRIGHT:
4 #
5 # This software is Copyright (c) 1996-2012 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 # {{{ CurrentUserHasRight
216
217 =head2 CurrentUserHasRight
218
219 Returns true if the current user has the right for this topic, for the
220 whole system or for whatever object this topic is associated with
221
222 =cut
223
224 sub CurrentUserHasRight {
225     my $self  = shift;
226     my $right = shift;
227
228     my $equiv = [ $RT::System ];
229     if ($self->ObjectId) {
230         my $obj = $self->ObjectType->new($self->CurrentUser);
231         $obj->Load($self->ObjectId);
232         push @{$equiv}, $obj;
233     }
234     if ($self->Id) {
235         return ( $self->CurrentUser->HasRight(
236                                               Right        => $right,
237                                               Object       => $self,
238                                               EquivObjects => $equiv,
239                                              ) );
240     } else {
241         # If we don't have an ID, we don't even know what object we're
242         # attached to -- so the only thing we can fall back on is the
243         # system object.
244         return ( $self->CurrentUser->HasRight(
245                                               Right        => $right,
246                                               Object       => $RT::System,
247                                              ) );
248     }
249     
250
251 }
252
253 # }}}
254
255
256 =head2 id
257
258 Returns the current value of id. 
259 (In the database, id is stored as int(11).)
260
261
262 =cut
263
264
265 =head2 Parent
266
267 Returns the current value of Parent. 
268 (In the database, Parent is stored as int(11).)
269
270
271
272 =head2 SetParent VALUE
273
274
275 Set Parent to VALUE. 
276 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
277 (In the database, Parent will be stored as a int(11).)
278
279
280 =cut
281
282
283 =head2 Name
284
285 Returns the current value of Name. 
286 (In the database, Name is stored as varchar(255).)
287
288
289
290 =head2 SetName VALUE
291
292
293 Set Name to VALUE. 
294 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
295 (In the database, Name will be stored as a varchar(255).)
296
297
298 =cut
299
300
301 =head2 Description
302
303 Returns the current value of Description. 
304 (In the database, Description is stored as varchar(255).)
305
306
307
308 =head2 SetDescription VALUE
309
310
311 Set Description to VALUE. 
312 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
313 (In the database, Description will be stored as a varchar(255).)
314
315
316 =cut
317
318
319 =head2 ObjectType
320
321 Returns the current value of ObjectType. 
322 (In the database, ObjectType is stored as varchar(64).)
323
324
325
326 =head2 SetObjectType VALUE
327
328
329 Set ObjectType to VALUE. 
330 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
331 (In the database, ObjectType will be stored as a varchar(64).)
332
333
334 =cut
335
336
337 =head2 ObjectId
338
339 Returns the current value of ObjectId. 
340 (In the database, ObjectId is stored as int(11).)
341
342
343
344 =head2 SetObjectId VALUE
345
346
347 Set ObjectId to VALUE. 
348 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
349 (In the database, ObjectId will be stored as a int(11).)
350
351
352 =cut
353
354
355
356 sub _CoreAccessible {
357     {
358      
359         id =>
360                 {read => 1, type => 'int(11)', default => ''},
361         Parent => 
362                 {read => 1, write => 1, type => 'int(11)', default => ''},
363         Name => 
364                 {read => 1, write => 1, type => 'varchar(255)', default => ''},
365         Description => 
366                 {read => 1, write => 1, type => 'varchar(255)', default => ''},
367         ObjectType => 
368                 {read => 1, write => 1, type => 'varchar(64)', default => ''},
369         ObjectId => 
370                 {read => 1, write => 1, type => 'int(11)', default => '0'},
371
372  }
373 };
374
375 RT::Base->_ImportOverlays();
376 1;