1 # BEGIN BPS TAGGED BLOCK {{{
5 # This software is Copyright (c) 1996-2016 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;
63 use Role::Basic 'with';
64 with "RT::Record::Role::Rights";
68 =head2 Load IDENTIFIER
70 Loads a class, either by name or by id
79 if ( $id =~ /^\d+$/ ) {
80 $self->SUPER::Load($id);
83 $self->LoadByCols( Name => $id );
87 __PACKAGE__->AddRight( Staff => SeeClass => 'See that this class exists'); # loc
88 __PACKAGE__->AddRight( Staff => CreateArticle => 'Create articles in this class'); # loc
89 __PACKAGE__->AddRight( General => ShowArticle => 'See articles in this class'); # loc
90 __PACKAGE__->AddRight( Staff => ShowArticleHistory => 'See changes to articles in this class'); # loc
91 __PACKAGE__->AddRight( General => SeeCustomField => 'View custom field values' ); # loc
92 __PACKAGE__->AddRight( Staff => ModifyArticle => 'Modify or delete articles in this class'); # loc
93 __PACKAGE__->AddRight( Staff => ModifyArticleTopics => 'Modify topics for articles in this class'); # loc
94 __PACKAGE__->AddRight( Staff => ModifyCustomField => 'Modify custom field values' ); # loc
95 __PACKAGE__->AddRight( Admin => AdminClass => 'Modify metadata and custom fields for this class'); # loc
96 __PACKAGE__->AddRight( Admin => AdminTopics => 'Modify topic hierarchy associated with this class'); # loc
97 __PACKAGE__->AddRight( Admin => ShowACL => 'Display Access Control List'); # loc
98 __PACKAGE__->AddRight( Admin => ModifyACL => 'Create, modify and delete Access Control List entries'); # loc
99 __PACKAGE__->AddRight( Staff => DeleteArticle => 'Delete articles in this class'); # loc
103 =head2 Create PARAMHASH
105 Create takes a hash of values and creates a row in the database:
108 varchar(255) 'Description'.
124 $self->CurrentUser->HasRight(
125 Right => 'AdminClass',
126 Object => $RT::System
130 return ( 0, $self->loc('Permission Denied') );
133 $self->SUPER::Create(
134 Name => $args{'Name'},
135 Description => $args{'Description'},
136 SortOrder => $args{'SortOrder'},
137 HotList => $args{'HotList'},
146 return undef unless ($newval);
147 my $obj = RT::Class->new($RT::SystemUser);
149 return undef if $obj->id && ( !$self->id || $self->id != $obj->id );
150 return $self->SUPER::ValidateName($newval);
164 unless ( $self->CurrentUserHasRight('AdminClass') ) {
165 return ( 0, $self->loc('Permission Denied') );
167 return ( $self->SUPER::_Set(@_) );
177 unless ( $self->CurrentUserHasRight('SeeClass') ) {
181 return ( $self->__Value(@_) );
186 sub ArticleCustomFields {
190 my $cfs = RT::CustomFields->new( $self->CurrentUser );
191 if ( $self->CurrentUserHasRight('SeeClass') ) {
192 $cfs->SetContextObject( $self );
193 $cfs->LimitToGlobalOrObjectId( $self->Id );
194 $cfs->LimitToLookupType( RT::Article->CustomFieldLookupType );
195 $cfs->ApplySortOrder;
203 Returns collection of Queues this Class is applied to.
204 Doesn't takes into account if object is applied globally.
211 my ($res, $ocfs_alias) = $self->_AppliedTo;
212 return $res unless $res;
215 ALIAS => $ocfs_alias,
217 OPERATOR => 'IS NOT',
226 Returns collection of Queues this Class is not applied to.
228 Doesn't takes into account if object is applied globally.
235 my ($res, $ocfs_alias) = $self->_AppliedTo;
236 return $res unless $res;
239 ALIAS => $ocfs_alias,
251 my $res = RT::Queues->new( $self->CurrentUser );
253 $res->OrderBy( FIELD => 'Name' );
254 my $ocfs_alias = $res->Join(
258 TABLE2 => 'ObjectClasses',
259 FIELD2 => 'ObjectId',
262 LEFTJOIN => $ocfs_alias,
263 ALIAS => $ocfs_alias,
267 return ($res, $ocfs_alias);
272 Takes object id and returns corresponding L<RT::ObjectClass>
273 record if this Class is applied to the object. Use 0 to check
274 if Class is applied globally.
281 return unless defined $id;
282 my $oc = RT::ObjectClass->new( $self->CurrentUser );
283 $oc->LoadByCols( Class=> $self->id, ObjectId => $id,
284 ObjectType => ( $id ? 'RT::Queue' : 'RT::System' ));
285 return undef unless $oc->id;
289 =head2 AddToObject OBJECT
291 Apply this Class to a single object, to start with we support Queues
301 my $id = $object->Id || 0;
303 unless ( $object->CurrentUserHasRight('AdminClass') ) {
304 return ( 0, $self->loc('Permission Denied') );
307 my $queue = RT::Queue->new( $self->CurrentUser );
309 my ($ok, $msg) = $queue->Load( $id );
311 return ( 0, $self->loc('Invalid Queue, unable to apply Class: [_1]',$msg ) );
316 if ( $self->IsApplied( $id ) ) {
317 return ( 0, $self->loc("Class is already applied to [_1]",$queue->Name) );
322 return (0, $self->loc("Class is already applied Globally") )
323 if $self->IsApplied( 0 );
326 my $applied = RT::ObjectClasses->new( $self->CurrentUser );
327 $applied->LimitToClass( $self->id );
328 while ( my $record = $applied->Next ) {
333 my $oc = RT::ObjectClass->new( $self->CurrentUser );
334 my ( $oid, $msg ) = $oc->Create(
335 ObjectId => $id, Class => $self->id,
336 ObjectType => ( $id ? 'RT::Queue' : 'RT::System' ),
338 return ( $oid, $msg );
342 =head2 RemoveFromObject OBJECT
344 Remove this class from a single queue object
348 sub RemoveFromObject {
351 my $id = $object->Id || 0;
353 unless ( $object->CurrentUserHasRight('AdminClass') ) {
354 return ( 0, $self->loc('Permission Denied') );
357 my $ocf = $self->IsApplied( $id );
359 return ( 0, $self->loc("This class does not apply to that object") );
362 # XXX: Delete doesn't return anything
363 my ( $oid, $msg ) = $ocf->Delete;
364 return ( $oid, $msg );
367 sub SubjectOverride {
369 my $override = $self->FirstAttribute('SubjectOverride');
370 return $override ? $override->Content : 0;
373 sub SetSubjectOverride {
375 my $override = shift;
377 if ( $override == $self->SubjectOverride ) {
378 return (0, "SubjectOverride is already set to that");
381 my $cf = RT::CustomField->new($self->CurrentUser);
382 $cf->Load($override);
385 my ($ok, $msg) = $self->SetAttribute( Name => 'SubjectOverride', Content => $override );
386 return ($ok, $ok ? $self->loc('Added Subject Override: [_1]', $cf->Name) :
387 $self->loc('Unable to add Subject Override: [_1] [_2]', $cf->Name, $msg));
389 my ($ok, $msg) = $self->DeleteAttribute('SubjectOverride');
390 return ($ok, $ok ? $self->loc('Removed Subject Override') :
391 $self->loc('Unable to add Subject Override: [_1] [_2]', $cf->Name, $msg));
397 Returns the current value of id.
398 (In the database, id is stored as int(11).)
406 Returns the current value of Name.
407 (In the database, Name is stored as varchar(255).)
415 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
416 (In the database, Name will be stored as a varchar(255).)
424 Returns the current value of Description.
425 (In the database, Description is stored as varchar(255).)
429 =head2 SetDescription VALUE
432 Set Description to VALUE.
433 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
434 (In the database, Description will be stored as a varchar(255).)
442 Returns the current value of SortOrder.
443 (In the database, SortOrder is stored as int(11).)
447 =head2 SetSortOrder VALUE
450 Set SortOrder to VALUE.
451 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
452 (In the database, SortOrder will be stored as a int(11).)
460 Returns the current value of Disabled.
461 (In the database, Disabled is stored as int(2).)
465 =head2 SetDisabled VALUE
468 Set Disabled to VALUE.
469 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
470 (In the database, Disabled will be stored as a int(2).)
478 Returns the current value of HotList.
479 (In the database, HotList is stored as int(2).)
483 =head2 SetHotList VALUE
486 Set HotList to VALUE.
487 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
488 (In the database, HotList will be stored as a int(2).)
496 Returns the current value of Creator.
497 (In the database, Creator is stored as int(11).)
505 Returns the current value of Created.
506 (In the database, Created is stored as datetime.)
514 Returns the current value of LastUpdatedBy.
515 (In the database, LastUpdatedBy is stored as int(11).)
523 Returns the current value of LastUpdated.
524 (In the database, LastUpdated is stored as datetime.)
531 sub _CoreAccessible {
535 {read => 1, type => 'int(11)', default => ''},
537 {read => 1, write => 1, type => 'varchar(255)', default => ''},
539 {read => 1, write => 1, type => 'varchar(255)', default => ''},
541 {read => 1, write => 1, type => 'int(11)', default => '0'},
543 {read => 1, write => 1, type => 'int(2)', default => '0'},
545 {read => 1, write => 1, type => 'int(2)', default => '0'},
547 {read => 1, auto => 1, type => 'int(11)', default => '0'},
549 {read => 1, auto => 1, type => 'datetime', default => ''},
551 {read => 1, auto => 1, type => 'int(11)', default => '0'},
553 {read => 1, auto => 1, type => 'datetime', default => ''},
558 sub FindDependencies {
560 my ($walker, $deps) = @_;
562 $self->SUPER::FindDependencies($walker, $deps);
564 my $articles = RT::Articles->new( $self->CurrentUser );
565 $articles->Limit( FIELD => "Class", VALUE => $self->Id );
566 $deps->Add( in => $articles );
568 my $topics = RT::Topics->new( $self->CurrentUser );
569 $topics->LimitToObject( $self );
570 $deps->Add( in => $topics );
572 my $objectclasses = RT::ObjectClasses->new( $self->CurrentUser );
573 $objectclasses->LimitToClass( $self->Id );
574 $deps->Add( in => $objectclasses );
576 # Custom Fields on things _in_ this class (CFs on the class itself
577 # have already been dealt with)
578 my $ocfs = RT::ObjectCustomFields->new( $self->CurrentUser );
579 $ocfs->Limit( FIELD => 'ObjectId',
582 ENTRYAGGREGATOR => 'OR' );
583 $ocfs->Limit( FIELD => 'ObjectId',
586 ENTRYAGGREGATOR => 'OR' );
587 my $cfs = $ocfs->Join(
589 FIELD1 => 'CustomField',
590 TABLE2 => 'CustomFields',
593 $ocfs->Limit( ALIAS => $cfs,
594 FIELD => 'LookupType',
595 OPERATOR => 'STARTSWITH',
596 VALUE => 'RT::Class-' );
597 $deps->Add( in => $ocfs );
602 my ($importer, $uid, $data) = @_;
604 $class->SUPER::PreInflate( $importer, $uid, $data );
606 return if $importer->MergeBy( "Name", $class, $uid, $data );
611 RT::Base->_ImportOverlays();