$OpenInteract::Component::VERSION
=
sprintf
(
"%d.%02d"
,
q$Revision: 2.16 $
=~ /(\d+)\.(\d+)/);
use
constant
DEFAULT_METHOD
=>
'handler'
;
use
constant
NOTFOUND_SECURITY
=> SEC_LEVEL_NONE;
sub
handler {
my
(
$class
,
$p
,
$return_info
) =
@_
;
my
$R
= OpenInteract::Request->instance;
unless
(
$p
->{name} ) {
$R
->scrib( 0,
"ERROR: cannot execute component without a name!"
,
"Information passed in:\n"
, Dumper(
$p
) );
return
undef
;
}
my
@modified_action
=
$class
->_modify_action(
$p
->{name} );
my
$action_info
=
$R
->lookup_action([
$p
->{name},
@modified_action
],
{
return
=>
'info'
,
skip_default
=> 1 });
unless
(
scalar
keys
%{
$action_info
} ) {
$R
->DEBUG &&
$R
->scrib( 1,
"No action info returned; just using template name."
);
$action_info
->{name} =
$p
->{name};
$action_info
->{template} =
$p
->{template} ||
$action_info
->{name};
$action_info
->{
package
} =
$p
->{
package
};
$R
->DEBUG &&
$R
->scrib( 1,
"Using template ($action_info->{template})"
,
"(package if needed: $action_info->{package})"
);
}
unless
(
$action_info
->{template} or
$action_info
->{class} or
ref
$action_info
->{code} ) {
$R
->DEBUG &&
$R
->scrib( 1,
"No relevant action info; using name ($p->{name}) as template"
);
$action_info
->{template} =
$p
->{name};
}
$R
->DEBUG &&
$R
->scrib( 2,
"Action_info:\n"
, Dumper(
$action_info
) );
if
(
$action_info
->{template} ) {
if
(
$action_info
->{template} =~ /^(\w+)::(\w+)$/ ) {
$action_info
->{template_name} =
$action_info
->{template};
$action_info
->{
package
} = $1;
$action_info
->{template} = $2;
}
else
{
$action_info
->{template_name} =
join
(
'::'
,
$action_info
->{
package
},
$action_info
->{template} );
}
}
$action_info
->{
package
} ||=
$action_info
->{package_name};
my
$params
= (
ref
$p
->{params} ) ?
$p
->{params} :
$p
;
$R
->DEBUG &&
$R
->scrib( 3,
"Parameters being passed to component:\n"
, Dumper(
$params
) );
my
(
$html
);
if
(
$action_info
->{template_name} ) {
$R
->DEBUG &&
$R
->scrib( 1,
"Generic template action with ($action_info->{template_name})"
);
$html
=
eval
{
$R
->template->handler( {},
$params
,
{
name
=>
$action_info
->{template_name} } ) };
}
elsif
(
ref
$action_info
->{code} eq
'CODE'
) {
$html
=
eval
{
$action_info
->{code}->(
$params
) };
}
elsif
(
my
$action_class
=
$action_info
->{class} ) {
$action_info
->{method} ||= DEFAULT_METHOD;
$R
->DEBUG &&
$R
->scrib( 1,
"Calling component with $action_class->$action_info->{method}"
);
unless
(
$action_info
->{security} eq
'no'
) {
my
$target_level
= SEC_LEVEL_NONE;
(
$target_level
,
$params
->{level} ) =
$class
->_check_security(
$action_info
);
return
undef
unless
(
$params
->{level} >=
$target_level
);
}
my
$method
=
$action_info
->{method};
$html
=
eval
{
$action_class
->
$method
(
$params
) };
}
$R
->scrib( 0,
"Died with error message: $@"
)
if
( $@ );
$R
->DEBUG &&
$R
->scrib( 2,
"Component generated the following:\n$html"
);
return
(
$return_info
) ? (
$html
,
$action_info
) :
$html
;
}
sub
_check_security {
my
(
$class
,
$action_info
) =
@_
;
my
$R
= OpenInteract::Request->instance;
no
strict
'refs'
;
my
$required_level
= SEC_LEVEL_WRITE;
if
(
my
$verbose_level
=
$action_info
->{security_required} ) {
$required_level
= SEC_LEVEL_WRITE
if
(
$verbose_level
eq
'WRITE'
);
$required_level
= SEC_LEVEL_READ
if
(
$verbose_level
eq
'READ'
);
$required_level
= SEC_LEVEL_NONE
if
(
$verbose_level
eq
'NONE'
);
}
elsif
(
$action_info
->{class} ) {
my
%all_levels
= %{
$action_info
->{class} .
'::security'
};
$required_level
=
$all_levels
{
$action_info
->{method} } || NOTFOUND_SECURITY;
}
$R
->DEBUG &&
$R
->scrib( 1,
"Checking security for component."
);
my
$current_level
=
eval
{
$R
->secure->check_security({
security_object_class
=>
$R
->security_object,
db
=>
$R
->db,
user
=>
$R
->{auth}->{user},
class
=>
$action_info
->{class},
object_id
=>
'0'
}) };
$current_level
||= SEC_LEVEL_WRITE;
$R
->DEBUG &&
$R
->scrib( 1,
"Target security: ($required_level); Actual: ($current_level)"
);
return
(
$required_level
,
$current_level
);
}
sub
_modify_action {
my
(
$class
,
$action
) =
@_
;
my
@modified
= (
lc
$action
);
$action
=~ s/[\_\-\s]//g;
push
@modified
,
$action
;
return
@modified
;
}
1;