Commit | Line | Data |
88f2d2fd |
1 | package Turnkey::Node; |
69c7a62f |
2 | |
3 | use strict; |
4 | use Class::MakeMethods::Template::Hash ( |
5 | new => [ 'new' ], |
88f2d2fd |
6 | 'array_of_objects -class Turnkey::Edge' => [ qw( edges ) ], |
7 | 'array_of_objects -class Turnkey::CompoundEdge' => [ qw( compoundedges ) ], |
8 | 'array_of_objects -class Turnkey::HyperEdge' => [ qw( hyperedges ) ], |
9 | 'hash' => [ qw( many via has) ], |
69c7a62f |
10 | scalar => [ qw( base name order primary_key primary_key_accessor table) ], |
11 | ); |
12 | |
13 | |
88f2d2fd |
14 | package Turnkey::Edge; |
69c7a62f |
15 | |
88f2d2fd |
16 | use strict; |
17 | use Class::MakeMethods::Template::Hash ( |
18 | new => ['new'], |
19 | scalar => [ qw( type ) ], |
20 | array => [ qw( traversals ) ], |
21 | object => [ |
22 | 'thisfield' => {class => 'SQL::Translator::Schema::Field'}, |
23 | 'thatfield' => {class => 'SQL::Translator::Schema::Field'}, |
24 | 'thisnode' => {class => 'Turnkey::Node'}, |
25 | 'thatnode' => {class => 'Turnkey::Node'}, |
26 | |
27 | ], |
28 | ); |
29 | |
30 | sub flip { |
31 | my $self = shift; |
32 | return Turnkey::Edge->new( thisfield => $self->thatfield, |
33 | thatfield => $self->thisfield, |
34 | thisnode => $self->thatnode, |
35 | thatnode => $self->thisnode, |
36 | type => $self->type eq 'import' ? 'export' : 'import' |
37 | ); |
69c7a62f |
38 | } |
39 | |
69c7a62f |
40 | |
88f2d2fd |
41 | package Turnkey::HyperEdge; |
42 | |
43 | use strict; |
44 | use base qw(Turnkey::Edge); |
45 | use Class::MakeMethods::Template::Hash ( |
46 | 'array_of_objects -class SQL::Translator::Schema::Field' => [ qw( thisviafield thatviafield thisfield thatfield) ], |
47 | 'array_of_objects -class Turnkey::Node' => [ qw( thisnode thatnode ) ], |
48 | object => [ 'vianode' => {class => 'Turnkey::Node'} ], |
49 | ); |
50 | |
51 | |
52 | package Turnkey::CompoundEdge; |
53 | |
54 | use strict; |
55 | use base qw(Turnkey::Edge); |
56 | use Class::MakeMethods::Template::Hash ( |
57 | new => ['new'], |
58 | object => [ |
59 | 'via' => {class => 'Turnkey::Node'}, |
60 | ], |
61 | 'array_of_objects -class Turnkey::Edge' => [ qw( edges ) ], |
62 | ); |
c00bb9f8 |
63 | |
88f2d2fd |
64 | |
65 | package SQL::Translator::Producer::Turnkey; |
c00bb9f8 |
66 | |
67 | use strict; |
68 | use vars qw[ $VERSION $DEBUG ]; |
88f2d2fd |
69 | $VERSION = sprintf "%d.%02d", q$Revision: 1.6 $ =~ /(\d+)\.(\d+)/; |
c00bb9f8 |
70 | $DEBUG = 1 unless defined $DEBUG; |
71 | |
72 | use SQL::Translator::Schema::Constants; |
73 | use SQL::Translator::Utils qw(header_comment); |
74 | use Data::Dumper; |
75 | use Template; |
76 | |
77 | my %CDBI_auto_pkgs = ( |
78 | MySQL => 'mysql', |
79 | PostgreSQL => 'Pg', |
80 | Oracle => 'Oracle', |
81 | ); |
82 | |
83 | # ------------------------------------------------------------------- |
84 | sub produce { |
85 | my $t = shift; |
86 | my $create = undef; |
c00bb9f8 |
87 | my $no_comments = $t->no_comments; |
88 | my $schema = $t->schema; |
89 | my $args = $t->producer_args; |
c00bb9f8 |
90 | |
88f2d2fd |
91 | my $parser_type = (split /::/, $t->parser_type)[-1]; |
92 | |
93 | local $DEBUG = $t->debug; |
94 | |
95 | my %meta = ( |
96 | format_fk => $t->format_fk_name, |
97 | template => $args->{'template'} || '', |
98 | baseclass => $args->{'main_pkg_name'} || $t->format_package_name('DBI'), |
99 | db_user => $args->{'db_user'} || '', |
100 | db_pass => $args->{'db_pass'} || '', |
101 | parser => $t->parser_type, |
102 | producer => __PACKAGE__, |
103 | dsn => $args->{'dsn'} || sprintf( 'dbi:%s:_', $CDBI_auto_pkgs{ $parser_type } |
104 | ? $CDBI_auto_pkgs{ $parser_type } |
105 | : $parser_type |
106 | ) |
107 | ); |
108 | |
c00bb9f8 |
109 | |
c8515c9f |
110 | # |
111 | # build package objects |
112 | # |
88f2d2fd |
113 | my %nodes; |
114 | my $order; |
69c7a62f |
115 | foreach my $table ($schema->get_tables){ |
88f2d2fd |
116 | |
69c7a62f |
117 | die __PACKAGE__." table ".$table->name." doesn't have a primary key!" unless $table->primary_key; |
118 | die __PACKAGE__." table ".$table->name." can't have a composite primary key!" if ($table->primary_key->fields)[1]; |
c00bb9f8 |
119 | |
88f2d2fd |
120 | my $node = Turnkey::Node->new(); |
121 | $nodes{ $table->name } = $node; |
c00bb9f8 |
122 | |
88f2d2fd |
123 | $node->order( ++$order ); |
124 | $node->name( $t->format_package_name($table->name) ); |
125 | $node->base( $meta{'baseclass'} ); |
126 | $node->table( $table ); |
127 | $node->primary_key( ($table->primary_key->fields)[0] ); |
69c7a62f |
128 | # Primary key may have a differenct accessor method name |
88f2d2fd |
129 | $node->primary_key_accessor( |
130 | defined($t->format_pk_name) |
131 | ? $t->format_pk_name->( $node->name, $node->primary_key ) |
132 | : undef |
133 | ); |
134 | } |
c8515c9f |
135 | |
88f2d2fd |
136 | foreach my $node (values %nodes){ |
137 | foreach my $field ($node->table->get_fields){ |
c8515c9f |
138 | next unless $field->is_foreign_key; |
139 | |
88f2d2fd |
140 | my $that = $nodes{ $field->foreign_key_reference->reference_table }; |
141 | #this means we have an incomplete schema |
142 | next unless $that; |
143 | |
144 | my $edge = Turnkey::Edge->new( |
145 | type => 'import', |
146 | thisnode => $node, |
147 | thisfield => $field, |
148 | thatnode => $that, |
149 | thatfield => ($field->foreign_key_reference->reference_fields)[0] |
150 | ); |
151 | |
152 | |
153 | $node->has($that->name, $node->has($that->name)+1); |
154 | $that->many($node->name, $that->many($node->name)+1); |
155 | |
156 | |
157 | $node->push_edges( $edge ); |
158 | $that->push_edges( $edge->flip ); |
c8515c9f |
159 | } |
69c7a62f |
160 | } |
c00bb9f8 |
161 | |
c8515c9f |
162 | # |
88f2d2fd |
163 | # type MM relationships |
c8515c9f |
164 | # |
88f2d2fd |
165 | foreach my $lnode (sort values %nodes){ |
166 | next if $lnode->table->is_data; |
167 | foreach my $inode1 (sort values %nodes){ |
168 | next if $inode1 eq $lnode; |
169 | |
170 | my @inode1_imports = grep { $_->type eq 'import' and $_->thatnode eq $inode1 } $lnode->edges; |
171 | next unless @inode1_imports; |
c8515c9f |
172 | |
88f2d2fd |
173 | foreach my $inode2 (sort values %nodes){ |
174 | my %i = map {$_->thatnode->name => 1} grep { $_->type eq 'import'} $lnode->edges; |
175 | if(scalar(keys %i) == 1) { |
c8515c9f |
176 | } else { |
88f2d2fd |
177 | last if $inode1 eq $inode2; |
c00bb9f8 |
178 | } |
88f2d2fd |
179 | |
180 | next if $inode2 eq $lnode; |
181 | my @inode2_imports = grep { $_->type eq 'import' and $_->thatnode eq $inode2 } $lnode->edges; |
182 | next unless @inode2_imports; |
183 | |
184 | my $cedge = Turnkey::CompoundEdge->new(); |
185 | $cedge->via($lnode); |
186 | |
187 | $cedge->push_edges( map {$_->flip} grep {$_->type eq 'import' and ($_->thatnode eq $inode1 or $_->thatnode eq $inode2)} $lnode->edges); |
188 | |
189 | if(scalar(@inode1_imports) == 1 and scalar(@inode2_imports) == 1){ |
190 | $cedge->type('one2one'); |
191 | |
192 | $inode1->via($inode2->name,$inode1->via($inode2->name)+1); |
193 | $inode2->via($inode1->name,$inode2->via($inode1->name)+1); |
194 | } |
195 | elsif(scalar(@inode1_imports) > 1 and scalar(@inode2_imports) == 1){ |
196 | $cedge->type('many2one'); |
197 | |
198 | $inode1->via($inode2->name,$inode1->via($inode2->name)+1); |
199 | $inode2->via($inode1->name,$inode2->via($inode1->name)+1); |
200 | } |
201 | elsif(scalar(@inode1_imports) == 1 and scalar(@inode2_imports) > 1){ |
202 | #handled above |
203 | } |
204 | elsif(scalar(@inode1_imports) > 1 and scalar(@inode2_imports) > 1){ |
205 | $cedge->type('many2many'); |
206 | |
207 | $inode1->via($inode2->name,$inode1->via($inode2->name)+1); |
208 | $inode2->via($inode1->name,$inode2->via($inode1->name)+1); |
209 | } |
210 | |
211 | $inode1->push_compoundedges($cedge); |
212 | $inode2->push_compoundedges($cedge) unless $inode1 eq $inode2; |
213 | |
c00bb9f8 |
214 | } |
69c7a62f |
215 | } |
216 | } |
217 | |
218 | # |
c8515c9f |
219 | # create methods |
69c7a62f |
220 | # |
88f2d2fd |
221 | foreach my $node_from (values %nodes){ |
222 | next unless $node_from->table->is_data; |
223 | foreach my $cedge ( $node_from->compoundedges ){ |
224 | my $hyperedge = Turnkey::HyperEdge->new; |
69c7a62f |
225 | |
88f2d2fd |
226 | my $node_to; |
c8515c9f |
227 | |
88f2d2fd |
228 | foreach my $edge ($cedge->edges){ |
229 | if($edge->thisnode->name eq $node_from->name){ |
230 | $hyperedge->vianode($edge->thatnode); |
c8515c9f |
231 | |
88f2d2fd |
232 | if($edge->thatnode->name ne $cedge->via->name){ |
233 | $node_to ||= $nodes{ $edge->thatnode->table->name }; |
234 | } |
c8515c9f |
235 | |
88f2d2fd |
236 | $hyperedge->push_thisnode($edge->thisnode); |
237 | $hyperedge->push_thisfield($edge->thisfield); |
238 | $hyperedge->push_thisviafield($edge->thatfield); |
c8515c9f |
239 | |
88f2d2fd |
240 | } else { |
c8515c9f |
241 | |
88f2d2fd |
242 | if($edge->thisnode->name ne $cedge->via->name){ |
243 | $node_to ||= $nodes{ $edge->thisnode->table->name }; |
244 | } |
c8515c9f |
245 | |
88f2d2fd |
246 | $hyperedge->push_thatnode($edge->thisnode); |
247 | $hyperedge->push_thatfield($edge->thisfield); |
248 | $hyperedge->push_thatviafield($edge->thatfield); |
249 | } |
250 | } |
251 | |
252 | if($hyperedge->count_thisnode == 1 and $hyperedge->count_thatnode == 1){ $hyperedge->type('one2one') } |
253 | elsif($hyperedge->count_thisnode > 1 and $hyperedge->count_thatnode == 1){ $hyperedge->type('many2one') } |
254 | elsif($hyperedge->count_thisnode == 1 and $hyperedge->count_thatnode > 1){ $hyperedge->type('one2many') } |
255 | elsif($hyperedge->count_thisnode > 1 and $hyperedge->count_thatnode > 1){ $hyperedge->type('many2many') } |
256 | |
257 | #warn $node_from->name ."\t". $node_to->name ."\t". $hyperedge->type ."\t". $hyperedge->vianode->name; |
258 | |
259 | $node_from->push_hyperedges($hyperedge); |
260 | } |
c8515c9f |
261 | } |
c00bb9f8 |
262 | |
88f2d2fd |
263 | $meta{"nodes"} = \%nodes; |
264 | return(translateForm($t, \%meta)); |
c00bb9f8 |
265 | } |
266 | |
267 | ########################################### |
268 | # Here documents for the tt2 templates # |
269 | ########################################### |
270 | |
88f2d2fd |
271 | my $turnkey_dbi_tt2 = <<EOF; |
272 | [% MACRO printPackage(node) BLOCK %] |
273 | # -------------------------------------------- |
274 | |
275 | package [% node.name %]; |
276 | use base '[% node.base %]'; |
277 | use Class::DBI::Pager; |
278 | |
279 | [% node.name %]->set_up_table('[% node.table.name %]'); |
280 | [% printPKAccessors(node.primary_key, node.table.name) %] |
281 | [% printHasA(node.edges, node) %] |
282 | [% printHasMany(node.edges, node) %] |
283 | [% printHasCompound(node.compoundedges, node.hyperedges, node.name) %] |
284 | [% END %] |
285 | |
286 | [% MACRO printPKAccessors(array, name) BLOCK %] |
287 | # |
288 | # Primary key accessors |
289 | # |
290 | [% FOREACH item = array %] |
291 | sub id { shift->[% item %] } |
292 | sub [% name %] { shift->[% item %] } |
293 | [% END %] |
294 | [% END %] |
295 | |
296 | [% MACRO printHasA(edges, name) BLOCK %] |
297 | # |
298 | # Has A |
299 | # |
300 | [% FOREACH edge = edges %] |
301 | [%- IF edge.type == 'import' -%] |
302 | [% node.name %]->has_a([% edge.thisfield.name %] => '[% edge.thatnode.name %]'); |
303 | [%- IF node.has(edge.thatnode.name) < 2 %] |
304 | sub [% edge.thatnode.table.name %] { return shift->[% edge.thisfield.name %] } |
305 | [%- ELSE %] |
306 | sub [% format_fk(edge.thisnode.table.name,edge.thisfield.name) %] { return shift->[% edge.thisfield.name %] } |
307 | [%- END %] |
308 | [%- END %] |
309 | [% END %] |
310 | [% END %] |
311 | |
312 | [% MACRO printHasMany(edges, node) BLOCK %] |
313 | # |
314 | # Has Many |
315 | # |
316 | [% FOREACH edge = edges %] |
317 | [%- IF edge.type == 'export' -%] |
318 | [% node.name %]->has_many([% edge.thatnode.table.name %]_[% edge.thatfield.name %], '[% edge.thatnode.name %]' => '[% edge.thatfield.name %]'); |
319 | [%- IF node.via(edge.thatnode.name) >= 1 %] |
320 | sub [% edge.thatnode.table.name %]_[% format_fk(edge.thatnode.table.name,edge.thatfield.name) %]s { return shift->[% edge.thatnode.table.name %]_[% edge.thatfield.name %] } |
321 | [%- ELSIF edge.thatnode.table.is_data %] |
322 | sub [% edge.thatnode.table.name %]s { return shift->[% edge.thatnode.table.name %]_[% edge.thatfield.name %] } |
323 | [%- END %] |
324 | [%- END %] |
325 | [% END %] |
326 | [% END %] |
327 | |
328 | [% MACRO printHasCompound(cedges,hedges,name) BLOCK %] |
329 | # |
330 | # Has Compound Many |
331 | # |
332 | [% FOREACH cedge = cedges %] |
333 | [% FOREACH edge = cedge.edges %] |
334 | [%- NEXT IF edge.thisnode.name != name -%] |
335 | sub [% cedge.via.table.name %]_[% format_fk(edge.thatnode.table.name,edge.thatfield.name) %]s { return shift->[% cedge.via.table.name %]_[% edge.thatfield.name %] } |
336 | [% END %] |
337 | [% END %] |
338 | [% FOREACH h = hedges %] |
339 | [%- NEXT IF h.thisnode.name != name -%] |
340 | [%- IF h.type == 'one2one' %] |
341 | 1sub [% h.thatnode.table.name %]s { my \$self = shift; return map \$_->[% h.thatviafield.name %], \$self->[% h.vianode.table.name %]_[% h.thisviafield.name %] } |
342 | [%- ELSIF h.type == 'one2many' %] |
343 | 2 |
344 | [%- ELSIF h.type == 'many2one' %] |
345 | 3sub [% h.thatnode.table.name %]s { my \$self = shift; return map \$_->[% h.thatviafield.name %], \$self->[% h.vianode.table.name %]_[% h.thisviafield.name %] } |
346 | [%- ELSIF h.type == 'many2many' %] |
347 | 4 |
348 | [%- END %] |
349 | [% END %] |
350 | [% END %] |
351 | |
352 | [% MACRO printList(array) BLOCK %][% FOREACH item = array %][% item %] [% END %][% END %] |
353 | package [% baseclass %]; |
354 | |
355 | # Created by SQL::Translator::Producer::Turnkey |
356 | # Template used: classdbi |
357 | |
358 | use strict; |
359 | use base qw(Class::DBI::Pg); |
360 | |
361 | Durian::Model::DBI->set_db('Main', '[% db_str %]', '[% db_user %]', '[% db_pass %]'); |
362 | |
363 | [% FOREACH node = nodes %] |
364 | [% printPackage(node.value) %] |
365 | [% END %] |
366 | EOF |
367 | |
c00bb9f8 |
368 | my $turnkey_atom_tt2 = <<'EOF'; |
369 | [% ###### DOCUMENT START ###### %] |
370 | |
88f2d2fd |
371 | [% FOREACH node = linkable %] |
c00bb9f8 |
372 | |
373 | ############################################## |
374 | |
88f2d2fd |
375 | package Durian::Atom::[% node.key FILTER ucfirst %]; |
c00bb9f8 |
376 | |
88f2d2fd |
377 | [% pname = node.key FILTER ucfirst%] |
c00bb9f8 |
378 | [% pkey = "Durian::Model::${pname}" %] |
379 | |
380 | use base qw(Durian::Atom); |
381 | use Data::Dumper; |
382 | |
383 | sub can_render { |
384 | return 1; |
385 | } |
386 | |
387 | sub render { |
388 | my $self = shift; |
389 | my $dbobject = shift; |
390 | # Assumption here that if it's not rendering on it's own dbobject |
391 | # then it's a list. This will be updated when AtomLists are implemented -boconnor |
88f2d2fd |
392 | if(ref($dbobject) eq 'Durian::Model::[% node.key FILTER ucfirst %]') { |
c00bb9f8 |
393 | return(_render_record($dbobject)); |
394 | } |
395 | else { return(_render_list($dbobject)); } |
396 | } |
397 | |
398 | sub _render_record { |
399 | my $dbobject = shift; |
400 | my @output = (); |
401 | my $row = {}; |
402 | my $field_hash = {}; |
88f2d2fd |
403 | [% FOREACH field = nodes.$pkey.columns_essential %] |
c00bb9f8 |
404 | $field_hash->{[% field %]} = $dbobject->[% field %](); |
405 | [% END %] |
406 | $row->{data} = $field_hash; |
407 | $row->{id} = $dbobject->id(); |
408 | push @output, $row; |
409 | return(\@output); |
410 | } |
411 | |
412 | sub _render_list { |
413 | my $dbobject = shift; |
414 | my @output = (); |
88f2d2fd |
415 | my @objects = $dbobject->[% node.key %]s; |
c00bb9f8 |
416 | foreach my $object (@objects) |
417 | { |
418 | my $row = {}; |
419 | my $field_hash = {}; |
88f2d2fd |
420 | [% FOREACH field = nodes.$pkey.columns_essential %] |
c00bb9f8 |
421 | $field_hash->{[% field %]} = $object->[% field %](); |
422 | [% END %] |
423 | $row->{data} = $field_hash; |
424 | $row->{id} = $object->id(); |
425 | push @output, $row; |
426 | } |
427 | return(\@output); |
428 | } |
429 | |
430 | sub head { |
431 | return 1; |
432 | } |
433 | |
434 | 1; |
435 | |
436 | [% END %] |
437 | EOF |
438 | |
c00bb9f8 |
439 | my $turnkey_xml_tt2 = <<EOF; |
440 | <?xml version="1.0" encoding="UTF-8"?> |
441 | <!DOCTYPE Durian SYSTEM "Durian.dtd"> |
442 | <Durian> |
443 | |
444 | <!-- The basic layout is fixed --> |
445 | <container bgcolor="#FFFFFF" cellpadding="0" cellspacing="0" height="90%" orientation="vertical" type="root" width="100%" xlink:label="RootContainer"> |
446 | <container cellpadding="3" cellspacing="0" orientation="horizontal" type="container" height="100%" width="100%" xlink:label="MiddleContainer"> |
447 | <container align="center" cellpadding="2" cellspacing="0" class="leftbar" orientation="vertical" type="minor" width="0%" xlink:label="MidLeftContainer"/> |
448 | <container cellpadding="0" cellspacing="0" orientation="vertical" width="100%" type="major" xlink:label="MainContainer"/> |
449 | </container> |
450 | </container> |
451 | |
452 | <!-- Atom Classes --> |
88f2d2fd |
453 | [% FOREACH node = linkable %] |
454 | <atom class="Durian::Atom::[% node.key FILTER ucfirst %]" name="[% node.key FILTER ucfirst %]" xlink:label="[% node.key FILTER ucfirst %]Atom"/> |
69c7a62f |
455 | [%- END -%] |
c00bb9f8 |
456 | |
457 | <!-- Atom Bindings --> |
458 | <atomatombindings> |
459 | [% FOREACH focus_atom = linkable %] |
460 | [% FOREACH link_atom = focus_atom.value %] |
461 | <atomatombinding xlink:from="#[% focus_atom.key FILTER ucfirst %]Atom" xlink:to="#[% link_atom.key FILTER ucfirst %]Atom" xlink:label="[% focus_atom.key FILTER ucfirst %]Atom2[% link_atom.key FILTER ucfirst %]Atom"/> |
69c7a62f |
462 | [%- END -%] |
463 | [%- END -%] |
c00bb9f8 |
464 | </atomatombindings> |
465 | |
466 | <atomcontainerbindings> |
69c7a62f |
467 | [% FOREACH focus_atom = linkable %] |
468 | <atomcontainerbindingslayout xlink:label="Durian::Model::[% focus_atom.key FILTER ucfirst %]"> |
469 | [% FOREACH link_atom = focus_atom.value %] |
470 | <atomcontainerbinding xlink:from="#MidLeftContainer" xlink:label="MidLeftContainer2[% link_atom.key FILTER ucfirst %]Atom" xlink:to="#[% link_atom.key FILTER ucfirst %]Atom"/> |
471 | [%- END -%] |
472 | <atomcontainerbinding xlink:from="#MainContainer" xlink:label="MainContainer2[% focus_atom.key FILTER ucfirst %]Atom" xlink:to="#[% focus_atom.key FILTER ucfirst %]Atom"/> |
473 | </atomcontainerbindingslayout> |
474 | [%- END -%] |
475 | </atomcontainerbindings> |
476 | |
477 | <uribindings> |
478 | <uribinding uri="/" class="Durian::Util::Frontpage"/> |
479 | </uribindings> |
480 | |
481 | <classbindings> |
482 | [% FOREACH focus_atom = linkable %] |
483 | <classbinding class="Durian::Model::[% focus_atom.key FILTER ucfirst %]" plugin="#[% focus_atom.key FILTER ucfirst %]Atom" rank="0"/> |
484 | [%- END -%] |
c00bb9f8 |
485 | |
69c7a62f |
486 | </classbindings> |
c00bb9f8 |
487 | |
488 | </Durian> |
489 | EOF |
490 | |
491 | my $turnkey_template_tt2 = <<'EOF'; |
492 | [% TAGS [- -] %] |
493 | [% MACRO renderpanel(panel,dbobject) BLOCK %] |
494 | <!-- begin panel: [% panel.label %] --> |
495 | <table border="0" width="[% panel.width %]" height="[% panel.height %]" bgcolor="[% panel.bgcolor %]" valign="top" cellpadding="[% panel.cellpadding %]" cellspacing="[% panel.cellspacing %]" align="[% panel.align %]" valign="[% panel.valign %]"> |
496 | <tr> |
497 | [% FOREACH p = panel.containers %] |
498 | [% IF p.can_render(panel) %] |
499 | <td valign="top" class="[% p.class %]" align="[% panel.align %]" height="[% p.height || 1 %]" width="[% p.width %]"> |
500 | [% IF p.type == 'Container' %] |
501 | [% renderpanel(p,dbobject) %] |
502 | [% ELSE %] |
503 | <table cellpadding="0" cellspacing="0" align="left" height="100%" width="100%"> |
504 | [% IF p.name %] |
505 | <tr bgcolor="#4444FF" height="1"> |
506 | <td><font color="#FFFFFF">[% p.name %][% IF panel.type == 'major' %]: [% dbobject.name %][% END %]</font></td> |
507 | <td align="right" width="0"><!--<nobr><img src="/images/v.gif"/><img src="/images/^.gif"/>[% IF p.delible == 'yes' %]<img src="/images/x.gif"/>[% END %]</nobr>--></td> |
508 | </tr> |
509 | [% END %] |
510 | <tr><td colspan="2" bgcolor="#FFFFFF"> |
511 | <!-- begin atom: [% p.label %] --> |
512 | <table cellpadding="0" cellspacing="0" align="left" height="100%" width="100%"><!-- [% ref(atom) %] [% ref(dbobject) %] --> |
513 | [% renderatom(p,dbobject) %] <!-- used to be renderplugin(p,panel) --> |
514 | </table> |
515 | </table> |
516 | [% END %] |
517 | </td> |
518 | [% IF panel.orientation == 'vertical' %] |
519 | </tr><tr> |
520 | [% END %] |
521 | [% END %] |
522 | [% END %] |
523 | </tr> |
524 | </table> |
525 | <!-- end panel: [% panel.label %] --> |
526 | [% END %] |
527 | [% MACRO renderatom(atom, dbobject) SWITCH atom.name %] |
88f2d2fd |
528 | [- FOREACH node = linkable -] |
529 | [% CASE '[- node.key FILTER ucfirst -]' %] |
530 | [% render[- node.key FILTER ucfirst -]Atom(atom.render(dbobject)) %] |
c00bb9f8 |
531 | [- END -] |
532 | [% CASE DEFAULT %] |
533 | [% renderlist(atom.render(dbobject)) %] |
534 | [% END %] |
88f2d2fd |
535 | [- FOREACH node = linkable -] |
536 | [% MACRO render[- node.key FILTER ucfirst -]Atom(lstArr) BLOCK %] |
c00bb9f8 |
537 | [% FOREACH record = lstArr %] |
538 | [% fields = record.data %] |
88f2d2fd |
539 | [- pname = node.key FILTER ucfirst -] |
c00bb9f8 |
540 | [- pkey = "Durian::Model::${pname}" -] |
88f2d2fd |
541 | [- FOREACH field = nodes.$pkey.columns_essential -] |
c00bb9f8 |
542 | <tr><td><b>[- field -]</b></td><td>[% fields.[- field -] %]</td></tr> |
543 | [- END -] |
544 | [% id = record.id %] |
88f2d2fd |
545 | <tr><td><a href="?id=[% id %];class=Durian::Model::[- node.key FILTER ucfirst -]">Link</a></td><td></td></tr> |
c00bb9f8 |
546 | [% END %] |
547 | [% END %] |
548 | [- END -] |
549 | [% MACRO renderlist(lstArr) BLOCK %] |
550 | [% FOREACH item = lstArr %] |
551 | <tr>[% item %]</tr> |
552 | [% END %] |
553 | [% END %] |
554 | EOF |
555 | |
88f2d2fd |
556 | |
c00bb9f8 |
557 | sub translateForm |
558 | { |
559 | my $t = shift; |
88f2d2fd |
560 | my $meta = shift; |
561 | # my $output = shift; |
c00bb9f8 |
562 | my $args = $t->producer_args; |
88f2d2fd |
563 | my $tt2 = $meta->{'template'}; |
c00bb9f8 |
564 | my $tt2Ref; |
69c7a62f |
565 | |
566 | if ($tt2 eq 'atom') { $tt2Ref = \$turnkey_atom_tt2; } |
567 | elsif ($tt2 eq 'classdbi') { $tt2Ref = \$turnkey_dbi_tt2; } |
568 | elsif ($tt2 eq 'xml') { $tt2Ref = \$turnkey_xml_tt2; } |
569 | elsif ($tt2 eq 'template') { $tt2Ref = \$turnkey_template_tt2; } |
570 | else { die __PACKAGE__." didn't recognize your template option: $tt2" } |
c00bb9f8 |
571 | |
c00bb9f8 |
572 | my $config = { |
573 | EVAL_PERL => 1, # evaluate Perl code blocks |
574 | }; |
575 | |
576 | # create Template object |
577 | my $template = Template->new($config); |
578 | |
579 | my $result; |
580 | # specify input filename, or file handle, text reference, etc. |
581 | # process input template, substituting variables |
88f2d2fd |
582 | $template->process($tt2Ref, $meta, \$result) || die $template->error(); |
c00bb9f8 |
583 | return($result); |
584 | } |
585 | |
586 | 1; |
587 | |
588 | # ------------------------------------------------------------------- |
589 | |
590 | =pod |
591 | |
592 | =head1 NAME |
593 | |
bcb3dbd2 |
594 | SQL::Translator::Producer::Turnkey - create Turnkey classes from schema |
c00bb9f8 |
595 | |
596 | =head1 SYNOPSIS |
597 | |
bcb3dbd2 |
598 | Creates output for use with the Turnkey project. |
c00bb9f8 |
599 | |
bcb3dbd2 |
600 | =head1 SEE ALSO |
601 | |
602 | L<http://turnkey.sourceforge.net>. |
c00bb9f8 |
603 | |
604 | =head1 AUTHORS |
605 | |
606 | Allen Day E<lt>allenday@ucla.eduE<gt> |
607 | Ying Zhang E<lt>zyolive@yahoo.comE<gt>, |
bcb3dbd2 |
608 | Brian O'Connor E<lt>brian.oconnor@excite.comE<gt>. |