summaryrefslogtreecommitdiff
path: root/FS/FS/m2m_Common.pm
diff options
context:
space:
mode:
authorivan <ivan>2007-01-26 08:04:37 +0000
committerivan <ivan>2007-01-26 08:04:37 +0000
commitf01e2ce0aa6c1925e6266d78797025ec68bfac07 (patch)
tree4b2efa16a130989e97eee59bfc72621d4d7a53fe /FS/FS/m2m_Common.pm
parent4d68624491e3500a0bdb737a421c3711e5defebf (diff)
top bar option!
Diffstat (limited to 'FS/FS/m2m_Common.pm')
-rw-r--r--FS/FS/m2m_Common.pm92
1 files changed, 63 insertions, 29 deletions
diff --git a/FS/FS/m2m_Common.pm b/FS/FS/m2m_Common.pm
index fd8700a..5dc2a8e 100644
--- a/FS/FS/m2m_Common.pm
+++ b/FS/FS/m2m_Common.pm
@@ -3,25 +3,26 @@ package FS::m2m_Common;
use strict;
use vars qw( @ISA $DEBUG );
use FS::Schema qw( dbdef );
-use FS::Record qw( qsearch qsearchs ); #dbh );
+use FS::Record qw( qsearch qsearchs dbh );
-@ISA = qw( FS::Record );
+#hmm. well. we seem to be used as a mixin.
+#@ISA = qw( FS::Record );
$DEBUG = 0;
=head1 NAME
-FS::m2m_Common - Base class for classes in a many-to-many relationship
+FS::m2m_Common - Mixin class for classes in a many-to-many relationship
=head1 SYNOPSIS
use FS::m2m_Common;
-@ISA = qw( FS::m2m_Common );
+@ISA = qw( FS::m2m_Common FS::Record );
=head1 DESCRIPTION
-FS::m2m_Common is intended as a base class for classes which have a
+FS::m2m_Common is intended as a mixin class for classes which have a
many-to-many relationship with another table (via a linking table).
Note: It is currently assumed that the link table contains two fields
@@ -31,7 +32,17 @@ named the same as the primary keys of ths base and target tables.
=over 4
-=item process_m2m
+=item process_m2m OPTION => VALUE, ...
+
+Available options:
+
+link_table (required) -
+
+target_table (required) -
+
+params (required) - hashref; keys are primary key values in target_table (values are boolean). For convenience, keys may optionally be prefixed with the name
+of the primary key, as in agentnum54 instead of 54, or passed as an arrayref
+of values.
=cut
@@ -39,41 +50,64 @@ sub process_m2m {
my( $self, %opt ) = @_;
my $self_pkey = $self->dbdef_table->primary_key;
+ my %hash = ( $self_pkey => $self->$self_pkey() );
my $link_table = $self->_load_table($opt{'link_table'});
my $target_table = $self->_load_table($opt{'target_table'});
my $target_pkey = dbdef->table($target_table)->primary_key;
- foreach my $target_obj ( qsearch($target_table, {} ) ) {
+ if ( ref($opt{'params'}) eq 'ARRAY' ) {
+ $opt{'params'} = { map { $_=>1 } @{$opt{'params'}} };
+ }
- my $targetnum = $target_obj->$target_pkey();
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ foreach my $del_obj (
+ grep {
+ my $targetnum = $_->$target_pkey();
+ ( ! $opt{'params'}->{$targetnum}
+ && ! $opt{'params'}->{"$target_pkey$targetnum"}
+ );
+ }
+ qsearch( $link_table, \%hash )
+ ) {
+ my $error = $del_obj->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
- my $link_obj = qsearchs( $link_table, {
- $self_pkey => $self->$self_pkey(),
- $target_pkey => $targetnum,
+ foreach my $add_targetnum (
+ grep { ! qsearchs( $link_table, { %hash, $target_pkey => $_ } ) }
+ map { /^($target_pkey)?(\d+)$/; $2; }
+ grep { /^($target_pkey)?(\d+)$/ }
+ grep { $opt{'params'}->{$_} }
+ keys %{ $opt{'params'} }
+ ) {
+
+ my $add_obj = "FS::$link_table"->new( {
+ %hash,
+ $target_pkey => $add_targetnum,
});
-
- if ( $link_obj && ! $opt{'params'}->{"$target_pkey$targetnum"} ) {
-
- my $d_link_obj = $link_obj; #need to save $link_obj for below.
- my $error = $d_link_obj->delete;
- die $error if $error;
-
- } elsif ( $opt{'params'}->{"$target_pkey$targetnum"} && ! $link_obj ) {
-
- #ok to clobber it now (but bad form nonetheless?)
- #$link_obj = new "FS::$link_table" ( {
- $link_obj = "FS::$link_table"->new( {
- $self_pkey => $self->$self_pkey(),
- $target_pkey => $targetnum,
- });
- my $error = $link_obj->insert;
- die $error if $error;
+ my $error = $add_obj->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
}
-
}
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
'';
}