use
5.10.1;
our
@ISA
=
qw(Exporter)
;
our
@EXPORT_OK
=
qw/apply_filter/
;
my
$logger
= Log::Log4perl::get_logger(
'Tk::Filter'
);
sub
_get_filter_action {
my
(
$elt
,
$elt_filter
,
$filtered_state
,
$unfiltered_state
,
$default_state
) =
@_
;
my
$action
=
$default_state
;
if
(
length
(
$elt_filter
) > 2) {
if
(
$elt
=~ /
$elt_filter
/) {
$action
=
$filtered_state
;
}
else
{
$action
=
$unfiltered_state
;
}
}
return
$action
;
}
sub
apply_filter {
my
(
%args
) =
@_
;
my
$show_only_custom
=
$args
{show_only_custom} // 0;
my
$hide_empty_values
=
$args
{hide_empty_values} // 0;
my
$instance
=
$args
{instance} // carp
"missing instance"
;
my
$actions
=
$args
{actions} // carp
"missing actions ref"
;
my
$fd_path
=
$args
{fd_path} //
''
;
%$actions
= ();
my
%combine_actions
= (
show
=> {
show
=>
'show'
,
''
=>
'show'
,
hide
=>
'show'
},
''
=> {
show
=>
'show'
,
''
=>
''
,
hide
=>
''
},
hide
=> {
show
=>
'show'
,
''
=>
''
,
hide
=>
'hide'
},
);
my
$leaf_cb
=
sub
{
my
(
$scanner
,
$data_ref
,
$node
,
$element_name
,
$index
,
$leaf_object
) =
@_
;
my
$loc
=
$leaf_object
->location;
my
$action
=
''
;
if
(
$show_only_custom
) {
$action
=
$leaf_object
->has_data ?
'show'
:
'hide'
;
}
if
(
$hide_empty_values
) {
my
$v
=
$leaf_object
->fetch(
qw/check no/
);
$action
=
'hide'
unless
(
defined
$v
and
length
(
$v
)) ;
}
$action
=
'show'
if
$loc
eq
$fd_path
;
$logger
->trace(
"leaf '$loc' filter is '$action'"
);
$data_ref
->{
return
} =
$data_ref
->{actions}{
$loc
} =
$action
;
};
my
$check_list_cb
=
sub
{
my
(
$scanner
,
$data_ref
,
$node
,
$element_name
,
undef
,
$obj
) =
@_
;
my
$loc
=
$obj
->location;
my
$action
=
''
;
if
(
$hide_empty_values
and not
$obj
->fetch()) {
$action
=
'hide'
;
}
$action
=
'show'
if
$loc
eq
$fd_path
;
$logger
->trace(
"check_list '$loc' filter is '$action'"
);
$data_ref
->{
return
} =
$data_ref
->{actions}{
$loc
} =
$action
;
};
my
$hash_cb
=
sub
{
my
(
$scanner
,
$data_ref
,
$node
,
$element_name
,
@keys
) =
@_
;
my
$obj
=
$node
->fetch_element(
$element_name
);
my
$loc
=
$obj
->location;
my
$hash_action
=
$hide_empty_values
||
$show_only_custom
?
'hide'
:
''
;
foreach
my
$key
(
@keys
) {
my
$inner_ref
= {
actions
=>
$data_ref
->{actions},
filter
=>
$data_ref
->{filter} };
$scanner
->scan_hash(
$inner_ref
,
$node
,
$element_name
,
$key
);
$hash_action
=
$combine_actions
{
$hash_action
}{
$inner_ref
->{
return
}};
}
$hash_action
=
'show'
if
$loc
eq
$fd_path
;
$logger
->trace(
"hash '$loc' filter is '$hash_action'"
);
$data_ref
->{
return
} =
$data_ref
->{actions}{
$loc
} =
$hash_action
;
};
my
$node_cb
=
sub
{
my
(
$scanner
,
$data_ref
,
$node
,
@element_list
) =
@_
;
my
$node_loc
=
$node
->location;
my
$elt_filter
=
$data_ref
->{filter};
my
$all_elt_action
=
$show_only_custom
?
'hide'
:
''
;
my
$default_action
= (
length
(
$elt_filter
) > 3) ?
'hide'
:
''
;
foreach
my
$elt
(
@element_list
) {
my
$filter_action
= _get_filter_action(
$elt
,
$elt_filter
,
'show'
,
'hide'
,
''
);
my
$obj
=
$node
->fetch_element(
$elt
);
my
$loc
=
$obj
->location;
$data_ref
->{actions} //= {};
my
$elt_action
;
if
(
$filter_action
eq
'show'
) {
my
$inner_ref
= {
actions
=>
$data_ref
->{actions},
filter
=>
''
};
$scanner
->scan_element(
$inner_ref
,
$node
,
$elt
);
$elt_action
=
$data_ref
->{actions}{
$loc
} =
$filter_action
;
$logger
->trace(
"node '$loc' elt $elt filter is active '$elt_action'"
);
}
else
{
my
$inner_ref
= {
actions
=>
$data_ref
->{actions},
filter
=>
$data_ref
->{filter} };
$scanner
->scan_element(
$inner_ref
,
$node
,
$elt
);
$elt_action
=
$data_ref
->{actions}{
$loc
} =
$inner_ref
->{
return
} ||
$default_action
;
$logger
->trace(
"node '$loc' elt $elt filter is not active '$elt_action'"
);
}
$all_elt_action
=
$combine_actions
{
$all_elt_action
}{
$elt_action
};
$logger
->trace(
"node '$loc' elt $elt all_elt_action is '$all_elt_action'"
);
}
my
$node_action
=
$node_loc
eq
$fd_path
?
'show'
:
$all_elt_action
;
$logger
->trace(
"node '$node_loc' filter is '$node_action'"
);
$data_ref
->{
return
} =
$data_ref
->{actions}{
$node_loc
} =
$node_action
;
};
my
$scan
= Config::Model::ObjTreeScanner-> new (
leaf_cb
=>
$leaf_cb
,
hash_element_cb
=>
$hash_cb
,
list_element_cb
=>
$hash_cb
,
node_content_cb
=>
$node_cb
,
) ;
my
$data_ref
= {
filter
=>
$args
{elt_filter_value} //
''
,
actions
=>
$actions
,
};
$scan
->scan_node(
$data_ref
,
$instance
->config_root) ;
}
1;