+ my %args = (
+ Name => undef,
+ Description => '',
+ CorrespondAddress => '',
+ CommentAddress => '',
+ Lifecycle => 'default',
+ SubjectTag => undef,
+ InitialPriority => 0,
+ FinalPriority => 0,
+ DefaultDueIn => 0,
+ Sign => undef,
+ SignAuto => undef,
+ Encrypt => undef,
+ _RecordTransaction => 1,
+ @_
+ );
+
+ unless ( $self->CurrentUser->HasRight(Right => 'AdminQueue', Object => $RT::System) )
+ { #Check them ACLs
+ return ( 0, $self->loc("No permission to create queues") );
+ }
+
+ {
+ my ($val, $msg) = $self->_ValidateName( $args{'Name'} );
+ return ($val, $msg) unless $val;
+ }
+
+ if ( $args{'Lifecycle'} && $args{'Lifecycle'} ne 'default' ) {
+ return ( 0, $self->loc('Invalid lifecycle name') )
+ unless $self->ValidateLifecycle( $args{'Lifecycle'} );
+ } else {
+ $args{'Lifecycle'} = undef;
+ }
+
+ my %attrs = map {$_ => 1} $self->ReadableAttributes;
+
+ #TODO better input validation
+ $RT::Handle->BeginTransaction();
+ my $id = $self->SUPER::Create( map { $_ => $args{$_} } grep exists $args{$_}, keys %attrs );
+ unless ($id) {
+ $RT::Handle->Rollback();
+ return ( 0, $self->loc('Queue could not be created') );
+ }
+
+ my $create_ret = $self->_CreateQueueGroups();
+ unless ($create_ret) {
+ $RT::Handle->Rollback();
+ return ( 0, $self->loc('Queue could not be created') );
+ }
+ if ( $args{'_RecordTransaction'} ) {
+ $self->_NewTransaction( Type => "Create" );
+ }
+ $RT::Handle->Commit;
+
+ for my $attr (qw/Sign SignAuto Encrypt/) {
+ next unless defined $args{$attr};
+ my $set = "Set" . $attr;
+ my ($status, $msg) = $self->$set( $args{$attr} );
+ $RT::Logger->error("Couldn't set attribute '$attr': $msg")
+ unless $status;
+ }
+
+ RT->System->QueueCacheNeedsUpdate(1);
+
+ return ( $id, $self->loc("Queue created") );
+}
+
+
+
+sub Delete {
+ my $self = shift;
+ return ( 0,
+ $self->loc('Deleting this object would break referential integrity') );
+}
+
+
+
+=head2 SetDisabled
+
+Takes a boolean.
+1 will cause this queue to no longer be available for tickets.
+0 will re-enable this queue.
+
+=cut
+
+sub SetDisabled {
+ my $self = shift;
+ my $val = shift;
+
+ $RT::Handle->BeginTransaction();
+ my $set_err = $self->_Set( Field =>'Disabled', Value => $val);
+ unless ($set_err) {
+ $RT::Handle->Rollback();
+ $RT::Logger->warning("Couldn't ".($val == 1) ? "disable" : "enable"." queue ".$self->PrincipalObj->Id);
+ return (undef);
+ }
+ $self->_NewTransaction( Type => ($val == 1) ? "Disabled" : "Enabled" );
+
+ $RT::Handle->Commit();
+
+ RT->System->QueueCacheNeedsUpdate(1);
+
+ if ( $val == 1 ) {
+ return (1, $self->loc("Queue disabled"));
+ } else {
+ return (1, $self->loc("Queue enabled"));
+ }
+
+}
+
+
+
+=head2 Load
+
+Takes either a numerical id or a textual Name and loads the specified queue.
+
+=cut
+
+sub Load {
+ my $self = shift;
+
+ my $identifier = shift;
+ if ( !$identifier ) {
+ return (undef);
+ }
+
+ if ( $identifier =~ /^(\d+)$/ ) {
+ $self->SUPER::LoadById($identifier);
+ }
+ else {
+ $self->LoadByCols( Name => $identifier );
+ }
+
+ return ( $self->Id );
+
+}
+
+
+
+=head2 ValidateName NAME
+
+Takes a queue name. Returns true if it's an ok name for
+a new queue. Returns undef if there's already a queue by that name.
+
+=cut
+
+sub ValidateName {
+ my $self = shift;
+ my $name = shift;
+
+ my ($ok, $msg) = $self->_ValidateName($name);
+
+ return $ok ? 1 : 0;
+}
+
+sub _ValidateName {
+ my $self = shift;
+ my $name = shift;
+
+ return (undef, "Queue name is required") unless length $name;
+
+ # Validate via the superclass first
+ # Case: short circuit if it's an integer so we don't have
+ # fale negatives when loading a temp queue
+ unless ( my $q = $self->SUPER::ValidateName($name) ) {
+ return ($q, $self->loc("'[_1]' is not a valid name.", $name));
+ }
+
+ my $tempqueue = RT::Queue->new(RT->SystemUser);
+ $tempqueue->Load($name);
+
+ #If this queue exists, return undef
+ if ( $tempqueue->Name() && $tempqueue->id != $self->id) {
+ return (undef, $self->loc("Queue already exists") );
+ }
+
+ return (1);
+}
+
+
+=head2 SetSign
+
+=cut
+
+sub Sign {
+ my $self = shift;
+ my $value = shift;
+
+ return undef unless $self->CurrentUserHasRight('SeeQueue');
+ my $attr = $self->FirstAttribute('Sign') or return 0;
+ return $attr->Content;
+}
+
+sub SetSign {
+ my $self = shift;
+ my $value = shift;
+
+ return ( 0, $self->loc('Permission Denied') )
+ unless $self->CurrentUserHasRight('AdminQueue');
+
+ my ($status, $msg) = $self->SetAttribute(
+ Name => 'Sign',
+ Description => 'Sign outgoing messages by default',
+ Content => $value,
+ );
+ return ($status, $msg) unless $status;
+ return ($status, $self->loc('Signing enabled')) if $value;
+ return ($status, $self->loc('Signing disabled'));
+}
+
+sub SignAuto {
+ my $self = shift;
+ my $value = shift;
+
+ return undef unless $self->CurrentUserHasRight('SeeQueue');
+ my $attr = $self->FirstAttribute('SignAuto') or return 0;
+ return $attr->Content;
+}
+
+sub SetSignAuto {
+ my $self = shift;
+ my $value = shift;
+
+ return ( 0, $self->loc('Permission Denied') )
+ unless $self->CurrentUserHasRight('AdminQueue');
+
+ my ($status, $msg) = $self->SetAttribute(
+ Name => 'SignAuto',
+ Description => 'Sign auto-generated outgoing messages',
+ Content => $value,
+ );
+ return ($status, $msg) unless $status;
+ return ($status, $self->loc('Signing enabled')) if $value;
+ return ($status, $self->loc('Signing disabled'));
+}
+
+sub Encrypt {
+ my $self = shift;
+ my $value = shift;
+
+ return undef unless $self->CurrentUserHasRight('SeeQueue');
+ my $attr = $self->FirstAttribute('Encrypt') or return 0;
+ return $attr->Content;
+}
+
+sub SetEncrypt {
+ my $self = shift;
+ my $value = shift;
+
+ return ( 0, $self->loc('Permission Denied') )
+ unless $self->CurrentUserHasRight('AdminQueue');
+
+ my ($status, $msg) = $self->SetAttribute(
+ Name => 'Encrypt',
+ Description => 'Encrypt outgoing messages by default',
+ Content => $value,
+ );
+ return ($status, $msg) unless $status;
+ return ($status, $self->loc('Encrypting enabled')) if $value;
+ return ($status, $self->loc('Encrypting disabled'));
+}
+
+=head2 Templates
+
+Returns an RT::Templates object of all of this queue's templates.
+
+=cut
+
+sub Templates {
+ my $self = shift;
+
+ my $templates = RT::Templates->new( $self->CurrentUser );
+
+ if ( $self->CurrentUserHasRight('ShowTemplate') ) {
+ $templates->LimitToQueue( $self->id );
+ }
+
+ return ($templates);
+}
+
+
+
+
+=head2 CustomField NAME
+
+Load the queue-specific custom field named NAME
+
+=cut
+
+sub CustomField {
+ my $self = shift;
+ my $name = shift;
+ my $cf = RT::CustomField->new($self->CurrentUser);
+ $cf->LoadByNameAndQueue(Name => $name, Queue => $self->Id);
+ return ($cf);
+}
+
+
+
+=head2 TicketCustomFields
+
+Returns an L<RT::CustomFields> object containing all global and
+queue-specific B<ticket> custom fields.
+
+=cut
+
+sub TicketCustomFields {
+ my $self = shift;
+
+ my $cfs = RT::CustomFields->new( $self->CurrentUser );
+ if ( $self->CurrentUserHasRight('SeeQueue') ) {
+ $cfs->SetContextObject( $self );
+ $cfs->LimitToGlobalOrObjectId( $self->Id );
+ $cfs->LimitToLookupType( 'RT::Queue-RT::Ticket' );
+ $cfs->ApplySortOrder;
+ }
+ return ($cfs);
+}
+
+
+
+=head2 TicketTransactionCustomFields
+
+Returns an L<RT::CustomFields> object containing all global and
+queue-specific B<transaction> custom fields.
+
+=cut
+
+sub TicketTransactionCustomFields {
+ my $self = shift;
+
+ my $cfs = RT::CustomFields->new( $self->CurrentUser );
+ if ( $self->CurrentUserHasRight('SeeQueue') ) {
+ $cfs->SetContextObject( $self );
+ $cfs->LimitToGlobalOrObjectId( $self->Id );
+ $cfs->LimitToLookupType( 'RT::Queue-RT::Ticket-RT::Transaction' );
+ $cfs->ApplySortOrder;
+ }
+ return ($cfs);
+}
+
+
+
+
+
+=head2 AllRoleGroupTypes
+
+Returns a list of the names of the various role group types that this queue
+has, including Requestor and Owner. If you don't want them, see
+L</ManageableRoleGroupTypes>.
+
+=cut
+
+sub AllRoleGroupTypes {
+ my $self = shift;
+ return ($self->ManageableRoleGroupTypes, qw(Requestor Owner));
+}
+
+=head2 IsRoleGroupType
+
+Returns whether the passed-in type is a role group type.
+
+=cut
+
+sub IsRoleGroupType {
+ my $self = shift;
+ my $type = shift;
+
+ for my $valid_type ($self->AllRoleGroupTypes) {
+ return 1 if $type eq $valid_type;
+ }
+
+ return 0;
+}
+
+=head2 ManageableRoleGroupTypes
+
+Returns a list of the names of the various role group types that this queue
+has, excluding Requestor and Owner. If you want them, see L</AllRoleGroupTypes>.
+
+=cut
+
+sub ManageableRoleGroupTypes {
+ return qw(Cc AdminCc);
+}
+
+=head2 IsManageableRoleGroupType
+
+Returns whether the passed-in type is a manageable role group type.
+
+=cut
+
+sub IsManageableRoleGroupType {
+ my $self = shift;
+ my $type = shift;
+
+ for my $valid_type ($self->ManageableRoleGroupTypes) {
+ return 1 if $type eq $valid_type;
+ }
+
+ return 0;
+}
+
+
+=head2 _CreateQueueGroups
+
+Create the ticket groups and links for this ticket.
+This routine expects to be called from Ticket->Create _inside of a transaction_
+
+It will create four groups for this ticket: Requestor, Cc, AdminCc and Owner.
+
+It will return true on success and undef on failure.
+
+
+=cut
+
+sub _CreateQueueGroups {
+ my $self = shift;
+
+ my @types = $self->AllRoleGroupTypes;
+
+ foreach my $type (@types) {
+ my $ok = $self->_CreateQueueRoleGroup($type);
+ return undef if !$ok;
+ }
+
+ return 1;
+}
+
+sub _CreateQueueRoleGroup {
+ my $self = shift;
+ my $type = shift;
+
+ my $type_obj = RT::Group->new($self->CurrentUser);
+ my ($id, $msg) = $type_obj->CreateRoleGroup(Instance => $self->Id,
+ Type => $type,
+ Domain => 'RT::Queue-Role');
+ unless ($id) {
+ $RT::Logger->error("Couldn't create a Queue group of type '$type' for queue ".
+ $self->Id.": ".$msg);
+ return(undef);
+ }
+
+ return $id;
+}
+
+
+
+# _HasModifyWatcherRight {{{
+sub _HasModifyWatcherRight {
+ my $self = shift;
+ my %args = (
+ Type => undef,
+ PrincipalId => undef,
+ Email => undef,
+ @_
+ );
+
+ return 1 if $self->CurrentUserHasRight('ModifyQueueWatchers');
+
+ #If the watcher we're trying to add is for the current user
+ if ( defined $args{'PrincipalId'} && $self->CurrentUser->PrincipalId eq $args{'PrincipalId'}) {
+ if ( $args{'Type'} eq 'AdminCc' ) {
+ return 1 if $self->CurrentUserHasRight('WatchAsAdminCc');
+ }
+ elsif ( $args{'Type'} eq 'Cc' or $args{'Type'} eq 'Requestor' ) {
+ return 1 if $self->CurrentUserHasRight('Watch');
+ }
+ else {
+ $RT::Logger->warning( "$self -> _HasModifyWatcher got passed a bogus type $args{Type}");
+ return ( 0, $self->loc('Invalid queue role group type [_1]', $args{Type}) );
+ }
+ }
+
+ return ( 0, $self->loc("Permission Denied") );
+}
+
+
+=head2 AddWatcher