Erfolgsrechnung 1st draft
[kivitendo-erp.git] / SL / Menu.pm
index 1ecb52f..ac8f728 100644 (file)
@@ -12,37 +12,46 @@ BEGIN {
    $yaml_xs =  eval { require YAML::XS };
 }
 
+our %menu_cache;
+
 sub new {
   my ($package, $domain) = @_;
 
-  my $path = File::Spec->catdir('menus', $domain);
+  if (!$menu_cache{$domain}) {
+    my $path = File::Spec->catdir('menus', $domain);
 
-  opendir my $dir, $path or die "can't open $path: $!";
-  my @files = sort grep -f "$path/$_", readdir $dir;
-  close $dir;
+    opendir my $dir, $path or die "can't open $path: $!";
+    my @files = sort grep -f "$path/$_", grep /\.yaml$/, readdir $dir;
+    close $dir;
 
-  my $nodes = [];
-  my $nodes_by_id = {};
-  for my $file (@files) {
-    my $data;
-    if ($yaml_xs) {
-      $data = YAML::XS::LoadFile(File::Spec->catfile($path, $file));
-    } else {
-      $data = YAML::LoadFile(File::Spec->catfile($path, $file));
+    my $nodes = [];
+    my $nodes_by_id = {};
+    for my $file (@files) {
+      my $data;
+      if ($yaml_xs) {
+        $data = YAML::XS::LoadFile(File::Spec->catfile($path, $file));
+      } else {
+        $data = YAML::LoadFile(File::Spec->catfile($path, $file));
+      }
+      _merge($nodes, $nodes_by_id, $data);
     }
-    _merge($nodes, $nodes_by_id, $data);
-  }
 
 
-  my $self = bless {
-    nodes => $nodes,
-    by_id => $nodes_by_id,
-  }, $package;
+    my $self = bless {
+      nodes => $nodes,
+      by_id => $nodes_by_id,
+    }, $package;
+
+    $self->build_tree;
+
+    $menu_cache{$domain} = $self;
+  } else {
+    $menu_cache{$domain}->clear_access;
+  }
 
-  $self->build_tree;
-  $self->set_access;
+  $menu_cache{$domain}->set_access;
 
-  return $self;
+  return $menu_cache{$domain};
 }
 
 sub _merge {
@@ -88,7 +97,7 @@ sub build_tree {
   # first, some sanity check. are all parents valid ids or empty?
   for my $node ($self->nodes) {
     next if !exists $node->{parent} || !$node->{parent} || $self->{by_id}->{$node->{id}};
-    die "menu: node $node->{id} has non-existant parent $node->{parent}";
+    die "menu: node $node->{id} has non-existent parent $node->{parent}";
   }
 
   my %by_parent;
@@ -211,13 +220,30 @@ sub parse_instance_conf_string {
   return $::instance_conf->data->{$setting};
 }
 
+sub parse_compare_string {
+  my ($self, $switch) = @_;
+  my ($setting, $mode) = split m/=/, $switch, 2;
+  return $::instance_conf->data->{$setting} eq $mode;
+}
+
+sub clear_access {
+  my ($self) = @_;
+  for my $node ($self->tree_walk("all")) {
+    delete $node->{visible};
+    delete $node->{visible_children};
+  }
+}
+
 sub set_access {
   my ($self) = @_;
-  # 1. evaluate access for all
-  # 2. if a menu has no visible children, its not visible either
+  # 1. evaluate appearence
+  # 2. evaluate access for all
+  # 3. if a menu has no visible children, its not visible either
 
   for my $node (reverse $self->tree_walk("all")) {
-    $node->{visible} = $node->{access}           ? $self->parse_access_string($node)
+    $node->{visible} = $node->{inclusion}        ? $self->parse_compare_string($node->{inclusion})  : 1
+                   && $node->{exclusion}        ? !$self->parse_compare_string($node->{exclusion}) : 1
+                   && $node->{access}           ? $self->parse_access_string($node)
                      : !$node->{children}        ? 1
                      : $node->{visible_children} ? 1
                      :                             0;