File Coverage

blib/lib/Lemonldap/NG/Portal/Menu.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             ##@file
2             # menu for lemonldap::ng portal
3              
4             ##@class
5             # menu class for lemonldap::ng portal
6             package Lemonldap::NG::Portal::Menu;
7              
8 1     1   22938 use strict;
  1         3  
  1         48  
9 1     1   5 use warnings;
  1         2  
  1         30  
10 1     1   852 use Lemonldap::NG::Portal::Simple;
  0            
  0            
11             use Lemonldap::NG::Portal::_LibAccess;
12             use base qw(Lemonldap::NG::Portal::_LibAccess);
13             use Clone qw(clone);
14              
15             our $VERSION = '1.4.0';
16             our $catlevel = 0;
17              
18             ## @method void menuInit()
19             # Prepare menu template elements
20             # @return nothing
21             sub menuInit {
22             my $self = shift;
23             $self->{apps}->{imgpath} ||= '/apps/';
24              
25             # Modules to display
26             $self->{menuModules} ||= "Appslist ChangePassword LoginHistory Logout";
27             $self->{menuDisplayModules} = $self->displayModules();
28              
29             # Extract password from POST data
30             $self->{oldpassword} = $self->param('oldpassword');
31             $self->{newpassword} = $self->param('newpassword');
32             $self->{confirmpassword} = $self->param('confirmpassword');
33             $self->{dn} = $self->{sessionInfo}->{dn};
34             $self->{user} = $self->{sessionInfo}->{_user};
35              
36             # Try to change password
37             $self->{menuError} =
38             $self->_subProcess(
39             qw(passwordDBInit modifyPassword passwordDBFinish sendPasswordMail))
40             unless $self->{ignorePasswordChange};
41              
42             # Default menu error code
43             $self->{menuError} = PE_PASSWORD_OK if ( $self->{passwordWasChanged} );
44             $self->{menuError} ||= $self->{error};
45              
46             # Tab to display
47             # Get the tab URL parameter
48             $self->{menuDisplayTab} = $self->param("tab") || "none";
49              
50             # Default to appslist if invalid tab URL parameter
51             $self->{menuDisplayTab} = "appslist"
52             unless ( $self->{menuDisplayTab} =~ /^(password|logout|loginHistory)$/ );
53              
54             # Force password tab in case of password error
55             $self->{menuDisplayTab} = "password"
56             if (
57             (
58             scalar(
59             grep { $_ == $self->{menuError} } (
60             25, #PE_PP_CHANGE_AFTER_RESET
61             26, #PE_PP_PASSWORD_MOD_NOT_ALLOWED
62             27, #PE_PP_MUST_SUPPLY_OLD_PASSWORD
63             28, #PE_PP_INSUFFICIENT_PASSWORD_QUALITY
64             29, #PE_PP_PASSWORD_TOO_SHORT
65             30, #PE_PP_PASSWORD_TOO_YOUNG
66             31, #PE_PP_PASSWORD_IN_HISTORY
67             32, #PE_PP_GRACE
68             33, #PE_PP_EXP_WARNING
69             34, #PE_PASSWORD_MISMATCH
70             39, #PE_BADOLDPASSWORD
71             74, #PE_MUST_SUPPLY_OLD_PASSWORD
72             )
73             )
74             )
75             );
76              
77             # Application list for old templates
78             if ( $self->{useOldMenuItems} ) {
79             $self->{menuAppslistMenu} = $self->appslistMenu();
80             $self->{menuAppslistDesc} = $self->appslistDescription();
81             }
82              
83             return;
84             }
85              
86             ## @method arrayref displayModules()
87             # List modules that can be displayed in Menu
88             # @return modules list
89             sub displayModules {
90             my $self = shift;
91             my $displayModules = [];
92              
93             # Modules list
94             my @modules = split( /\s/, $self->{menuModules} );
95              
96             # Foreach module, eval condition
97             # Store module in result if condition is valid
98             foreach my $module (@modules) {
99             my $cond = $self->{ 'portalDisplay' . $module };
100             $cond = 1 unless defined $cond;
101              
102             $self->lmLog( "Evaluate condition $cond for module $module", 'debug' );
103              
104             if ( $self->safe->reval($cond) ) {
105             my $moduleHash = { $module => 1 };
106             $moduleHash->{'APPSLIST_LOOP'} = $self->appslist()
107             if ( $module eq 'Appslist' );
108             if ( $module eq 'LoginHistory' ) {
109             $moduleHash->{'SUCCESS_LOGIN'} =
110             $self->mkSessionArray(
111             $self->{sessionInfo}->{loginHistory}->{successLogin},
112             "", 0, 0 );
113             $moduleHash->{'FAILED_LOGIN'} =
114             $self->mkSessionArray(
115             $self->{sessionInfo}->{loginHistory}->{failedLogin},
116             "", 0, 1 );
117             }
118             push @$displayModules, $moduleHash;
119             }
120             }
121              
122             return $displayModules;
123             }
124              
125             ## @method arrayref appslist()
126             # Returns categories and applications list as HTML::Template loop
127             # @return categories and applications list
128             sub appslist {
129             my ($self) = splice @_;
130             my $appslist = [];
131              
132             return $appslist unless defined $self->{applicationList};
133              
134             # Reset level
135             $catlevel = 0;
136              
137             my $applicationList = clone( $self->{applicationList} );
138             my $filteredList = $self->_filter($applicationList);
139             push @$appslist, $self->_buildCategoryHash( "", $filteredList, $catlevel );
140              
141             # We must return an ARRAY ref
142             return ( ref $appslist->[0]->{categories} eq "ARRAY" )
143             ? $appslist->[0]->{categories}
144             : [];
145             }
146              
147             ## @method private hashref _buildCategoryHash(string catname,hashref cathash, int catlevel)
148             # Build hash for a category
149             # @param catname Category name
150             # @param cathash Hash of category elements
151             # @param catlevel Category level
152             # @return Category Hash
153             sub _buildCategoryHash {
154             my ( $self, $catid, $cathash, $catlevel ) = splice @_;
155             my $catname = $cathash->{catname} || $catid;
156             my $applications;
157             my $categories;
158              
159             # Extract applications from hash
160             my $apphash;
161             foreach my $catkey ( sort keys %$cathash ) {
162             next if $catkey =~ /(type|options|catname)/;
163             if ( $cathash->{$catkey}->{type} eq "application" ) {
164             $apphash->{$catkey} = $cathash->{$catkey};
165             }
166             }
167              
168             # Display applications first
169             if ( scalar keys %$apphash > 0 ) {
170             foreach my $appkey ( sort keys %$apphash ) {
171             push @$applications,
172             $self->_buildApplicationHash( $appkey, $apphash->{$appkey} );
173             }
174             }
175              
176             # Display subcategories
177             foreach my $catkey ( sort keys %$cathash ) {
178             next if $catkey =~ /(type|options|catname)/;
179             if ( $cathash->{$catkey}->{type} eq "category" ) {
180             push @$categories,
181             $self->_buildCategoryHash( $catkey, $cathash->{$catkey},
182             $catlevel + 1 );
183             }
184             }
185              
186             my $categoryHash = {
187             category => 1,
188             catname => $catname,
189             catid => $catid,
190             catlevel => $catlevel
191             };
192             $categoryHash->{applications} = $applications if $applications;
193             $categoryHash->{categories} = $categories if $categories;
194             return $categoryHash;
195             }
196              
197             ## @method private hashref _buildApplicationHash(string appid, hashref apphash)
198             # Build hash for an application
199             # @param $appid Application ID
200             # @param $apphash Hash of application elements
201             # @return Application Hash
202             sub _buildApplicationHash {
203             my ( $self, $appid, $apphash ) = splice @_;
204             my $applications;
205              
206             # Get application items
207             my $appname = $apphash->{options}->{name} || $appid;
208             my $appuri = $apphash->{options}->{uri} || "";
209             my $appdesc = $apphash->{options}->{description};
210             my $applogo = $apphash->{options}->{logo};
211              
212             # Detect sub applications
213             my $subapphash;
214             foreach my $key ( sort keys %$apphash ) {
215             next if $key =~ /(type|options|catname)/;
216             if ( $apphash->{$key}->{type} eq "application" ) {
217             $subapphash->{$key} = $apphash->{$key};
218             }
219             }
220              
221             # Display sub applications
222             if ( scalar keys %$subapphash > 0 ) {
223             foreach my $appkey ( sort keys %$subapphash ) {
224             push @$applications,
225             $self->_buildApplicationHash( $appkey, $subapphash->{$appkey} );
226             }
227             }
228              
229             my $applicationHash = {
230             application => 1,
231             appname => $appname,
232             appuri => $appuri,
233             appdesc => $appdesc,
234             applogo => $applogo,
235             appid => $appid,
236             };
237             $applicationHash->{applications} = $applications if $applications;
238             return $applicationHash;
239             }
240              
241             ## @method string appslistMenu()
242             # Returns HTML code for application list menu.
243             # @return HTML string
244             sub appslistMenu {
245             my $self = shift;
246              
247             # We no more use XML file for menu configuration
248             unless ( defined $self->{applicationList} ) {
249             $self->abort(
250             "XML menu configuration is deprecated",
251             "Please use lmMigrateConfFiles2ini to migrate your menu configuration"
252             );
253             }
254              
255             # Use configuration to get menu parameters
256             my $applicationList = clone( $self->{applicationList} );
257             my $filteredList = $self->_filter($applicationList);
258              
259             return $self->_displayConfCategory( "", $filteredList, $catlevel );
260             }
261              
262             ## @method string appslistDescription()
263             # Returns HTML code for application description.
264             # @return HTML string
265             sub appslistDescription {
266             my $self = shift;
267              
268             # We no more use XML file for menu configuration
269             unless ( defined $self->{applicationList} ) {
270             $self->lmLog(
271             "XML menu configuration is deprecated. Please use lmMigrateConfFiles2ini to migrate your menu configuration",
272             'error'
273             );
274             return " ";
275             }
276              
277             # Use configuration to get menu parameters
278             my $applicationList = clone( $self->{applicationList} );
279             return $self->_displayConfDescription( "", $applicationList );
280             }
281              
282             ## @method string _displayConfCategory(string catname, hashref cathash, int catlevel)
283             # Creates and returns HTML code for a category.
284             # @param catname Category name
285             # @param cathash Hash of category elements
286             # @param catlevel Category level
287             # @return HTML string
288             sub _displayConfCategory {
289             my ( $self, $catname, $cathash, $catlevel ) = splice @_;
290             my $html;
291             my $key;
292              
293             # Init HTML list
294             $html .= "<ul class=\"category cat-level-$catlevel\">\n";
295             $html .= "<li class=\"catname\">\n";
296             $html .= "<span>$catname</span>\n" if $catname;
297              
298             # Increase category level
299             $catlevel++;
300              
301             # Extract applications from hash
302             my $apphash;
303             foreach $key ( keys %$cathash ) {
304             next if $key =~ /(type|options|catname)/;
305             if ( $cathash->{$key}->{type}
306             and $cathash->{$key}->{type} eq "application" )
307             {
308             $apphash->{$key} = $cathash->{$key};
309             }
310             }
311              
312             # display applications first
313             if ( scalar keys %$apphash > 0 ) {
314             $html .= "<ul>";
315             foreach $key ( keys %$apphash ) {
316             $html .= $self->_displayConfApplication( $key, $apphash->{$key} );
317             }
318             $html .= "</ul>";
319             }
320              
321             # Display subcategories
322             foreach $key ( keys %$cathash ) {
323             next if $key =~ /(type|options|catname)/;
324             if ( $cathash->{$key}->{type}
325             and $cathash->{$key}->{type} eq "category" )
326             {
327             $html .=
328             $self->_displayConfCategory( $key, $cathash->{$key}, $catlevel );
329             }
330             }
331              
332             # Close HTML list
333             $html .= "</li>\n";
334             $html .= "</ul>\n";
335              
336             return $html;
337             }
338              
339             ## @method private string _displayConfApplication(string appid, hashref apphash)
340             # Creates HTML code for an application.
341             # @param $appid Application ID
342             # @param $apphash Hash of application elements
343             # @return HTML string
344             sub _displayConfApplication {
345             my $self = shift;
346             my ( $appid, $apphash ) = @_;
347             my $html;
348             my $key;
349              
350             # Get application items
351             my $appname = $apphash->{options}->{name} || $appid;
352             my $appuri = $apphash->{options}->{uri} || "";
353              
354             # Display application
355             $html .=
356             "<li title=\"$appid\" class=\"appname $appid\"><span>"
357             . ( $appuri ? "<a href=\"$appuri\">$appname</a>" : "<a>$appname</a>" )
358             . "</span>\n";
359              
360             # Detect sub applications
361             my $subapphash;
362             foreach $key ( keys %$apphash ) {
363             next if $key =~ /(type|options|catname)/;
364             if ( $apphash->{$key}->{type} eq "application" ) {
365             $subapphash->{$key} = $apphash->{$key};
366             }
367             }
368              
369             # Display sub applications
370             if ( scalar keys %$subapphash > 0 ) {
371             $html .= "<ul>";
372             foreach $key ( keys %$subapphash ) {
373             $html .=
374             $self->_displayConfApplication( $key, $subapphash->{$key} );
375             }
376             $html .= "</ul>";
377             }
378              
379             $html .= "</li>";
380             return $html;
381             }
382              
383             ## @method private string _displayConfDescription(string appid, hashref apphash)
384             # Create HTML code for application description.
385             # @param $appid Application ID
386             # @param $apphash Hash
387             # @return HTML string
388             sub _displayConfDescription {
389             my $self = shift;
390             my ( $appid, $apphash ) = @_;
391             my $html = "";
392             my $key;
393              
394             if ( defined $apphash->{type} and $apphash->{type} eq "application" ) {
395              
396             # Get application items
397             my $appname = $apphash->{options}->{name} || $appid;
398             my $appuri = $apphash->{options}->{uri} || "";
399             my $appdesc = $apphash->{options}->{description};
400             my $applogofile = $apphash->{options}->{logo};
401             my $applogo = $self->{apps}->{imgpath} . $applogofile
402             if $applogofile;
403              
404             # Display application description
405             $html .= "<div id=\"$appid\" class=\"appsdesc\">\n";
406             $html .=
407             "<a href=\"$appuri\"><img src=\"$applogo\" alt=\"$appid logo\" /></a>\n"
408             if $applogofile;
409             $html .= "<p class=\"appname\">$appname</p>\n" if defined $appname;
410             $html .= "<p class=\"appdesc\">$appdesc</p>\n" if defined $appdesc;
411             $html .= "</div>\n";
412             }
413              
414             # Sublevels
415             foreach $key ( keys %$apphash ) {
416             next if $key =~ /(type|options|catname)/;
417             $html .= $self->_displayConfDescription( $key, $apphash->{$key} );
418             }
419              
420             return $html;
421             }
422              
423             ## @method private string _filter(hashref apphash)
424             # Duplicate hash reference
425             # Remove unauthorized menu elements
426             # Hide empty categories
427             # @param $apphash Menu elements
428             # @return filtered hash
429             sub _filter {
430             my ( $self, $apphash ) = splice @_;
431             my $filteredHash;
432             my $key;
433              
434             # Copy hash reference into a new hash
435             foreach $key ( keys %$apphash ) {
436             $filteredHash->{$key} = $apphash->{$key};
437             }
438              
439             # Filter hash
440             $self->_filterHash($filteredHash);
441              
442             # Hide empty categories
443             $self->_isCategoryEmpty($filteredHash);
444              
445             return $filteredHash;
446             }
447              
448             ## @method private string _filterHash(hashref apphash)
449             # Remove unauthorized menu elements
450             # @param $apphash Menu elements
451             # @return filtered hash
452             sub _filterHash {
453             my $self = shift;
454             my ($apphash) = @_;
455             my $key;
456             my $appkey;
457              
458             foreach $key ( keys %$apphash ) {
459             next if $key =~ /(type|options|catname)/;
460             if ( $apphash->{$key}->{type}
461             and $apphash->{$key}->{type} eq "category" )
462             {
463              
464             # Filter the category
465             $self->_filterHash( $apphash->{$key} );
466             }
467             if ( $apphash->{$key}->{type}
468             and $apphash->{$key}->{type} eq "application" )
469             {
470              
471             # Find sub applications and filter them
472             foreach $appkey ( keys %{ $apphash->{$key} } ) {
473             next if $appkey =~ /(type|options|catname)/;
474              
475             # We have sub elements, so we filter them
476             $self->_filterHash( $apphash->{$key} );
477             }
478              
479             # Check rights
480             my $appdisplay = $apphash->{$key}->{options}->{display}
481             || "auto";
482             my $appuri = $apphash->{$key}->{options}->{uri};
483              
484             # Remove if display is "no" or "off"
485             delete $apphash->{$key} and next if ( $appdisplay =~ /^(no|off)$/ );
486              
487             # Keep node if display is "yes" or "on"
488             next if ( $appdisplay =~ /^(yes|on)$/ );
489              
490             # Check grant function if display is "auto" (this is the default)
491             delete $apphash->{$key} unless ( $self->_grant($appuri) );
492             next;
493             }
494             }
495              
496             }
497              
498             ## @method private void _isCategoryEmpty(hashref apphash)
499             # Check if a category is empty
500             # @param $apphash Menu elements
501             # @return boolean
502             sub _isCategoryEmpty {
503             my $self = shift;
504             my ($apphash) = @_;
505             my $key;
506              
507             # Test sub categories
508             foreach $key ( keys %$apphash ) {
509             next if $key =~ /(type|options|catname)/;
510             if ( $apphash->{$key}->{type}
511             and $apphash->{$key}->{type} eq "category" )
512             {
513             delete $apphash->{$key}
514             if $self->_isCategoryEmpty( $apphash->{$key} );
515             }
516             }
517              
518             # Test this category
519             if ( $apphash->{type} and $apphash->{type} eq "category" ) {
520              
521             # Temporary store 'options'
522             my $tmp_options = $apphash->{options};
523             my $tmp_catname = $apphash->{catname};
524              
525             delete $apphash->{type};
526             delete $apphash->{options};
527             delete $apphash->{catname};
528              
529             if ( scalar( keys %$apphash ) ) {
530              
531             # There are sub categories or sub applications
532             # Restore type and options
533             $apphash->{type} = "category";
534             $apphash->{options} = $tmp_options;
535             $apphash->{catname} = $tmp_catname;
536              
537             # Return false
538             return 0;
539             }
540             else {
541              
542             # Return true
543             return 1;
544             }
545             }
546             return 0;
547             }
548              
549             1;
550              
551             __END__
552              
553             =head1 NAME
554              
555             =encoding utf8
556              
557             Lemonldap::NG::Portal::Menu - Portal menu functions
558              
559             =head1 SYNOPSIS
560              
561             use Lemonldap::NG::Portal::Simple;
562             my $portal = Lemonldap::NG::Portal::Simple->new(
563             {
564             }
565             );
566              
567             # Init portal menu
568             $portal->menuInit();
569              
570              
571             =head1 DESCRIPTION
572              
573             Lemonldap::NG::Portal::Menu is used to build menu.
574              
575             =head1 SEE ALSO
576              
577             L<Lemonldap::NG::Portal>, L<http://lemonldap-ng.org/>
578              
579             =head1 AUTHOR
580              
581             =over
582              
583             =item Clement Oudot, E<lt>clem.oudot@gmail.comE<gt>
584              
585             =item François-Xavier Deltombe, E<lt>fxdeltombe@gmail.com.E<gt>
586              
587             =item Xavier Guimard, E<lt>x.guimard@free.frE<gt>
588              
589             =back
590              
591             =head1 BUG REPORT
592              
593             Use OW2 system to report bug or ask for features:
594             L<http://jira.ow2.org>
595              
596             =head1 DOWNLOAD
597              
598             Lemonldap::NG is available at
599             L<http://forge.objectweb.org/project/showfiles.php?group_id=274>
600              
601             =head1 COPYRIGHT AND LICENSE
602              
603             =over
604              
605             =item Copyright (C) 2008, 2009, 2010 by Xavier Guimard, E<lt>x.guimard@free.frE<gt>
606              
607             =item Copyright (C) 2012 by François-Xavier Deltombe, E<lt>fxdeltombe@gmail.com.E<gt>
608              
609             =item Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 by Clement Oudot, E<lt>clem.oudot@gmail.comE<gt>
610              
611             =back
612              
613             This library is free software; you can redistribute it and/or modify
614             it under the terms of the GNU General Public License as published by
615             the Free Software Foundation; either version 2, or (at your option)
616             any later version.
617              
618             This program is distributed in the hope that it will be useful,
619             but WITHOUT ANY WARRANTY; without even the implied warranty of
620             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
621             GNU General Public License for more details.
622              
623             You should have received a copy of the GNU General Public License
624             along with this program. If not, see L<http://www.gnu.org/licenses/>.
625              
626             =cut
627              
628