1 # BEGIN BPS TAGGED BLOCK {{{
5 # This software is Copyright (c) 1996-2014 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 => 'Create, modify and delete Access Control List entries', #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 && ( !$self->id || $self->id != $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->SetContextObject( $self );
279 $cfs->LimitToGlobalOrObjectId( $self->Id );
280 $cfs->LimitToLookupType( RT::Article->CustomFieldLookupType );
281 $cfs->ApplySortOrder;
289 Returns collection of Queues this Class is applied to.
290 Doesn't takes into account if object is applied globally.
297 my ($res, $ocfs_alias) = $self->_AppliedTo;
298 return $res unless $res;
301 ALIAS => $ocfs_alias,
303 OPERATOR => 'IS NOT',
312 Returns collection of Queues this Class is not applied to.
314 Doesn't takes into account if object is applied globally.
321 my ($res, $ocfs_alias) = $self->_AppliedTo;
322 return $res unless $res;
325 ALIAS => $ocfs_alias,
337 my $res = RT::Queues->new( $self->CurrentUser );
339 $res->OrderBy( FIELD => 'Name' );
340 my $ocfs_alias = $res->Join(
344 TABLE2 => 'ObjectClasses',
345 FIELD2 => 'ObjectId',
348 LEFTJOIN => $ocfs_alias,
349 ALIAS => $ocfs_alias,
353 return ($res, $ocfs_alias);
358 Takes object id and returns corresponding L<RT::ObjectClass>
359 record if this Class is applied to the object. Use 0 to check
360 if Class is applied globally.
367 return unless defined $id;
368 my $oc = RT::ObjectClass->new( $self->CurrentUser );
369 $oc->LoadByCols( Class=> $self->id, ObjectId => $id,
370 ObjectType => ( $id ? 'RT::Queue' : 'RT::System' ));
371 return undef unless $oc->id;
375 =head2 AddToObject OBJECT
377 Apply this Class to a single object, to start with we support Queues
387 my $id = $object->Id || 0;
389 unless ( $object->CurrentUserHasRight('AdminClass') ) {
390 return ( 0, $self->loc('Permission Denied') );
393 my $queue = RT::Queue->new( $self->CurrentUser );
395 my ($ok, $msg) = $queue->Load( $id );
397 return ( 0, $self->loc('Invalid Queue, unable to apply Class: [_1]',$msg ) );
402 if ( $self->IsApplied( $id ) ) {
403 return ( 0, $self->loc("Class is already applied to [_1]",$queue->Name) );
408 return (0, $self->loc("Class is already applied Globally") )
409 if $self->IsApplied( 0 );
412 my $applied = RT::ObjectClasses->new( $self->CurrentUser );
413 $applied->LimitToClass( $self->id );
414 while ( my $record = $applied->Next ) {
419 my $oc = RT::ObjectClass->new( $self->CurrentUser );
420 my ( $oid, $msg ) = $oc->Create(
421 ObjectId => $id, Class => $self->id,
422 ObjectType => ( $id ? 'RT::Queue' : 'RT::System' ),
424 return ( $oid, $msg );
428 =head2 RemoveFromObject OBJECT
430 Remove this class from a single queue object
434 sub RemoveFromObject {
437 my $id = $object->Id || 0;
439 unless ( $object->CurrentUserHasRight('AdminClass') ) {
440 return ( 0, $self->loc('Permission Denied') );
443 my $ocf = $self->IsApplied( $id );
445 return ( 0, $self->loc("This class does not apply to that object") );
448 # XXX: Delete doesn't return anything
449 my ( $oid, $msg ) = $ocf->Delete;
450 return ( $oid, $msg );
457 Returns the current value of id.
458 (In the database, id is stored as int(11).)
466 Returns the current value of Name.
467 (In the database, Name is stored as varchar(255).)
475 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
476 (In the database, Name will be stored as a varchar(255).)
484 Returns the current value of Description.
485 (In the database, Description is stored as varchar(255).)
489 =head2 SetDescription VALUE
492 Set Description to VALUE.
493 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
494 (In the database, Description will be stored as a varchar(255).)
502 Returns the current value of SortOrder.
503 (In the database, SortOrder is stored as int(11).)
507 =head2 SetSortOrder VALUE
510 Set SortOrder to VALUE.
511 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
512 (In the database, SortOrder will be stored as a int(11).)
520 Returns the current value of Disabled.
521 (In the database, Disabled is stored as int(2).)
525 =head2 SetDisabled VALUE
528 Set Disabled to VALUE.
529 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
530 (In the database, Disabled will be stored as a int(2).)
538 Returns the current value of HotList.
539 (In the database, HotList is stored as int(2).)
543 =head2 SetHotList VALUE
546 Set HotList to VALUE.
547 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
548 (In the database, HotList will be stored as a int(2).)
556 Returns the current value of Creator.
557 (In the database, Creator is stored as int(11).)
565 Returns the current value of Created.
566 (In the database, Created is stored as datetime.)
574 Returns the current value of LastUpdatedBy.
575 (In the database, LastUpdatedBy is stored as int(11).)
583 Returns the current value of LastUpdated.
584 (In the database, LastUpdated is stored as datetime.)
591 sub _CoreAccessible {
595 {read => 1, type => 'int(11)', default => ''},
597 {read => 1, write => 1, type => 'varchar(255)', default => ''},
599 {read => 1, write => 1, type => 'varchar(255)', default => ''},
601 {read => 1, write => 1, type => 'int(11)', default => '0'},
603 {read => 1, write => 1, type => 'int(2)', default => '0'},
605 {read => 1, write => 1, type => 'int(2)', default => '0'},
607 {read => 1, auto => 1, type => 'int(11)', default => '0'},
609 {read => 1, auto => 1, type => 'datetime', default => ''},
611 {read => 1, auto => 1, type => 'int(11)', default => '0'},
613 {read => 1, auto => 1, type => 'datetime', default => ''},
618 RT::Base->_ImportOverlays();