File Coverage

blib/lib/OPM/Maker/Command/sopm.pm
Criterion Covered Total %
statement 351 376 93.3
branch 116 170 68.2
condition 23 41 56.1
subroutine 32 36 88.8
pod 6 6 100.0
total 528 629 83.9


line stmt bran cond sub pod time code
1             package OPM::Maker::Command::sopm;
2             $OPM::Maker::Command::sopm::VERSION = '1.2.0';
3 33     33   27528 use v5.10;
  33         133  
4              
5 33     33   187 use strict;
  33         66  
  33         663  
6 33     33   154 use warnings;
  33         69  
  33         922  
7              
8             # ABSTRACT: Build .sopm file based on metadata
9              
10 33     33   229 use Carp;
  33         80  
  33         2978  
11 33     33   16270 use File::Find::Rule;
  33         267672  
  33         253  
12 33     33   1813 use File::Basename;
  33         75  
  33         2107  
13 33     33   210 use File::Spec;
  33         67  
  33         648  
14 33     33   16305 use IO::File;
  33         255468  
  33         4091  
15 33     33   20605 use JSON;
  33         258692  
  33         265  
16 33     33   4788 use List::Util qw(first max);
  33         78  
  33         2129  
17 33     33   13348 use Path::Class ();
  33         822949  
  33         850  
18 33     33   21568 use XML::LibXML;
  33         1360405  
  33         246  
19 33     33   20915 use XML::LibXML::PrettyPrint;
  33         247879  
  33         343  
20              
21 33     33   20167 use OPM::Maker -command;
  33         1550579  
  33         368  
22 33     33   217566 use OPM::Maker::Utils::OTRS3;
  33         1092  
  33         4153  
23 33     33   18082 use OPM::Maker::Utils::OTRS4;
  33         85  
  33         145793  
