add o2m_Common.pm to 1.9, RT#7514
authorivan <ivan>
Thu, 29 Apr 2010 07:43:21 +0000 (07:43 +0000)
committerivan <ivan>
Thu, 29 Apr 2010 07:43:21 +0000 (07:43 +0000)
FS/FS/o2m_Common.pm [new file with mode: 0644]
FS/MANIFEST

diff --git a/FS/FS/o2m_Common.pm b/FS/FS/o2m_Common.pm
new file mode 100644 (file)
index 0000000..7b5e413
--- /dev/null
@@ -0,0 +1,152 @@
+package FS::o2m_Common;
+
+use strict;
+use vars qw( $DEBUG $me );
+use Carp;
+use FS::Schema qw( dbdef );
+use FS::Record qw( qsearch qsearchs dbh );
+
+$DEBUG = 1;
+
+$me = '[FS::o2m_Common]';
+
+=head1 NAME
+
+FS::o2m_Common - Mixin class for tables with a related table
+
+=head1 SYNOPSIS
+
+use FS::o2m_Common;
+
+@ISA = qw( FS::o2m_Common FS::Record );
+
+=head1 DESCRIPTION
+
+FS::o2m_Common is intended as a mixin class for classes which have a
+related table.
+
+=head1 METHODS
+
+=over 4
+
+=item process_o2m OPTION => VALUE, ...
+
+Available options:
+
+table (required) - Table into which the records are inserted.
+
+num_col (optional) - Column in table which links to the primary key of the base table.  If not specified, it is assumed this has the same name.
+
+params (required) - Hashref of keys and values, often passed as C<scalar($cgi->Vars)> from a form.
+
+fields (required) - Arrayref of field names for each record in table.  Pulled from params as "pkeyNN_field" where pkey is table's primary key and NN is the entry's numeric identifier.
+
+=cut
+
+#a little more false laziness w/m2m_Common.pm than m2_name_Common.pm
+# still, far from the worse of it.  at least we're a reuable mixin!
+sub process_o2m {
+  my( $self, %opt ) = @_;
+
+  my $self_pkey = $self->dbdef_table->primary_key;
+  my $link_sourcekey = $opt{'num_col'} || $self_pkey;
+
+  my $hashref = {}; #$opt{'hashref'} || {};
+  $hashref->{$link_sourcekey} = $self->$self_pkey();
+
+  my $table = $self->_load_table($opt{'table'});
+  my $table_pkey = dbdef->table($table)->primary_key;
+
+#  my $link_static = $opt{'link_static'} || {};
+
+  warn "$me processing o2m from ". $self->table. ".$link_sourcekey".
+       " to $table\n"
+    if $DEBUG;
+
+  #if ( ref($opt{'params'}) eq 'ARRAY' ) {
+  #  $opt{'params'} = { map { $_=>1 } @{$opt{'params'}} };
+  #}
+
+  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;
+
+  my @fields = grep { /^$table_pkey\d+$/ }
+               keys %{ $opt{'params'} };
+
+  my %edits = map  { $opt{'params'}->{$_} => $_ }
+              grep { $opt{'params'}->{$_} }
+              @fields;
+
+  foreach my $del_obj (
+    grep { ! $edits{$_->$table_pkey()} }
+         qsearch( $table, $hashref )
+  ) {
+    my $error = $del_obj->delete;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+
+  foreach my $pkey_value ( keys %edits ) {
+    my $old_obj = qsearchs( $table, { %$hashref, $table_pkey => $pkey_value } ),
+    my $add_param = $edits{$pkey_value};
+    my %hash = ( $table_pkey => $pkey_value,
+                 map { $_ => $opt{'params'}->{$add_param."_$_"} }
+                     @{ $opt{'fields'} }
+               );
+    #next unless grep { $_ =~ /\S/ } values %hash;
+
+    my $new_obj = "FS::$table"->new( { %$hashref, %hash } );
+    my $error = $new_obj->replace($old_obj);
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+
+  foreach my $add_param ( grep { ! $opt{'params'}->{$_} } @fields ) {
+
+    my %hash = map { $_ => $opt{'params'}->{$add_param."_$_"} }
+               @{ $opt{'fields'} };
+    next unless grep { $_ =~ /\S/ } values %hash;
+
+    my $add_obj = "FS::$table"->new( { %$hashref, %hash } );
+    my $error = $add_obj->insert;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+  '';
+}
+
+sub _load_table {
+  my( $self, $table ) = @_;
+  eval "use FS::$table";
+  die $@ if $@;
+  $table;
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::Record>
+
+=cut
+
+1;
+
index 5f76153..5bcb853 100644 (file)
@@ -460,6 +460,7 @@ FS/cust_statement.pm
 t/cust_statement.t
 FS/cdr_batch.pm
 t/cdr_batch.t
+FS/o2m_Common.pm
 FS/svc_pbx.pm
 t/svc_pbx.t
 FS/h_svc_www.pm