summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xLedgerSMB/Inifile.pm143
-rwxr-xr-xLedgerSMB/Menu.pm165
-rw-r--r--t/12-menu.t154
-rw-r--r--t/data/12-menu1.ini5
-rw-r--r--t/data/12-menu2.ini9
-rw-r--r--t/data/12-menu3.ini9
-rw-r--r--t/data/12-menu4.ini19
7 files changed, 438 insertions, 66 deletions
diff --git a/LedgerSMB/Inifile.pm b/LedgerSMB/Inifile.pm
index 1b89502c..97c1a7ff 100755
--- a/LedgerSMB/Inifile.pm
+++ b/LedgerSMB/Inifile.pm
@@ -1,37 +1,112 @@
-#=====================================================================
-# LedgerSMB
-# Small Medium Business Accounting software
-# http://www.ledgersmb.org/
-#
-# Copyright (C) 2006
-# This work contains copyrighted information from a number of sources all used
-# with permission.
-#
-# This file contains source code included with or based on SQL-Ledger which
-# is Copyright Dieter Simader and DWS Systems Inc. 2000-2005 and licensed
-# under the GNU General Public License version 2 or, at your option, any later
-# version. For a full list including contact information of contributors,
-# maintainers, and copyright holders, see the CONTRIBUTORS file.
-#
-# Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
-# Copyright (C) 2002
-#
-# Author: DWS Systems Inc.
-# Web: http://www.sql-ledger.org
-#
-# Contributors:
-# Tony Fraser <tony@sybaspace.com>
-#
-#======================================================================
-#
-# This file has undergone whitespace cleanup.
-#
-#======================================================================
-#
-# routines to retrieve / manipulate win ini style files
-# ORDER is used to keep the elements in the order they appear in .ini
-#
-#=====================================================================
+
+=head1 NAME
+
+Inifile Routines to load LedgerSMB menu files.
+
+=head1 STATUS
+
+API I<deprecated>, removed in 1.3.
+
+=head1 SYNOPSIS
+
+Routines to load LedgerSMB menu files. LedgerSMB menu files are a specific
+form of ini file.
+
+Files use both ';' and '#' to denote line comments. Any text after a line that
+starts with '.' (i.e. ".foo") is ignored. Menu items are denoted as [section],
+with the sections containing key=value pairs. The keys 'module', 'action',
+'target', 'href', and 'submenu' are specially treated, while other keys are
+output as arguments to the destination link. Blank lines are ignored.
+
+=head2 Special key treatment
+
+=over
+
+=item action
+
+This key is deleted on menuitem calls if there is no href value.
+
+=item module
+
+This is the Perl script that the menu item will call if the href attribute is
+not set. This key is always deleted on a menuitem call.
+
+=item target
+
+The value given for target will be passed as the target attribute for the tag.
+This key is always deleted on a menuitem call.
+
+=item href
+
+When set, this key's value becomes the base URL for the menu item. This key is
+always deleted on a menuitem call.
+
+=item submenu
+
+This key is not displayed in output, but is deleted from the Menufile object
+when menuitem is called on the item.
+
+=back
+
+=head2 Value Interpolation
+
+If a value for a regular key includes an equals sign (=), values from the user's
+configuration are substituted into the place of the string preceding and the
+first encountered equals sign in the value. So a menu entry of 'apples=login='
+would have the substition of 'apples=$myconfig->{login}' on generation of the
+menu link.
+
+=head1 METHODS
+
+=over
+
+=item new ([$filename])
+
+Create a new Menufile object. If a filename is specified, load the file with
+add_file.
+
+=item add_file ($filename)
+
+Load the contents of the specified file into the Menufile object. If the file
+cannot be read, Form->error will be called with the failure message. Attempts
+to load already loaded items will result in the newer item merging with and
+overwriting stored data from the previous load.
+
+Menu item titles are stored as keys in the Menufile object, and a special key,
+ORDER maintains a list of the order in which menu items were first seen.
+
+=back
+
+=head1 Copyright (C) 2006, The LedgerSMB core team.
+
+ #====================================================================
+ # LedgerSMB
+ # Small Medium Business Accounting software
+ # http://www.ledgersmb.org/
+ #
+ # Copyright (C) 2006
+ # This work contains copyrighted information from a number of sources
+ # all used with permission.
+ #
+ # This file contains source code included with or based on SQL-Ledger
+ # which is Copyright Dieter Simader and DWS Systems Inc. 2000-2005
+ # and licensed under the GNU General Public License version 2 or, at
+ # your option, any later version. For a full list including contact
+ # information of contributors, maintainers, and copyright holders,
+ # see the CONTRIBUTORS file.
+ #
+ # Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
+ # Copyright (C) 2002
+ #
+ # Author: DWS Systems Inc.
+ # Web: http://www.sql-ledger.org
+ #
+ # Contributors:
+ # Tony Fraser <tony@sybaspace.com>
+ #
+ #=====================================================================
+
+=cut
package Inifile;
diff --git a/LedgerSMB/Menu.pm b/LedgerSMB/Menu.pm
index dce0be8e..3de367b6 100755
--- a/LedgerSMB/Menu.pm
+++ b/LedgerSMB/Menu.pm
@@ -1,35 +1,136 @@
-#=====================================================================
-# LedgerSMB
-# Small Medium Business Accounting software
-# http://www.ledgersmb.org/
-#
-# Copyright (C) 2006
-# This work contains copyrighted information from a number of sources all used
-# with permission.
-#
-# This file contains source code included with or based on SQL-Ledger which
-# is Copyright Dieter Simader and DWS Systems Inc. 2000-2005 and licensed
-# under the GNU General Public License version 2 or, at your option, any later
-# version. For a full list including contact information of contributors,
-# maintainers, and copyright holders, see the CONTRIBUTORS file.
-#
-# Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
-# Copyright (C) 2002
-#
-# Author: DWS Systems Inc.
-# Web: http://www.sql-ledger.org
-#
-# Contributors: Tony Fraser <tony@sybaspace.com>
-#
-#======================================================================
-#
-# This file has undergone whitespace cleanup.
-#
-#======================================================================
-#
-# routines for menu items
-#
-#=====================================================================
+
+=head1 NAME
+
+Menu Routines to handle LedgerSMB menu files and format entries for display.
+
+=head1 STATUS
+
+API I<deprecated>, data format I<deprecated>, replaced in 1.3 by
+LedgerSMB::Menu.
+
+=head1 SYNOPIS
+
+Routines to handle LedgerSMB menu files and conversion of menu entries into a
+form usable by a web browser. LedgerSMB menu files are a specific form of ini
+file. Subclasses LedgerSMB::Inifile.
+
+Files use both ';' and '#' to denote line comments. Any text after a line that
+starts with '.' (i.e. ".foo") is ignored. Menu items are denoted as [section],
+with the sections containing key=value pairs. The keys 'module', 'action',
+'target', 'href', and 'submenu' are specially treated, while other keys are
+output as arguments to the destination link. Blank lines are ignored.
+
+=head2 Special key treatment
+
+=over
+
+=item action
+
+This key is deleted on menuitem calls if there is no href value.
+
+=item module
+
+This is the Perl script that the menu item will call if the href attribute is
+not set. This key is always deleted on a menuitem call.
+
+=item target
+
+The value given for target will be passed as the target attribute for the tag.
+This key is always deleted on a menuitem call.
+
+=item href
+
+When set, this key's value becomes the base URL for the menu item. This key is
+always deleted on a menuitem call.
+
+=item submenu
+
+This key is not displayed in output, but is deleted from the Menufile object
+when menuitem is called on the item.
+
+=back
+
+=head2 Value Interpolation
+
+If a value for a regular key includes an equals sign (=), values from the user's
+configuration are substituted into the place of the string preceding and the
+first encountered equals sign in the value. So a menu entry of 'apples=login='
+would have the substition of 'apples=$myconfig->{login}' on generation of the
+menu link.
+
+=head1 METHODS
+
+=over
+
+=item new ([$filename])
+
+Create a new Menu object. If a filename is specified, load the file with
+add_file.
+
+=item add_file ($filename)
+
+Load the contents of the specified file into the Menu object. If the file
+cannot be read, Form->error will be called with the failure message. Attempts
+to load already loaded items will result in the newer item merging with and
+overwriting stored data from the previous load.
+
+Menu item titles are stored as keys in the Menufile object, and a special key,
+ORDER maintains a list of the order in which menu items were first seen.
+
+=item menuitem ($myconfig, $form, $item)
+
+Formats the menu item for the given key $item as an HTML <a href=""> open tag.
+Returns the tag and deletes the module, target, href, action, and submenu
+attributes for the item from the Menufile object.
+
+If the menubar attribute of the passed in Form attribute is set, no style will
+be set for the tag, otherwise the style is set to "display:block".
+
+=item access_control ($myconfig, [$menulevel])
+
+Returns the list of menu items that can be displayed with $myconfig->{acs} at
+the selected menu level. $menulevel is the string corresponding to a displayed
+menu, such as 'AR' or 'AR--Reports'. A blank level corresponds to the top
+level. Merely excluding a top-level element does not exclude corresponding
+lower level elements, i.e. excluding 'AR' will not block 'AR--Reports'.
+
+$myconfig->{acs} is a semicolon seperated list of menu items to exclude.
+
+This is only a cosmetic form of access_control. Users can still access
+"disallowed" sections of the application by manually entering in the URL.
+
+=back
+
+=head1 Copyright (C) 2006, The LedgerSMB core team.
+
+ #====================================================================
+ # LedgerSMB
+ # Small Medium Business Accounting software
+ # http://www.ledgersmb.org/
+ #
+ # Copyright (C) 2006
+ # This work contains copyrighted information from a number of sources
+ # all used with permission.
+ #
+ # This file contains source code included with or based on SQL-Ledger
+ # which is Copyright Dieter Simader and DWS Systems Inc. 2000-2005
+ # and licensed under the GNU General Public License version 2 or, at
+ # your option, any later version. For a full list including contact
+ # information of contributors, maintainers, and copyright holders,
+ # see the CONTRIBUTORS file.
+ #
+ # Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
+ # Copyright (C) 2002
+ #
+ # Author: DWS Systems Inc.
+ # Web: http://www.sql-ledger.org
+ #
+ # Contributors:
+ # Tony Fraser <tony@sybaspace.com>
+ #
+ #=====================================================================
+
+=cut
package Menu;
diff --git a/t/12-menu.t b/t/12-menu.t
new file mode 100644
index 00000000..c6d775d6
--- /dev/null
+++ b/t/12-menu.t
@@ -0,0 +1,154 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+$ENV{TMPDIR} = 't/var';
+
+use Test::More tests => 37;
+my $notrap = 1;
+if ($^O ne 'MSWin32') { #Test::Trap known to crash Win32
+ eval 'use Test::Trap';
+ if ($@) {
+ $notrap = 1;
+ } else {
+ use Test::Trap qw(trap $trap);
+ $notrap = 0;
+ }
+}
+
+use LedgerSMB::Form;
+use LedgerSMB::Menu;
+
+my $ini;
+my @r;
+my $form;
+my $myconfig;
+
+# general new and add_file checks
+$ini = new Menu;
+ok(defined $ini, 'new: File not provided');
+isa_ok($ini, 'Menu', 'new: File not provided gives correct type');
+$ini->add_file('t/data/12-menu1.ini');
+is_deeply($ini->{'AR--Add Transaction'},
+ {'action' => 'add', 'module' => 'ar.pl'},
+ 'add_file: First file added, leaf correct');
+is_deeply($ini->{'ORDER'},
+ ['AR', 'AR--Add Transaction'],
+ 'add_file: First file added, order correct');
+
+$ini->add_file('t/data/12-menu2.ini');
+is_deeply($ini->{'AR--Add Transaction'},
+ {'action' => 'add', 'module' => 'ar.pl'},
+ 'add_file: Second file added, old leaf correct');
+is_deeply($ini->{'AR--foo'},
+ {'module' => 'am.pl'},
+ 'add_file: Second file added, new leaf correct');
+is_deeply($ini->{'ORDER'},
+ ['AR', 'AR--Add Transaction', 'section', 'AR--foo'],
+ 'add_file: Second file added, order correct');
+
+$ini = Menu->new('t/data/12-menu2.ini');
+ok(defined $ini, 'new: File provided');
+isa_ok($ini, 'Menu', 'new: File provided gives correct type');
+is_deeply($ini->{'AR--foo'},
+ {'module' => 'am.pl'},
+ 'new: File provided, leaf correct');
+is_deeply($ini->{'ORDER'},
+ ['section', 'AR--foo'],
+ 'new: File provided, order correct');
+
+$ini->add_file('t/data/12-menu3.ini');
+is_deeply($ini->{'AR--foo'},
+ {'module' => 'ax.pl'},
+ 'add_file: Data re-added, leaf correct, not duplicated');
+is_deeply($ini->{'ORDER'},
+ ['section', 'AR--foo'],
+ 'add_file: Data re-added, order correct, not duplicated');
+
+# menuitem checks
+$form = new Form;
+$form->{script} = 'tt.pl';
+$form->{tag} = '1';
+$myconfig = {'login' => 'testuser', 'numberformat' => '1000.00'};
+$ini = new Menu('t/data/12-menu4.ini');
+is_deeply($ini->{'AR--foo'},
+ {'module' => 'ax.pl', 'action' => 'add', 'type' => 'foo'},
+ 'new: Data for menu item test 1 correct');
+is_deeply($ini->{'New Window'}, {'target' => '_blank'},
+ 'new: Data for menu item test 2 correct');
+is_deeply($ini->{'Website'}, {'href' => 'ledgersmb.org'},
+ 'new: Data for menu item test 3 correct');
+is_deeply($ini->{'AR--test'},
+ {'module' => 'test', 'apples' => 'login=', 'pears' => 'numberformat=2'},
+ 'new: Data for menu item test 4 correct');
+is_deeply($ini->{'AR'}, {'target' => 'acc_menu', 'type' => 'test'},
+ 'new: Data for menu item test 5 correct');
+
+is($ini->menuitem($myconfig, $form, 'AR--foo'), '<a style="display:block;"href="ax.pl?path=bin/mozilla&amp;action=add&amp;level=AR--foo&amp;login=&amp;timeout=&amp;sessionid=&amp;js=&amp;type=foo">',
+ 'menuitem: Menu item test 1, base');
+ok(!defined $ini->{'AR--foo'}->{'module'}, 'menuitem: Deleted module');
+ok(!defined $ini->{'AR--foo'}->{'action'}, 'menuitem: Deleted action');
+is($ini->menuitem($myconfig, $form, 'New Window'), '<a style="display:block;"href="tt.pl?path=bin/mozilla&amp;action=section_menu&amp;level=New%20Window&amp;login=&amp;timeout=&amp;sessionid=&amp;js=" target="_blank">',
+ 'menuitem: Menu item test 2, target');
+is($ini->menuitem($myconfig, $form, 'Website'), '<a href="ledgersmb.org">',
+ 'menuitem: Menu item test 3, href');
+ok(!defined $ini->{'Website'}->{'href'}, 'menuitem: Deleted href');
+$form->{menubar} = 1;
+is($ini->menuitem($myconfig, $form, 'AR--test'), '<a style=""href="test?path=bin/mozilla&amp;action=section_menu&amp;level=AR--test&amp;login=&amp;timeout=&amp;sessionid=&amp;js=&amp;apples=testuser&amp;pears=1000.002">',
+ 'menuitem: Menu item test 4, myconfig substitutions');
+is($ini->menuitem($myconfig, $form, 'AR'), '<a style=""href="tt.pl?path=bin/mozilla&amp;action=section_menu&amp;level=AR&amp;login=&amp;timeout=&amp;sessionid=&amp;js=&amp;type=test#id1" target="acc_menu">',
+ 'menuitem: Menu item test 5, acc_menu');
+ok(!defined $ini->{'AR'}->{'target'}, 'menuitem: Deleted target');
+
+# access_control check
+$myconfig = {'acs' => 'AR--test'};
+$ini = new Menu('t/data/12-menu4.ini');
+is_deeply([$ini->access_control($myconfig)], ['AR', 'New Window', 'Website'],
+ 'access_control: Single item, not top exclusion, top');
+is_deeply([$ini->access_control($myconfig, 'AR')], ['AR--foo'],
+ 'access_control: Single item, not top exclusion, submenu');
+$myconfig = {'acs' => 'Website'};
+is_deeply([$ini->access_control($myconfig)], ['AR', 'New Window'],
+ 'access_control: Single item, top exclusion, top');
+is_deeply([$ini->access_control($myconfig, 'AR')], ['AR--foo', 'AR--test'],
+ 'access_control: Single item, top exclusion, sub menu');
+$myconfig = {'acs' => 'AR--test;AR--foo;New Window'};
+is_deeply([$ini->access_control($myconfig)], ['AR', 'Website'],
+ 'access_control: Multiple items, top');
+is_deeply([$ini->access_control($myconfig, 'AR')], [],
+ 'access_control: Multiple items, sub menu');
+$myconfig = {'acs' => 'AR'};
+is_deeply([$ini->access_control($myconfig)], ['New Window', 'Website'],
+ 'access_control: Top menu exclusion, top');
+is_deeply([$ini->access_control($myconfig, 'AR')], ['AR--foo', 'AR--test'],
+ 'access_control: Top menu exclusion, sub menu');
+
+# file not found check
+SKIP: {
+ skip 'file not found test, Test::Trap not usable', 2 if !$notrap;
+ $ini = new Menu;
+ @r = trap{$ini->add_file('t/data/12-not-a-file')};
+ is_deeply($ini->{'ORDER'}, [],
+ 'add_file: Non-existent file added, order correct');
+ like($trap->die, qr|12-not-a-file :|,
+ 'add_file: Non-existent file causes error display');
+}
+### Gratuitous testing to increase coverage rating
+##$ini = undef;
+##@r = trap{$ini = Menu::new};
+##isa_ok($ini, 'main', 'new: No type passed gives main type');
+##
+##my $pkg = 'foo';
+##$ini = undef;
+##@r = trap{$ini = Menu::new(\$pkg)};
+##like($trap->{warn}[0], qr|has no copy constructor! creating a new object|,
+## 'new: Type passed scalar reference');
+##isa_ok($ini, 'SCALAR', 'new: Type passed scalar reference gives SCALAR type');
+##Menu::add_file($ini, 't/data/12-menu1.ini');
+##is_deeply($ini->{'AR--Add Transaction'},
+## {'action' => 'add', 'module' => 'ar.pl'},
+## 'add_file: File added to SCALAR, leaf correct');
+##is_deeply($ini->{'ORDER'},
+## ['AR', 'AR--Add Transaction'],
+## 'add_file: File added to SCALAR, order correct');
diff --git a/t/data/12-menu1.ini b/t/data/12-menu1.ini
new file mode 100644
index 00000000..6ad5b3fb
--- /dev/null
+++ b/t/data/12-menu1.ini
@@ -0,0 +1,5 @@
+[AR]
+
+[AR--Add Transaction]
+module=ar.pl
+action=add
diff --git a/t/data/12-menu2.ini b/t/data/12-menu2.ini
new file mode 100644
index 00000000..0064ff6b
--- /dev/null
+++ b/t/data/12-menu2.ini
@@ -0,0 +1,9 @@
+# Second test inifile
+[section] ; New section
+[AR--foo] ; But appending now to an old one
+module=am.pl
+.
+No more content... Time to go home
+Yes, really.
+[This is not a real section]
+not=real
diff --git a/t/data/12-menu3.ini b/t/data/12-menu3.ini
new file mode 100644
index 00000000..858fddf2
--- /dev/null
+++ b/t/data/12-menu3.ini
@@ -0,0 +1,9 @@
+# Third test inifile
+[AR--foo] ; But appending now to an old one
+module=ax.pl
+[section] ; New section
+.
+No more content... Time to go home
+Yes, really.
+[This is not a real section]
+not=real
diff --git a/t/data/12-menu4.ini b/t/data/12-menu4.ini
new file mode 100644
index 00000000..1233af84
--- /dev/null
+++ b/t/data/12-menu4.ini
@@ -0,0 +1,19 @@
+# Fourth test menu file
+[AR]
+type=test
+target=acc_menu
+
+[AR--foo]
+module=ax.pl
+action=add
+type=foo
+[AR--test]
+module=test
+apples=login= ; becomes apples=$myconfig->{login}
+pears=numberformat=2 ; becomes pears=$myconfig->{numberformat}2
+
+[New Window]
+target=_blank
+
+[Website]
+href=ledgersmb.org