24              
25             sub abstract {
26 0     0 1 0 return "build sopm file based on metadata";
27             }
28              
29             sub usage_desc {
30 0     0 1 0 return "opmbuild sopm [--config ] [--cvs] ";
31             }
32              
33             sub opt_spec {
34             return (
35 0     0 1 0 [ 'config=s', 'JSON file that provides all the metadata' ],
36             [ 'cvs' , 'Add CVS tag to .sopm' ],
37             );
38             }
39              
40             sub validate_args {
41 0     0 1 0 my ($self, $opt, $args) = @_;
42              
43 0 0       0 if ( !$opt->{config} ) {
44 0   0     0 my @json_files = File::Find::Rule->file->name( '*.json' )->in( $args->[0] || '.' );
45              
46             @json_files > 1 ?
47             $self->usage_error( 'found more than one json file, please specify the config file to use' ) :
48 0 0       0 do{ $opt->{config} = $json_files[0] };
  0         0  
49             }
50            
51 0 0       0 if ( !$opt->{config} ) {
52 0         0 $self->usage_error( 'Please specify the config file to use' );
53             }
54            
55 0         0 my $config = Path::Class::File->new( $opt->{config} );
56 0         0 my $json = JSON->new->relaxed;
57 0         0 my $json_text = $config->slurp;
58 0 0       0 $self->usage_error( 'config file has to be in JSON format: ' . $@ ) if ! eval{ $json->decode( $json_text ); 1; };
  0         0  
  0         0  
59             }
60              
61             sub execute {
62 36     36 1 63796 my ($self, $opt, $args) = @_;
63              
64 36 50       168 if ( !$opt->{config} ) {
65 0         0 print $self->usage->text;
66 0         0 return;
67             }
68            
69 36         331 my $config = Path::Class::File->new( $opt->{config} );
70 36         7420 my $json_text = $config->slurp;
71 36         11395 my $object = JSON->new->relaxed;
72 36         1063 my $json = $object->decode( $json_text );
73 36         109 my $name = $json->{name};
74              
75 36 50       728 chdir $args->[0] if $args->[0];
76              
77             # check needed info
78 36         136 for my $needed (qw(name version framework)) {
79 108 50       340 if ( !$json->{$needed} ) {
80 0         0 carp "Need $needed in config file";
81 0         0 exit 1;
82             }
83             }
84            
85 36         82 my @xml_parts;
86             my %major_versions;
87              
88             {
89 36         69 for my $framework ( @{ $json->{framework} } ) {
  36         69  
  36         103  
90 61         113 my $version = $framework;
91 61         122 my $min = '';
92 61         87 my $max = '';
93              
94 61 100       158 if ( 'HASH' eq ref $framework ) {
95 3         6 $version = $framework->{version};
96 3         3 $min = $framework->{min};
97 3         7 $max = $framework->{max};
98             }
99              
100 61 100       406 push @xml_parts, sprintf " %s",
    100          
101             ( $min ? qq~ Minimum="$min"~ : '' ),
102             ( $max ? qq~ Maximum="$max"~ : '' ),
103             $version;
104              
105 61         214 my $major_version = (split /\./, $version)[0];
106 61         200 $major_versions{$major_version}++;
107             }
108              
109 36 100       175 if ( 2 <= keys %major_versions ) {
110 2         513 carp "Two major versions declared in framework settings. Those might be incompatible.\n";
111             }
112             }
113              
114 36         492 my %utils_versions = (
115             OTRS => {
116             '3' => 'OTRS3',
117             '4' => 'OTRS4',
118             '5' => 'OTRS4',
119             '6' => 'OTRS4',
120             '7' => 'OTRS4',
121             },
122             KIX => {
123             '5' => 'OTRS4',
124             },
125             OTOBO => {
126             '10' => 'OTRS4',
127             },
128             );
129              
130 36         242 my ($max) = max keys %major_versions;
131              
132 36   100     298 my $product = uc ( $json->{product} // 'OTRS' );
133 36 100       200 if ( $product eq 'KIX' ) {
134 1         2 $max = 5;
135             }
136              
137 36   33     157 my $mod = $utils_versions{$product}->{$max} || $utils_versions{OTRS}->{4};
138 36         110 my $utils = 'OPM::Maker::Utils::' . $mod;
139              
140 36 100       116 if ( $json->{requires} ) {
141             {
142 16         30 for my $name ( sort keys %{ $json->{requires}->{package} } ) {
  16         78  
143 16         97 push @xml_parts, sprintf ' %s', $json->{requires}->{package}->{$name}, $name;
144             }
145             }
146            
147             {
148 16         28 for my $name ( sort keys %{ $json->{requires}->{module} } ) {
  16         41  
  16         24  
  16         59  
149 16         73 push @xml_parts, sprintf ' %s', $json->{requires}->{module}->{$name}, $name;
150             }
151             }
152             }
153              
154 36   50     213 push @xml_parts, sprintf " %s", $json->{vendor}->{name} || '';
155 36   50     205 push @xml_parts, sprintf " %s", $json->{vendor}->{url} || '';
156              
157 36 50       167 if ( $json->{description} ) {
158 36         78 for my $lang ( sort keys %{ $json->{description} } ) {
  36         139  
159 36         176 push @xml_parts, sprintf ' %s', $lang, $json->{description}->{$lang};
160             }
161             }
162              
163 36 50       236 if ( $json->{license} ) {
164 36         152 push @xml_parts, sprintf ' %s', $json->{license};
165             }
166              
167             # create filelist
168             {
169 36         67 my @files = File::Find::Rule->file->in( '.' );
  36         1346  
170              
171             # remove "hidden" files from list; and do not list .sopm
172             @files = grep{
173 36         34465 ( substr( $_, 0, 1 ) ne '.' ) &&
174             $_ !~ m{[\\/]\.} &&
175 166 50 33     1129 $_ ne $json->{name} . '.sopm'
176             }sort @files;
177              
178 36 100 66     205 if ( $json->{exclude_files} and 'ARRAY' eq ref $json->{exclude_files} ) {
179             # ignore ignore file ;-)
180 1         3 my $ignore_name = '.opmbuild_filetest_ignore';
181 1 50       1 push @{ $json->{exclude_files} }, $ignore_name if !grep{ $_ eq $ignore_name } @{ $json->{exclude_files} };
  1         3  
  1         3  
  1         3  
182              
183 1         3 for my $index ( reverse 0 .. $#files ) {
184 2         4 my $file = $files[$index];
185             my $excluded = first {
186 3     3   7 eval{ $file =~ /$_\z/ };
  3         32  
187 2         10 }@{ $json->{exclude_files} };
  2         7  
188              
189 2 100       11 splice @files, $index, 1 if $excluded;
190             }
191              
192             # create ignore file
193 1 50       7 my $fh = IO::File->new( $ignore_name, 'w' ) or die $!;
194 1         169 my $ignore_files = join "\n", @{ $json->{exclude_files} };
  1         5  
195 1         10 $fh->print( $ignore_files );
196 1         15 $fh->close;
197             }
198              
199 36         342 $utils->filecheck( \@files );
200              
201             push @xml_parts,
202             sprintf " \n%s\n ",
203 36 50       90 join "\n", map{ my $permission = $_ =~ /^bin/ ? 755 : 644; qq~ ~ }@files;
  164         364  
  164         650  
204             }
205              
206 36 100 66     159 if ( $json->{changes_file} && -f $config->dir . "/" . $json->{changes_file} ) {
207 1         53 my $changes_file = Path::Class::File->new( $config->dir, $json->{changes_file} );
208 1         108 my $lines = $changes_file->slurp( iomode => '<:encoding(UTF-8)' );
209              
210 1   50     1518 my @entries = grep{ ( $_ // '' ) ne '' }split m{
  5         17  
211             (?:\s+)?
212             ( # headline with version and date
213             ^
214             \d+\.\d+ (?:\.\d+)? # version
215             \s+ - \s+
216             \d{4}-\d{2}-\d{2} \s # date
217             \d{2}:\d{2}:\d{2} # time
218             )
219             \s+
220             }xms, $lines;
221              
222 1         4 while ( @entries ) {
223 2         6 my ($header, $desc) = ( shift(@entries), shift(@entries) );
224              
225 2   50     13 my ($version, $date) = split /\s+-\s+/, $header // '';
226              
227 2         10 $desc =~ s{\s+\z}{};
228              
229 2         25 push @xml_parts, sprintf qq~ ~, $version, $date, $desc;
230             }
231             }
232              
233             # changelog
234             {
235 36         76 CHANGE:
236 36 100       65 for my $change ( @{ $json->{changes} || [] } ) {
  36         206  
237 2         3 my $version = '';
238 2         4 my $date = '';
239 2         3 my $info = '';
240              
241 2 100       6 if ( !ref $change ) {
    50          
242 1         2 $info = $change;
243             }
244             elsif ( 'HASH' eq ref $change ) {
245 1         2 $info = $change->{message};
246 1 50       6 $version = sprintf( ' Version="%s"', $change->{version} ) if $change->{version};
247 1 50       6 $date = sprintf( ' Date="%s"', $change->{date} ) if $change->{date};
248             }
249              
250 2 50       5 next CHANGE if !length $info;
251              
252 2         8 push @xml_parts, sprintf " %s", $version, $date, $info;
253             }
254             }
255              
256 36         156 my %actions = (
257             Install => 'post',
258             Uninstall => 'pre',
259             Upgrade => 'post',
260             );
261              
262 36         276 my %action_code = (
263             TableCreate => \&_TableCreate,
264             Insert => \&_Insert,
265             TableDrop => \&_TableDrop,
266             ColumnAdd => \&_ColumnAdd,
267             ColumnDrop => \&_ColumnDrop,
268             ColumnChange => \&_ColumnChange,
269             ForeignKeyCreate => \&_ForeignKeyCreate,
270             ForeignKeyDrop => \&_ForeignKeyDrop,
271             UniqueDrop => \&_UniqueDrop,
272             UniqueCreate => \&_UniqueCreate,
273             );
274            
275 36         153 my %tables_to_delete;
276             my %own_tables;
277 36         0 my @columns_to_delete;
278 36         0 my %db_actions;
279              
280 36         65 my $table_counter = 0;
281 36         65 my $column_counter;
282              
283             ACTION:
284 36 100       59 for my $action ( @{ $json->{database} || [] } ) {
  36         200  
285 32         62 my $tmp_version = $action->{version};
286 32 100       91 my @versions = ref $tmp_version ? @{$tmp_version} : ($tmp_version);
  8         20  
287              
288             VERSION:
289 32         58 for my $version ( @versions ) {
290 40 100       86 my $action_type = $version ? 'Upgrade' : 'Install';
291 40         65 my $op = $action->{type};
292              
293 40 100       88 if ( $action->{uninstall} ) {
294 1         2 $action_type = 'Uninstall';
295             }
296              
297 40 50       121 next VERSION if !$action_code{$op};
298              
299 40   66     141 my $phase = $action->{phase} || $actions{ $action_type };
300              
301 40 100       114 if ( $op eq 'TableCreate' ) {
    50          
302 15         25 my $table = $action->{name};
303 15         37 $tables_to_delete{$table} = $table_counter++;
304 15         33 $own_tables{$table} = 1;
305             }
306             elsif ( $op eq 'TableDrop' ) {
307 0         0 my $table = $action->{name};
308 0         0 delete $tables_to_delete{$table};
309             }
310              
311 40 100       85 if ( $op eq 'ColumnAdd' ) {
312 3         5 my $table = $action->{name};
313 3 100       8 if ( !$own_tables{$table} ) {
314             unshift @columns_to_delete, +{
315             name => $table,
316 2 50       4 columns => [ map { $_->{name} } @{ $action->{columns} || [] } ],
  2         10  
  2         7  
317             };
318             }
319             }
320            
321 40         72 $action->{version} = $version;
322 40         65 push @{ $db_actions{$action_type}->{$phase} }, $action_code{$op}->($action);
  40         135  
323             }
324             }
325            
326 33         76 for my $columns_delete ( @columns_to_delete ) {
327 1         1 push @{ $db_actions{Uninstall}->{pre} }, _ColumnDrop($columns_delete);
  1         4  
328             }
329              
330 33 100       119 if ( %tables_to_delete ) {
331 11         47 for my $table ( sort { $tables_to_delete{$b} <=> $tables_to_delete{$a} }keys %tables_to_delete ) {
  3         12  
332 14         45 push @{ $db_actions{Uninstall}->{pre} }, _TableDrop({ name => $table });
  14         82  
333             }
334             }
335              
336 33         96 for my $action_type ( qw/Install Upgrade Uninstall/ ) {
337 99         183 for my $phase ( qw/pre post/ ) {
338            
339 198 100       524 next if !$db_actions{$action_type}->{$phase};
340            
341             push @xml_parts,
342             sprintf qq~
343             %s
344 34         118 ~, join "\n", @{ $db_actions{$action_type}->{$phase} };
  34         239  
345             }
346             }
347              
348             CODE:
349 33 100       73 for my $code ( @{ $json->{code} || [] } ) {
  33         190  
350 30 100       85 if ( !ref $code ) {
351 4 100       48 $code = {
352             type => $code,
353             version => 0,
354             phase => ( $code eq 'Uninstall' ? 'pre' : 'post' ),
355             };
356             }
357              
358 30         89 $code->{type} = 'Code' . $code->{type};
359              
360 30 100       77 if ( $code->{inline} ) {
361 1         3 push @xml_parts, _InlineCode( $code );
362 1         4 next CODE;
363             }
364              
365             push @xml_parts, $utils->packagesetup(
366             $code->{type},
367             $code->{version},
368             $code->{function} || $code->{type},
369             $code->{phase},
370             $code->{package},
371 29   66     208 );
372             }
373              
374 33 100       153 for my $intro ( @{ $json->{intro} || [] } ) {
  33         206  
375 2         5 push @xml_parts, _IntroTemplate( $intro );
376             }
377              
378 33         102 my $cvs = "";
379 33 100       148 if ( $opt->{cvs} ) {
380 1         3 $cvs = sprintf qq~\n \$Id: %s.sopm,v 1.1.1.1 2011/04/15 07:49:58 rb Exp \$~, $name;
381             }
382              
383 33         143 my %product_start_tags = (
384             OTRS => 'otrs_package',
385             KIX => 'otrs_package',
386             OTOBO => 'otobo_package',
387             );
388              
389 33         101 my $start_tag = $product_start_tags{$product};
390            
391             my $xml = sprintf q~
392             <%s version="1.0">
393             %s
394             %s
395             %s
396             %s
397            
398             ~,
399             $start_tag,
400             __PACKAGE__->VERSION(),
401             $cvs,
402             $name,
403             $json->{version},
404 33         259 join( "\n", @xml_parts ),
405             $start_tag;
406              
407 33 50       339 my $fh = IO::File->new( $name . '.sopm', 'w' ) or die $!;
408 33         5853 $fh->print( $xml );
409 33         1002 $fh->close;
410             }
411              
412             sub _InlineCode {
413 1     1   2 my ($code) = @_;
414              
415 1         4 my @parts = split /::/, $code->{inline};
416              
417 1         2 my $method = pop @parts;
418 1         2 $parts[-1] .= '.pm';
419 1         6 my $file = Path::Class::File->new( @parts );
420              
421 1         37 my $content = $file->slurp( iomode => '<:encoding(utf-8)' );
422              
423 1         1517 my ($method_body) = $content =~ m{
424             ^sub \s+ \Q$method\E \s* \{ \s+
425             (.*?)
426             ^\}\s+
427             }xms;
428              
429             my $version = $code->{version} ?
430 1 50       5 ' Version="' . $code->{version} . '"' :
431             '';
432              
433             my $xml = sprintf q~ <%s Type="%s"%s>
434             %s
435 1   50     11 ]]>~, $code->{type}, $code->{phase} // 'post', $version, $method_body, $code->{type};
436              
437 1         11 return $xml;
438             }
439              
440             sub _IntroTemplate {
441 2     2   4 my ($intro) = @_;
442              
443 2 50       5 my $version = $intro->{version} ? ' Version="' . $intro->{version} . '"' : '';
444 2         3 my $type = $intro->{type};
445 2 100       6 my $text = ref $intro->{text} ? join( "
\n", @{ $intro->{text} } ) : $intro->{text};
  1         2  
446 2   100     7 my $phase = $intro->{time} || "post";
447 2 100       5 my $lang = $intro->{lang} ? ' Lang="' . $intro->{lang} . '"' : '';
448 2 100       6 my $title = $intro->{title} ? ' Title="' . $intro->{title} . '"' : '';
449              
450 2         15 return qq~
451             $text
452             ]]>~;
453             }
454              
455             sub _Insert {
456 16     16   29 my ($action) = @_;
457              
458              
459 16         28 my $table = $action->{name};
460 16         23 my $version = $action->{version};
461              
462 16 100       48 my $version_string = $version ? ' Version="' . $version . '"' : '';
463              
464 16         39 my $string = ' \n";
465              
466             COLUMN:
467 16 50       32 for my $column ( @{ $action->{columns} || [] } ) {
  16         48  
468 112 100       233 my $value = ref $column->{value} ? join( "\n", @{ $column->{value} } ) : $column->{value};
  6         14  
469 112   50     206 $value //= '';
470              
471             $string .= sprintf ' %s' . "\n",
472             $column->{name},
473             ( $column->{type} ?
474 112 100       398 (' Type="' . $column->{type} . '"', '' ) :
475             ("", $value)
476             );
477             }
478              
479 16         35 $string .= ' ';
480              
481 16         53 return $string;
482             }
483              
484             sub _TableDrop {
485 14     14   47 my ($action) = @_;
486              
487 14         27 my $table = $action->{name};
488              
489 14         62 return ' ';
490             }
491              
492             sub _TableCreate {
493 15     15   29 my ($action) = @_;
494              
495 15         28 my $table = $action->{name};
496 15         28 my $version = $action->{version};
497              
498 15 50       32 my $version_string = $version ? ' Version="' . $version . '"' : '';
499              
500 15         52 my $string = ' \n";
501              
502             COLUMN:
503 15 50       101 for my $column ( @{ $action->{columns} || [] } ) {
  15         50  
504 43         105 my $type = _TypeCheck( $column->{type}, 'TableCreate' );
505             $string .= sprintf ' ' . "\n",
506             $column->{name},
507             $column->{required},
508             $type,
509             ( $column->{size} ? ' Size="' . $column->{size} . '"' : "" ),
510             ( $column->{auto_increment} ? ' AutoIncrement="true"' : "" ),
511 42 100       300 ( $column->{primary_key} ? ' PrimaryKey="true"' : "" ),
    100          
    100          
512             }
513              
514             UNIQUE:
515 14 100       140 for my $unique ( @{ $action->{unique} || [] } ) {
  14         82  
516 4         6 my $table = $unique->{name};
517 4   66     31 $string .= ' {columns} || ["unique$table"] } ) ) . '">' . "\n";
518              
519 4 50       6 for my $column ( @{ $unique->{columns} || [] } ) {
  4         10  
520 8         19 $string .= ' ' . "\n";
521             }
522              
523 4         8 $string .= ' ' . "\n";
524             }
525              
526             KEY:
527 14 100       28 for my $key ( @{ $action->{keys} || [] } ) {
  14         48  
528 10         18 my $table = $key->{name};
529 10         25 $string .= ' ' . "\n";
530              
531 10 50       58 for my $reference ( @{ $key->{references} || [] } ) {
  10         32  
532 10         19 my $local = $reference->{local};
533 10         17 my $foreign = $reference->{foreign};
534 10         37 $string .= ' ' . "\n";
535             }
536              
537 10         22 $string .= ' ' . "\n";
538             }
539              
540 14         30 $string .= ' ';
541              
542 14         54 return $string;
543             }
544              
545             sub _ColumnAdd {
546 3     3   5 my ($action) = @_;
547              
548 3         5 my $table = $action->{name};
549 3         5 my $version = $action->{version};
550              
551 3 50       9 my $version_string = $version ? ' Version="' . $version . '"' : '';
552              
553 3         8 my $string = ' \n";
554              
555             COLUMN:
556 3 50       4 for my $column ( @{ $action->{columns} || [] } ) {
  3         23  
557 3         7 my $type = _TypeCheck( $column->{type}, 'ColumnAdd' );
558             $string .= sprintf ' ' . "\n",
559             $column->{name},
560             $column->{required},
561             $type,
562             ( $column->{size} ? ' Size="' . $column->{size} . '"' : "" ),
563             ( $column->{auto_increment} ? ' AutoIncrement="true"' : "" ),
564 2 50       17 ( $column->{primary_key} ? ' PrimaryKey="true"' : "" ),
    50          
    50          
565             }
566              
567 2         5 $string .= ' ';
568              
569 2         24 return $string;
570             }
571              
572             sub _ColumnDrop {
573 2     2   5 my ($action) = @_;
574              
575 2         4 my $table = $action->{name};
576 2         3 my $version = $action->{version};
577              
578 2 50       6 my $version_string = $version ? ' Version="' . $version . '"' : '';
579              
580 2         5 my $string = ' \n";
581              
582             COLUMN:
583 2 50       4 for my $column ( @{ $action->{columns} || [] } ) {
  2         6  
584 2         9 $string .= sprintf qq~ \n~, $column;
585             }
586              
587 2         4 $string .= ' ';
588              
589 2         7 return $string;
590             }
591              
592             sub _ForeignKeyCreate {
593 1     1   23 my ($action) = @_;
594              
595 1         5 my $table = $action->{name};
596 1         2 my $version = $action->{version};
597              
598 1 50       3 my $version_string = $version ? ' Version="' . $version . '"' : '';
599              
600 1         4 my $string = ' \n";
601              
602             COLUMN:
603 1 50       2 for my $reference ( @{ $action->{references} || [] } ) {
  1         3  
604             $string .= sprintf '
605            
606             ' . "\n",
607             $reference->{name},
608             $reference->{local},
609 2         10 $reference->{foreign};
610             }
611              
612 1         2 $string .= ' ';
613              
614 1         5 return $string;
615             }
616              
617             sub _ForeignKeyDrop {
618 1     1   21 my ($action) = @_;
619              
620 1         4 my $table = $action->{name};
621 1         2 my $version = $action->{version};
622              
623 1 50       4 my $version_string = $version ? ' Version="' . $version . '"' : '';
624              
625 1         4 my $string = ' \n";
626              
627             COLUMN:
628 1 50       1 for my $reference ( @{ $action->{references} || [] } ) {
  1         4  
629             $string .= sprintf '
630            
631             ' . "\n",
632             $reference->{name},
633             $reference->{local},
634 2         9 $reference->{foreign};
635             }
636              
637 1         3 $string .= ' ';
638              
639 1         4 return $string;
640             }
641              
642             sub _UniqueCreate {
643 1     1   21 my ($action) = @_;
644              
645 1         5 my $table = $action->{name};
646 1         2 my $version = $action->{version};
647              
648 1 50       3 my $version_string = $version ? ' Version="' . $version . '"' : '';
649              
650 1         3 my $string = ' \n";
651 1         5 $string .= sprintf qq~ \n~, $action->{unique_name};
652              
653             COLUMN:
654 1 50       2 for my $column ( @{ $action->{columns} || [] } ) {
  1         3  
655 2         6 $string .= sprintf qq~ \n~,
656             $column;
657             }
658              
659 1         2 $string .= qq~ \n~;
660 1         2 $string .= ' ';
661              
662 1         4 return $string;
663             }
664              
665             sub _UniqueDrop {
666 1     1   22 my ($action) = @_;
667              
668 1         4 my $table = $action->{name};
669 1         2 my $version = $action->{version};
670              
671 1 50       4 my $version_string = $version ? ' Version="' . $version . '"' : '';
672              
673 1         3 my $string = ' \n";
674              
675             $string .= sprintf qq~ \n~,
676 1         5 $action->{unique_name};
677              
678 1         2 $string .= ' ';
679              
680 1         4 return $string;
681             }
682              
683             sub _ColumnChange {
684 1     1   3 my ($action) = @_;
685              
686 1         2 my $table = $action->{name};
687 1         1 my $version = $action->{version};
688              
689 1 50       3 my $version_string = $version ? ' Version="' . $version . '"' : '';
690              
691 1         3 my $string = ' \n";
692              
693             COLUMN:
694 1 50       2 for my $column ( @{ $action->{columns} || [] } ) {
  1         4  
695 1         2 my $type = _TypeCheck( $column->{type}, 'ColumnChange' );
696             $string .= sprintf ' ' . "\n",
697             $column->{new_name},
698             $column->{old_name},
699             $column->{required},
700             $type,
701             ( $column->{size} ? ' Size="' . $column->{size} . '"' : "" ),
702             ( $column->{auto_increment} ? ' AutoIncrement="true"' : "" ),
703 0 0       0 ( $column->{primary_key} ? ' PrimaryKey="true"' : "" ),
    0          
    0          
704             }
705              
706 0         0 $string .= ' ';
707              
708 0         0 return $string;
709             }
710              
711             sub _TypeCheck {
712 47     47   96 my ($type, $action) = @_;
713              
714 47         183 my %types = (
715             DATE => 1,
716             SMALLINT => 1,
717             BIGINT => 1,
718             INTEGER => 1,
719             DECIMAL => 1,
720             VARCHAR => 1,
721             LONGBLOB => 1,
722             );
723              
724 47 100       137 if ( !$types{$type} ) {
725 3         119 croak "$type is not allowed in $action. Allowed types: ", join ', ', sort keys %types;
726             }
727              
728 44         199 return $type;
729             }
730              
731             sub VERSION {
732 33   50 33 1 673 return $OPM::Maker::Command::sopm::VERSION || '1.0.0';
733             }
734              
735             1;
736              
737             __END__