kivitendo/SL/DBUpgrade2.pm @ a97d97a0
4fd8bdbf | Moritz Bunkus | package SL::DBUpgrade2;
|
||
faef45c2 | Moritz Bunkus | use SL::Common;
|
||
4fd8bdbf | Moritz Bunkus | require Exporter;
|
||
76c486e3 | Sven Schöling | our @ISA = qw(Exporter);
|
||
4fd8bdbf | Moritz Bunkus | |||
76c486e3 | Sven Schöling | our @EXPORT = qw(parse_dbupdate_controls sort_dbupdate_controls);
|
||
use strict;
|
||||
4fd8bdbf | Moritz Bunkus | |||
sub parse_dbupdate_controls {
|
||||
$main::lxdebug->enter_sub();
|
||||
my ($form, $dbdriver) = @_;
|
||||
my $locale = $main::locale;
|
||||
local *IN;
|
||||
my %all_controls;
|
||||
my $path = "sql/${dbdriver}-upgrade2";
|
||||
foreach my $file_name (<$path/*.sql>, <$path/*.pl>) {
|
||||
next unless (open(IN, $file_name));
|
||||
my $file = $file_name;
|
||||
$file =~ s|.*/||;
|
||||
my $control = {
|
||||
"priority" => 1000,
|
||||
53c7990b | Moritz Bunkus | "depends" => [],
|
||
4fd8bdbf | Moritz Bunkus | };
|
||
while (<IN>) {
|
||||
chomp();
|
||||
next unless (/^(--|\#)\s*\@/);
|
||||
s/^(--|\#)\s*\@//;
|
||||
s/\s*$//;
|
||||
next if ($_ eq "");
|
||||
my @fields = split(/\s*:\s*/, $_, 2);
|
||||
next unless (scalar(@fields) == 2);
|
||||
if ($fields[0] eq "depends") {
|
||||
push(@{$control->{"depends"}}, split(/\s+/, $fields[1]));
|
||||
} else {
|
||||
$control->{$fields[0]} = $fields[1];
|
||||
}
|
||||
}
|
||||
91836534 | Moritz Bunkus | next if ($control->{ignore});
|
||
faef45c2 | Moritz Bunkus | $control->{charset} ||= Common::DEFAULT_CHARSET;
|
||
53c7990b | Moritz Bunkus | if (!$control->{"tag"}) {
|
||
_control_error($form, $file_name, $locale->text("Missing 'tag' field.")) ;
|
||||
}
|
||||
4fd8bdbf | Moritz Bunkus | |||
53c7990b | Moritz Bunkus | if ($control->{"tag"} =~ /[^a-zA-Z0-9_\(\)\-]/) {
|
||
_control_error($form, $file_name, $locale->text("The 'tag' field must only consist of alphanumeric characters or the carachters - _ ( )"))
|
||||
}
|
||||
4fd8bdbf | Moritz Bunkus | |||
53c7990b | Moritz Bunkus | if (defined($all_controls{$control->{"tag"}})) {
|
||
_control_error($form, $file_name, sprintf($locale->text("More than one control file with the tag '%s' exist."), $control->{"tag"}))
|
||||
}
|
||||
4fd8bdbf | Moritz Bunkus | |||
53c7990b | Moritz Bunkus | if (!$control->{"description"}) {
|
||
_control_error($form, $file_name, sprintf($locale->text("Missing 'description' field."))) ;
|
||||
}
|
||||
4fd8bdbf | Moritz Bunkus | |||
53c7990b | Moritz Bunkus | $control->{"priority"} *= 1;
|
||
$control->{"priority"} ||= 1000;
|
||||
$control->{"file"} = $file;
|
||||
4fd8bdbf | Moritz Bunkus | |||
53c7990b | Moritz Bunkus | delete @{$control}{qw(depth applied)};
|
||
4fd8bdbf | Moritz Bunkus | |||
$all_controls{$control->{"tag"}} = $control;
|
||||
close(IN);
|
||||
}
|
||||
foreach my $control (values(%all_controls)) {
|
||||
foreach my $dependency (@{$control->{"depends"}}) {
|
||||
53c7990b | Moritz Bunkus | _control_error($form, $control->{"file"}, sprintf($locale->text("Unknown dependency '%s'."), $dependency)) if (!defined($all_controls{$dependency}));
|
||
4fd8bdbf | Moritz Bunkus | }
|
||
map({ $_->{"loop"} = 0; } values(%all_controls));
|
||||
53c7990b | Moritz Bunkus | _check_for_loops($form, $control->{"file"}, \%all_controls, $control->{"tag"});
|
||
4fd8bdbf | Moritz Bunkus | }
|
||
map({ _dbupdate2_calculate_depth(\%all_controls, $_->{"tag"}) }
|
||||
values(%all_controls));
|
||||
$main::lxdebug->leave_sub();
|
||||
return \%all_controls;
|
||||
}
|
||||
sub _check_for_loops {
|
||||
my ($form, $file_name, $controls, $tag, @path) = @_;
|
||||
push(@path, $tag);
|
||||
ad876674 | Moritz Bunkus | my $ctrl = $controls->{$tag};
|
||
if ($ctrl->{"loop"} == 1) {
|
||||
# Not done yet.
|
||||
53c7990b | Moritz Bunkus | _control_error($form, $file_name, $main::locale->text("Dependency loop detected:") . " " . join(" -> ", @path))
|
||
ad876674 | Moritz Bunkus | } elsif ($ctrl->{"loop"} == 0) {
|
||
# Not checked yet.
|
||||
$ctrl->{"loop"} = 1;
|
||||
53c7990b | Moritz Bunkus | map({ _check_for_loops($form, $file_name, $controls, $_, @path); } @{ $ctrl->{"depends"} });
|
||
ad876674 | Moritz Bunkus | $ctrl->{"loop"} = 2;
|
||
}
|
||||
4fd8bdbf | Moritz Bunkus | }
|
||
sub _control_error {
|
||||
my ($form, $file_name, $message) = @_;
|
||||
0cfb13d0 | Udo Spallek | $form = $main::form;
|
||
4fd8bdbf | Moritz Bunkus | my $locale = $main::locale;
|
||
53c7990b | Moritz Bunkus | $form->error(sprintf($locale->text("Error in database control file '%s': %s"), $file_name, $message));
|
||
4fd8bdbf | Moritz Bunkus | }
|
||
sub _dbupdate2_calculate_depth {
|
||||
2c7a89dd | Sven Schöling | $main::lxdebug->enter_sub(2);
|
||
4fd8bdbf | Moritz Bunkus | |||
my ($tree, $tag) = @_;
|
||||
my $node = $tree->{$tag};
|
||||
2c7a89dd | Sven Schöling | return $main::lxdebug->leave_sub(2) if (defined($node->{"depth"}));
|
||
4fd8bdbf | Moritz Bunkus | |||
my $max_depth = 0;
|
||||
foreach $tag (@{$node->{"depends"}}) {
|
||||
_dbupdate2_calculate_depth($tree, $tag);
|
||||
my $value = $tree->{$tag}->{"depth"};
|
||||
$max_depth = $value if ($value > $max_depth);
|
||||
}
|
||||
$node->{"depth"} = $max_depth + 1;
|
||||
2c7a89dd | Sven Schöling | $main::lxdebug->leave_sub(2);
|
||
4fd8bdbf | Moritz Bunkus | }
|
||
sub sort_dbupdate_controls {
|
||||
53c7990b | Moritz Bunkus | return sort({ $a->{"depth"} != $b->{"depth"} ? $a->{"depth"} <=> $b->{"depth"}
|
||
: $a->{"priority"} != $b->{"priority"} ? $a->{"priority"} <=> $b->{"priority"}
|
||||
: $a->{"tag"} cmp $b->{"tag"} } values(%{$_[0]}));
|
||||
4fd8bdbf | Moritz Bunkus | }
|
||
1;
|