File Coverage

blib/lib/Bigtop/ScriptHelp.pm
Criterion Covered Total %
statement 20 302 6.6
branch 0 62 0.0
condition 0 13 0.0
subroutine 7 23 30.4
pod 6 6 100.0
total 33 406 8.1


line stmt bran cond sub pod time code
1             package Bigtop::ScriptHelp;
2 42     42   40176 use strict; use warnings;
  42     42   75  
  42         1760  
  42         223  
  42         85  
  42         1336  
3              
4 42     42   225 use base 'Exporter';
  42         84  
  42         5482  
5              
6             our @EXPORT = qw( valid_ident );
7              
8 42     42   42082 use File::HomeDir;
  42         333814  
  42         3314  
9 42     42   366 use File::Spec;
  42         91  
  42         975  
10 42     42   222 use Cwd;
  42         84  
  42         168022  
11              
12             my %non_entry = (
13             id => 1,
14             created => 1,
15             modified => 1,
16             );
17              
18             sub _get_config_block {
19 0     0   0 my $app_name = shift;
20 0         0 my $build_dir = shift;
21              
22 0         0 $app_name =~ s/::/_/g;
23 0         0 $app_name = lc( $app_name );
24              
25 0         0 my $conf_file = File::Spec->catfile(
26             $build_dir, 'docs', 'app.gantry.conf'
27             );
28              
29 0         0 return << "EO_Config_Default";
30             config {
31             engine MP20;
32             template_engine TT;
33             Init Std {}
34             Conf Gantry { conffile `$conf_file`; instance $app_name; }
35             HttpdConf Gantry { gantry_conf 1; }
36             SQL SQLite {}
37             SQL Postgres {}
38             SQL MySQL {}
39             CGI Gantry { with_server 1; flex_db 1; gantry_conf 1; }
40             Control Gantry { dbix 1; }
41             Model GantryDBIxClass {}
42             SiteLook GantryDefault {}
43             }
44             EO_Config_Default
45             }
46              
47             sub get_minimal_default {
48 0     0 1 0 my $class = shift;
49 0   0     0 my $name = shift || 'Sample';
50              
51 0         0 my $cwd = getcwd();
52 0         0 my $dir_name = $name;
53 0         0 $dir_name =~ s/::/-/g;
54              
55 0         0 my $cgi = lc( $dir_name ) . '.cgi';
56              
57 0         0 my $build_dir = File::Spec->catfile( $cwd, $dir_name );
58 0         0 my $app_db = File::Spec->catfile( $build_dir, 'app.db' );
59              
60             # See if they have a bigtopdef or ~/.bigtopdef
61             # If no .bigtopdef, whip something up from scratch
62 0         0 my $def_file;
63 0         0 my $home_dir = File::HomeDir->my_home();
64 0         0 my $home_def = File::Spec->catfile( $home_dir, '.bigtopdef' );
65 0 0       0 if ( -f 'bigtopdef' ) {
    0          
66 0         0 $def_file = 'bigtopdef';
67             }
68             elsif ( -f $home_def ) {
69 0         0 $def_file = $home_def;
70             }
71              
72 0 0 0     0 if ( $def_file and not $ENV{ BIGTOP_REAL_DEF } ) {
73 0         0 return _minimal_from_file( $def_file, $name );
74             }
75              
76 0         0 my $config = _get_config_block( $name, $build_dir );
77              
78 0         0 return << "EO_Little_Default";
79             $config
80             app $name {
81             config {
82             dbconn `dbi:SQLite:dbname=app.db` => no_accessor;
83             template_wrapper `genwrapper.tt` => no_accessor;
84             doc_rootp `/static` => no_accessor;
85             show_dev_navigation 1 => no_accessor;
86             }
87             config CGI {
88             dbconn `dbi:SQLite:dbname=$app_db` => no_accessor;
89             app_rootp `/cgi-bin/$cgi` => no_accessor;
90             }
91             controller is base_controller {
92             method do_main is base_links {
93             }
94             method site_links is links {
95             }
96             }
97             }
98             EO_Little_Default
99             }
100              
101             sub _minimal_from_file {
102 0     0   0 my $file = shift;
103 0         0 my $app_name = shift;
104              
105             # form substitution names
106 0         0 my $short_name = $app_name;
107 0         0 $short_name =~ s/.*:://;
108              
109 0         0 my $no_colon_name = $app_name;
110 0         0 $no_colon_name =~ s/::/_/g;
111 0         0 $no_colon_name = lc( $no_colon_name );
112              
113 0         0 my %subs = (
114             app_name => $app_name,
115             no_colon_name => $no_colon_name,
116             short_name => $short_name,
117             );
118              
119             # apply substitution names
120 0         0 require Template;
121              
122 0         0 my $retval;
123 0         0 my $tt = Template->new( { ABSOLUTE => 1 } );
124 0         0 $tt->process( $file, \%subs, \$retval );
125              
126             # give it to 'em
127 0         0 return $retval;
128             }
129              
130             sub get_big_default {
131 0     0 1 0 my $class = shift;
132 0         0 my $style = shift;
133 0         0 my $app_name = shift;
134 0         0 my $extras = join ' ', @_;
135              
136 0         0 my $starter_kit = $class->get_minimal_default( $app_name );
137 0         0 my $tree = Bigtop::Parser->parse_string( $starter_kit );
138              
139 0         0 $class->augment_tree( $style, $tree, $extras );
140              
141 0         0 return Bigtop::Deparser->deparse( $tree );
142             }
143              
144             sub _transpose {
145 0     0   0 my $foreign_key_for = shift;
146              
147 0         0 my %retval;
148              
149 0         0 foreach my $foreign_key ( keys %{ $foreign_key_for } ) {
  0         0  
150 0         0 foreach my $table_info ( @{ $foreign_key_for->{ $foreign_key } } ) {
  0         0  
151 0         0 push @{ $retval{ $table_info->{ table } } }, $foreign_key;
  0         0  
152             }
153             }
154              
155 0         0 return \%retval;
156             }
157              
158             sub _correlate_columns {
159 0     0   0 my $columns = shift;
160 0         0 my $ast = shift;
161              
162 0         0 my %correlation;
163              
164             # first walk existing tables in the tree
165 0 0       0 if ( defined $ast ) {
166 0         0 my $tables = $ast->walk_postorder( 'all_table_names' );
167              
168 0         0 foreach my $table ( @{ $tables } ) {
  0         0  
169              
170 0         0 my $columns = $ast->walk_postorder( 'all_field_names', $table );
171              
172 0         0 $correlation{ $table } = $columns;
173             }
174             }
175              
176             # then walk new columns
177 0         0 foreach my $table ( keys %{ $columns } ) {
  0         0  
178 0         0 my @table_columns;
179 0         0 foreach my $col ( @{ $columns->{ $table } } ) {
  0         0  
180 0         0 push @table_columns, $col->{ name };
181             }
182 0         0 $correlation{ $table } = \@table_columns;
183             }
184              
185 0         0 return \%correlation;
186             }
187              
188             sub _safely_order {
189 0     0   0 my $requested_tables = shift;
190 0         0 my $foreign_key_for = shift;
191              
192 0         0 my @ordered_tables;
193 0         0 my %requests = map { $_ => 1 } @{ $requested_tables };
  0         0  
  0         0  
194              
195 0         0 my %fk_tree;
196 0         0 foreach my $fk ( keys %{ $foreign_key_for } ) {
  0         0  
197 0         0 foreach my $f_table ( @{ $foreign_key_for->{ $fk } } ) {
  0         0  
198 0         0 push @{ $fk_tree{ $fk } }, $f_table->{ table };
  0         0  
199             }
200             }
201              
202 0         0 my @chains;
203 0         0 foreach my $chain_leaf ( keys %fk_tree ) {
204 0         0 push @chains, [ _build_chain( $chain_leaf, \%fk_tree ) ];
205             }
206              
207 0         0 my %handled;
208              
209 0         0 foreach my $chain ( @chains ) {
210 0         0 LINK:
211 0         0 foreach my $link ( @{ $chain } ) {
212 0 0       0 next LINK unless $requests{ $link };
213 0 0       0 next LINK if $handled{ $link }++;
214              
215 0         0 push @ordered_tables, $link;
216             }
217             }
218              
219             STRAY:
220 0         0 foreach my $table ( @{ $requested_tables } ) {
  0         0  
221 0 0       0 next STRAY unless $requests{ $table };
222 0 0       0 next STRAY if $handled{ $table }++;
223 0         0 push @ordered_tables, $table;
224             }
225              
226 0         0 return \@ordered_tables;
227             }
228              
229             sub _build_chain {
230 0     0   0 my $chain_leaf = shift;
231 0         0 my $fk_tree = shift;
232              
233 0         0 my @retval = ( $chain_leaf );
234              
235 0 0       0 return @retval unless ( defined $fk_tree->{ $chain_leaf } );
236              
237 0         0 foreach my $parent ( @{ $fk_tree->{ $chain_leaf } } ) {
  0         0  
238 0         0 unshift @retval, _build_chain( $parent, $fk_tree );
239             }
240              
241 0         0 return @retval;
242             }
243              
244             sub _make_native_fields {
245 0     0   0 my $columns_for = shift;
246 0         0 my $table = shift;
247 0         0 my $foreign_targets = shift;
248              
249 0         0 my $columns = $columns_for->{ $table };
250 0         0 my $foreign_display;
251             my $second_main_col;
252 0         0 my @exclude_from_form;
253              
254             # first handle the columns
255 0         0 my $retval = '';
256 0         0 my $space = ' ';
257 0         0 my $outer_indent = $space x 8;
258 0         0 my $is_spacing = $space x 12;
259              
260 0         0 foreach my $column ( @{ $columns } ) {
  0         0  
261              
262 0 0       0 if ( $column->{ default } ) {
263 0         0 push @{ $column->{ types } }, "`DEFAULT '$column->{ default }'`";
  0         0  
264             }
265              
266 0         0 my $type_string = join ', ', @{ $column->{ types } };
  0         0  
267              
268 0         0 my $decorations = '';
269 0 0       0 if ( $non_entry{ $column->{ name } } ) {
270 0         0 push @exclude_from_form, $column->{ name };
271             }
272             else {
273             $second_main_col = $column->{ name }
274 0 0 0     0 if $foreign_display and not $second_main_col;
275              
276 0 0       0 $foreign_display = $column->{ name } unless $foreign_display;
277              
278 0         0 $type_string = "${is_spacing}$type_string";
279              
280             die "invalid column name $column->{ name }\n"
281 0 0       0 unless valid_ident( $column->{ name } );
282              
283 0         0 my $label = Bigtop::ScriptHelp->default_label( $column->{ name } );
284              
285 0 0       0 $label = "`$label`" if ( $label =~ /\s+/ );
286              
287 0         0 $decorations = << "EO_DEC";
288             label $label;
289             html_form_type text;
290             EO_DEC
291 0 0       0 if ( $column->{ optional } ) {
292 0         0 $decorations .= << "EO_OPTIONAL";
293             html_form_optional 1;
294             EO_OPTIONAL
295             }
296 0 0       0 if ( $column->{ default } ) {
297 0         0 $decorations .= << "EO_DEFAULT";
298             html_form_default_value `$column->{ default }`;
299             EO_DEFAULT
300             }
301             }
302              
303 0         0 $retval .= "${outer_indent}field $column->{ name } {\n";
304 0         0 $retval .= "${outer_indent} is $type_string;\n";
305 0 0       0 $retval .= $decorations if $decorations;
306 0         0 $retval .= "${outer_indent}}\n";
307             }
308              
309             # finish by adding foreign_display
310 0         0 $retval .= "${outer_indent}foreign_display `%$foreign_display`;";
311              
312 0         0 foreach my $foreign_target ( @{ $foreign_targets->{ $table } } ) {
  0         0  
313 0         0 $retval .=
314             "\n${outer_indent}refered_to_by `$foreign_target`;";
315             }
316              
317 0         0 my $main_cols = $foreign_display;
318 0 0       0 $main_cols .= ", $second_main_col" if $second_main_col;
319              
320 0         0 return ( $retval, $main_cols, join( ', ', @exclude_from_form ) );
321             }
322              
323             sub _make_foreign_key_fields {
324 0     0   0 my $foreign_key_for = shift;
325 0         0 my $model = shift;
326 0         0 my $col_num_2_name = shift;
327              
328 0         0 my @foreign_fields;
329 0         0 my $foreign_text = "\n";
330 0 0       0 if ( defined $foreign_key_for->{ $model } ) {
331 0         0 foreach my $foreign_key ( @{ $foreign_key_for->{ $model } } ) {
  0         0  
332              
333             my $label = Bigtop::ScriptHelp->default_label(
334             _strip_schema( $foreign_key->{ table } )
335 0         0 );
336              
337 0         0 my $name = $foreign_key->{ table };
338 0         0 $name =~ s/\./_/;
339              
340 0         0 my $reference_str = "`$foreign_key->{ table }`";
341 0 0       0 if ( defined $foreign_key->{ col } ) {
342             my $col_name = $col_num_2_name->{ $foreign_key->{ table } }
343 0         0 [ $foreign_key->{ col } - 1 ];
344              
345 0 0       0 $reference_str .= " => $col_name" if $col_name;
346             }
347              
348 0         0 my $new_foreigner = <<"EO_Foreign_Field";
349             field $name {
350             is int4;
351             label `$label`;
352             refers_to $reference_str;
353             html_form_type select;
354             }
355             EO_Foreign_Field
356 0         0 push @foreign_fields, $new_foreigner;
357             }
358 0         0 $foreign_text = join '', @foreign_fields;
359             }
360              
361 0         0 chomp $foreign_text;
362              
363 0         0 return $foreign_text;
364             }
365              
366             sub _strip_schema {
367 0     0   0 my $input = shift;
368 0         0 $input =~ s/^[^\.]*\.//;
369              
370 0         0 return $input;
371             }
372              
373             sub augment_tree {
374 0     0 1 0 my $class = shift;
375 0         0 my $style = shift;
376 0         0 my $ast = shift;
377 0         0 my $art = shift;
378              
379             # parse existing tree, get a list of all the extant tables
380 0         0 my %initial_tables = map { $_ => 1 }
  0         0  
381 0         0 keys %{ $ast->{application}{lookup}{tables} };
382 0         0 my $joins = $ast->{application}{lookup}{join_tables};
383              
384 0         0 foreach my $join_member ( keys %{ $joins } ) {
  0         0  
385              
386 0         0 foreach my $membership ( @{ $joins->{ $join_member } } ) {
  0         0  
387              
388 0         0 my ( $join_table ) = values %{ $membership->{ joins } };
  0         0  
389              
390 0         0 $initial_tables{ $join_table } = 1;
391             }
392             }
393              
394 0         0 my $parsed_art = $style->get_db_layout( $art, \%initial_tables );
395             my ( $tables, $new_tables, $joiners, $foreign_key_for, $columns ) = (
396             $parsed_art->{ all_tables },
397             $parsed_art->{ new_tables },
398             $parsed_art->{ joiners },
399             $parsed_art->{ foreigners },
400             $parsed_art->{ columns },
401 0         0 );
402              
403 0         0 my $foreign_targets = _transpose( $foreign_key_for );
404              
405 0         0 my $col_num_2_name = _correlate_columns( $columns, $ast );
406              
407 0         0 $new_tables = _safely_order( $new_tables, $foreign_key_for );
408              
409             # make new tables with tentmaker hooks
410 0         0 my %new_table;
411             my %new_controller_for;
412 0         0 foreach my $table ( @{ $new_tables } ) {
  0         0  
413 0         0 my $controller = Bigtop::ScriptHelp->default_controller( $table );
414              
415 0         0 my $schema_free = _strip_schema( $table );
416              
417 0         0 my $descr = $schema_free;
418 0         0 $descr =~ s/_/ /g;
419              
420 0         0 my $model_label = Bigtop::ScriptHelp->default_label( $schema_free );
421              
422 0         0 my $rel_loc = $table;
423 0         0 $rel_loc =~ s/\./_/;
424              
425 0         0 $new_table{ $table } = $ast->create_block(
426             'table', $table, { columns => $columns->{ $table } }
427             );
428              
429 0         0 my ( $foreign_display, $on_main_listing, $all_fields_but ) =
430             _get_controller_fields( $columns->{ $table } );
431              
432             # set a foreign display
433 0 0       0 if ( defined $foreign_display ) {
434 0         0 $ast->change_statement(
435             {
436             type => 'table',
437             ident => $new_table{ $table }->get_ident,
438             keyword => 'foreign_display',
439             new_value => "%$foreign_display",
440             }
441             );
442             }
443              
444             # make a controller for the new table
445 0         0 $new_controller_for{ $table } = $ast->create_block(
446             'controller',
447             $controller,
448             { subtype => 'AutoCRUD',
449             table => $table,
450             text_description => $descr,
451             page_link_label => $model_label,
452             rel_loc => $rel_loc,
453             on_main_listing => $on_main_listing,
454             all_fields_but => $all_fields_but,
455             }
456             );
457             }
458              
459 0         0 foreach my $point_from ( keys %{ $foreign_key_for } ) {
  0         0  
460 0         0 my $ident = $ast->{application}
461             {lookup}
462             {tables}
463             {$point_from}
464             {__IDENT__};
465              
466 0 0       0 if ( not defined $ident ) { # must be new
467 0         0 $ident = $new_table{ $point_from }->get_ident();
468             }
469              
470 0         0 foreach my $foreign_key ( @{ $foreign_key_for->{ $point_from } } ) {
  0         0  
471              
472 0         0 my $name = $foreign_key->{ table };
473 0         0 $name =~ s/\./_/;
474              
475             my $label =
476             Bigtop::ScriptHelp->default_label(
477             _strip_schema( $foreign_key->{ table } )
478 0         0 );
479              
480 0         0 my $foreign_key_ref_str = $foreign_key->{ table };
481 0 0       0 if ( defined $foreign_key->{ col } ) {
482             my $col_name = $col_num_2_name->{ $foreign_key->{ table } }
483 0         0 [ $foreign_key->{ col } - 1 ];
484              
485             $foreign_key_ref_str = {
486             keys => $foreign_key->{ table },
487 0 0       0 values => $col_name
488             } if $col_name;
489             }
490              
491 0         0 my $refers_to_field = $ast->create_subblock(
492             {
493             parent => {
494             type => 'table', ident => $ident
495             },
496             new_child => {
497             type => 'field',
498             name => $name,
499             },
500             }
501             );
502              
503 0         0 $ast->change_statement(
504             {
505             type => 'field',
506             ident => $refers_to_field->{__IDENT__},
507             keyword => 'is',
508             new_value => 'int4',
509             }
510             );
511 0         0 $ast->change_statement(
512             {
513             type => 'field',
514             ident => $refers_to_field->{__IDENT__},
515             keyword => 'label',
516             new_value => $label,
517             }
518             );
519 0         0 $ast->change_statement(
520             {
521             type => 'field',
522             ident => $refers_to_field->{__IDENT__},
523             keyword => 'refers_to',
524             new_value => $foreign_key_ref_str,
525             }
526             );
527 0         0 $ast->change_statement(
528             {
529             type => 'field',
530             ident => $refers_to_field->{__IDENT__},
531             keyword => 'html_form_type',
532             new_value => 'select',
533             }
534             );
535             }
536             }
537              
538 0         0 foreach my $point_to ( keys %{ $foreign_targets } ) {
  0         0  
539 0         0 my $ident = $ast->{application}
540             {lookup}
541             {tables}
542             {$point_to}
543             {__IDENT__};
544              
545 0 0       0 if ( not defined $ident ) {
546 0         0 $ident = $new_table{ $point_to }->get_ident();
547             }
548              
549 0         0 my @all_referrers;
550             my @referrer_values;
551              
552             # find existing referrals
553 0         0 my $original_referrers = $ast->get_statement(
554             {
555             type => 'table',
556             ident => $ident,
557             keyword => 'refered_to_by',
558             }
559             );
560              
561 0         0 foreach my $original_referrer ( @{ $original_referrers } ) {
  0         0  
562 0         0 my ( $table, $has_many_name ) =
563             split /\s*=>\s*/, $original_referrer;
564              
565 0   0     0 $has_many_name ||= '';
566              
567 0         0 push @all_referrers, $table;
568 0         0 push @referrer_values, $has_many_name;
569             }
570              
571             # add new ones and set as new value
572 0         0 push @all_referrers, @{ $foreign_targets->{ $point_to } };
  0         0  
573              
574 0         0 $ast->change_statement(
575             {
576             type => 'table',
577             ident => $ident,
578             keyword => 'refered_to_by',
579             new_value => {
580             keys => join( '][', @all_referrers ),
581             values => join( '][', @referrer_values ),
582             }
583             }
584             );
585             }
586              
587             # Make three ways.
588 0         0 foreach my $joiner ( @{ $joiners } ) {
  0         0  
589 0         0 my ( $table1, $table2 ) = @{ $joiner };
  0         0  
590 0         0 my $second = $table2;
591 0         0 $second =~ s/.*\.//;
592 0         0 my $join_name = "${table1}_${second}";
593 0         0 my $join_table = $ast->create_block( 'join_table', $join_name, {} );
594              
595             $ast->change_statement(
596             {
597             type => 'join_table',
598             ident => $join_table->{ join_table }{ __IDENT__ },
599 0         0 keyword => 'joins',
600             new_value => {
601             keys => $table1,
602             values => $table2,
603             }
604             }
605             );
606             }
607              
608 0         0 return; # This is an in place tree modifier.
609             }
610              
611             sub _get_controller_fields {
612 0     0   0 my $columns = shift;
613              
614 0         0 my $foreign_display;
615             my $second_main_col;
616 0         0 my @exclude_from_form;
617              
618 0         0 foreach my $column ( @{ $columns } ) {
  0         0  
619 0 0       0 if ( $non_entry{ $column->{ name } } ) {
620 0         0 push @exclude_from_form, $column->{ name };
621             }
622             else {
623             $second_main_col = $column->{ name }
624 0 0 0     0 if $foreign_display and not $second_main_col;
625              
626 0 0       0 $foreign_display = $column->{ name } unless $foreign_display;
627             }
628             }
629              
630 0         0 my $main_cols = $foreign_display;
631 0 0       0 $main_cols .= ", $second_main_col" if $second_main_col;
632              
633 0         0 return ( $foreign_display, $main_cols, join( ', ', @exclude_from_form ) );
634             }
635              
636             sub valid_ident {
637 53     53 1 88 my $candidate = shift;
638              
639             # XXX this regex is allowing leading digits
640 53         588 return $candidate =~ /^\w[\w\d_:\.]*$/;
641             }
642              
643             sub default_label {
644 0     0 1   my $class = shift;
645 0           my $name = shift;
646              
647 0           my @output_pieces = _name_breaker( $name, qr/_/ );
648              
649 0           return join ' ', @output_pieces; # one space separator
650             }
651              
652             sub default_controller {
653 0     0 1   my $class = shift;
654 0           my $table = shift;
655              
656 0           my $name = $class->default_label( $table );
657 0           $name =~ s/ //g;
658              
659 0           my @output_pieces = _name_breaker( $name, qr/\./ );
660              
661 0           return join '', @output_pieces; # no space separator
662             }
663              
664             sub _name_breaker {
665 0     0     my $name = shift;
666 0           my $split_on = shift;
667              
668 0           my @output_pieces;
669              
670 0           foreach my $piece ( split $split_on, $name ) {
671 0           $piece = ucfirst $piece;
672 0           push @output_pieces, $piece;
673             }
674              
675 0           return @output_pieces;
676             }
677              
678             1;
679              
680             =head1 NAME
681              
682             Bigtop::ScriptHelp - A helper modules for command line utilities
683              
684             =head1 SYNOPSIS
685              
686             #!/usr/bin/perl
687             use Bigtop::ScriptHelp;
688              
689             my $default = Bigtop::ScriptHelp->get_minimal_default();
690             my $tree = Bigtop::Parser->parse_string( $default );
691             # ...
692              
693             my $style = 'SomeStyle'; # must live in Bigtop::ScriptHelp::Style::
694              
695             my $better_default = Bigtop::ScriptHelp->get_big_default(
696             $style, $name, $art
697             );
698             my $better_tree = Bigtop::Parser->parse_string( $better_default );
699              
700             Bigtop::ScriptHelp->augment_tree( $style, $bigtop_tree, $art );
701              
702             my $new_field_label = Bigtop::ScriptHelp->default_label( $name );
703              
704             =head1 DESCRIPTION
705              
706             This module is used by the bigtop and tentmaker scripts. It provides
707             convenience functions for them.
708              
709             =head1 Styles
710              
711             Whenever a user is building or augmenting a bigtop file, they can
712             specify new tables and their relationships via a script help style of their
713             choice. All the styles are modules in the Bigtop::ScriptHelp::Style::
714             namespace. See C for general information about
715             styles and individual modules under its namespace for how each style
716             works. That said, here is a list of the styles available when this was
717             written.
718              
719             =head2 Kickstart
720              
721             This is the default style.
722              
723             It allows short text descriptions of database relationships.
724             For example:
725              
726             bigtop -n App 'contact<-birth_day'
727              
728             But recent versions allow you to specify column names, their types, whether
729             they are optional, and to give them literal default values. See
730             C for details. This is my favorite
731             style (so it's no surprise that it is the default).
732              
733             =head2 Pg8Live
734              
735             This style must be requested:
736              
737             bigtop -n App -s Pg8Live dsninfo username password
738              
739             It will connect to the database described by the dsninfo with the supplied
740             username and password and create a bigtop file from it. This will create
741             a full AutoCRUD app for the database. The bigtop file will have all the
742             tables, their columns including types and defaults. It will also know about
743             all primary and foreign keys in the original database. Depending on how
744             exotic the input database is, it will also know to autoincrement the primary
745             key.
746              
747             Writing your own style is easy. See C for
748             the requirements and the two existing styles for examples.
749              
750             =head1 METHODS
751              
752             All methods are class methods.
753              
754             =over 4
755              
756             =item get_minimal_default
757              
758             Params: app_name (optional, defaults to Sample)
759              
760             Returns: a little default bigtop string suitable for initial building.
761             It has everything you need for your app except tables and controllers.
762              
763             =item get_big_default
764              
765             Params:
766              
767             script help style
768             app name
769             a list of data for the style
770              
771             Returns: a bigtop file suitable for immediately creating an app and
772             starting it.
773              
774             =item augment_tree
775              
776             Params:
777              
778             script help style
779             a Bigtop::Parser syntax tree (what you got from a parse_* method)
780             a string of data for the style (join all elements with spaces)
781              
782             Returns: nothing, but the tree you passed will be updated.
783              
784             =item default_label
785              
786             Params: a new name
787              
788             Returns: a default label for that name
789              
790             Example of conversion: if name is birth_date, the label becomes 'Birth Date'.
791              
792             =item default_controller
793              
794             Params: a new table name
795              
796             Returns: a default label for that table's controller
797              
798             Example of conversion: if table name is birth_date, the controller
799             becomes 'BirthDate'.
800              
801             =back
802              
803             =head1 FUNCTIONS
804              
805             The following functions are meant for internal use, but you might like
806             them too. Don't call them through the class, call them as functions.
807              
808             =over 4
809              
810             =item valid_ident
811              
812             Exported by default.
813              
814             Params: a proposed ident
815              
816             Returns: true if the ident looks good, false otherwise. Note that the
817             regex is not perfect. For instance, it will allow leading numbers.
818             Further it absolutely will not notice if a table or controller name is
819             reserved.
820              
821             =back
822              
823             =head1 AUTHOR
824              
825             Phil Crow, Ecrow.phil@gmail.comE
826              
827             =head1 COPYRIGHT AND LICENSE
828              
829             Copyright (C) 2006-7, Phil Crow
830              
831             This library is free software; you can redistribute it and/or modify
832             it under the same terms as Perl itself, either Perl version 5.8.6 or,
833             at your option, any later version of Perl 5 you may have available.
834              
835             =cut