Skip to content

Commit

Permalink
Databases: Include search query matches (#3216)
Browse files Browse the repository at this point in the history
- Also adds test coverage.
  • Loading branch information
maccabeelevine authored Nov 14, 2023
1 parent 4f10e0b commit c8a3c83
Show file tree
Hide file tree
Showing 3 changed files with 281 additions and 1 deletion.
8 changes: 8 additions & 0 deletions config/vufind/EDS.ini
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,14 @@ AU = None
; For EDS:
;resultFacetNameKey = 'value'

; Also display databases whose names contain the search query.
; Default is true. These are displayed above facet matches.
;useQuery = true

; Ignore the search query if it is below this length, ignoring
; useQuery above.
;useQueryMinLength = 3

; Load database URLs from LibGuides. Default is false.
; Requires configuration in LibGuidesAPI.ini.
;useLibGuides = true
Expand Down
38 changes: 37 additions & 1 deletion module/VuFind/src/VuFind/Recommend/Databases.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

use function count;
use function intval;
use function strlen;

/**
* Databases Recommendations Module
Expand Down Expand Up @@ -104,6 +105,20 @@ class Databases implements RecommendInterface, \Laminas\Log\LoggerAwareInterface
*/
protected $configFileDatabases;

/**
* Configuration of whether to use the query string as a match point
*
* @var bool
*/
protected $useQuery;

/**
* Minimum string length of a query to use as a match point
*
* @var bool
*/
protected $useQueryMinLength;

/**
* Configuration of whether to use LibGuides as a data source
*
Expand Down Expand Up @@ -163,6 +178,9 @@ public function setConfig($settings)
? $databasesConfig->resultFacet->toArray() : [];
$this->resultFacetNameKey = $databasesConfig->resultFacetNameKey ?? 'value';

$this->useQuery = $databasesConfig->useQuery ?? true;
$this->useQueryMinLength = $databasesConfig->useQueryMinLength ?? 3;

$this->useLibGuides = $databasesConfig->useLibGuides ?? false;
if ($this->useLibGuides) {
// Cache the data related to profiles for up to 10 minutes:
Expand Down Expand Up @@ -230,6 +248,23 @@ public function getResults()
}
$nameToDatabase = $this->getDatabases();
$databases = [];

// Add databases from search query
if ($this->useQuery) {
$query = strtolower($this->results->getParams()->getQuery()->getString());
if (strlen($query) >= $this->useQueryMinLength) {
foreach ($nameToDatabase as $name => $databaseInfo) {
if (str_contains(strtolower($name), $query)) {
$databases[$name] = $databaseInfo;
}
if (count($databases) >= $this->limit) {
return $databases;
}
}
}
}

// Add databases from result facets
foreach ($resultDatabases as $resultDatabase) {
try {
$name = $resultDatabase[$this->resultFacetNameKey];
Expand All @@ -242,9 +277,10 @@ public function getResults()
$databases[$name] = $databaseInfo;
}
if (count($databases) >= $this->limit) {
break;
return $databases;
}
}

return $databases;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
<?php

/**
* Databases Test Class
*
* PHP version 8
*
* Copyright (C) Villanova University 2023.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category VuFind
* @package Tests
* @author Maccabee Levine <msl321@lehigh.edu>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:testing:unit_tests Wiki
*/

namespace VuFindTest\Recommend;

use Laminas\Cache\Storage\Adapter\AbstractAdapter as CacheAdapter;
use VuFind\Recommend\Databases;

/**
* Databases Test Class
*
* @category VuFind
* @package Tests
* @author Maccabee Levine <msl321@lehigh.edu>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:testing:unit_tests Wiki
*/
class DatabasesTest extends \PHPUnit\Framework\TestCase
{
/**
* Test forgetting the Databases config section.
*
* @return void
*/
public function testEmptyConfig()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage("must have section 'Databases'");

$configData = [];
$module = $this->buildModuleAndProcessResults($configData);
}

/**
* Test a default config.
*
* @return void
*/
public function testNormal()
{
$configData = $this->mockConfigData();
$module = $this->buildModuleAndProcessResults($configData);

$databases = $module->getResults();
$this->assertCount(3, $databases);
$this->assertArrayHasKey('History DB', $databases);
$this->assertArrayNotHasKey('Art DB', $databases);
}

/**
* Test setting useQuery to false.
*
* @return void
*/
public function testDontUseQuery()
{
$configData = $this->mockConfigData();
$configData['Databases']['useQuery'] = false;
$module = $this->buildModuleAndProcessResults($configData);

$databases = $module->getResults();
$this->assertCount(2, $databases);
$this->assertArrayNotHasKey('History DB', $databases);
}

/**
* Test setting useLibGuides to true.
*
* @return void
*/
public function testUseLibGuides()
{
$configData = $this->mockConfigData();
$configData['Databases']['useLibGuides'] = true;
$module = $this->buildModuleAndProcessResults($configData);

$databases = $module->getResults();
$this->assertCount(4, $databases);
$this->assertArrayHasKey('Art DB', $databases);
}

/**
* Build a Databases module, set config and process results.
*
* @param $configData array A Databases config section
*
* @return object
*/
protected function buildModuleAndProcessResults($configData)
{
$configManager = $this->createMock(\VuFind\Config\PluginManager::class);
$configManager->expects($this->any())->method('get')
->will($this->returnValue(new \Laminas\Config\Config($configData)));

$libGuidesGetter = function () {
$libGuides = $this->getMockBuilder(\VuFind\Connection\LibGuides::class)
->disableOriginalConstructor()
->getMock();
$libGuidesData = $this->mockLibGuidesData();
$libGuides->method('getAZ')->willReturn($libGuidesData);
return $libGuides;
};

$cache = $this->getMockBuilder(CacheAdapter::class)->getMock();
$module = $this->getMockBuilder(Databases::class)
->setConstructorArgs([$configManager, $libGuidesGetter, $cache])
->onlyMethods(['getCachedData', 'putCachedData'])
->getMock();

$settings = '5:EDS';
$module->setConfig($settings);

$facetList = $this->mockFacetList();
$results = $this->mockResults($facetList);
$module->process($results);

return $module;
}

/**
* Mock up search results.
*
* @param $facetList array Result facets
* @param $queryString string Query string
*
* @return object
*/
protected function mockResults($facetList, $queryString = 'History')
{
$results = $this->getMockBuilder(\VuFind\Search\EDS\Results::class)
->disableOriginalConstructor()
->getMock();
$results->method('getFacetList')->willReturn($facetList);

$params = $this->getMockBuilder(\VuFind\Search\Base\Params::class)
->disableOriginalConstructor()
->getMock();
$results->method('getParams')->willReturn($params);
$query = $this->getMockBuilder(\VuFindSearch\Query\Query::class)
->disableOriginalConstructor()
->getMock();
$params->method('getQuery')->willReturn($query);
$query->method('getString')->willReturn($queryString);

return $results;
}

/**
* Mock up a standard Databases config section.
*
* @return array
*/
protected function mockConfigData()
{
return [
'Databases' => [
'resultFacet' => [
'ContentProvider',
'list',
],
'resultFacetNameKey' => 'value',
'useQuery' => true,
'url' => [
'Sociology DB' => 'http://people.com',
'Biology DB' => 'http://cells.com',
'History DB' => 'http://thepast.com',
],
],
];
}

/**
* Mock up a results facet list.
*
* @return array
*/
protected function mockFacetList()
{
return [
'ContentProvider' => [
'list' => [
'db_1' => [
'value' => 'Sociology DB',
],
'db_2' => [
'value' => 'Biology DB',
],
'db_4' => [
'value' => 'Art DB',
],
],
],
];
}

/**
* Mock up LibGuides API databases data.
*
* @return array
*/
protected function mockLibGuidesData()
{
return [
'db_4' => (object)[
'name' => 'Art DB',
'url' => 'fridakahlo.com',
],
];
}
}

0 comments on commit c8a3c83

Please sign in to comment.