-# BEGIN LICENSE BLOCK
-#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-#
-# (Except where explictly superceded by other copyright notices)
-#
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+# <sales@bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
+#
# This work is made available to you under the terms of Version 2 of
# the GNU General Public License. A copy of that license should have
# been provided with this software, but in any event can be snarfed
# from www.gnu.org.
-#
+#
# This work is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
-#
-# Unless otherwise specified, all modifications, corrections or
-# extensions to this work which alter its source code become the
-# property of Best Practical Solutions, LLC when submitted for
-# inclusion in the work.
-#
-#
-# END LICENSE BLOCK
-# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
-# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
-#
-# !! DO NOT EDIT THIS FILE !!
#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
+#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
+
+package RT::CachedGroupMember;
use strict;
+use warnings;
-=head1 NAME
+use base 'RT::Record';
-RT::CachedGroupMember
+sub Table {'CachedGroupMembers'}
+=head1 NAME
+
+ RT::CachedGroupMember
=head1 SYNOPSIS
+ use RT::CachedGroupMember;
+
=head1 DESCRIPTION
=head1 METHODS
=cut
-package RT::CachedGroupMember;
-use RT::Record;
+# {{ Create
+
+=head2 Create PARAMHASH
+Create takes a hash of values and creates a row in the database:
+
+ 'Group' is the "top level" group we're building the cache for. This
+ is an RT::Principal object
+
+ 'Member' is the RT::Principal of the user or group we're adding to
+ the cache.
+
+ 'ImmediateParent' is the RT::Principal of the group that this
+ principal belongs to to get here
+
+ int(11) 'Via' is an internal reference to CachedGroupMembers->Id of
+ the "parent" record of this cached group member. It should be empty if
+ this member is a "direct" member of this group. (In that case, it will
+ be set to this cached group member's id after creation)
-use vars qw( @ISA );
-@ISA= qw( RT::Record );
+ This routine should _only_ be called by GroupMember->Create
-sub _Init {
- my $self = shift;
+=cut
+
+sub Create {
+ my $self = shift;
+ my %args = ( Group => '',
+ Member => '',
+ ImmediateParent => '',
+ Via => '0',
+ Disabled => '0',
+ @_ );
+
+ unless ( $args{'Member'}
+ && UNIVERSAL::isa( $args{'Member'}, 'RT::Principal' )
+ && $args{'Member'}->Id ) {
+ $RT::Logger->debug("$self->Create: bogus Member argument");
+ }
+
+ unless ( $args{'Group'}
+ && UNIVERSAL::isa( $args{'Group'}, 'RT::Principal' )
+ && $args{'Group'}->Id ) {
+ $RT::Logger->debug("$self->Create: bogus Group argument");
+ }
+
+ unless ( $args{'ImmediateParent'}
+ && UNIVERSAL::isa( $args{'ImmediateParent'}, 'RT::Principal' )
+ && $args{'ImmediateParent'}->Id ) {
+ $RT::Logger->debug("$self->Create: bogus ImmediateParent argument");
+ }
+
+ # If the parent group for this group member is disabled, it's disabled too, along with all its children
+ if ( $args{'ImmediateParent'}->Disabled ) {
+ $args{'Disabled'} = $args{'ImmediateParent'}->Disabled;
+ }
+
+ my $id = $self->SUPER::Create(
+ GroupId => $args{'Group'}->Id,
+ MemberId => $args{'Member'}->Id,
+ ImmediateParentId => $args{'ImmediateParent'}->Id,
+ Disabled => $args{'Disabled'},
+ Via => $args{'Via'}, );
+
+ unless ($id) {
+ $RT::Logger->warning( "Couldn't create "
+ . $args{'Member'}
+ . " as a cached member of "
+ . $args{'Group'}->Id . " via "
+ . $args{'Via'} );
+ return (undef); #this will percolate up and bail out of the transaction
+ }
+ if ( $self->__Value('Via') == 0 ) {
+ my ( $vid, $vmsg ) = $self->__Set( Field => 'Via', Value => $id );
+ unless ($vid) {
+ $RT::Logger->warning( "Due to a via error, couldn't create "
+ . $args{'Member'}
+ . " as a cached member of "
+ . $args{'Group'}->Id . " via "
+ . $args{'Via'} );
+ return (undef)
+ ; #this will percolate up and bail out of the transaction
+ }
+ }
+
+ return $id if $args{'Member'}->id == $args{'Group'}->id;
+
+ if ( $args{'Member'}->IsGroup() ) {
+ my $GroupMembers = $args{'Member'}->Object->MembersObj();
+ while ( my $member = $GroupMembers->Next() ) {
+ my $cached_member =
+ RT::CachedGroupMember->new( $self->CurrentUser );
+ my $c_id = $cached_member->Create(
+ Group => $args{'Group'},
+ Member => $member->MemberObj,
+ ImmediateParent => $args{'Member'},
+ Disabled => $args{'Disabled'},
+ Via => $id );
+ unless ($c_id) {
+ return (undef); #percolate the error upwards.
+ # the caller will log an error and abort the transaction
+ }
+
+ }
+ }
+
+ return ($id);
- $self->Table('CachedGroupMembers');
- $self->SUPER::_Init(@_);
}
+=head2 Delete
+Deletes the current CachedGroupMember from the group it's in and cascades
+the delete to all submembers. This routine could be completely excised if
+mysql supported foreign keys with cascading deletes.
-=item Create PARAMHASH
+=cut
-Create takes a hash of values and creates a row in the database:
+sub Delete {
+ my $self = shift;
- int(11) 'GroupId'.
- int(11) 'MemberId'.
- int(11) 'Via'.
- int(11) 'ImmediateParentId'.
- smallint(6) 'Disabled'.
+
+ my $member = $self->MemberObj();
+ if ( $member->IsGroup ) {
+ my $deletable = RT::CachedGroupMembers->new( $self->CurrentUser );
+
+ $deletable->Limit( FIELD => 'id',
+ OPERATOR => '!=',
+ VALUE => $self->id );
+ $deletable->Limit( FIELD => 'Via',
+ OPERATOR => '=',
+ VALUE => $self->id );
+
+ while ( my $kid = $deletable->Next ) {
+ my $kid_err = $kid->Delete();
+ unless ($kid_err) {
+ $RT::Logger->error(
+ "Couldn't delete CachedGroupMember " . $kid->Id );
+ return (undef);
+ }
+ }
+ }
+ my $ret = $self->SUPER::Delete();
+ unless ($ret) {
+ $RT::Logger->error( "Couldn't delete CachedGroupMember " . $self->Id );
+ return (undef);
+ }
+ return $ret;
+}
-=cut
+=head2 SetDisabled
+SetDisableds the current CachedGroupMember from the group it's in and cascades
+the SetDisabled to all submembers. This routine could be completely excised if
+mysql supported foreign keys with cascading SetDisableds.
-sub Create {
+=cut
+
+sub SetDisabled {
my $self = shift;
- my %args = (
- GroupId => '',
- MemberId => '',
- Via => '',
- ImmediateParentId => '',
- Disabled => '0',
-
- @_);
- $self->SUPER::Create(
- GroupId => $args{'GroupId'},
- MemberId => $args{'MemberId'},
- Via => $args{'Via'},
- ImmediateParentId => $args{'ImmediateParentId'},
- Disabled => $args{'Disabled'},
-);
+ my $val = shift;
+
+ # if it's already disabled, we're good.
+ return (1) if ( $self->__Value('Disabled') == $val);
+ my $err = $self->_Set(Field => 'Disabled', Value => $val);
+ my ($retval, $msg) = $err->as_array();
+ unless ($retval) {
+ $RT::Logger->error( "Couldn't SetDisabled CachedGroupMember " . $self->Id .": $msg");
+ return ($err);
+ }
+
+ my $member = $self->MemberObj();
+ if ( $member->IsGroup ) {
+ my $deletable = RT::CachedGroupMembers->new( $self->CurrentUser );
+
+ $deletable->Limit( FIELD => 'Via', OPERATOR => '=', VALUE => $self->id );
+ $deletable->Limit( FIELD => 'id', OPERATOR => '!=', VALUE => $self->id );
+
+ while ( my $kid = $deletable->Next ) {
+ my $kid_err = $kid->SetDisabled($val );
+ unless ($kid_err) {
+ $RT::Logger->error( "Couldn't SetDisabled CachedGroupMember " . $kid->Id );
+ return ($kid_err);
+ }
+ }
+ }
+ return ($err);
+}
+
+
+
+=head2 GroupObj
+
+Returns the RT::Principal object for this group Group
+=cut
+
+sub GroupObj {
+ my $self = shift;
+ my $principal = RT::Principal->new( $self->CurrentUser );
+ $principal->Load( $self->GroupId );
+ return ($principal);
+}
+
+
+
+=head2 ImmediateParentObj
+
+Returns the RT::Principal object for this group ImmediateParent
+
+=cut
+
+sub ImmediateParentObj {
+ my $self = shift;
+ my $principal = RT::Principal->new( $self->CurrentUser );
+ $principal->Load( $self->ImmediateParentId );
+ return ($principal);
}
-=item id
+=head2 MemberObj
+
+Returns the RT::Principal object for this group member
+
+=cut
+
+sub MemberObj {
+ my $self = shift;
+ my $principal = RT::Principal->new( $self->CurrentUser );
+ $principal->Load( $self->MemberId );
+ return ($principal);
+}
+
+# }}}
+
+
+
+
-Returns the current value of id.
+
+=head2 id
+
+Returns the current value of id.
(In the database, id is stored as int(11).)
=cut
-=item GroupId
+=head2 GroupId
-Returns the current value of GroupId.
+Returns the current value of GroupId.
(In the database, GroupId is stored as int(11).)
-=item SetGroupId VALUE
+=head2 SetGroupId VALUE
-Set GroupId to VALUE.
+Set GroupId to VALUE.
Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
(In the database, GroupId will be stored as a int(11).)
=cut
-=item MemberId
+=head2 MemberId
-Returns the current value of MemberId.
+Returns the current value of MemberId.
(In the database, MemberId is stored as int(11).)
-=item SetMemberId VALUE
+=head2 SetMemberId VALUE
-Set MemberId to VALUE.
+Set MemberId to VALUE.
Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
(In the database, MemberId will be stored as a int(11).)
=cut
-=item Via
+=head2 Via
-Returns the current value of Via.
+Returns the current value of Via.
(In the database, Via is stored as int(11).)
-=item SetVia VALUE
+=head2 SetVia VALUE
-Set Via to VALUE.
+Set Via to VALUE.
Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
(In the database, Via will be stored as a int(11).)
=cut
-=item ImmediateParentId
+=head2 ImmediateParentId
-Returns the current value of ImmediateParentId.
+Returns the current value of ImmediateParentId.
(In the database, ImmediateParentId is stored as int(11).)
-=item SetImmediateParentId VALUE
+=head2 SetImmediateParentId VALUE
-Set ImmediateParentId to VALUE.
+Set ImmediateParentId to VALUE.
Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
(In the database, ImmediateParentId will be stored as a int(11).)
=cut
-=item Disabled
+=head2 Disabled
-Returns the current value of Disabled.
+Returns the current value of Disabled.
(In the database, Disabled is stored as smallint(6).)
-=item SetDisabled VALUE
+=head2 SetDisabled VALUE
-Set Disabled to VALUE.
+Set Disabled to VALUE.
Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
(In the database, Disabled will be stored as a smallint(6).)
-sub _ClassAccessible {
+sub _CoreAccessible {
{
-
+
id =>
- {read => 1, type => 'int(11)', default => ''},
- GroupId =>
- {read => 1, write => 1, type => 'int(11)', default => ''},
- MemberId =>
- {read => 1, write => 1, type => 'int(11)', default => ''},
- Via =>
- {read => 1, write => 1, type => 'int(11)', default => ''},
- ImmediateParentId =>
- {read => 1, write => 1, type => 'int(11)', default => ''},
- Disabled =>
- {read => 1, write => 1, type => 'smallint(6)', default => '0'},
+ {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
+ GroupId =>
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
+ MemberId =>
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
+ Via =>
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
+ ImmediateParentId =>
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
+ Disabled =>
+ {read => 1, write => 1, sql_type => 5, length => 6, is_blob => 0, is_numeric => 1, type => 'smallint(6)', default => '0'},
}
};
-
- eval "require RT::CachedGroupMember_Overlay";
- if ($@ && $@ !~ qr{^Can't locate RT/CachedGroupMember_Overlay.pm}) {
- die $@;
- };
-
- eval "require RT::CachedGroupMember_Vendor";
- if ($@ && $@ !~ qr{^Can't locate RT/CachedGroupMember_Vendor.pm}) {
- die $@;
- };
-
- eval "require RT::CachedGroupMember_Local";
- if ($@ && $@ !~ qr{^Can't locate RT/CachedGroupMember_Local.pm}) {
- die $@;
- };
-
-
-
-
-=head1 SEE ALSO
-
-This class allows "overlay" methods to be placed
-into the following files _Overlay is for a System overlay by the original author,
-_Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customizations.
-
-These overlay files can contain new subs or subs to replace existing subs in this module.
-
-If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line
-
- no warnings qw(redefine);
-
-so that perl does not kick and scream when you redefine a subroutine or variable in your overlay.
-
-RT::CachedGroupMember_Overlay, RT::CachedGroupMember_Vendor, RT::CachedGroupMember_Local
-
-=cut
-
+RT::Base->_ImportOverlays();
1;