From dd7118a8aea0baede95d16ce911eb41a78bb957a Mon Sep 17 00:00:00 2001 From: Olli-Antti Kivilahti Date: Fri, 13 Jan 2017 12:47:15 +0200 Subject: [PATCH 1/3] Bug 17897: Koha::SearchMappingManager - Simplify search mapping modifications Currently there is a lot of DBIC-magic everywhere where search mappings (search_fields, search_marc_to_field, search_marc_map -tables) are CRUD:ed. Encapsulate this hard-to-read DBIC-magic into a Manager class which promotes code-reusability and thus, simpler test case writing. Includes tests for Buug 17885 Rebased-by: Emmi Takkinen --- Koha/SearchEngine/Elasticsearch.pm | 27 +--- Koha/SearchMappingManager.pm | 151 ++++++++++++++++++ .../Koha/SearchEngine/ElasticSearch.t | 127 +++++++++++++++ 3 files changed, 280 insertions(+), 25 deletions(-) create mode 100644 Koha/SearchMappingManager.pm create mode 100644 t/db_dependent/Koha/SearchEngine/ElasticSearch.t diff --git a/Koha/SearchEngine/Elasticsearch.pm b/Koha/SearchEngine/Elasticsearch.pm index 3f26cbc027..12897629c6 100644 --- a/Koha/SearchEngine/Elasticsearch.pm +++ b/Koha/SearchEngine/Elasticsearch.pm @@ -27,6 +27,7 @@ use Koha::Exceptions::Elasticsearch; use Koha::Filter::MARC::EmbedSeeFromHeadings; use Koha::SearchFields; use Koha::SearchMarcMaps; +use Koha::SearchMappingManager; use Koha::Caches; use C4::Heading; use C4::AuthoritiesMarc qw( GuessAuthTypeCode ); @@ -1258,31 +1259,7 @@ sub _foreach_mapping { my ( $self, $sub ) = @_; # TODO use a caching framework here - my $search_fields = Koha::Database->schema->resultset('SearchField')->search( - { - 'search_marc_map.index_name' => $self->index, - }, - { join => { search_marc_to_fields => 'search_marc_map' }, - '+select' => [ - 'search_marc_to_fields.facet', - 'search_marc_to_fields.suggestible', - 'search_marc_to_fields.sort', - 'search_marc_to_fields.search', - 'search_marc_to_fields.filter', - 'search_marc_map.marc_type', - 'search_marc_map.marc_field', - ], - '+as' => [ - 'facet', - 'suggestible', - 'sort', - 'search', - 'filter', - 'marc_type', - 'marc_field', - ], - } - ); + my $search_fields = Koha::SearchMappingManager::get_search_mappings(); while ( my $search_field = $search_fields->next ) { $sub->( diff --git a/Koha/SearchMappingManager.pm b/Koha/SearchMappingManager.pm new file mode 100644 index 0000000000..e8f41bd926 --- /dev/null +++ b/Koha/SearchMappingManager.pm @@ -0,0 +1,151 @@ +package Koha::SearchMappingManager; + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use Carp; + +use Koha::Database; + +=head1 NAME + +Koha::SearchMappingManager - Manager for operating on search field mappings + +=head1 SYNOPSIS + +This class helps to interface with the complex internals of the koha.search_*-tables +and their respective Koha::Objects in a correct manner. + +=cut + + + + +=head2 get_search_mappings + + my $search_fields = Koha::SearchMappingManager::get_search_mappings({index_name => 'biblios|authorities'}); + + while ( my $search_field = $search_fields->next ) { + $sub->( + $search_field->get_column('name'), + $search_field->get_column('type'), + $search_field->get_column('facet'), + $search_field->get_column('suggestible'), + $search_field->get_column('sort'), + $search_field->get_column('marc_type'), + $search_field->get_column('marc_field'), + ); + } + +Get each entry from the searchengine mappings tables. + +@PARAMS HASHRef of keys: + index_name => 'biblios|authorities' #Which Koha record types to look for + name => 'title' #The koha.search_fields.name +@RETURNS Koha::Schma::Resultset::SearchField with enriched fields from other relevant tables +@THROWS die when parameters are not properly given. Should throw a Koha::Exception::BadParameter, + but pushing all those Exceptions to the community version would take ages. + +=cut + +sub get_search_mappings { + my ($params) = @_; + die "get_search_mappings():> parameter 'index_name' is missing" unless ($params->{index_name}); + + my $search = { + 'search_marc_map.index_name' => $params->{index_name}, + }; + $search->{'me.name'} = $params->{name} if $params->{name}; + + return Koha::Database->schema->resultset('SearchField')->search( + $search, + { join => { search_marc_to_fields => 'search_marc_map' }, + '+select' => [ + 'search_marc_to_fields.facet', + 'search_marc_to_fields.suggestible', + 'search_marc_to_fields.sort', + 'search_marc_to_fields.search', + 'search_marc_map.marc_type', + 'search_marc_map.marc_field', + ], + '+as' => [ + 'facet', + 'suggestible', + 'sort', + 'search', + 'marc_type', + 'marc_field', + ], + } + ); +} + +=head2 flush + + Koha::SearchMappingManager::flush(); + +Removes all entries from the Koha's search mapping tables + +=cut + +sub flush { + my $schema = Koha::Database->schema; + $schema->resultset('SearchField')->delete_all(); + $schema->resultset('SearchMarcMap')->delete_all(); + $schema->resultset('SearchMarcToField')->delete_all(); +} + + +=head2 add_mapping + + Koha::SearchMappingManager::add_mapping({name => 'ln-test', + label => 'original language', + type => 'keyword', + index_name => 'biblios', + marc_type => 'marc21', + marc_field => '024a', + facet => 1, + suggestible => 1, + sort => 1}); + +=cut + +sub add_mapping { + my ($params) = @_; + + my $search_field = Koha::SearchFields->find_or_create({ name => $params->{name} , + label => $params->{label}, + type => $params->{type} ,}, + { key => 'name' }); + + my $marc_field = Koha::SearchMarcMaps->find_or_create({ index_name => $params->{index_name}, + marc_type => $params->{marc_type} , + marc_field => $params->{marc_field}, }); + + ##update_or_create + my $p = { + search_field_id => $search_field->id, + search_marc_map_id => $marc_field->id, + }; + $p->{facet} = $params->{facet} if $params->{facet}; + $p->{suggestible} = $params->{suggestible} if $params->{suggestible}; + $p->{sort} = $params->{sort} if $params->{sort}; + $p->{search} = $params->{search} if $params->{search}; + Koha::Database->schema->resultset('SearchMarcToField')->update_or_create($p); +} + +1; diff --git a/t/db_dependent/Koha/SearchEngine/ElasticSearch.t b/t/db_dependent/Koha/SearchEngine/ElasticSearch.t new file mode 100644 index 0000000000..9f14548872 --- /dev/null +++ b/t/db_dependent/Koha/SearchEngine/ElasticSearch.t @@ -0,0 +1,127 @@ +#!/usr/bin/perl + +# Copyright 2015 Catalyst IT +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl qw(2014); +use utf8; +use Test::More; + +use Koha::SearchEngine::Elasticsearch; +use Koha::SearchMappingManager; + + +subtest "Reset Elasticsearch mappings", \&reset_elasticsearch_mappings; +sub reset_elasticsearch_mappings { + my ($rv, $mappings, $count, $mapping); + + ok(1, 'Scenario: Reset Elasticsearch mappings to an empty database'); + #There might or might not be any mappings. Whatever the initial status is, make sure we start from empty tables + $rv = Koha::SearchMappingManager::flush(); + ok($rv, 'Given empty search mapping tables'); + eval { + $rv = Koha::SearchEngine::Elasticsearch->reset_elasticsearch_mappings(); + }; + if ($@){ + ok(0, $@); + } + ok(not($@), 'When reset_elasticsearch_mappings() has been ran'); + + $mappings = Koha::SearchMappingManager::get_search_mappings({index_name => 'biblios'}); + $count = $mappings->count(); + ok($count, 'Then search mapping tables have been populated'); + + + + ok(1, 'Scenario: Reset Elasticsearch mappings when custom mappings already exist'); + $rv = Koha::SearchMappingManager::add_mapping({name => 'ln-test', + label => 'original language', + type => 'keyword', + index_name => 'biblios', + marc_type => 'marc21', + marc_field => '024a', + facet => 1, + suggestible => 1, + sort => 1}); + ok($rv, 'Given a mapping table with a custom search field'); + eval { + $rv = Koha::SearchEngine::Elasticsearch->reset_elasticsearch_mappings(); + }; + if ($@){ + ok(0, $@); + } + ok(not($@), 'When reset_elasticsearch_mappings() has been ran'); + + $mappings = Koha::SearchMappingManager::get_search_mappings({index_name => 'biblios'}); + $count = $mappings->count(); + ok($count > 10, 'Then search mapping tables have been populated'); +} + +subtest "Get Elasticsearch mappings", \&get_search_mappings; +sub get_search_mappings { + my ($mappings, $mapping); + + ok(1, 'Scenario: Get a single search mapping by name'); + $mappings = Koha::SearchMappingManager::get_search_mappings({index_name => 'biblios', name => 'ff7-00'}); + ok($mappings, 'When a search mappings is fetched'); + $mapping = $mappings->next(); + is($mapping->get_column('name'), 'ff7-00', 'Then the search mapping "name" matches'); + is($mapping->get_column('type'), '', 'And the search mapping "type" matches'); + is($mapping->get_column('facet'), '0', 'And the search mapping "facet" matches'); + is($mapping->get_column('suggestible'), '0', 'And the search mapping "suggestible" matches'); + is($mapping->get_column('sort'), undef, 'And the search mapping "sort" matches'); + is($mapping->get_column('search'), '1', 'And the search mapping "search" matches'); + is($mapping->get_column('marc_type'), 'marc21', 'And the search mapping "marc_type" matches'); + is($mapping->get_column('marc_field'), '007_/0', 'And the search mapping "marc_field" matches'); + + ok(1, 'Scenario: Get all search mappings'); + $mappings = Koha::SearchMappingManager::get_search_mappings({index_name => 'biblios'}); + ok($mappings, 'When search mappings are fetched'); + ok($mappings->count() > 10, 'Then we have "'.$mappings->count().'" search mappings :)') +} + +subtest "Add a search mapping", \&add_mapping; +sub add_mapping { + my ($rv, $mappings, $mapping, $count); + + ok(1, "Scenario: Add the same mapping twice and hope for no duplicate mappings"); + $rv = Koha::SearchMappingManager::add_mapping({name => 'ln-test', + label => 'original language', + type => 'keyword', + index_name => 'biblios', + marc_type => 'marc21', + marc_field => '024a', + facet => 1, + suggestible => 1, + sort => 1}); + $rv = Koha::SearchMappingManager::add_mapping({name => 'ln-test', + label => 'original language', + type => 'keyword', + index_name => 'biblios', + marc_type => 'marc21', + marc_field => '024a', + facet => 1, + suggestible => 1, + sort => 1}); + ok(1, "When the same search mapping is added twice"); + + $mappings = Koha::SearchMappingManager::get_search_mappings({index_name => 'biblios', name => 'ln-test'}); + $count = $mappings->count(); + is($count, 1, "Then we received only one mapping from the database"); +} + +done_testing; -- 2.34.1