Commit | Line | Data |
88f2d2fd |
1 | package SQL::Translator::Producer::Turnkey; |
c00bb9f8 |
2 | |
3 | use strict; |
4 | use vars qw[ $VERSION $DEBUG ]; |
65157eda |
5 | $VERSION = sprintf "%d.%02d", q$Revision: 1.8 $ =~ /(\d+)\.(\d+)/; |
c00bb9f8 |
6 | $DEBUG = 1 unless defined $DEBUG; |
7 | |
8 | use SQL::Translator::Schema::Constants; |
d8dc07e7 |
9 | use SQL::Translator::Schema::Graph; |
10 | use SQL::Translator::Schema::Graph::HyperEdge; |
65157eda |
11 | use Log::Log4perl; Log::Log4perl::init('/etc/log4perl.conf'); |
c00bb9f8 |
12 | use Data::Dumper; |
13 | use Template; |
14 | |
d8dc07e7 |
15 | my %producer2dsn = ( |
c00bb9f8 |
16 | MySQL => 'mysql', |
17 | PostgreSQL => 'Pg', |
18 | Oracle => 'Oracle', |
19 | ); |
20 | |
21 | # ------------------------------------------------------------------- |
22 | sub produce { |
65157eda |
23 | my $log = Log::Log4perl->get_logger('sql.translator'); |
24 | |
c00bb9f8 |
25 | my $t = shift; |
26 | my $create = undef; |
c00bb9f8 |
27 | my $args = $t->producer_args; |
d8dc07e7 |
28 | my $no_comments = $t->no_comments; |
29 | my $baseclass = $args->{'main_pkg_name'} || $t->format_package_name('DBI'); |
65157eda |
30 | my $graph = SQL::Translator::Schema::Graph->new(translator => $t, |
31 | baseclass => $baseclass |
32 | ); |
c00bb9f8 |
33 | |
88f2d2fd |
34 | my $parser_type = (split /::/, $t->parser_type)[-1]; |
35 | |
36 | local $DEBUG = $t->debug; |
37 | |
38 | my %meta = ( |
39 | format_fk => $t->format_fk_name, |
40 | template => $args->{'template'} || '', |
d8dc07e7 |
41 | baseclass => $baseclass, |
88f2d2fd |
42 | db_user => $args->{'db_user'} || '', |
43 | db_pass => $args->{'db_pass'} || '', |
44 | parser => $t->parser_type, |
45 | producer => __PACKAGE__, |
d8dc07e7 |
46 | dsn => $args->{'dsn'} || sprintf( 'dbi:%s:_', $producer2dsn{ $parser_type } |
47 | ? $producer2dsn{ $parser_type } |
88f2d2fd |
48 | : $parser_type |
49 | ) |
50 | ); |
51 | |
69c7a62f |
52 | # |
c8515c9f |
53 | # create methods |
69c7a62f |
54 | # |
d8dc07e7 |
55 | foreach my $node_from ($graph->node_values){ |
65157eda |
56 | |
57 | next unless $node_from->table->is_data or !$node_from->table->is_trivial_link; |
58 | |
88f2d2fd |
59 | foreach my $cedge ( $node_from->compoundedges ){ |
69c7a62f |
60 | |
d8dc07e7 |
61 | my $hyperedge = SQL::Translator::Schema::Graph::HyperEdge->new(); |
c8515c9f |
62 | |
d8dc07e7 |
63 | my $node_to; |
88f2d2fd |
64 | foreach my $edge ($cedge->edges){ |
65 | if($edge->thisnode->name eq $node_from->name){ |
66 | $hyperedge->vianode($edge->thatnode); |
c8515c9f |
67 | |
88f2d2fd |
68 | if($edge->thatnode->name ne $cedge->via->name){ |
d8dc07e7 |
69 | $node_to ||= $graph->node($edge->thatnode->table->name); |
88f2d2fd |
70 | } |
c8515c9f |
71 | |
d8dc07e7 |
72 | $hyperedge->push_thisnode($edge->thisnode); |
73 | $hyperedge->push_thisfield($edge->thisfield); |
74 | $hyperedge->push_thisviafield($edge->thatfield); |
c8515c9f |
75 | |
88f2d2fd |
76 | } else { |
88f2d2fd |
77 | if($edge->thisnode->name ne $cedge->via->name){ |
d8dc07e7 |
78 | $node_to ||= $graph->node($edge->thisnode->table->name); |
88f2d2fd |
79 | } |
d8dc07e7 |
80 | $hyperedge->push_thatnode($edge->thisnode); |
81 | $hyperedge->push_thatfield($edge->thisfield); |
82 | $hyperedge->push_thatviafield($edge->thatfield); |
88f2d2fd |
83 | } |
65157eda |
84 | $log->debug($edge->thisfield->name); |
85 | $log->debug($edge->thatfield->name); |
88f2d2fd |
86 | } |
65157eda |
87 | |
88f2d2fd |
88 | if($hyperedge->count_thisnode == 1 and $hyperedge->count_thatnode == 1){ $hyperedge->type('one2one') } |
89 | elsif($hyperedge->count_thisnode > 1 and $hyperedge->count_thatnode == 1){ $hyperedge->type('many2one') } |
90 | elsif($hyperedge->count_thisnode == 1 and $hyperedge->count_thatnode > 1){ $hyperedge->type('one2many') } |
91 | elsif($hyperedge->count_thisnode > 1 and $hyperedge->count_thatnode > 1){ $hyperedge->type('many2many') } |
92 | |
65157eda |
93 | #warn join "\n", sort keys %::SQL::Translator::Schema::Graph::HyperEdge::; |
94 | |
95 | #node_to won't always be defined b/c of multiple edges to a single other node |
96 | if(defined($node_to)){ |
97 | $log->debug($node_from->name); |
98 | $log->debug($node_to->name); |
99 | |
100 | if(scalar($hyperedge->thisnode) > 1){ |
101 | $log->debug($hyperedge->type ." via ". $hyperedge->vianode->name); |
102 | my $i = 0; |
103 | foreach my $thisnode ( $hyperedge->thisnode ){ |
104 | $log->debug($thisnode->name .' '. |
105 | $hyperedge->thisfield_index(0)->name .' -> '. |
106 | $hyperedge->thisviafield_index($i)->name .' '. |
107 | $hyperedge->vianode->name .' '. |
108 | $hyperedge->thatviafield_index(0)->name .' <- '. |
109 | $hyperedge->thatfield_index(0)->name .' '. |
110 | $hyperedge->thatnode_index(0)->name ."\n" |
111 | ); |
112 | $i++; |
113 | } |
d8dc07e7 |
114 | } |
65157eda |
115 | $node_from->push_hyperedges($hyperedge); |
d8dc07e7 |
116 | } |
88f2d2fd |
117 | } |
c8515c9f |
118 | } |
c00bb9f8 |
119 | |
d8dc07e7 |
120 | $meta{"nodes"} = $graph->node; |
88f2d2fd |
121 | return(translateForm($t, \%meta)); |
c00bb9f8 |
122 | } |
123 | |
d8dc07e7 |
124 | sub translateForm { |
125 | my $t = shift; |
126 | my $meta = shift; |
127 | my $args = $t->producer_args; |
128 | my $type = $meta->{'template'}; |
129 | my $tt2; |
130 | $tt2 = template($type); |
131 | my $template = Template->new({ |
65157eda |
132 | PRE_CHOMP => 1, |
133 | POST_CHOMP => 0, |
d8dc07e7 |
134 | EVAL_PERL => 1 |
135 | }); |
136 | |
137 | my $result; |
d8dc07e7 |
138 | $template->process(\$tt2, $meta, \$result) || die $template->error(); |
139 | return($result); |
140 | } |
141 | |
142 | 1; |
143 | |
144 | # ------------------------------------------------------------------- |
145 | |
146 | =pod |
147 | |
148 | =head1 NAME |
149 | |
150 | SQL::Translator::Producer::Turnkey - create Turnkey classes from schema |
151 | |
152 | =head1 SYNOPSIS |
153 | |
154 | Creates output for use with the Turnkey project. |
155 | |
156 | =head1 SEE ALSO |
157 | |
158 | L<http://turnkey.sourceforge.net>. |
159 | |
160 | =head1 AUTHORS |
161 | |
162 | Allen Day E<lt>allenday@ucla.eduE<gt> |
d8dc07e7 |
163 | Brian O\'Connor E<lt>brian.oconnor@excite.comE<gt>. |
164 | |
165 | =cut |
166 | |
167 | sub template { |
168 | my $type = shift; |
169 | |
c00bb9f8 |
170 | ########################################### |
171 | # Here documents for the tt2 templates # |
172 | ########################################### |
173 | |
d8dc07e7 |
174 | if($type eq 'classdbi'){ |
175 | return <<EOF; |
88f2d2fd |
176 | [% MACRO printPackage(node) BLOCK %] |
177 | # -------------------------------------------- |
178 | |
179 | package [% node.name %]; |
180 | use base '[% node.base %]'; |
181 | use Class::DBI::Pager; |
182 | |
183 | [% node.name %]->set_up_table('[% node.table.name %]'); |
184 | [% printPKAccessors(node.primary_key, node.table.name) %] |
185 | [% printHasA(node.edges, node) %] |
186 | [% printHasMany(node.edges, node) %] |
187 | [% printHasCompound(node.compoundedges, node.hyperedges, node.name) %] |
65157eda |
188 | [% #printHasFriendly(node) %] |
88f2d2fd |
189 | [% END %] |
190 | |
191 | [% MACRO printPKAccessors(array, name) BLOCK %] |
192 | # |
193 | # Primary key accessors |
194 | # |
195 | [% FOREACH item = array %] |
196 | sub id { shift->[% item %] } |
197 | sub [% name %] { shift->[% item %] } |
198 | [% END %] |
65157eda |
199 | |
88f2d2fd |
200 | [% END %] |
201 | |
202 | [% MACRO printHasA(edges, name) BLOCK %] |
203 | # |
204 | # Has A |
205 | # |
65157eda |
206 | |
88f2d2fd |
207 | [% FOREACH edge = edges %] |
65157eda |
208 | [% IF edge.type == 'import' %] |
88f2d2fd |
209 | [% node.name %]->has_a([% edge.thisfield.name %] => '[% edge.thatnode.name %]'); |
65157eda |
210 | [% IF node.has(edge.thatnode.name) < 2 %] |
88f2d2fd |
211 | sub [% edge.thatnode.table.name %] { return shift->[% edge.thisfield.name %] } |
65157eda |
212 | [% ELSE %] |
88f2d2fd |
213 | sub [% format_fk(edge.thisnode.table.name,edge.thisfield.name) %] { return shift->[% edge.thisfield.name %] } |
65157eda |
214 | [% END %] |
215 | |
216 | [% END %] |
88f2d2fd |
217 | [% END %] |
65157eda |
218 | |
88f2d2fd |
219 | [% END %] |
220 | |
221 | [% MACRO printHasMany(edges, node) BLOCK %] |
222 | # |
223 | # Has Many |
224 | # |
65157eda |
225 | |
88f2d2fd |
226 | [% FOREACH edge = edges %] |
65157eda |
227 | [% IF edge.type == 'export' %] |
88f2d2fd |
228 | [% node.name %]->has_many([% edge.thatnode.table.name %]_[% edge.thatfield.name %], '[% edge.thatnode.name %]' => '[% edge.thatfield.name %]'); |
65157eda |
229 | [% IF node.via(edge.thatnode.name) >= 1 %] |
88f2d2fd |
230 | sub [% edge.thatnode.table.name %]_[% format_fk(edge.thatnode.table.name,edge.thatfield.name) %]s { return shift->[% edge.thatnode.table.name %]_[% edge.thatfield.name %] } |
65157eda |
231 | [% ELSIF edge.thatnode.table.is_data %] |
232 | [% IF node.edgecount(edge.thatnode.name) > 1 %] |
233 | sub [% edge.thatnode.table.name %]_[% format_fk(edge.thatnode.name,edge.thatfield.name) %]s { return shift->[% edge.thatnode.table.name %]_[% edge.thatfield.name %] } |
234 | [% ELSE %] |
88f2d2fd |
235 | sub [% edge.thatnode.table.name %]s { return shift->[% edge.thatnode.table.name %]_[% edge.thatfield.name %] } |
65157eda |
236 | [% END %] |
237 | [% END %] |
238 | |
239 | [% END %] |
88f2d2fd |
240 | [% END %] |
65157eda |
241 | |
88f2d2fd |
242 | [% END %] |
243 | |
244 | [% MACRO printHasCompound(cedges,hedges,name) BLOCK %] |
245 | # |
246 | # Has Compound Many |
247 | # |
248 | [% FOREACH cedge = cedges %] |
249 | [% FOREACH edge = cedge.edges %] |
65157eda |
250 | [% NEXT IF edge.thisnode.name != name %] |
88f2d2fd |
251 | sub [% cedge.via.table.name %]_[% format_fk(edge.thatnode.table.name,edge.thatfield.name) %]s { return shift->[% cedge.via.table.name %]_[% edge.thatfield.name %] } |
252 | [% END %] |
253 | [% END %] |
65157eda |
254 | |
88f2d2fd |
255 | [% FOREACH h = hedges %] |
65157eda |
256 | ########## [% h.type %] ########## |
257 | [% IF h.type == 'one2one' %] |
258 | sub [% h.thatnode.table.name %]s { my \$self = shift; return map \$_->[% h.thatviafield.name %], \$self->[% h.vianode.table.name %]_[% h.thisviafield.name %] } |
259 | |
260 | [% ELSIF h.type == 'one2many' %] |
261 | [% thisnode = h.thisnode_index(0) %] |
262 | [% i = 0 %] |
263 | [% FOREACH thatnode = h.thatnode %] |
264 | #[% thisnode.name %]::[% h.thisfield_index(0).name %] -> [% h.vianode.name %]::[% h.thisviafield_index(i).name %] ... [% h.vianode.name %]::[% h.thatviafield_index(0).name %] <- [% h.thatnode_index(0).name %]::[% h.thatfield_index(0).name %] |
265 | sub [% h.vianode.table.name %]_[% format_fk(h.vianode,h.thatviafield_index(0).name) %]s { my \$self = shift; return map \$_->[% h.thatviafield_index(0).name %], \$self->[% h.vianode.table.name %]_[% h.thisviafield_index(i).name %] } |
266 | [% i = i + 1 %] |
267 | [% END %] |
268 | |
269 | [% ELSIF h.type == 'many2one' %] |
270 | [% i = 0 %] |
d8dc07e7 |
271 | [% FOREACH thisnode = h.thisnode %] |
65157eda |
272 | #[% thisnode.name %]::[% h.thisfield_index(0).name %] -> [% h.vianode.name %]::[% h.thisviafield_index(i).name %] ... [% h.vianode.name %]::[% h.thatviafield_index(0).name %] <- [% h.thatnode_index(0).name %]::[% h.thatfield_index(0).name %] |
273 | sub [% h.vianode.table.name %]_[% format_fk(h.vianode,h.thisviafield_index(i).name) %]_[% format_fk(h.vianode,h.thatviafield_index(0).name) %]s { my \$self = shift; return map \$_->[% h.thatviafield_index(0).name %], \$self->[% h.vianode.table.name %]_[% h.thisviafield_index(i).name %] } |
274 | [% i = i + 1 %] |
275 | |
d8dc07e7 |
276 | [% END %] |
65157eda |
277 | |
278 | [% ELSIF h.type == 'many2many' %] |
279 | [% i = 0 %] |
280 | [% FOREACH thisnode = h.thisnode %] |
281 | [% j = 0 %] |
282 | [% FOREACH thatnode = h.thatnode %] |
283 | #[% thisnode.name %]::[% h.thisfield_index(i).name %] -> [% h.vianode.name %]::[% h.thisviafield_index(i).name %] ... [% h.vianode.name %]::[% h.thatviafield_index(j).name %] <- [% h.thatnode_index(j).name %]::[% h.thatfield_index(j).name %] |
284 | sub [% h.vianode.table.name %]_[% format_fk(h.vianode,h.thisviafield_index(i).name) %]_[% format_fk(h.vianode,h.thatviafield_index(j).name) %]s { my \$self = shift; return map \$_->[% %], \$self->[% %] } |
285 | [% j = j + 1 %] |
286 | |
287 | [% END %] |
288 | [% i = i + 1 %] |
289 | [% END %] |
290 | [% END %] |
88f2d2fd |
291 | [% END %] |
65157eda |
292 | |
88f2d2fd |
293 | [% END %] |
294 | |
d8dc07e7 |
295 | [% MACRO printHasFriendly(node) BLOCK %] |
296 | # |
297 | # Has Friendly |
298 | # |
299 | hello, sailor! |
300 | [% END %] |
301 | |
88f2d2fd |
302 | [% MACRO printList(array) BLOCK %][% FOREACH item = array %][% item %] [% END %][% END %] |
303 | package [% baseclass %]; |
304 | |
305 | # Created by SQL::Translator::Producer::Turnkey |
306 | # Template used: classdbi |
307 | |
308 | use strict; |
309 | use base qw(Class::DBI::Pg); |
310 | |
d8dc07e7 |
311 | [% baseclass %]->set_db('Main', '[% db_str %]', '[% db_user %]', '[% db_pass %]'); |
88f2d2fd |
312 | |
313 | [% FOREACH node = nodes %] |
314 | [% printPackage(node.value) %] |
315 | [% END %] |
316 | EOF |
317 | |
d8dc07e7 |
318 | } elsif($type eq 'atom'){ |
319 | return <<'EOF'; |
c00bb9f8 |
320 | [% ###### DOCUMENT START ###### %] |
321 | |
88f2d2fd |
322 | [% FOREACH node = linkable %] |
c00bb9f8 |
323 | |
324 | ############################################## |
325 | |
88f2d2fd |
326 | package Durian::Atom::[% node.key FILTER ucfirst %]; |
c00bb9f8 |
327 | |
88f2d2fd |
328 | [% pname = node.key FILTER ucfirst%] |
c00bb9f8 |
329 | [% pkey = "Durian::Model::${pname}" %] |
330 | |
331 | use base qw(Durian::Atom); |
332 | use Data::Dumper; |
333 | |
334 | sub can_render { |
335 | return 1; |
336 | } |
337 | |
338 | sub render { |
339 | my $self = shift; |
340 | my $dbobject = shift; |
341 | # Assumption here that if it's not rendering on it's own dbobject |
342 | # then it's a list. This will be updated when AtomLists are implemented -boconnor |
88f2d2fd |
343 | if(ref($dbobject) eq 'Durian::Model::[% node.key FILTER ucfirst %]') { |
c00bb9f8 |
344 | return(_render_record($dbobject)); |
345 | } |
346 | else { return(_render_list($dbobject)); } |
347 | } |
348 | |
349 | sub _render_record { |
350 | my $dbobject = shift; |
351 | my @output = (); |
352 | my $row = {}; |
353 | my $field_hash = {}; |
88f2d2fd |
354 | [% FOREACH field = nodes.$pkey.columns_essential %] |
c00bb9f8 |
355 | $field_hash->{[% field %]} = $dbobject->[% field %](); |
356 | [% END %] |
357 | $row->{data} = $field_hash; |
358 | $row->{id} = $dbobject->id(); |
359 | push @output, $row; |
360 | return(\@output); |
361 | } |
362 | |
363 | sub _render_list { |
364 | my $dbobject = shift; |
365 | my @output = (); |
88f2d2fd |
366 | my @objects = $dbobject->[% node.key %]s; |
c00bb9f8 |
367 | foreach my $object (@objects) |
368 | { |
369 | my $row = {}; |
370 | my $field_hash = {}; |
88f2d2fd |
371 | [% FOREACH field = nodes.$pkey.columns_essential %] |
c00bb9f8 |
372 | $field_hash->{[% field %]} = $object->[% field %](); |
373 | [% END %] |
374 | $row->{data} = $field_hash; |
375 | $row->{id} = $object->id(); |
376 | push @output, $row; |
377 | } |
378 | return(\@output); |
379 | } |
380 | |
381 | sub head { |
382 | return 1; |
383 | } |
384 | |
385 | 1; |
386 | |
387 | [% END %] |
388 | EOF |
389 | |
d8dc07e7 |
390 | } elsif($type eq 'xml'){ |
391 | return <<EOF; |
c00bb9f8 |
392 | <?xml version="1.0" encoding="UTF-8"?> |
393 | <!DOCTYPE Durian SYSTEM "Durian.dtd"> |
394 | <Durian> |
395 | |
396 | <!-- The basic layout is fixed --> |
397 | <container bgcolor="#FFFFFF" cellpadding="0" cellspacing="0" height="90%" orientation="vertical" type="root" width="100%" xlink:label="RootContainer"> |
398 | <container cellpadding="3" cellspacing="0" orientation="horizontal" type="container" height="100%" width="100%" xlink:label="MiddleContainer"> |
399 | <container align="center" cellpadding="2" cellspacing="0" class="leftbar" orientation="vertical" type="minor" width="0%" xlink:label="MidLeftContainer"/> |
400 | <container cellpadding="0" cellspacing="0" orientation="vertical" width="100%" type="major" xlink:label="MainContainer"/> |
401 | </container> |
402 | </container> |
403 | |
404 | <!-- Atom Classes --> |
88f2d2fd |
405 | [% FOREACH node = linkable %] |
406 | <atom class="Durian::Atom::[% node.key FILTER ucfirst %]" name="[% node.key FILTER ucfirst %]" xlink:label="[% node.key FILTER ucfirst %]Atom"/> |
69c7a62f |
407 | [%- END -%] |
c00bb9f8 |
408 | |
409 | <!-- Atom Bindings --> |
410 | <atomatombindings> |
411 | [% FOREACH focus_atom = linkable %] |
412 | [% FOREACH link_atom = focus_atom.value %] |
413 | <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 |
414 | [%- END -%] |
415 | [%- END -%] |
c00bb9f8 |
416 | </atomatombindings> |
417 | |
418 | <atomcontainerbindings> |
69c7a62f |
419 | [% FOREACH focus_atom = linkable %] |
420 | <atomcontainerbindingslayout xlink:label="Durian::Model::[% focus_atom.key FILTER ucfirst %]"> |
421 | [% FOREACH link_atom = focus_atom.value %] |
422 | <atomcontainerbinding xlink:from="#MidLeftContainer" xlink:label="MidLeftContainer2[% link_atom.key FILTER ucfirst %]Atom" xlink:to="#[% link_atom.key FILTER ucfirst %]Atom"/> |
423 | [%- END -%] |
424 | <atomcontainerbinding xlink:from="#MainContainer" xlink:label="MainContainer2[% focus_atom.key FILTER ucfirst %]Atom" xlink:to="#[% focus_atom.key FILTER ucfirst %]Atom"/> |
425 | </atomcontainerbindingslayout> |
426 | [%- END -%] |
427 | </atomcontainerbindings> |
428 | |
429 | <uribindings> |
430 | <uribinding uri="/" class="Durian::Util::Frontpage"/> |
431 | </uribindings> |
432 | |
433 | <classbindings> |
434 | [% FOREACH focus_atom = linkable %] |
435 | <classbinding class="Durian::Model::[% focus_atom.key FILTER ucfirst %]" plugin="#[% focus_atom.key FILTER ucfirst %]Atom" rank="0"/> |
436 | [%- END -%] |
c00bb9f8 |
437 | |
69c7a62f |
438 | </classbindings> |
c00bb9f8 |
439 | |
440 | </Durian> |
441 | EOF |
442 | |
d8dc07e7 |
443 | } elsif($type eq 'template'){ |
444 | return <<'EOF'; |
c00bb9f8 |
445 | [% TAGS [- -] %] |
446 | [% MACRO renderpanel(panel,dbobject) BLOCK %] |
447 | <!-- begin panel: [% panel.label %] --> |
448 | <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 %]"> |
449 | <tr> |
450 | [% FOREACH p = panel.containers %] |
451 | [% IF p.can_render(panel) %] |
452 | <td valign="top" class="[% p.class %]" align="[% panel.align %]" height="[% p.height || 1 %]" width="[% p.width %]"> |
453 | [% IF p.type == 'Container' %] |
454 | [% renderpanel(p,dbobject) %] |
455 | [% ELSE %] |
456 | <table cellpadding="0" cellspacing="0" align="left" height="100%" width="100%"> |
457 | [% IF p.name %] |
458 | <tr bgcolor="#4444FF" height="1"> |
459 | <td><font color="#FFFFFF">[% p.name %][% IF panel.type == 'major' %]: [% dbobject.name %][% END %]</font></td> |
460 | <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> |
461 | </tr> |
462 | [% END %] |
463 | <tr><td colspan="2" bgcolor="#FFFFFF"> |
464 | <!-- begin atom: [% p.label %] --> |
465 | <table cellpadding="0" cellspacing="0" align="left" height="100%" width="100%"><!-- [% ref(atom) %] [% ref(dbobject) %] --> |
466 | [% renderatom(p,dbobject) %] <!-- used to be renderplugin(p,panel) --> |
467 | </table> |
468 | </table> |
469 | [% END %] |
470 | </td> |
471 | [% IF panel.orientation == 'vertical' %] |
472 | </tr><tr> |
473 | [% END %] |
474 | [% END %] |
475 | [% END %] |
476 | </tr> |
477 | </table> |
478 | <!-- end panel: [% panel.label %] --> |
479 | [% END %] |
480 | [% MACRO renderatom(atom, dbobject) SWITCH atom.name %] |
88f2d2fd |
481 | [- FOREACH node = linkable -] |
482 | [% CASE '[- node.key FILTER ucfirst -]' %] |
483 | [% render[- node.key FILTER ucfirst -]Atom(atom.render(dbobject)) %] |
c00bb9f8 |
484 | [- END -] |
485 | [% CASE DEFAULT %] |
486 | [% renderlist(atom.render(dbobject)) %] |
487 | [% END %] |
88f2d2fd |
488 | [- FOREACH node = linkable -] |
489 | [% MACRO render[- node.key FILTER ucfirst -]Atom(lstArr) BLOCK %] |
c00bb9f8 |
490 | [% FOREACH record = lstArr %] |
491 | [% fields = record.data %] |
88f2d2fd |
492 | [- pname = node.key FILTER ucfirst -] |
c00bb9f8 |
493 | [- pkey = "Durian::Model::${pname}" -] |
88f2d2fd |
494 | [- FOREACH field = nodes.$pkey.columns_essential -] |
c00bb9f8 |
495 | <tr><td><b>[- field -]</b></td><td>[% fields.[- field -] %]</td></tr> |
496 | [- END -] |
497 | [% id = record.id %] |
88f2d2fd |
498 | <tr><td><a href="?id=[% id %];class=Durian::Model::[- node.key FILTER ucfirst -]">Link</a></td><td></td></tr> |
c00bb9f8 |
499 | [% END %] |
500 | [% END %] |
501 | [- END -] |
502 | [% MACRO renderlist(lstArr) BLOCK %] |
503 | [% FOREACH item = lstArr %] |
504 | <tr>[% item %]</tr> |
505 | [% END %] |
506 | [% END %] |
507 | EOF |
508 | |
c00bb9f8 |
509 | 1; |
510 | |
d8dc07e7 |
511 | } |
512 | } |