my
@_cdata
=
qw(_CDBI_Class _PrimaryFields _Field_Handlers _PrimaryKey)
;
__PACKAGE__->mk_classdata(
$_
)
for
@_cdata
;
our
$VERSION
=
'0.21'
;
sub
class_dbi_object {
shift
()->class_dbi_object_gr(
'_CDBIM_'
,
@_
); }
sub
class_dbi_object_gr {
my
(
$self
,
$gr
,
$val
) =
@_
;
return
$self
->{_class_dbi_objects}->{
$gr
}
if
@_
== 2;
$self
->{_class_dbi_objects}->{
$gr
} =
$val
;
}
sub
cdbi_bind_from_fields {
my
(
$class
,
$gr
) =
@_
;
for
my
$v
(@{
$class
->Widgets_List }) {
my
$wgr
=
$v
->options->{cdbi_group} ||
'_CDBIM_'
;
$v
->options->{cdbi_group} =
$wgr
;
next
unless
$wgr
eq
$gr
;
my
$f
= HTML::Tested::ClassDBI::Field->new(
$class
,
$v
,
$gr
)
or
next
;
$class
->_Field_Handlers->{
$v
->options->{cdbi_group} }
->{
$v
->name} =
$f
;
}
}
sub
CDBI_Class {
return
shift
()->_CDBI_Class->{_CDBIM_} }
sub
PrimaryFields {
return
shift
()->_PrimaryFields->{_CDBIM_} }
sub
Field_Handlers {
return
shift
()->_Field_Handlers->{_CDBIM_} }
sub
PrimaryKey {
return
shift
()->_PrimaryKey->{_CDBIM_} }
sub
bind_to_class_dbi {
shift
()->bind_to_class_dbi_gr(
'_CDBIM_'
,
@_
); }
sub
bind_to_class_dbi_gr {
my
(
$class
,
$gr
,
$dbi_class
,
$opts
) =
@_
;
$class
->
$_
({})
for
grep
{ !
$class
->
$_
}
@_cdata
;
$class
->_CDBI_Class->{
$gr
} =
$dbi_class
;
$class
->_Field_Handlers->{
$gr
} = {};
$class
->_PrimaryFields->{
$gr
} = {};
$class
->cdbi_bind_from_fields(
$gr
);
$class
->_load_db_info(
$gr
);
my
$pk
=
$opts
?
$opts
->{PrimaryKey} :
undef
;
$class
->_PrimaryKey->{
$gr
} =
$pk
if
$pk
;
confess
"# No Primary fields given\n"
unless
(
$pk
|| %{
$class
->_PrimaryFields->{
$gr
} });
}
sub
_get_cdbi_pk_for_retrieve {
my
(
$self
,
$gr
) =
@_
;
my
$pk
=
$self
->_PrimaryKey->{
$gr
} or
goto
PFIELDS;
my
%pkh
;
for
my
$f
(
@$pk
) {
my
$v
=
$self
->
$f
;
goto
PFIELDS
unless
defined
(
$v
);
my
$h
=
$self
->_Field_Handlers->{
$gr
}->{
$f
};
$pkh
{
$h
?
$h
->column_name :
$f
} =
$v
;
}
return
\
%pkh
if
%pkh
;
PFIELDS:
my
$res
= {};
my
%pf
= %{
$self
->_PrimaryFields->{
$gr
} };
my
(
$pv
,
$pc
);
while
(
my
(
$k
,
$v
) =
each
%pf
) {
$pv
=
$self
->
$k
;
next
unless
defined
$pv
;
$pc
=
$v
;
last
;
}
return
undef
unless
defined
(
$pv
);
my
@vals
=
split
(
'_'
,
$pv
);
for
(
my
$i
= 0;
$i
<
@$pc
;
$i
++) {
$res
->{
$pc
->[
$i
] } =
$vals
[
$i
];
}
return
$res
;
}
sub
_fill_in_from_class_dbi {
my
(
$self
,
$gr
) =
@_
;
my
$fhs
=
$self
->_Field_Handlers->{
$gr
};
my
$cdbi
=
$self
->class_dbi_object_gr(
$gr
);
while
(
my
(
$f
,
$h
) =
each
%$fhs
) {
$self
->
$f
(
$h
->get_column_value(
$cdbi
));
}
}
sub
cdbi_retrieve {
shift
()->_call_for_all(
'cdbi_retrieve_gr'
,
@_
); }
sub
cdbi_retrieve_gr {
my
(
$self
,
$gr
) =
@_
;
my
$pk
=
$self
->_get_cdbi_pk_for_retrieve(
$gr
);
return
unless
defined
(
$pk
);
my
$cdbi
=
$self
->_CDBI_Class->{
$gr
}->retrieve(
ref
(
$pk
) ?
%$pk
:
$pk
);
$self
->class_dbi_object_gr(
$gr
,
$cdbi
);
return
$cdbi
;
}
sub
cdbi_load {
return
shift
()->_call_for_all(
'cdbi_load_gr'
,
@_
); }
sub
_get_cdbi_object {
my
(
$self
,
$gr
) =
@_
;
return
$self
->class_dbi_object_gr(
$gr
) ||
$self
->cdbi_retrieve_gr(
$gr
);
}
sub
cdbi_load_gr {
my
(
$self
,
$gr
) =
@_
;
my
$cdbi
=
$self
->_get_cdbi_object(
$gr
) or
return
;
$self
->_fill_in_from_class_dbi(
$gr
);
return
$cdbi
;
}
sub
query_class_dbi {
my
(
$class
,
$func
,
@params
) =
@_
;
my
@cdbis
=
$class
->CDBI_Class->
$func
(
@params
);
return
[
map
{
my
$c
=
$class
->new;
$c
->class_dbi_object(
$_
);
$c
->_fill_in_from_class_dbi(
'_CDBIM_'
);
$c
;
}
@cdbis
];
}
sub
_call_for_all {
my
(
$self
,
$func
,
@args
) =
@_
;
$self
->
$func
(
$_
,
@args
)
for
keys
%{
$self
->_CDBI_Class };
return
$self
->class_dbi_object;
}
sub
cdbi_create {
return
shift
()->_call_for_all(
'cdbi_create_gr'
,
@_
); }
sub
cdbi_create_gr {
my
(
$self
,
$gr
,
$args
) =
@_
;
my
$cargs
=
$self
->_get_cdbi_pk_for_retrieve(
$gr
) || {};
$self
->_update_fields(
$gr
,
sub
{
$cargs
->{
$_
[0] } =
$_
[1]; },
$args
);
my
$res
;
eval
{
$res
=
$self
->_CDBI_Class->{
$gr
}->create(
$cargs
); };
confess
"SQL error: $@\n"
. Dumper(
$self
)
if
$@;
$self
->class_dbi_object_gr(
$gr
,
$res
);
$self
->_fill_in_from_class_dbi(
$gr
);
return
$res
;
}
sub
_update_fields {
my
(
$self
,
$gr
,
$setter
,
$args
) =
@_
;
while
(
my
(
$field
,
$h
) =
each
%{
$self
->_Field_Handlers->{
$gr
} }) {
$h
->update_column(
$setter
,
$self
,
$field
)
if
exists
$self
->{
$field
};
}
my
$cdbi
=
$self
->_CDBI_Class->{
$gr
};
while
(
my
(
$n
,
$v
) =
each
%{
$args
|| {} }) {
$setter
->(
$n
,
$v
)
if
$cdbi
->can(
$n
);
}
}
sub
cdbi_update {
return
shift
()->_call_for_all(
'cdbi_update_gr'
,
@_
); }
sub
cdbi_update_gr {
my
(
$self
,
$gr
,
$args
) =
@_
;
my
$cdbi
=
$self
->_get_cdbi_object(
$gr
)
or confess(
"# Nothing found to update"
);
$self
->_update_fields(
$gr
,
sub
{
my
(
$c
,
$val
) =
@_
;
no
warnings
'uninitialized'
;
$cdbi
->
$c
(
$val
)
if
$cdbi
->
$c
ne
$val
;
},
$args
);
eval
{
$cdbi
->update; };
confess
"SQL error: $@\n"
. Dumper(
$self
)
if
$@;
$self
->_fill_in_from_class_dbi(
$gr
);
return
$cdbi
;
}
sub
cdbi_create_or_update {
return
shift
()->_call_for_all(
'cdbi_create_or_update_gr'
,
@_
);
}
sub
cdbi_create_or_update_gr {
my
(
$self
,
$gr
,
$args
) =
@_
;
return
$self
->_get_cdbi_object(
$gr
) ?
$self
->cdbi_update_gr(
$gr
,
$args
)
:
$self
->cdbi_create_gr(
$gr
,
$args
);
}
sub
cdbi_construct {
return
shift
()->cdbi_construct_gr(
'_CDBIM_'
); }
sub
cdbi_construct_gr {
my
(
$self
,
$gr
) =
@_
;
my
$pk
=
$self
->_get_cdbi_pk_for_retrieve(
$gr
)
or confess
"No primary key for $gr"
;
return
$self
->_CDBI_Class->{
$gr
}->construct(
$pk
);
}
sub
cdbi_delete {
shift
()->cdbi_delete_gr(
'_CDBIM_'
,
@_
); }
sub
cdbi_delete_gr {
my
$c
=
shift
()->cdbi_construct_gr(
shift
());
$c
->
delete
;
}
sub
_load_db_info {
my
(
$class
,
$gr
) =
@_
;
while
(
my
(
$n
,
$h
) =
each
%{
$class
->_Field_Handlers->{
$gr
} }) {
my
$w
=
$class
->ht_find_widget(
$n
);
$h
->setup_type_info(
$class
->_CDBI_Class->{
$gr
},
$w
);
}
}
sub
cdbi_set_many {
my
(
$class
,
$h_objs
,
$c_objs
) =
@_
;
my
@pcs
=
$class
->CDBI_Class->primary_columns;
my
%c_objs
;
for
my
$co
(
@$c_objs
) {
$c_objs
{
join
(
'_'
,
map
{
$co
->
$_
}
@pcs
) } =
$co
;
}
for
my
$ho
(
@$h_objs
) {
my
$pk
=
$ho
->_get_cdbi_pk_for_retrieve(
'_CDBIM_'
);
my
$co
=
$c_objs
{
join
(
'_'
,
grep
{
defined
(
$_
) }
map
{
$pk
->{
$_
} }
@pcs
) };
$ho
->class_dbi_object(
$co
);
}
}
1;