import of rt 3.0.4
[freeside.git] / rt / sbin / factory
diff --git a/rt/sbin/factory b/rt/sbin/factory
new file mode 100644 (file)
index 0000000..8abb192
--- /dev/null
@@ -0,0 +1,427 @@
+#!/usr/bin/perl
+# BEGIN LICENSE BLOCK
+# 
+# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# 
+# (Except where explictly superceded by other copyright notices)
+# 
+# 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
+
+use DBI;
+
+my $database  = shift;
+my $namespace = shift;
+
+my $CollectionBaseclass = 'RT::SearchBuilder';
+my $RecordBaseclass     = 'RT::Record';
+
+my $driver   = 'mysql';
+my $hostname = 'localhost';
+my $user     = 'root';
+my $password = '';
+
+
+my $LicenseBlock = << '.';
+# BEGIN LICENSE BLOCK
+# 
+# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# 
+# (Except where explictly superceded by other copyright notices)
+# 
+# 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
+.
+
+my $Attribution = << '.';
+# 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 !!
+#
+
+use strict;
+.
+
+my $dsn = "DBI:$driver:database=$database;host=$hostname";
+
+my $dbh = DBI->connect( $dsn, $user, $password );
+
+#get all tables out of database
+my @tables = $dbh->tables();
+
+my ( %tablemap, $typemap, %modulemap );
+
+foreach my $table (@tables) {
+    next if ($table eq 'sessions');
+    $tablemap{$table}  = $table;
+    $modulemap{$table} = $table;
+    if ( $table =~ /^(.*)s$/ ) {
+        $tablemap{$1}  = $table;
+        $modulemap{$1} = $1;
+    }
+}
+$tablemap{'CreatedBy'} = 'User';
+$tablemap{'UpdatedBy'} = 'User';
+
+$typemap{'id'}            = 'ro';
+$typemap{'Creator'}       = 'auto';
+$typemap{'Created'}       = 'auto';
+$typemap{'Updated'}       = 'auto';
+$typemap{'UpdatedBy'}     = 'auto';
+$typemap{'LastUpdated'}   = 'auto';
+$typemap{'LastUpdatedBy'} = 'auto';
+
+foreach my $table (@tables) {
+    next if ($table eq 'sessions');
+    my $tablesingle = $table;
+    $tablesingle =~ s/s$//;
+    my $tableplural = $tablesingle . "s";
+
+    if ( $tablesingle eq 'ACL' ) {
+        $tablesingle = "ACE";
+        $tableplural = "ACL";
+    }
+
+    my %requirements;
+
+    my $CollectionClassName = $namespace . "::" . $tableplural;
+    my $RecordClassName     = $namespace . "::" . $tablesingle;
+
+    my $path = $namespace;
+    $path =~ s/::/\//g;
+
+    my $RecordClassPath     = $path . "/" . $tablesingle . ".pm";
+    my $CollectionClassPath = $path . "/" . $tableplural . ".pm";
+
+    #create a collection class
+    my $CreateInParams;
+    my $CreateOutParams;
+    my $ClassAccessible = "";
+    my $FieldsPod       = "";
+    my $CreatePod       = "";
+    my %fields;
+    my $sth = $dbh->prepare("DESCRIBE $table");
+    $sth->execute;
+
+    while ( my $row = $sth->fetchrow_hashref() ) {
+        my $field   = $row->{'Field'};
+        my $type    = $row->{'Type'};
+        my $default = $row->{'Default'};
+        $fields{$field} = 1;
+
+        #generate the 'accessible' datastructure
+
+        if ( $typemap{$field} eq 'auto' ) {
+            $ClassAccessible .= "        $field => 
+               {read => 1, auto => 1,";
+        }
+        elsif ( $typemap{$field} eq 'ro' ) {
+            $ClassAccessible .= "        $field =>
+               {read => 1,";
+        }
+        else {
+            $ClassAccessible .= "        $field => 
+               {read => 1, write => 1,";
+
+        }
+
+        $ClassAccessible .= " type => '$type', default => '$default'},\n";
+
+        #generate pod for the accessible fields
+        $FieldsPod .= "
+=head2 $field
+
+Returns the current value of $field. 
+(In the database, $field is stored as $type.)
+
+";
+
+        unless ( $typemap{$field} eq 'auto' || $typemap{$field} eq 'ro' ) {
+            $FieldsPod .= "
+
+=head2 Set$field VALUE
+
+
+Set $field to VALUE. 
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, $field will be stored as a $type.)
+
+";
+        }
+
+        $FieldsPod .= "
+=cut
+
+";
+
+        if ( $modulemap{$field} ) {
+            $FieldsPod .= "
+=head2 ${field}Obj
+
+Returns the $modulemap{$field} Object which has the id returned by $field
+
+
+=cut
+
+sub ${field}Obj {
+       my \$self = shift;
+       my \$$field =  ${namespace}::$modulemap{$field}->new(\$self->CurrentUser);
+       \$$field->Load(\$self->__Value('$field'));
+       return(\$$field);
+}
+";
+            $requirements{ $tablemap{$field} } =
+              "use ${namespace}::$modulemap{$field};";
+
+        }
+
+        unless ( $typemap{$field} eq 'auto' || $field eq 'id' ) {
+
+            #generate create statement
+            $CreateInParams .= "                $field => '$default',\n";
+            $CreateOutParams .=
+              "                         $field => \$args{'$field'},\n";
+
+            #gerenate pod for the create statement     
+            $CreatePod .= "  $type '$field'";
+            $CreatePod .= " defaults to '$default'" if ($default);
+            $CreatePod .= ".\n";
+
+        }
+
+    }
+
+    $Create = "
+sub Create {
+    my \$self = shift;
+    my \%args = ( 
+$CreateInParams
+                 \@_);
+    \$self->SUPER::Create(
+$CreateOutParams);
+
+}
+";
+    $CreatePod .= "\n=cut\n\n";
+
+    my $CollectionClass = $LicenseBlock . $Attribution .
+
+      "
+
+=head1 NAME
+
+  $CollectionClassName -- Class Description
+=head1 SYNOPSIS
+
+  use $CollectionClassName
+
+=head1 DESCRIPTION
+
+
+=head1 METHODS
+
+=cut
+
+package $CollectionClassName;
+
+use $CollectionBaseclass;
+use $RecordClassName;
+
+use vars qw( \@ISA );
+\@ISA= qw($CollectionBaseclass);
+
+
+sub _Init {
+    my \$self = shift;
+    \$self->{'table'} = '$table';
+    \$self->{'primary_key'} = 'id';
+
+";
+
+    if ( $fields{'SortOrder'} ) {
+
+        $CollectionClass .= "
+
+  # By default, order by name
+  \$self->OrderBy( ALIAS => 'main',
+                  FIELD => 'SortOrder',
+                  ORDER => 'ASC');
+";
+    }
+    $CollectionClass .= "
+    return ( \$self->SUPER::_Init(\@_) );
+}
+
+
+=head2 NewItem
+
+Returns an empty new $RecordClassName item
+
+=cut
+
+sub NewItem {
+    my \$self = shift;
+    return($RecordClassName->new(\$self->CurrentUser));
+}
+" . MagicImport($CollectionClassName);
+
+    my $RecordClassHeader = $Attribution . "
+
+=head1 NAME
+
+$RecordClassName
+
+
+=head1 SYNOPSIS
+
+=head1 DESCRIPTION
+
+=head1 METHODS
+
+=cut
+
+package $RecordClassName;
+use $RecordBaseclass; 
+";
+
+    foreach my $key ( keys %requirements ) {
+        $RecordClassHeader .= $requirements{$key} . "\n";
+    }
+    $RecordClassHeader .= "
+
+use vars qw( \@ISA );
+\@ISA= qw( $RecordBaseclass );
+
+sub _Init {
+  my \$self = shift; 
+
+  \$self->Table('$table');
+  \$self->SUPER::_Init(\@_);
+}
+
+";
+
+    my $RecordClass = $LicenseBlock .  $RecordClassHeader . "
+
+$RecordInit
+
+=head2 Create PARAMHASH
+
+Create takes a hash of values and creates a row in the database:
+
+$CreatePod
+
+$Create
+
+$FieldsPod
+
+sub _ClassAccessible {
+    {
+     
+$ClassAccessible
+ }
+};
+
+" . MagicImport($RecordClassName);
+
+    print "About to make $RecordClassPath, $CollectionClassPath\n";
+    `mkdir -p $path`;
+
+    open( RECORD, ">$RecordClassPath" );
+    print RECORD $RecordClass;
+    close(RECORD);
+
+    open( COL, ">$CollectionClassPath" );
+    print COL $CollectionClass;
+    close($COL);
+
+}
+
+sub MagicImport {
+    my $class = shift;
+
+    #if (exists \$warnings::{unimport})  {
+    #        no warnings qw(redefine);
+
+    my $path = $class;
+    $path =~ s#::#/#gi;
+
+
+    my $content = "
+        eval \"require @{[$class]}_Overlay\";
+        if (\$@ && \$@ !~ qr{^Can't locate ".$path."_Overlay.pm}) {
+            die \$@;
+        };
+
+        eval \"require @{[$class]}_Vendor\";
+        if (\$@ && \$@ !~ qr{^Can't locate ".$path."_Vendor.pm}) {
+            die \$@;
+        };
+
+        eval \"require @{[$class]}_Local\";
+        if (\$@ && \$@ !~ qr{^Can't locate ".$path."_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.
+
+@{[$class]}_Overlay, @{[$class]}_Vendor, @{[$class]}_Local
+
+=cut
+
+
+1;
+";
+
+    return $content;
+}
+
+# }}}
+