From 0d364dacf6db4b6c4442a264fff4d9de925ab6b2 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Mon, 8 Aug 2016 14:13:40 +0100 Subject: [PATCH] Bug 17080: Handle default values for NOT NULL columns from Koha::Object->new MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Recently we face the same issue on different modules after we moved them to the Koha namespace using Koha::Object of using DBIx::Class directly. 1/ Koha::Patron::Modification on bug 16960 comment 14 and 15 2/ Koha::Patron::Category from bug 17069 3/ C4::Members::AddMember (which does not use Koha::Object) on bug 16917 If a DB column is defined as NOT NULL and has a default value, the DBIx::Class $rs->update_or_insert method won't use the default value if the column name has been passed to the constructor. We do that almost everywhere as we retrieve the data from the HTML forms without checking/cleaning them. There are several ways to fix that: 1/ Continue to fix them case by case (what we did for the recent issues) 2/ Try to fix them globally (existing ones and the next ones) This patch propose a global solution to avoid future issues of this kind. The idea is not to pass the undefined values which cannot be nullable to the DBIx::Class constructor. Tested all patches together. Works as expected. Signed-off-by: Marc Véron Signed-off-by: Nick Clemens Signed-off-by: Kyle M Hall --- Koha/Object.pm | 13 +++++++++++-- t/db_dependent/Koha/Objects.t | 12 ++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Koha/Object.pm b/Koha/Object.pm index cf55089c06..c6bfede2c5 100644 --- a/Koha/Object.pm +++ b/Koha/Object.pm @@ -57,8 +57,17 @@ sub new { my $self = {}; if ($attributes) { - $self->{_result} = - Koha::Database->new()->schema()->resultset( $class->_type() ) + my $schema = Koha::Database->new->schema; + + # Remove the arguments which exist, are not defined but NOT NULL to use the default value + my $columns_info = $schema->resultset( $class->_type )->result_source->columns_info; + for my $column_name ( keys %$attributes ) { + my $c_info = $columns_info->{$column_name}; + next if $c_info->{is_nullable}; + next if not exists $attributes->{$column_name} or defined $attributes->{$column_name}; + delete $attributes->{$column_name}; + } + $self->{_result} = $schema->resultset( $class->_type() ) ->new($attributes); } diff --git a/t/db_dependent/Koha/Objects.t b/t/db_dependent/Koha/Objects.t index b5fdd75eae..fe3a3fb3bf 100644 --- a/t/db_dependent/Koha/Objects.t +++ b/t/db_dependent/Koha/Objects.t @@ -24,6 +24,8 @@ use Test::Warn; use Koha::Authority::Types; use Koha::Cities; +use Koha::Patron::Category; +use Koha::Patron::Categories; use Koha::Patrons; use Koha::Database; @@ -80,6 +82,16 @@ subtest 'not_covered_yet' => sub { plan tests => 1; warning_is { Koha::Patrons->search->not_covered_yet } { carped => 'The method not_covered_yet is not covered by tests' }, "If a method is not covered by tests, the AUTOLOAD method won't execute the method"; }; +subtest 'new' => sub { + plan tests => 2; + my $a_cat_code = 'A_CAT_CODE'; + my $patron_category = Koha::Patron::Category->new( { categorycode => $a_cat_code } )->store; + is( Koha::Patron::Categories->find($a_cat_code)->category_type, 'A', 'Koha::Object->new should set the default value' ); + Koha::Patron::Categories->find($a_cat_code)->delete; + $patron_category = Koha::Patron::Category->new( { categorycode => $a_cat_code, category_type => undef } )->store; + is( Koha::Patron::Categories->find($a_cat_code)->category_type, 'A', 'Koha::Object->new should set the default value even if the argument exists but is not defined' ); + Koha::Patron::Categories->find($a_cat_code)->delete; +}; subtest 'search_related' => sub { plan tests => 8; -- 2.39.2