RT# 82092 - custom fields now save and fixed so name label is displayed insted of...
[freeside.git] / FS / FS / part_virtual_field.pm
1 package FS::part_virtual_field;
2
3 use strict;
4 use vars qw( @ISA );
5 use FS::Record;
6 use FS::Schema qw( dbdef );
7 use CGI qw(escapeHTML);
8
9 @ISA = qw( FS::Record );
10
11 =head1 NAME
12
13 FS::part_virtual_field - Object methods for part_virtual_field records
14
15 =head1 SYNOPSIS
16
17   use FS::part_virtual_field;
18
19   $record = new FS::part_virtual_field \%hash;
20   $record = new FS::part_virtual_field { 'column' => 'value' };
21
22   $error = $record->insert;
23
24   $error = $new_record->replace($old_record);
25
26   $error = $record->delete;
27
28   $error = $record->check;
29
30 =head1 DESCRIPTION
31
32 An FS::part_virtual_field object represents the definition of a custom field 
33 (see the BACKGROUND section).  FS::part_virtual_field contains the name and 
34 base table of the field. 
35
36 FS::part_virtual_field inherits from FS::Record.  The following fields are 
37 currently supported:
38
39 =over 2
40
41 =item vfieldpart - primary key (assigned automatically)
42
43 =item name - name of the field
44
45 =item dbtable - table for which this virtual field is defined
46
47 =item length - expected length of the value (UI hint)
48
49 =item label - descriptive label for the field (UI hint)
50
51 =back
52
53 =head1 METHODS
54
55 =over 4
56
57 =item new HASHREF
58
59 Create a new record.  To add the record to the database, see "insert".
60
61 =cut
62
63 sub table { 'part_virtual_field'; }
64 sub virtual_fields { () }
65 sub virtual_fields_hash { () }
66
67 =item widget UI_TYPE MODE [ VALUE ]
68
69 Generates UI code for a widget suitable for editing/viewing the field, based on 
70 list_source and length.  
71
72 The only UI_TYPE currently supported is 'HTML', and possible MODEs are 'view'
73 and 'edit'.
74
75 In HTML, all widgets are assumed to be table rows.  View widgets look like
76 <TR><TD ALIGN="right">Label</TD><TD BGCOLOR="#ffffff">Value</TD></TR>
77
78 (Most of the display style stuff, such as the colors, should probably go into 
79 a separate module specific to the UI.  That can wait, though.  The API for 
80 this function won't change.)
81
82 VALUE (optional) is the current value of the field.
83
84 =cut
85
86 sub widget {
87   my $self = shift;
88   my ($ui_type, $mode, $value, $header_col_type) = @_;
89   $header_col_type = 'TD' unless $header_col_type;
90   my $text;
91   my $label = $self->label || $self->name;
92
93   if ($ui_type eq 'HTML') {
94     if ($mode eq 'view') {
95       $text = q!<TR><!.$header_col_type.q! ALIGN="right">! . $label .
96               q!</!.$header_col_type.q!><TD BGCOLOR="#ffffff">! . $value .
97               q!</TD></TR>! . "\n";
98     } elsif ($mode eq 'edit') {
99       $text = q!<TR><!.$header_col_type.q! ALIGN="right">! . $label .
100               q!</!.$header_col_type.q!><TD>!;
101         $text .= q!<INPUT TYPE=text NAME="! . $self->name .
102                 q!" VALUE="! . escapeHTML($value) . q!"!;
103         if ($self->length) {
104           $text .= q! SIZE="! . $self->length . q!"!;
105         }
106         $text .= '>';
107       $text .= q!</TD></TR>! . "\n";
108     } else {
109       return '';
110     }
111   } else {
112     return '';
113   }
114   return $text;
115 }
116
117
118 =item insert
119
120 Adds this record to the database.  If there is an error, returns the error,
121 otherwise returns false.
122
123 =item delete
124
125 Deletes this record from the database.  If there is an error, returns the
126 error, otherwise returns false.
127
128 =item replace OLD_RECORD
129
130 Replaces OLD_RECORD with this one in the database.  If there is an error,
131 returns the error, otherwise returns false.
132
133 =item check
134
135 If there is an error, returns the error, otherwise returns false.
136 Called by the insert and replace methods.
137
138 =back
139
140 =cut
141
142 sub check {
143   my $self = shift;
144
145   my $error = $self->ut_text('name') ||
146               $self->ut_text('dbtable') ||
147               $self->ut_number('length')
148               ;
149   return $error if $error;
150
151   # Make sure it's a real table with a numeric primary key
152   my ($table, $pkey);
153   if($table = dbdef->table($self->dbtable)) {
154     if($pkey = $table->primary_key) {
155       if($table->column($pkey)->type =~ /int/i) {
156         # this is what it should be
157       } else {
158         $error = "$table.$pkey is not an integer";
159       }
160     } else {
161       $error = "$table does not have a single-field primary key";
162     }
163   } else {
164     $error = "$table does not exist in the schema";
165   }
166   return $error if $error;
167
168   $self->SUPER::check;  
169 }
170
171 =head1 NOTES
172
173 =head1 BUGS
174
175 =head1 SEE ALSO
176
177 L<FS::Record>
178
179 =cut
180
181 1;
182
183