1 # BEGIN BPS TAGGED BLOCK {{{
5 # This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
6 # <sales@bestpractical.com>
8 # (Except where explicitly superseded by other copyright notices)
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
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.
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.
30 # CONTRIBUTION SUBMISSION POLICY:
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.)
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.
47 # END BPS TAGGED BLOCK }}}
53 use base 'RT::Record';
61 use RT::ObjectClasses;
65 =head2 Load IDENTIFIER
67 Loads a class, either by name or by id
76 if ( $id =~ /^\d+$/ ) {
77 $self->SUPER::Load($id);
80 $self->LoadByCols( Name => $id );
84 # {{{ This object provides ACLs
88 SeeClass => 'See that this class exists', #loc_pair
89 CreateArticle => 'Create articles in this class', #loc_pair
90 ShowArticle => 'See articles in this class', #loc_pair
91 ShowArticleHistory => 'See changes to articles in this class', #loc_pair
92 ModifyArticle => 'Modify or delete articles in this class', #loc_pair
93 ModifyArticleTopics => 'Modify topics for articles in this class', #loc_pair
94 AdminClass => 'Modify metadata and custom fields for this class', #loc_pair
95 AdminTopics => 'Modify topic hierarchy associated with this class', #loc_pair
96 ShowACL => 'Display Access Control List', #loc_pair
97 ModifyACL => 'Modify Access Control List', #loc_pair
98 DeleteArticle => 'Delete articles in this class', #loc_pair
101 our $RIGHT_CATEGORIES = {
103 CreateArticle => 'Staff',
104 ShowArticle => 'General',
105 ShowArticleHistory => 'Staff',
106 ModifyArticle => 'Staff',
107 ModifyArticleTopics => 'Staff',
108 AdminClass => 'Admin',
109 AdminTopics => 'Admin',
111 ModifyACL => 'Admin',
112 DeleteArticle => 'Staff',
115 # TODO: This should be refactored out into an RT::ACLedObject or something
116 # stuff the rights into a hash of rights that can exist.
118 # Tell RT::ACE that this sort of object can get acls granted
119 $RT::ACE::OBJECT_TYPES{'RT::Class'} = 1;
121 # TODO this is ripe for a refacor, since this is stolen from Queue
122 __PACKAGE__->AddRights(%$RIGHTS);
123 __PACKAGE__->AddRightCategories(%$RIGHT_CATEGORIES);
125 =head2 AddRights C<RIGHT>, C<DESCRIPTION> [, ...]
127 Adds the given rights to the list of possible rights. This method
128 should be called during server startup, not at runtime.
135 $RIGHTS = { %$RIGHTS, %new };
136 %RT::ACE::LOWERCASERIGHTNAMES = ( %RT::ACE::LOWERCASERIGHTNAMES,
137 map { lc($_) => $_ } keys %new);
140 =head2 AddRightCategories C<RIGHT>, C<CATEGORY> [, ...]
142 Adds the given right and category pairs to the list of right categories. This
143 method should be called during server startup, not at runtime.
147 sub AddRightCategories {
148 my $self = shift if ref $_[0] or $_[0] eq __PACKAGE__;
150 $RIGHT_CATEGORIES = { %$RIGHT_CATEGORIES, %new };
153 =head2 AvailableRights
155 Returns a hash of available rights for this object. The keys are the right names and the values are a description of what t
160 sub AvailableRights {
165 sub RightCategories {
166 return $RIGHT_CATEGORIES;
175 =head2 Create PARAMHASH
177 Create takes a hash of values and creates a row in the database:
180 varchar(255) 'Description'.
196 $self->CurrentUser->HasRight(
197 Right => 'AdminClass',
198 Object => $RT::System
202 return ( 0, $self->loc('Permission Denied') );
205 $self->SUPER::Create(
206 Name => $args{'Name'},
207 Description => $args{'Description'},
208 SortOrder => $args{'SortOrder'},
209 HotList => $args{'HotList'},
218 return undef unless ($newval);
219 my $obj = RT::Class->new($RT::SystemUser);
221 return undef if ( $obj->Id );
222 return $self->SUPER::ValidateName($newval);
236 unless ( $self->CurrentUserHasRight('AdminClass') ) {
237 return ( 0, $self->loc('Permission Denied') );
239 return ( $self->SUPER::_Set(@_) );
249 unless ( $self->CurrentUserHasRight('SeeClass') ) {
253 return ( $self->__Value(@_) );
258 sub CurrentUserHasRight {
263 $self->CurrentUser->HasRight(
265 Object => ( $self->Id ? $self : $RT::System ),
266 EquivObjects => [ $RT::System, $RT::System ]
272 sub ArticleCustomFields {
276 my $cfs = RT::CustomFields->new( $self->CurrentUser );
277 if ( $self->CurrentUserHasRight('SeeClass') ) {
278 $cfs->LimitToGlobalOrObjectId( $self->Id );
279 $cfs->LimitToLookupType( RT::Article->CustomFieldLookupType );
280 $cfs->ApplySortOrder;
288 Returns collection of Queues this Class is applied to.
289 Doesn't takes into account if object is applied globally.
296 my ($res, $ocfs_alias) = $self->_AppliedTo;
297 return $res unless $res;
300 ALIAS => $ocfs_alias,
302 OPERATOR => 'IS NOT',
311 Returns collection of Queues this Class is not applied to.
313 Doesn't takes into account if object is applied globally.
320 my ($res, $ocfs_alias) = $self->_AppliedTo;
321 return $res unless $res;
324 ALIAS => $ocfs_alias,
336 my $res = RT::Queues->new( $self->CurrentUser );
338 $res->OrderBy( FIELD => 'Name' );
339 my $ocfs_alias = $res->Join(
343 TABLE2 => 'ObjectClasses',
344 FIELD2 => 'ObjectId',
347 LEFTJOIN => $ocfs_alias,
348 ALIAS => $ocfs_alias,
352 return ($res, $ocfs_alias);
357 Takes object id and returns corresponding L<RT::ObjectClass>
358 record if this Class is applied to the object. Use 0 to check
359 if Class is applied globally.
366 return unless defined $id;
367 my $oc = RT::ObjectClass->new( $self->CurrentUser );
368 $oc->LoadByCols( Class=> $self->id, ObjectId => $id,
369 ObjectType => ( $id ? 'RT::Queue' : 'RT::System' ));
370 return undef unless $oc->id;
374 =head2 AddToObject OBJECT
376 Apply this Class to a single object, to start with we support Queues
386 my $id = $object->Id || 0;
388 unless ( $object->CurrentUserHasRight('AdminClass') ) {
389 return ( 0, $self->loc('Permission Denied') );
392 my $queue = RT::Queue->new( $self->CurrentUser );
394 my ($ok, $msg) = $queue->Load( $id );
396 return ( 0, $self->loc('Invalid Queue, unable to apply Class: [_1]',$msg ) );
401 if ( $self->IsApplied( $id ) ) {
402 return ( 0, $self->loc("Class is already applied to [_1]",$queue->Name) );
407 return (0, $self->loc("Class is already applied Globally") )
408 if $self->IsApplied( 0 );
411 my $applied = RT::ObjectClasses->new( $self->CurrentUser );
412 $applied->LimitToClass( $self->id );
413 while ( my $record = $applied->Next ) {
418 my $oc = RT::ObjectClass->new( $self->CurrentUser );
419 my ( $oid, $msg ) = $oc->Create(
420 ObjectId => $id, Class => $self->id,
421 ObjectType => ( $id ? 'RT::Queue' : 'RT::System' ),
423 return ( $oid, $msg );
427 =head2 RemoveFromObject OBJECT
429 Remove this class from a single queue object
433 sub RemoveFromObject {
436 my $id = $object->Id || 0;
438 unless ( $object->CurrentUserHasRight('AdminClass') ) {
439 return ( 0, $self->loc('Permission Denied') );
442 my $ocf = $self->IsApplied( $id );
444 return ( 0, $self->loc("This class does not apply to that object") );
447 # XXX: Delete doesn't return anything
448 my ( $oid, $msg ) = $ocf->Delete;
449 return ( $oid, $msg );
456 Returns the current value of id.
457 (In the database, id is stored as int(11).)
465 Returns the current value of Name.
466 (In the database, Name is stored as varchar(255).)
474 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
475 (In the database, Name will be stored as a varchar(255).)
483 Returns the current value of Description.
484 (In the database, Description is stored as varchar(255).)
488 =head2 SetDescription VALUE
491 Set Description to VALUE.
492 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
493 (In the database, Description will be stored as a varchar(255).)
501 Returns the current value of SortOrder.
502 (In the database, SortOrder is stored as int(11).)
506 =head2 SetSortOrder VALUE
509 Set SortOrder to VALUE.
510 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
511 (In the database, SortOrder will be stored as a int(11).)
519 Returns the current value of Disabled.
520 (In the database, Disabled is stored as int(2).)
524 =head2 SetDisabled VALUE
527 Set Disabled to VALUE.
528 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
529 (In the database, Disabled will be stored as a int(2).)
537 Returns the current value of HotList.
538 (In the database, HotList is stored as int(2).)
542 =head2 SetHotList VALUE
545 Set HotList to VALUE.
546 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
547 (In the database, HotList will be stored as a int(2).)
555 Returns the current value of Creator.
556 (In the database, Creator is stored as int(11).)
564 Returns the current value of Created.
565 (In the database, Created is stored as datetime.)
573 Returns the current value of LastUpdatedBy.
574 (In the database, LastUpdatedBy is stored as int(11).)
582 Returns the current value of LastUpdated.
583 (In the database, LastUpdated is stored as datetime.)
590 sub _CoreAccessible {
594 {read => 1, type => 'int(11)', default => ''},
596 {read => 1, write => 1, type => 'varchar(255)', default => ''},
598 {read => 1, write => 1, type => 'varchar(255)', default => ''},
600 {read => 1, write => 1, type => 'int(11)', default => '0'},
602 {read => 1, write => 1, type => 'int(2)', default => '0'},
604 {read => 1, write => 1, type => 'int(2)', default => '0'},
606 {read => 1, auto => 1, type => 'int(11)', default => '0'},
608 {read => 1, auto => 1, type => 'datetime', default => ''},
610 {read => 1, auto => 1, type => 'int(11)', default => '0'},
612 {read => 1, auto => 1, type => 'datetime', default => ''},
617 RT::Base->_ImportOverlays();