[Bps-public-commit] r17011 - in RT-Extension-MergeUsers/trunk: . lib/RT/Extension
falcone at bestpractical.com
falcone at bestpractical.com
Sun Nov 23 18:48:03 EST 2008
Author: falcone
Date: Sun Nov 23 18:48:03 2008
New Revision: 17011
Removed:
RT-Extension-MergeUsers/trunk/lib/RT/User_Vendor.pm
RT-Extension-MergeUsers/trunk/lib/RT/Users_Vendor.pm
Modified:
RT-Extension-MergeUsers/trunk/ (props changed)
RT-Extension-MergeUsers/trunk/lib/RT/Extension/MergeUsers.pm
Log:
r41881 at ketch: falcone | 2008-11-23 18:10:16 -0500
* fold User* code into the extension .pm
Modified: RT-Extension-MergeUsers/trunk/lib/RT/Extension/MergeUsers.pm
==============================================================================
--- RT-Extension-MergeUsers/trunk/lib/RT/Extension/MergeUsers.pm (original)
+++ RT-Extension-MergeUsers/trunk/lib/RT/Extension/MergeUsers.pm Sun Nov 23 18:48:03 2008
@@ -1,5 +1,259 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2008 Best Practical Solutions, LLC
+# <sales at 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.
+#
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# 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 }}}
+use strict;
+use warnings; no warnings qw(redefine);
+
package RT::Extension::MergeUsers;
-our $VERSION = '0.02';
+our $VERSION = '0.03_01';
+
+package RT::User;
+
+our %EFFECTIVE_ID_CACHE;
+
+use RT::Interface::Web::Handler;
+use Hook::LexWrap;
+
+{ my $i = 0;
+wrap 'RT::Interface::Web::Handler::CleanupRequest' => sub {
+ return if ++$i%100; # flush cache every N requests
+ %EFFECTIVE_ID_CACHE = ();
+}; }
+
+sub CanonicalizeEmailAddress {
+ my $self = shift;
+ my $address = shift;
+
+ if ($RT::CanonicalizeEmailAddressMatch && $RT::CanonicalizeEmailAddressReplace ) {
+ $address =~ s/$RT::CanonicalizeEmailAddressMatch/$RT::CanonicalizeEmailAddressReplace/gi;
+ }
+
+ # get the user whose email address this is
+ my $canonical_user = RT::User->new($RT::SystemUser);
+ $canonical_user->LoadByCols( EmailAddress => $address );
+ return $address unless $canonical_user->id;
+
+ # if we got a user, check for a parent
+ my ($effective_id) = $canonical_user->Attributes->Named("EffectiveId");
+ return $address unless $effective_id && $effective_id->id;
+
+ $canonical_user->LoadByCols( id => $effective_id->Content );
+ return $address unless $canonical_user->id;
+
+ # is there another parent user above this one?
+ return $canonical_user->CanonicalizeEmailAddress(
+ $canonical_user->EmailAddress
+ );
+}
+
+sub LoadByCols {
+ my $self = shift;
+ $self->SUPER::LoadByCols(@_);
+ return $self->id unless my $oid = $self->id;
+
+ unless ( exists $EFFECTIVE_ID_CACHE{ $oid } ) {
+ my $effective_id = RT::Attribute->new( $RT::SystemUser );
+ $effective_id->LoadByCols(
+ Name => 'EffectiveId',
+ ObjectType => ref($self) || $self,
+ ObjectId => $oid,
+ );
+ if ( $effective_id->id && $effective_id->Content && $effective_id->Content != $oid ) {
+ $self->LoadByCols( id => $effective_id->Content );
+ $EFFECTIVE_ID_CACHE{ $oid } = $self->id;
+ } else {
+ $EFFECTIVE_ID_CACHE{ $oid } = undef;
+ }
+ }
+ elsif ( defined $EFFECTIVE_ID_CACHE{ $oid } ) {
+ $self->LoadByCols( id => $EFFECTIVE_ID_CACHE{ $oid } );
+ }
+
+ return $self->id;
+}
+
+sub LoadOriginal {
+ my $self = shift;
+ return $self->SUPER::LoadByCols( @_ );
+}
+
+sub MergeInto {
+ my $self = shift;
+ my $user = shift;
+
+ # Load the user objects we were called with
+ my $merge;
+ if (ref $user) {
+ return (0, "User is not loaded") unless $user->id;
+
+ $merge = RT::User->new($RT::SystemUser);
+ $merge->Load($user->id);
+ return (0, "Could not reload user #". $user->id)
+ unless $merge->id;
+ } else {
+ $merge = RT::User->new($RT::SystemUser);
+ $merge->Load($user);
+ return (0, "Could not load user '$user'") unless $merge->id;
+ }
+
+ # Get copies of the canonicalized users
+ my $email;
+ if (defined $merge->Attributes->Named('EffectiveId')) {
+ $email = $merge->CanonicalizeEmailAddress($merge->EmailAddress);
+ $merge->LoadByEmail($email);
+ }
+ return (0, "Could not load user to be merged") unless $merge->id;
+
+ my $canonical_self = RT::User->new($RT::SystemUser);
+ $canonical_self->Load($self->id);
+ if (defined $canonical_self->Attributes->Named('EffectiveId')) {
+ $email = $canonical_self->CanonicalizeEmailAddress($canonical_self->EmailAddress);
+ $canonical_self->LoadByEmail($email);
+ }
+ return (0, "Could not load user to merge into") unless $canonical_self->id;
+
+ # No merging into yourself!
+ return (0, "Could not merge @{[$merge->Name]} into itself")
+ if $merge->id == $canonical_self->id;
+
+ # No merging if the user you're merging into was merged into you
+ # (ie. you're the primary address for this user)
+ my ($new) = $merge->Attributes->Named("EffectiveId");
+ return (0, "User @{[$canonical_self->Name]} has already been merged")
+ if defined $new and $new->Content == $canonical_self->id;
+
+ # do the merge
+ $canonical_self->SetAttribute(
+ Name => "EffectiveId",
+ Description => "Primary ID of this email address",
+ Content => $merge->id,
+ );
+
+ $canonical_self->SetComments( join "\n", grep /\S/,
+ $canonical_self->Comments,
+ "Merged into ". $merge->EmailAddress ." (". $merge->id .")",
+ );
+ $merge->SetComments(join "\n", grep /\S/,
+ $merge->Comments,
+ $canonical_self->EmailAddress." (".$canonical_self->id.") merged into this user",
+ );
+ return (1, "Merged users successfuly");
+}
+
+sub UnMerge {
+ my $self = shift;
+
+ my ($current) = $self->Attributes->Named("EffectiveId");
+ return (0, "Not a merged user") unless $current;
+
+ my $merge = RT::User->new($RT::SystemUser);
+ $merge->Load( $current->Content );
+
+ $current->Delete;
+ $self->SetComments( join "\n", grep /\S/,
+ $self->Comments,
+ "Unmerged from ". $merge->EmailAddress ." (".$merge->id.")",
+ );
+
+ $merge->SetComments(join "\n", grep /\S/,
+ $merge->Comments,
+ $self->EmailAddress ." (". $self->id .") unmerged from this user",
+ );
+
+ return ($merge->id, "Unmerged from @{[$merge->EmailAddress]}");
+}
+
+sub SetEmailAddress {
+ my $self = shift;
+ my $value = shift;
+
+ return ( 0, $self->loc('Email address in use') )
+ unless $self->ValidateEmailAddress( $value );
+
+ # if value is valid then either there is no user or
+ # user is merged into this one
+ my $tmp = RT::User->new($RT::SystemUser);
+ $tmp->LoadOriginal( EmailAddress => $value );
+ if ( $tmp->id && $tmp->id != $self->id ) {
+ # there is a different user record
+ $tmp->_Set( Field => 'EmailAddress', Value => undef );
+ }
+
+ return $self->_Set( Field => 'EmailAddress', Value => $value );
+}
+
+package RT::Users;
+use RT::Users;
+
+=head2 Next
+
+This custom iterator makes sure that duplicate users are never shown in search results.
+
+=cut
+
+sub Next {
+ my $self = shift;
+
+ my $user = $self->SUPER::Next(@_);
+ return unless ($user && $user->id);
+ unless ($user) {
+ $self->{seen_users} = undef;
+ return undef;
+ }
+
+
+
+ my ($effective_id) = $user->Attributes->Named("EffectiveId");
+ if ($effective_id && $effective_id->Content && $effective_id->Content != $user->id) {
+ $user->LoadByCols(id =>$effective_id->Content);
+ }
+ return $self->Next() if ($self->{seen_users}->{$user->id}++);
+
+ return $user;
+
+}
1;
More information about the Bps-public-commit
mailing list