From 6a55e803f09a02bb6d94707a5e678704eaf60769 Mon Sep 17 00:00:00 2001 From: Petro Vashchuk Date: Mon, 12 Jul 2021 10:45:22 +0300 Subject: [PATCH] Bug 28700: unblessed in Object.pm has blessed values in some cases This "unblessed" sub acts as such: creates a hash from fields prepared in memory by DBIX::Class. In case when we get data from DB our fields are filled with scalars and all unblessed hash returned as keys with scalar values. This is the expected behavior and feature for which this method was created. But in some cases, when we modify the DBIX::Class field in Perl code (and then it get stored into DB), we pass some special objects to DBIX::Class, not scalars. For example DateTime object. It is stored in proper form into DB (converted by DBIX::Class to proper text form with required date format), but still kept in memory for this field _as object_! And this is the source of the bug: because now when we use the "unblessed" method, the value for DATE or TIMESTAMP field is returned for us by DBIX::Class in the same form as we provided it some lines above in Perl code: i.e. as "DateTime Object". For example: when the "dateaccessioned" column in the "items" table is NULL, "dateaccessioned" gets prefilled by this Perl code (file: Koha/Item.pm around line 198): unless ( $self->dateaccessioned ) { $self->dateaccessioned($today); } my $result = $self->SUPER::store; if ( $log_action && C4::Context->preference("CataloguingLog") ) { $action eq 'create' ? logaction( "CATALOGUING", "ADD", $self->itemnumber, "item" ) : logaction( "CATALOGUING", "MODIFY", $self->itemnumber, "item " . Dumper( $self->unblessed ) ); } it gets assigned with DateTime object, stored in Perl process in DBIX::Class as Object, and converted to scalar only when stored to DB, but, in the same code piece above, when we have Dumper( $self->unblessed ), it is passed as blessed value for key "dateaccessioned", so as we see, when we dumping this record just a few lines below into object_log, the "dateaccessioned" value appears as a blessed object rather than the standard date/time text scalar we expect it to be. This patch adds the ability for the "unblessed" subroutine in the Object.pm to make scalar results for ref type DateTime. I have chosen "->stringify" for DateTime because that anyway will happen if we try to use the DateTime object in any strings, concatenations, or prints. For now, it returns the iso8601 text date which has all the needed data saved. It might be different from which value stored in the end into DB because the DB field might be simpler (just date), but anyway we _expect_ that unblessed method should give just scalars as keys/values, or refs to deeper structures like arrays/hashes but scalars as well, not objects inside (nothing blessed inside). I also added a warning for us to have it logged if we have any other blessed values returned as a key by the unblessed method. To reproduce: 1) at the items table pick any item you see fit, find the "dateaccessioned" column of it, and set it NULL. 2) go to your koha and edit that item (doesn't matter what you change as long as you make some change), save it afterward. 3) check the action_logs table and find there a newly created MODIFY item row, "info" column of that contains dumped data, find "dateaccessioned" among that data and notice that it is an object, optional: check and note about the size of it. 4) apply the patch. 5) repeat steps 1-3, ensure that "dateaccessioned" contains usual date/time data (iso8601 formatted in our case). --- Koha/Object.pm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Koha/Object.pm b/Koha/Object.pm index 6f55c3b486..a3c055f8f2 100644 --- a/Koha/Object.pm +++ b/Koha/Object.pm @@ -318,8 +318,11 @@ Returns an unblessed representation of object. sub unblessed { my ($self) = @_; - - return { $self->_result->get_columns }; + my %res = $self->_result->get_columns; + for my $k (keys %res) { + $res{$k} = "$res{$k}" if ref $res{$k}; + } + return \%res; } =head3 $object->get_from_storage; -- 2.31.1