From 846c61ff899487393c689a77e83849d417de4bdb Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Mon, 2 Oct 2023 19:46:31 +0000 Subject: [PATCH 01/32] Show side recommendations with combined search --- config/vufind/combined.ini | 5 ++++ .../VuFind/Controller/CombinedController.php | 29 ++++++++++++++----- .../src/VuFind/Search/Combined/Options.php | 1 + .../templates/combined/results-list.phtml | 23 +++++++++++++++ .../templates/combined/results.phtml | 16 +++++++++- 5 files changed, 65 insertions(+), 9 deletions(-) diff --git a/config/vufind/combined.ini b/config/vufind/combined.ini index 467d89dc236..447e91fd764 100644 --- a/config/vufind/combined.ini +++ b/config/vufind/combined.ini @@ -28,6 +28,11 @@ ; specified recommendations will be loaded into the top ; area of the column. If set to false, recommendations ; will be suppressed (default). +; include_recommendations_side = If set to true, standard 'side' recommendations +; will be displayed in the sidebar column. If set to an array of +; recommendation settings (as per searches.ini), the specified recommendations +; will be loaded into the side column. If set to false, side recommendations +; will be suppressed (default). ; filter = One or more filters to apply to search results displayed in the column. ; Use multiple "filter[] = ..." lines if multiple filters are needed. ; hiddenFilter = One or more hidden filters to apply to search results displayed in diff --git a/module/VuFind/src/VuFind/Controller/CombinedController.php b/module/VuFind/src/VuFind/Controller/CombinedController.php index 21d913a5679..8d93907ee11 100644 --- a/module/VuFind/src/VuFind/Controller/CombinedController.php +++ b/module/VuFind/src/VuFind/Controller/CombinedController.php @@ -225,6 +225,15 @@ public function resultsAction() $settings = $this->serviceLocator->get(\VuFind\Config\PluginManager::class) ->get('config'); + // Identify if any modules use include_recommendations_side + $anySideRecommendations = false; + foreach ($config as $subconfig) { + if ($subconfig['include_recommendations_side'] ?? false) { + $anySideRecommendations = true; + break; + } + } + // Build view model: return $this->createViewModel( [ @@ -237,6 +246,7 @@ public function resultsAction() 'supportsCart' => $supportsCart, 'supportsCartOptions' => $supportsCartOptions, 'showBulkOptions' => $settings->Site->showBulkOptions ?? false, + 'anySideRecommendations' => $anySideRecommendations, ] ); } @@ -325,15 +335,18 @@ protected function adjustQueryForSettings($settings, $searchType = null) // Override the search type: $query->type = $searchType; - // Always leave noresults active (useful for 0-hit searches) and - // side inactive (no room to display) but display or hide top based - // on include_recommendations setting. - if ($settings['include_recommendations'] ?? false) { - $query->noRecommend = 'side'; - if (is_array($settings['include_recommendations'])) { - $query->recommendOverride - = ['top' => $settings['include_recommendations']]; + // Always leave noresults active (useful for 0-hit searches). + // Display or hide top based on include_recommendations setting. + // Display or hide top based on include_recommendations_side setting. + if (($settings['include_recommendations'] ?? false) || ($settings['include_recommendations_side'] ?? false)) { + $recommendOverride = []; + if (is_array($settings['include_recommendations'] ?? null)) { + $recommendOverride['top'] = $settings['include_recommendations']; + } + if (is_array($settings['include_recommendations_side'] ?? null)) { + $recommendOverride['side'] = $settings['include_recommendations_side']; } + $query->recommendOverride = $recommendOverride; } else { $query->noRecommend = 'top,side'; } diff --git a/module/VuFind/src/VuFind/Search/Combined/Options.php b/module/VuFind/src/VuFind/Search/Combined/Options.php index 6c8bc251f53..56ea6b4dcd4 100644 --- a/module/VuFind/src/VuFind/Search/Combined/Options.php +++ b/module/VuFind/src/VuFind/Search/Combined/Options.php @@ -81,6 +81,7 @@ public function getRecommendationSettings($handler = null) $recommend = []; $config = $this->configLoader->get('combined'); foreach (['top', 'bottom'] as $location) { + // foreach (['top', 'bottom', 'side'] as $location) { if (isset($config->RecommendationModules->$location)) { $recommend[$location] = $config->RecommendationModules->$location->toArray(); diff --git a/themes/bootstrap3/templates/combined/results-list.phtml b/themes/bootstrap3/templates/combined/results-list.phtml index 5ad1b2aa574..305416dc86a 100644 --- a/themes/bootstrap3/templates/combined/results-list.phtml +++ b/themes/bootstrap3/templates/combined/results-list.phtml @@ -68,6 +68,29 @@ getRecommendations('top')) as $current): ?> recommend($current)?> + getRecommendations('side')) as $current): + $recommendationClass = str_replace("\\", "_", get_class($current)); + $recommendationJs = << + inlineScript(\Laminas\View\Helper\HeadScript::SCRIPT, $recommendationJs, 'SET')?> + + context()->renderInContext( 'search/controls/showing.phtml', diff --git a/themes/bootstrap3/templates/combined/results.phtml b/themes/bootstrap3/templates/combined/results.phtml index eef92032ea6..b4c3c4c1002 100644 --- a/themes/bootstrap3/templates/combined/results.phtml +++ b/themes/bootstrap3/templates/combined/results.phtml @@ -73,7 +73,21 @@ 'showBulkOptions' => $this->showBulkOptions, ]; ?> - context($this)->renderInContext('combined/stack-' . $placement . '.phtml', $viewParams); ?> + + +
+ context($this)->renderInContext('combined/stack-' . $placement . '.phtml', $viewParams); ?> +
+ +
+ results->getRecommendations('side') as $index => $current): ?> + recommend($current, 'side', $index)?> + +
+ + context($this)->renderInContext('combined/stack-' . $placement . '.phtml', $viewParams); ?> + + getRecommendations('bottom'); ?>
From 8810025954f831645c89d99c020b70087d1f8d6c Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Mon, 2 Oct 2023 19:49:40 +0000 Subject: [PATCH 02/32] Fix php-cs-fixer --- .../src/VuFind/Search/Combined/Options.php | 2 +- .../templates/combined/results-list.phtml | 28 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/module/VuFind/src/VuFind/Search/Combined/Options.php b/module/VuFind/src/VuFind/Search/Combined/Options.php index 56ea6b4dcd4..509a472e381 100644 --- a/module/VuFind/src/VuFind/Search/Combined/Options.php +++ b/module/VuFind/src/VuFind/Search/Combined/Options.php @@ -81,7 +81,7 @@ public function getRecommendationSettings($handler = null) $recommend = []; $config = $this->configLoader->get('combined'); foreach (['top', 'bottom'] as $location) { - // foreach (['top', 'bottom', 'side'] as $location) { + // foreach (['top', 'bottom', 'side'] as $location) { if (isset($config->RecommendationModules->$location)) { $recommend[$location] = $config->RecommendationModules->$location->toArray(); diff --git a/themes/bootstrap3/templates/combined/results-list.phtml b/themes/bootstrap3/templates/combined/results-list.phtml index 305416dc86a..6ba0a36b0c1 100644 --- a/themes/bootstrap3/templates/combined/results-list.phtml +++ b/themes/bootstrap3/templates/combined/results-list.phtml @@ -69,22 +69,22 @@ recommend($current)?> getRecommendations('side')) as $current): - $recommendationClass = str_replace("\\", "_", get_class($current)); + $recommendationClass = str_replace('\\', '_', $current::class); $recommendationJs = << inlineScript(\Laminas\View\Helper\HeadScript::SCRIPT, $recommendationJs, 'SET')?>
- results->getRecommendations('side') as $index => $current): ?> - recommend($current, 'side', $index)?> - +
context($this)->renderInContext('combined/stack-' . $placement . '.phtml', $viewParams); ?> From 3a3d110815d1fca142038868595f9921bcd5a79f Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Tue, 3 Oct 2023 16:40:14 +0000 Subject: [PATCH 08/32] Fix php-cs-fixer --- module/VuFind/src/VuFind/Controller/CombinedController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/VuFind/src/VuFind/Controller/CombinedController.php b/module/VuFind/src/VuFind/Controller/CombinedController.php index 384bb81a6d5..020206f0238 100644 --- a/module/VuFind/src/VuFind/Controller/CombinedController.php +++ b/module/VuFind/src/VuFind/Controller/CombinedController.php @@ -351,7 +351,7 @@ protected function adjustQueryForSettings($settings, $searchType = null) $noRecommend[] = 'side'; } $query->recommendOverride = $recommendOverride; - $query->noRecommend = count($noRecommend) ? implode(",", $noRecommend) : false; + $query->noRecommend = count($noRecommend) ? implode(',', $noRecommend) : false; } /** From 0e8750ffd79928b6ca1019bb79fd0438d87f017a Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Tue, 3 Oct 2023 18:29:19 +0000 Subject: [PATCH 09/32] Force order of recommendation modules --- .../src/VuFind/Controller/CombinedController.php | 13 ++++++------- .../templates/combined/results-list.phtml | 6 +++--- themes/bootstrap3/templates/combined/results.phtml | 8 ++++++-- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/module/VuFind/src/VuFind/Controller/CombinedController.php b/module/VuFind/src/VuFind/Controller/CombinedController.php index 020206f0238..07cea25bcf4 100644 --- a/module/VuFind/src/VuFind/Controller/CombinedController.php +++ b/module/VuFind/src/VuFind/Controller/CombinedController.php @@ -225,12 +225,11 @@ public function resultsAction() $settings = $this->serviceLocator->get(\VuFind\Config\PluginManager::class) ->get('config'); - // Identify if any modules use include_recommendations_side - $anySideRecommendations = false; - foreach ($config as $subconfig) { - if ($subconfig['include_recommendations_side'] ?? false) { - $anySideRecommendations = true; - break; + // Identify if any modules use include_recommendations_side. + $columnSideRecommendations = []; + foreach ($config as $column => $subconfig) { + foreach ($subconfig['include_recommendations_side'] ?? [] as $recommendation) { + $columnSideRecommendations[] = strtok($recommendation, ':'); } } @@ -246,7 +245,7 @@ public function resultsAction() 'supportsCart' => $supportsCart, 'supportsCartOptions' => $supportsCartOptions, 'showBulkOptions' => $settings->Site->showBulkOptions ?? false, - 'anySideRecommendations' => $anySideRecommendations, + 'columnSideRecommendations' => $columnSideRecommendations, ] ); } diff --git a/themes/bootstrap3/templates/combined/results-list.phtml b/themes/bootstrap3/templates/combined/results-list.phtml index 9af12115b65..dc5ca50dc97 100644 --- a/themes/bootstrap3/templates/combined/results-list.phtml +++ b/themes/bootstrap3/templates/combined/results-list.phtml @@ -69,12 +69,12 @@ recommend($current)?> getRecommendations('side')) as $current): - $recommendationClass = str_replace('\\', '_', $current::class); + $recommendationClass = array_reverse(explode('\\', $current::class))[0]; $recommendationJs = << - +
context($this)->renderInContext('combined/stack-' . $placement . '.phtml', $viewParams); ?>
- + +
+ +
+
context($this)->renderInContext('combined/stack-' . $placement . '.phtml', $viewParams); ?> From 0fdbc46908a49cf45c05ed2b27ca9e6069ed429a Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Wed, 4 Oct 2023 13:36:01 +0000 Subject: [PATCH 10/32] Use actual recommendation module class name --- module/VuFind/src/VuFind/Controller/CombinedController.php | 7 +++++-- themes/bootstrap3/templates/combined/results-list.phtml | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/module/VuFind/src/VuFind/Controller/CombinedController.php b/module/VuFind/src/VuFind/Controller/CombinedController.php index 07cea25bcf4..87905e38978 100644 --- a/module/VuFind/src/VuFind/Controller/CombinedController.php +++ b/module/VuFind/src/VuFind/Controller/CombinedController.php @@ -227,9 +227,12 @@ public function resultsAction() // Identify if any modules use include_recommendations_side. $columnSideRecommendations = []; - foreach ($config as $column => $subconfig) { + $recommendationManager = $this->serviceLocator->get(\VuFind\Recommend\PluginManager::class); + foreach ($config as $subconfig) { foreach ($subconfig['include_recommendations_side'] ?? [] as $recommendation) { - $columnSideRecommendations[] = strtok($recommendation, ':'); + $recommendationModuleName = strtok($recommendation, ':'); + $recommendationModule = $recommendationManager->get($recommendationModuleName); + $columnSideRecommendations[] = str_replace('\\', '_', $recommendationModule::class); } } diff --git a/themes/bootstrap3/templates/combined/results-list.phtml b/themes/bootstrap3/templates/combined/results-list.phtml index dc5ca50dc97..a2ed80e9dc9 100644 --- a/themes/bootstrap3/templates/combined/results-list.phtml +++ b/themes/bootstrap3/templates/combined/results-list.phtml @@ -69,7 +69,7 @@ recommend($current)?> getRecommendations('side')) as $current): - $recommendationClass = array_reverse(explode('\\', $current::class))[0]; + $recommendationClass = str_replace('\\', '_', $current::class); $recommendationJs = << Date: Thu, 5 Oct 2023 15:27:32 +0000 Subject: [PATCH 11/32] Add EDS recommendation module to direct link to DBs --- config/vufind/LibGuidesAPI.ini | 9 + languages/en.ini | 1 + .../src/VuFind/Connection/LibGuides.php | 62 ++++++- .../src/VuFind/Recommend/EDSDatabases.php | 174 ++++++++++++++++++ .../VuFind/Recommend/EDSDatabasesFactory.php | 77 ++++++++ .../src/VuFind/Recommend/PluginManager.php | 2 + .../templates/Recommend/EDSDatabases.phtml | 17 ++ 7 files changed, 338 insertions(+), 4 deletions(-) create mode 100644 module/VuFind/src/VuFind/Recommend/EDSDatabases.php create mode 100644 module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php create mode 100644 themes/bootstrap3/templates/Recommend/EDSDatabases.phtml diff --git a/config/vufind/LibGuidesAPI.ini b/config/vufind/LibGuidesAPI.ini index 7689528f771..b5ec2558925 100644 --- a/config/vufind/LibGuidesAPI.ini +++ b/config/vufind/LibGuidesAPI.ini @@ -26,6 +26,15 @@ api_base_url = https://lgapi-us.libapps.com/1.2 ; Duration (seconds) to cache response data. Default is 600. ;cache_lifetime = 600 +; Calls to GET (...)/az endpoint +; Note this is not used for the LibGuidesAZ search +; implementation; see LibGuidesAZ.ini for that. +; This is used where the full list of databases is needed +; by EDSDatabases. +[GetAZ] +; Duration (seconds) to cache response data. Default is 600. +;cache_lifetime = 600 + ; Configuration for LibGuidesProfile recommendation module [Profile] ; Enable one or more strategies for matching the best profile diff --git a/languages/en.ini b/languages/en.ini index 08a1fd3fbd8..57dde8f6a89 100644 --- a/languages/en.ini +++ b/languages/en.ini @@ -356,6 +356,7 @@ edit_list_fail = "Sorry, you are not permitted to edit this list" edit_list_success = "List successfully updated." Edition = "Edition" EDS Results = "EDS Results" +eds_databases = "Search Databases Directly" eds_expander_fulltext = "Also search within the full text of the articles" eds_expander_relatedsubjects = "Apply equivalent subjects" eds_expander_thesaurus = "Apply related words" diff --git a/module/VuFind/src/VuFind/Connection/LibGuides.php b/module/VuFind/src/VuFind/Connection/LibGuides.php index f767b80a57c..e43f9226123 100644 --- a/module/VuFind/src/VuFind/Connection/LibGuides.php +++ b/module/VuFind/src/VuFind/Connection/LibGuides.php @@ -122,6 +122,49 @@ public function __construct( * if an error occurs */ public function getAccounts() + { + if (!$this->authenticateAndSetHeaders()) { + return null; + } + + $result = $this->doGet( + $this->baseUrl . '/accounts?expand=profile,subjects' + ); + + if (isset($result->errorCode)) { + return null; + } + return $result; + } + + /** + * Load all LibGuides AZ databases. + * + * @return object|null A JSON object of all LibGuides databases, or null + * if an error occurs + */ + public function getAZ() + { + if (!$this->authenticateAndSetHeaders()) { + return null; + } + + $result = $this->doGet( + $this->baseUrl . '/az' + ); + + if (isset($result->errorCode)) { + return null; + } + return $result; + } + + /** + * Authentiate to the LibGuides API and set authentiation headers. + * + * @return bool Indicates if authentiation succeeded. + */ + protected function authenticateAndSetHeaders() { $tokenData = $this->authenticateWithClientCredentials( $this->baseUrl . '/oauth/token', @@ -129,7 +172,7 @@ public function getAccounts() $this->clientSecret ); if (!$tokenData) { - return null; + return false; } $headers = []; @@ -143,10 +186,21 @@ public function getAccounts() $headers[] = 'User-Agent: ' . $this->userAgent; $this->client->setHeaders($headers); + + return true; + } + + /** + * Perform a GET request to the LibGuides API. + * + * @param string $url Full request url + * + * @return object|null A JSON object of the repsons data, or null if an error occurs + */ + protected function doGet($url) + { $this->client->setMethod('GET'); - $this->client->setUri( - $this->baseUrl . '/accounts?expand=profile,subjects' - ); + $this->client->setUri($url); try { $response = $this->client->send(); } catch (Exception $ex) { diff --git a/module/VuFind/src/VuFind/Recommend/EDSDatabases.php b/module/VuFind/src/VuFind/Recommend/EDSDatabases.php new file mode 100644 index 00000000000..285059d7f55 --- /dev/null +++ b/module/VuFind/src/VuFind/Recommend/EDSDatabases.php @@ -0,0 +1,174 @@ + + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:recommendation_modules Wiki + */ + +namespace VuFind\Recommend; + +use Laminas\Cache\Storage\Adapter\AbstractAdapter as CacheAdapter; +use Laminas\Config\Config; +use VuFind\Connection\LibGuides; + +use function intval; + +/** + * EDSDatabases Recommendations Module + * + * This class displays a list of external links to the research databases represented + * by EDS results. (Unlike the EDS ContentProvider facet that would narrow down the + * results within VuFind.) + * + * @category VuFind + * @package Recommendations + * @author Maccabee Levine + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:recommendation_modules Wiki + */ +class EDSDatabases implements RecommendInterface +{ + use \VuFind\Cache\CacheTrait; + + /** + * Results object + * + * @var \VuFind\Search\Base\Results + */ + protected $results; + + /** + * LibGuides connector + * + * @var LibGuides + */ + protected $libGuides; + + /** + * Constructor + * + * @param LibGuides $libGuides LibGuides API connection + * @param Config $config LibGuides API configuration object + * @param CacheAdapter $cache Object cache + */ + public function __construct( + LibGuides $libGuides, + Config $config, + CacheAdapter $cache + ) { + $this->libGuides = $libGuides; + $this->setCacheStorage($cache); + + // Cache the data related to profiles for up to 10 minutes: + $this->cacheLifetime = intval($config->GetAZ->cache_lifetime ?? 600); + } + + /** + * Store the configuration of the recommendation module. + * + * @param string $settings Settings from searches.ini. + * + * @return void + */ + public function setConfig($settings) + { + // No action needed. + } + + /** + * Called before the Search Results object performs its main search + * (specifically, in response to \VuFind\Search\SearchRunner::EVENT_CONFIGURED). + * This method is responsible for setting search parameters needed by the + * recommendation module and for reading any existing search parameters that may + * be needed. + * + * @param \VuFind\Search\Base\Params $params Search parameter object + * @param \Laminas\Stdlib\Parameters $request Parameter object representing user + * request. + * + * @return void + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function init($params, $request) + { + // No action needed. + } + + /** + * Called after the Search Results object has performed its main search. This + * may be used to extract necessary information from the Search Results object + * or to perform completely unrelated processing. + * + * @param \VuFind\Search\Base\Results $results Search results object + * + * @return void + */ + public function process($results) + { + $this->results = $results; + } + + /** + * Get terms related to the query. + * + * @return array + */ + public function getResults() + { + $records = $this->results->getResults(); + $nameToDatabase = $this->getLibGuidesDatabases(); + $databases = []; + foreach ($records as $record) { + $databaseInfo = $nameToDatabase[$record->getDbLabel()] ?? null; + if ($databaseInfo) { + $databases[$record->getDbLabel()] = $databaseInfo; + } + } + return $databases; + } + + /** + * Load or retrieve from the cache the list of LibGuides A-Z databases. + * + * @return array An array mapping a database name to the full object + * from the LibGuides /az API. + */ + protected function getLibGuidesDatabases() + { + $nameToDatabase = $this->getCachedData('libGuidesAZ-nameToDatabase'); + if (empty($nameToDatabase)) { + $databases = $this->libGuides->getAZ(); + + $nameToDatabase = []; + foreach ($databases as $database) { + $nameToDatabase[$database->name] = $database; + } + + $this->putCachedData('libGuidesAZ-nameToDatabase', $nameToDatabase); + } + return $nameToDatabase; + } +} diff --git a/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php b/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php new file mode 100644 index 00000000000..e13f3eb0c6f --- /dev/null +++ b/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php @@ -0,0 +1,77 @@ + + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ + +namespace VuFind\Recommend; + +use Psr\Container\ContainerInterface; + +/** + * EDS Databases recommendation module factory. + * + * @category VuFind + * @package Recommendations + * @author Maccabee Levine + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class EDSDatabasesFactory implements \Laminas\ServiceManager\Factory\FactoryInterface +{ + /** + * Create an object + * + * @param ContainerInterface $container Service manager + * @param string $requestedName Service being created + * @param null|array $options Extra options (optional) + * + * @return object + * + * @throws ServiceNotFoundException if unable to resolve the service. + * @throws ServiceNotCreatedException if an exception is raised when + * creating a service. + * @throws ContainerException&\Throwable if any other error occurs + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function __invoke( + ContainerInterface $container, + $requestedName, + array $options = null + ) { + if (!empty($options)) { + throw new \Exception('Unexpected options passed to factory.'); + } + return new $requestedName( + $container->get(\VuFind\Connection\LibGuides::class), + $container->get(\VuFind\Config\PluginManager::class) + ->get('EDS'), + $container->get(\VuFind\Cache\Manager::class) + ->getCache('object'), + ); + } +} diff --git a/module/VuFind/src/VuFind/Recommend/PluginManager.php b/module/VuFind/src/VuFind/Recommend/PluginManager.php index dd03088dfa3..e0d6b9f677d 100644 --- a/module/VuFind/src/VuFind/Recommend/PluginManager.php +++ b/module/VuFind/src/VuFind/Recommend/PluginManager.php @@ -57,6 +57,7 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager 'collectionsidefacets' => CollectionSideFacets::class, 'doi' => DOI::class, 'dplaterms' => DPLATerms::class, + 'edsdatabases' => EDSDatabases::class, 'edsresults' => EDSResults::class, 'edsresultsdeferred' => EDSResultsDeferred::class, 'epfresults' => EPFResults::class, @@ -116,6 +117,7 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager Deprecated::class => InvokableFactory::class, DOI::class => InvokableFactory::class, DPLATerms::class => DPLATermsFactory::class, + EDSDatabases::class => EDSDatabasesFactory::class, EDSResults::class => InjectSearchRunnerFactory::class, EDSResultsDeferred::class => InvokableFactory::class, EPFResults::class => InjectSearchRunnerFactory::class, diff --git a/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml b/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml new file mode 100644 index 00000000000..315137f1370 --- /dev/null +++ b/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml @@ -0,0 +1,17 @@ +
+ recommend->getResults(); ?> + +

transEsc('eds_databases')?>

+ + +
From 5da0e2e32c9b728472d4a88d70609934c96d3318 Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Wed, 11 Oct 2023 17:31:30 +0000 Subject: [PATCH 12/32] Add optional intro --- languages/en.ini | 3 ++- themes/bootstrap3/templates/Recommend/EDSDatabases.phtml | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/languages/en.ini b/languages/en.ini index 57dde8f6a89..6a2642d70f8 100644 --- a/languages/en.ini +++ b/languages/en.ini @@ -356,7 +356,8 @@ edit_list_fail = "Sorry, you are not permitted to edit this list" edit_list_success = "List successfully updated." Edition = "Edition" EDS Results = "EDS Results" -eds_databases = "Search Databases Directly" +eds_databases = "Search Relevant Databases" +eds_databases_intro = "Search directly in databases for enhanced functionality." eds_expander_fulltext = "Also search within the full text of the articles" eds_expander_relatedsubjects = "Apply equivalent subjects" eds_expander_thesaurus = "Apply related words" diff --git a/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml b/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml index 315137f1370..f3546b46442 100644 --- a/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml +++ b/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml @@ -2,11 +2,14 @@ recommend->getResults(); ?>

transEsc('eds_databases')?>

+ transEsc('eds_databases_intro', [], '')): ?> +

transEsc('eds_databases_intro')?>

+
- + escapeHtml($database->name)?> From d97133e61269aeb2824ea964b2826f02f5d1b996 Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Wed, 11 Oct 2023 17:37:51 +0000 Subject: [PATCH 13/32] Proxy url --- themes/bootstrap3/templates/Recommend/EDSDatabases.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml b/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml index f3546b46442..594db174bcd 100644 --- a/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml +++ b/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml @@ -9,7 +9,7 @@
- + escapeHtml($database->name)?> From b8711e6fc5a62601ecf7732780ebd329b85e3328 Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Wed, 11 Oct 2023 17:38:59 +0000 Subject: [PATCH 14/32] Open link in external tab --- themes/bootstrap3/templates/Recommend/EDSDatabases.phtml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml b/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml index 594db174bcd..d8994fc1583 100644 --- a/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml +++ b/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml @@ -9,7 +9,8 @@
- + + icon('external-link') ?> escapeHtml($database->name)?> From 51499ea7f18ba7bed0b0b5c0a4eeedcc5ff005ad Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Wed, 11 Oct 2023 17:51:00 +0000 Subject: [PATCH 15/32] Fix config loading so caching works --- module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php b/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php index e13f3eb0c6f..9741095d86a 100644 --- a/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php +++ b/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php @@ -69,7 +69,7 @@ public function __invoke( return new $requestedName( $container->get(\VuFind\Connection\LibGuides::class), $container->get(\VuFind\Config\PluginManager::class) - ->get('EDS'), + ->get('LibGuidesAPI'), $container->get(\VuFind\Cache\Manager::class) ->getCache('object'), ); From 21f46bb6e08ae4f4e72404fbfda8fcaf60b429b0 Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Fri, 27 Oct 2023 15:28:32 +0000 Subject: [PATCH 16/32] Fix typo --- module/VuFind/src/VuFind/Connection/LibGuides.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/VuFind/src/VuFind/Connection/LibGuides.php b/module/VuFind/src/VuFind/Connection/LibGuides.php index e43f9226123..a46a35616f3 100644 --- a/module/VuFind/src/VuFind/Connection/LibGuides.php +++ b/module/VuFind/src/VuFind/Connection/LibGuides.php @@ -195,7 +195,7 @@ protected function authenticateAndSetHeaders() * * @param string $url Full request url * - * @return object|null A JSON object of the repsons data, or null if an error occurs + * @return object|null A JSON object of the response data, or null if an error occurs */ protected function doGet($url) { From a6977fe8b9fd140d5c7a84b59473e6fa3576b343 Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Fri, 27 Oct 2023 15:41:16 +0000 Subject: [PATCH 17/32] Pass config manager so other configs would be available --- module/VuFind/src/VuFind/Recommend/EDSDatabases.php | 11 ++++++----- .../src/VuFind/Recommend/EDSDatabasesFactory.php | 3 +-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/module/VuFind/src/VuFind/Recommend/EDSDatabases.php b/module/VuFind/src/VuFind/Recommend/EDSDatabases.php index 285059d7f55..026c8ca5450 100644 --- a/module/VuFind/src/VuFind/Recommend/EDSDatabases.php +++ b/module/VuFind/src/VuFind/Recommend/EDSDatabases.php @@ -69,20 +69,21 @@ class EDSDatabases implements RecommendInterface /** * Constructor * - * @param LibGuides $libGuides LibGuides API connection - * @param Config $config LibGuides API configuration object - * @param CacheAdapter $cache Object cache + * @param LibGuides $libGuides LibGuides API connection + * @param \VuFind\Config\PluginManager $configManager Config PluginManager + * @param CacheAdapter $cache Object cache */ public function __construct( LibGuides $libGuides, - Config $config, + \VuFind\Config\PluginManager $configManager, CacheAdapter $cache ) { $this->libGuides = $libGuides; $this->setCacheStorage($cache); // Cache the data related to profiles for up to 10 minutes: - $this->cacheLifetime = intval($config->GetAZ->cache_lifetime ?? 600); + $libGuidesApiConfig = $configManager->get('LibGuidesAPI'); + $this->cacheLifetime = intval($libGuidesApiConfig->GetAZ->cache_lifetime ?? 600); } /** diff --git a/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php b/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php index 9741095d86a..b62f7d48c52 100644 --- a/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php +++ b/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php @@ -68,8 +68,7 @@ public function __invoke( } return new $requestedName( $container->get(\VuFind\Connection\LibGuides::class), - $container->get(\VuFind\Config\PluginManager::class) - ->get('LibGuidesAPI'), + $container->get(\VuFind\Config\PluginManager::class), $container->get(\VuFind\Cache\Manager::class) ->getCache('object'), ); From ca48db13bcb7fc11362a2df92c965760c5c24e85 Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Fri, 27 Oct 2023 18:23:30 +0000 Subject: [PATCH 18/32] Support url configuration in EDS.ini --- config/vufind/EDS.ini | 15 +++++ .../src/VuFind/Recommend/EDSDatabases.php | 63 +++++++++++++++---- .../VuFind/Recommend/EDSDatabasesFactory.php | 2 +- .../templates/Recommend/EDSDatabases.phtml | 6 +- 4 files changed, 70 insertions(+), 16 deletions(-) diff --git a/config/vufind/EDS.ini b/config/vufind/EDS.ini index 4882805ae99..be799b80b4c 100644 --- a/config/vufind/EDS.ini +++ b/config/vufind/EDS.ini @@ -323,3 +323,18 @@ AU = None ; documentation on options for different adapters. ; ttl, Time to Live, i.e. cache entry life time in seconds. 300 seconds by default. ;options[ttl] = 300 + +; This section supports the EDSDatabases recommendation module, +; which displays a list of the results' databases, each linking +; to that database's individual website. +[Databases] + +; Load database URLs from LibGuides. Default is false. +; Requires configuration in LibGuidesAPI.ini. +;useLibGuides = true + +; Map of database name (matching EDS API 'DbLabel' value) to website URL. +; These databases are added to any retrieved from LibGuides, and override +; the LibGuides URLs if the same name is present here. +;url[Expensive Science Database] = https://some.url +;url[Cool Humanities Database] = https://another.url diff --git a/module/VuFind/src/VuFind/Recommend/EDSDatabases.php b/module/VuFind/src/VuFind/Recommend/EDSDatabases.php index 026c8ca5450..072a5e34b62 100644 --- a/module/VuFind/src/VuFind/Recommend/EDSDatabases.php +++ b/module/VuFind/src/VuFind/Recommend/EDSDatabases.php @@ -59,6 +59,20 @@ class EDSDatabases implements RecommendInterface */ protected $results; + /** + * Databases listed in EDS.ini + * + * @var array + */ + protected $edsDatabases; + + /** + * Configuration of whether to use LibGuides as a data source + * + * @var bool + */ + protected $useLibGuides; + /** * LibGuides connector * @@ -69,21 +83,30 @@ class EDSDatabases implements RecommendInterface /** * Constructor * - * @param LibGuides $libGuides LibGuides API connection * @param \VuFind\Config\PluginManager $configManager Config PluginManager + * @param LibGuides $libGuides LibGuides API connection * @param CacheAdapter $cache Object cache */ public function __construct( - LibGuides $libGuides, \VuFind\Config\PluginManager $configManager, + LibGuides $libGuides, CacheAdapter $cache ) { - $this->libGuides = $libGuides; - $this->setCacheStorage($cache); - - // Cache the data related to profiles for up to 10 minutes: - $libGuidesApiConfig = $configManager->get('LibGuidesAPI'); - $this->cacheLifetime = intval($libGuidesApiConfig->GetAZ->cache_lifetime ?? 600); + $edsConfig = $configManager->get('EDS'); + $edsDatabaseUrls = isset($edsConfig->Databases->url) ? $edsConfig->Databases->url->toArray() : []; + $this->edsDatabases = array_map(function ($url) { + return ['url' => $url]; + }, $edsDatabaseUrls); + + $this->useLibGuides = $edsConfig->Databases->useLibGuides ?? false; + if ($this->useLibGuides) { + $this->libGuides = $libGuides; + $this->setCacheStorage($cache); + + // Cache the data related to profiles for up to 10 minutes: + $libGuidesApiConfig = $configManager->get('LibGuidesAPI'); + $this->cacheLifetime = intval($libGuidesApiConfig->GetAZ->cache_lifetime ?? 600); + } } /** @@ -140,7 +163,7 @@ public function process($results) public function getResults() { $records = $this->results->getResults(); - $nameToDatabase = $this->getLibGuidesDatabases(); + $nameToDatabase = $this->getDatabases(); $databases = []; foreach ($records as $record) { $databaseInfo = $nameToDatabase[$record->getDbLabel()] ?? null; @@ -151,11 +174,27 @@ public function getResults() return $databases; } + /** + * Generate a combined list of databases from all enabled sources. + * + * @return An array mapping a database name to a sub-array with + * the url. + */ + protected function getDatabases() + { + $databases = []; + if ($this->useLibGuides) { + $databases = $this->getLibGuidesDatabases(); + } + $databases = array_merge($databases, $this->edsDatabases); + return $databases; + } + /** * Load or retrieve from the cache the list of LibGuides A-Z databases. * - * @return array An array mapping a database name to the full object - * from the LibGuides /az API. + * @return array An array mapping a database name to an array + * representing the full object retrieved from the LibGuides /az API. */ protected function getLibGuidesDatabases() { @@ -165,7 +204,7 @@ protected function getLibGuidesDatabases() $nameToDatabase = []; foreach ($databases as $database) { - $nameToDatabase[$database->name] = $database; + $nameToDatabase[$database->name] = (array)$database; } $this->putCachedData('libGuidesAZ-nameToDatabase', $nameToDatabase); diff --git a/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php b/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php index b62f7d48c52..85dcdecb42d 100644 --- a/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php +++ b/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php @@ -67,8 +67,8 @@ public function __invoke( throw new \Exception('Unexpected options passed to factory.'); } return new $requestedName( - $container->get(\VuFind\Connection\LibGuides::class), $container->get(\VuFind\Config\PluginManager::class), + $container->get(\VuFind\Connection\LibGuides::class), $container->get(\VuFind\Cache\Manager::class) ->getCache('object'), ); diff --git a/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml b/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml index d8994fc1583..fac10cfc1b7 100644 --- a/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml +++ b/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml @@ -6,12 +6,12 @@

transEsc('eds_databases_intro')?>

- + $database): ?> From 90e36aa9b889eca93d3b22a0275251c8f5b49420 Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Fri, 27 Oct 2023 18:56:39 +0000 Subject: [PATCH 19/32] Get database list from facets --- module/VuFind/src/VuFind/Recommend/EDSDatabases.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/module/VuFind/src/VuFind/Recommend/EDSDatabases.php b/module/VuFind/src/VuFind/Recommend/EDSDatabases.php index 072a5e34b62..82da0a3724b 100644 --- a/module/VuFind/src/VuFind/Recommend/EDSDatabases.php +++ b/module/VuFind/src/VuFind/Recommend/EDSDatabases.php @@ -162,13 +162,14 @@ public function process($results) */ public function getResults() { - $records = $this->results->getResults(); + $resultDatabases = $this->results->getFacetList(['ContentProvider' => null])['ContentProvider']['list'] ?? []; $nameToDatabase = $this->getDatabases(); $databases = []; - foreach ($records as $record) { - $databaseInfo = $nameToDatabase[$record->getDbLabel()] ?? null; + foreach ($resultDatabases as $resultDatabase) { + $name = $resultDatabase['value']; + $databaseInfo = $nameToDatabase[$name] ?? null; if ($databaseInfo) { - $databases[$record->getDbLabel()] = $databaseInfo; + $databases[$name] = $databaseInfo; } } return $databases; From 46333eacb6934c303c349f5dcf5749c3b720d790 Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Mon, 30 Oct 2023 12:43:24 +0000 Subject: [PATCH 20/32] Document module in searches.ini --- config/vufind/searches.ini | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config/vufind/searches.ini b/config/vufind/searches.ini index 95f1fc20dd3..e21ea6a07bf 100644 --- a/config/vufind/searches.ini +++ b/config/vufind/searches.ini @@ -254,6 +254,9 @@ WorkKeys = year ; DPLATerms:[collapsed] ; Display results from the DPLA catalog. Provide a boolean to have the sidebar ; collapsed or open on page load. +; EDSDatabases:[result limit] +; Displays a list of the databases referenced in EDS facets, each linking +; to its individual website. ; EDSResults:[GET parameter]:[result limit] ; Display EDS search results matching the terms found in the specified ; GET parameter (default = "lookfor"), limited to a specified number of From 9f88a40282f499ea4bd081f915b0850da52c461e Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Mon, 30 Oct 2023 12:45:23 +0000 Subject: [PATCH 21/32] Limit results to configured number --- .../VuFind/src/VuFind/Recommend/EDSDatabases.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/module/VuFind/src/VuFind/Recommend/EDSDatabases.php b/module/VuFind/src/VuFind/Recommend/EDSDatabases.php index 82da0a3724b..e43b97ddcc6 100644 --- a/module/VuFind/src/VuFind/Recommend/EDSDatabases.php +++ b/module/VuFind/src/VuFind/Recommend/EDSDatabases.php @@ -33,6 +33,7 @@ use Laminas\Config\Config; use VuFind\Connection\LibGuides; +use function count; use function intval; /** @@ -59,6 +60,13 @@ class EDSDatabases implements RecommendInterface */ protected $results; + /** + * Number of results to show + * + * @var int + */ + protected $limit; + /** * Databases listed in EDS.ini * @@ -118,7 +126,10 @@ public function __construct( */ public function setConfig($settings) { - // No action needed. + $settings = explode(':', $settings); + $this->limit + = (isset($settings[0]) && is_numeric($settings[0]) && $settings[0] > 0) + ? intval($settings[0]) : 5; } /** @@ -171,6 +182,9 @@ public function getResults() if ($databaseInfo) { $databases[$name] = $databaseInfo; } + if (count($databases) >= $this->limit) { + break; + } } return $databases; } From 6c2d5e049a3570cd10a2b3d61ced9cdd3b358551 Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Thu, 2 Nov 2023 19:53:51 +0000 Subject: [PATCH 22/32] Generalize to work beyond EDS --- config/vufind/EDS.ini | 11 ++- config/vufind/LibGuidesAPI.ini | 2 +- config/vufind/searches.ini | 6 +- languages/en.ini | 4 +- .../{EDSDatabases.php => Databases.php} | 96 ++++++++++++++----- ...abasesFactory.php => DatabasesFactory.php} | 6 +- .../src/VuFind/Recommend/PluginManager.php | 4 +- .../{EDSDatabases.phtml => Databases.phtml} | 8 +- 8 files changed, 96 insertions(+), 41 deletions(-) rename module/VuFind/src/VuFind/Recommend/{EDSDatabases.php => Databases.php} (70%) rename module/VuFind/src/VuFind/Recommend/{EDSDatabasesFactory.php => DatabasesFactory.php} (92%) rename themes/bootstrap3/templates/Recommend/{EDSDatabases.phtml => Databases.phtml} (74%) diff --git a/config/vufind/EDS.ini b/config/vufind/EDS.ini index be799b80b4c..e9bdb1bded0 100644 --- a/config/vufind/EDS.ini +++ b/config/vufind/EDS.ini @@ -324,11 +324,20 @@ AU = None ; ttl, Time to Live, i.e. cache entry life time in seconds. 300 seconds by default. ;options[ttl] = 300 -; This section supports the EDSDatabases recommendation module, +; This section supports the Databases recommendation module, ; which displays a list of the results' databases, each linking ; to that database's individual website. [Databases] +; Define the facet hierarcy path leading to each database. +; For EDS (the databases are at ContentProvider/list): +;resultFacet[] = 'ContentProvider' +;resultFacet[] = 'list' + +; For each database facet, define the key to the database name +; For EDS: +;resultFacetNameKey = 'value' + ; Load database URLs from LibGuides. Default is false. ; Requires configuration in LibGuidesAPI.ini. ;useLibGuides = true diff --git a/config/vufind/LibGuidesAPI.ini b/config/vufind/LibGuidesAPI.ini index b5ec2558925..33d4908552a 100644 --- a/config/vufind/LibGuidesAPI.ini +++ b/config/vufind/LibGuidesAPI.ini @@ -30,7 +30,7 @@ api_base_url = https://lgapi-us.libapps.com/1.2 ; Note this is not used for the LibGuidesAZ search ; implementation; see LibGuidesAZ.ini for that. ; This is used where the full list of databases is needed -; by EDSDatabases. +; by the Databases recommendation module. [GetAZ] ; Duration (seconds) to cache response data. Default is 600. ;cache_lifetime = 600 diff --git a/config/vufind/searches.ini b/config/vufind/searches.ini index e21ea6a07bf..bb983cd0ac9 100644 --- a/config/vufind/searches.ini +++ b/config/vufind/searches.ini @@ -251,12 +251,12 @@ WorkKeys = year ; Display catalog search results matching the terms found in the specified ; GET parameter (default = "lookfor"), limited to a specified number of ; matches (default = 5). This is designed for use with non-catalog modules. +; Databases:[result limit] +; Displays a list of the databases referenced in EDS or similar facets, each +; linking to its individual website. ; DPLATerms:[collapsed] ; Display results from the DPLA catalog. Provide a boolean to have the sidebar ; collapsed or open on page load. -; EDSDatabases:[result limit] -; Displays a list of the databases referenced in EDS facets, each linking -; to its individual website. ; EDSResults:[GET parameter]:[result limit] ; Display EDS search results matching the terms found in the specified ; GET parameter (default = "lookfor"), limited to a specified number of diff --git a/languages/en.ini b/languages/en.ini index 6a2642d70f8..fef3e7f044b 100644 --- a/languages/en.ini +++ b/languages/en.ini @@ -301,6 +301,8 @@ Created = "Created" csrf_validation_failed = "The request could not be processed. Please try again." Data Set = "Data Set" Database = "Database" +databases = "Search Relevant Databases" +databases_intro = "Search directly in databases for enhanced functionality." Date = "Date" Date of birth = "Date of birth" Date of death = "Date of death" @@ -356,8 +358,6 @@ edit_list_fail = "Sorry, you are not permitted to edit this list" edit_list_success = "List successfully updated." Edition = "Edition" EDS Results = "EDS Results" -eds_databases = "Search Relevant Databases" -eds_databases_intro = "Search directly in databases for enhanced functionality." eds_expander_fulltext = "Also search within the full text of the articles" eds_expander_relatedsubjects = "Apply equivalent subjects" eds_expander_thesaurus = "Apply related words" diff --git a/module/VuFind/src/VuFind/Recommend/EDSDatabases.php b/module/VuFind/src/VuFind/Recommend/Databases.php similarity index 70% rename from module/VuFind/src/VuFind/Recommend/EDSDatabases.php rename to module/VuFind/src/VuFind/Recommend/Databases.php index e43b97ddcc6..d952f3a701b 100644 --- a/module/VuFind/src/VuFind/Recommend/EDSDatabases.php +++ b/module/VuFind/src/VuFind/Recommend/Databases.php @@ -1,7 +1,7 @@ get('EDS'); - $edsDatabaseUrls = isset($edsConfig->Databases->url) ? $edsConfig->Databases->url->toArray() : []; - $this->edsDatabases = array_map(function ($url) { - return ['url' => $url]; - }, $edsDatabaseUrls); - - $this->useLibGuides = $edsConfig->Databases->useLibGuides ?? false; - if ($this->useLibGuides) { - $this->libGuides = $libGuides; - $this->setCacheStorage($cache); - - // Cache the data related to profiles for up to 10 minutes: - $libGuidesApiConfig = $configManager->get('LibGuidesAPI'); - $this->cacheLifetime = intval($libGuidesApiConfig->GetAZ->cache_lifetime ?? 600); - } + $this->configManager = $configManager; + $this->libGuides = $libGuides; + $this->setCacheStorage($cache); } /** @@ -130,6 +147,25 @@ public function setConfig($settings) $this->limit = (isset($settings[0]) && is_numeric($settings[0]) && $settings[0] > 0) ? intval($settings[0]) : 5; + $databasesConfigFile = $settings[1] ?? 'EDS'; + + $databasesConfig = $this->configManager->get($databasesConfigFile); + $configUrls = isset($databasesConfig->Databases->url) + ? $databasesConfig->Databases->url->toArray() : []; + $this->configFileDatabases = array_map(function ($url) { + return ['url' => $url]; + }, $configUrls); + + $this->resultFacet = isset($databasesConfig->Databases->resultFacet) + ? $databasesConfig->Databases->resultFacet->toArray() : []; + $this->resultFacetNameKey = $databasesConfig->Databases->resultFacetNameKey ?? 'value'; + + $this->useLibGuides = $databasesConfig->Databases->useLibGuides ?? false; + if ($this->useLibGuides) { + // Cache the data related to profiles for up to 10 minutes: + $libGuidesApiConfig = $this->configManager->get('LibGuidesAPI'); + $this->cacheLifetime = intval($libGuidesApiConfig->GetAZ->cache_lifetime ?? 600); + } } /** @@ -173,11 +209,21 @@ public function process($results) */ public function getResults() { - $resultDatabases = $this->results->getFacetList(['ContentProvider' => null])['ContentProvider']['list'] ?? []; + if (count($this->resultFacet) < 1) { + throw new \Exception('At least one facet key required.'); + } + + $resultDatabasesTopFacet = array_shift($this->resultFacet); + $resultDatabases = $this->results->getFacetList([$resultDatabasesTopFacet => null])[$resultDatabasesTopFacet]; + while (count($this->resultFacet) && $resultDatabases) { + // Throw exception if the key is not found + $resultDatabases = $resultDatabases[array_shift($this->resultFacet)]; + } $nameToDatabase = $this->getDatabases(); $databases = []; foreach ($resultDatabases as $resultDatabase) { - $name = $resultDatabase['value']; + // Throw exception if the name is not found + $name = $resultDatabase[$this->resultFacetNameKey]; $databaseInfo = $nameToDatabase[$name] ?? null; if ($databaseInfo) { $databases[$name] = $databaseInfo; @@ -201,7 +247,7 @@ protected function getDatabases() if ($this->useLibGuides) { $databases = $this->getLibGuidesDatabases(); } - $databases = array_merge($databases, $this->edsDatabases); + $databases = array_merge($databases, $this->configFileDatabases); return $databases; } diff --git a/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php b/module/VuFind/src/VuFind/Recommend/DatabasesFactory.php similarity index 92% rename from module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php rename to module/VuFind/src/VuFind/Recommend/DatabasesFactory.php index 85dcdecb42d..3a11f21aeb1 100644 --- a/module/VuFind/src/VuFind/Recommend/EDSDatabasesFactory.php +++ b/module/VuFind/src/VuFind/Recommend/DatabasesFactory.php @@ -1,7 +1,7 @@ CatalogResults::class, 'channels' => Channels::class, 'collectionsidefacets' => CollectionSideFacets::class, + 'databases' => Databases::class, 'doi' => DOI::class, 'dplaterms' => DPLATerms::class, - 'edsdatabases' => EDSDatabases::class, 'edsresults' => EDSResults::class, 'edsresultsdeferred' => EDSResultsDeferred::class, 'epfresults' => EPFResults::class, @@ -114,10 +114,10 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager CatalogResults::class => InjectSearchRunnerFactory::class, Channels::class => InvokableFactory::class, CollectionSideFacets::class => CollectionSideFacetsFactory::class, + Databases::class => DatabasesFactory::class, Deprecated::class => InvokableFactory::class, DOI::class => InvokableFactory::class, DPLATerms::class => DPLATermsFactory::class, - EDSDatabases::class => EDSDatabasesFactory::class, EDSResults::class => InjectSearchRunnerFactory::class, EDSResultsDeferred::class => InvokableFactory::class, EPFResults::class => InjectSearchRunnerFactory::class, diff --git a/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml b/themes/bootstrap3/templates/Recommend/Databases.phtml similarity index 74% rename from themes/bootstrap3/templates/Recommend/EDSDatabases.phtml rename to themes/bootstrap3/templates/Recommend/Databases.phtml index fac10cfc1b7..69a38d2296d 100644 --- a/themes/bootstrap3/templates/Recommend/EDSDatabases.phtml +++ b/themes/bootstrap3/templates/Recommend/Databases.phtml @@ -1,9 +1,9 @@ -
+
recommend->getResults(); ?> -

transEsc('eds_databases')?>

- transEsc('eds_databases_intro', [], '')): ?> -

transEsc('eds_databases_intro')?>

+

transEsc('databases')?>

+ transEsc('databases_intro', [], '')): ?> +

transEsc('databases_intro')?>

$database): ?> From fdabd1238503acfd4a1d82d6838f1f0991450016 Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Thu, 2 Nov 2023 20:10:19 +0000 Subject: [PATCH 23/32] Reference configuration in EDS.ini --- config/vufind/searches.ini | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/config/vufind/searches.ini b/config/vufind/searches.ini index bb983cd0ac9..fea852f56ea 100644 --- a/config/vufind/searches.ini +++ b/config/vufind/searches.ini @@ -251,9 +251,10 @@ WorkKeys = year ; Display catalog search results matching the terms found in the specified ; GET parameter (default = "lookfor"), limited to a specified number of ; matches (default = 5). This is designed for use with non-catalog modules. -; Databases:[result limit] +; Databases:[result limit]:[ini name] ; Displays a list of the databases referenced in EDS or similar facets, each -; linking to its individual website. +; linking to its individual website. The .ini file must contain a [Databases] +; section with the relevant configuration; see example in EDS.ini. ; DPLATerms:[collapsed] ; Display results from the DPLA catalog. Provide a boolean to have the sidebar ; collapsed or open on page load. From 1bc8c1b8ecf288ce15503b366bb636ccfce7b2c1 Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Mon, 6 Nov 2023 15:40:31 +0000 Subject: [PATCH 24/32] Fix the same typo done three times! --- module/VuFind/src/VuFind/Connection/LibGuides.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/VuFind/src/VuFind/Connection/LibGuides.php b/module/VuFind/src/VuFind/Connection/LibGuides.php index a46a35616f3..d789a63f99c 100644 --- a/module/VuFind/src/VuFind/Connection/LibGuides.php +++ b/module/VuFind/src/VuFind/Connection/LibGuides.php @@ -160,9 +160,9 @@ public function getAZ() } /** - * Authentiate to the LibGuides API and set authentiation headers. + * Authenticate to the LibGuides API and set authentication headers. * - * @return bool Indicates if authentiation succeeded. + * @return bool Indicates if authentication succeeded. */ protected function authenticateAndSetHeaders() { From ef71eb65f39b406e1268a4079788d5275067d56a Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Mon, 6 Nov 2023 15:47:09 +0000 Subject: [PATCH 25/32] Add example default_side_recommend to EDS.ini --- config/vufind/EDS.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/config/vufind/EDS.ini b/config/vufind/EDS.ini index e9bdb1bded0..b96665e688b 100644 --- a/config/vufind/EDS.ini +++ b/config/vufind/EDS.ini @@ -32,6 +32,7 @@ default_view = brief ; sections below. ;default_top_recommend[] = TopFacets:FacetsTop:EDS default_side_recommend[] = SideFacets:Facets:CheckboxFacets:EDS +;default_side_recommend[] = Databases:5:EDS ;default_noresults_recommend[] = SwitchTab default_noresults_recommend[] = SwitchType default_noresults_recommend[] = RemoveFilters From bc3ec16b0c3d7d84c3df95855715557a05beea2f Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Mon, 6 Nov 2023 15:57:24 +0000 Subject: [PATCH 26/32] Simplify reference to Databases config --- module/VuFind/src/VuFind/Recommend/Databases.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/module/VuFind/src/VuFind/Recommend/Databases.php b/module/VuFind/src/VuFind/Recommend/Databases.php index d952f3a701b..104765f4b75 100644 --- a/module/VuFind/src/VuFind/Recommend/Databases.php +++ b/module/VuFind/src/VuFind/Recommend/Databases.php @@ -149,18 +149,20 @@ public function setConfig($settings) ? intval($settings[0]) : 5; $databasesConfigFile = $settings[1] ?? 'EDS'; - $databasesConfig = $this->configManager->get($databasesConfigFile); - $configUrls = isset($databasesConfig->Databases->url) - ? $databasesConfig->Databases->url->toArray() : []; + $databasesConfig = $this->configManager->get($databasesConfigFile)->Databases; + if (!$databasesConfig){ + throw new \Exception("Databases config file $databasesConfigFile must have section 'Databases'."); + } + $configUrls = isset($databasesConfig->url) ? $databasesConfig->url->toArray() : []; $this->configFileDatabases = array_map(function ($url) { return ['url' => $url]; }, $configUrls); - $this->resultFacet = isset($databasesConfig->Databases->resultFacet) - ? $databasesConfig->Databases->resultFacet->toArray() : []; - $this->resultFacetNameKey = $databasesConfig->Databases->resultFacetNameKey ?? 'value'; + $this->resultFacet = isset($databasesConfig->resultFacet) + ? $databasesConfig->resultFacet->toArray() : []; + $this->resultFacetNameKey = $databasesConfig->resultFacetNameKey ?? 'value'; - $this->useLibGuides = $databasesConfig->Databases->useLibGuides ?? false; + $this->useLibGuides = $databasesConfig->useLibGuides ?? false; if ($this->useLibGuides) { // Cache the data related to profiles for up to 10 minutes: $libGuidesApiConfig = $this->configManager->get('LibGuidesAPI'); From 1eac8ec85e6d3882517e019f6cac3f28e748f3ea Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Mon, 6 Nov 2023 17:11:14 +0000 Subject: [PATCH 27/32] Fix phpcbf --- module/VuFind/src/VuFind/Recommend/Databases.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/VuFind/src/VuFind/Recommend/Databases.php b/module/VuFind/src/VuFind/Recommend/Databases.php index 104765f4b75..a388a9b93fc 100644 --- a/module/VuFind/src/VuFind/Recommend/Databases.php +++ b/module/VuFind/src/VuFind/Recommend/Databases.php @@ -150,7 +150,7 @@ public function setConfig($settings) $databasesConfigFile = $settings[1] ?? 'EDS'; $databasesConfig = $this->configManager->get($databasesConfigFile)->Databases; - if (!$databasesConfig){ + if (!$databasesConfig) { throw new \Exception("Databases config file $databasesConfigFile must have section 'Databases'."); } $configUrls = isset($databasesConfig->url) ? $databasesConfig->url->toArray() : []; From 29c3dcfec2b78a41877c57b9860d2a73f47f5a0f Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Wed, 8 Nov 2023 19:18:04 +0000 Subject: [PATCH 28/32] Fix hierarchy typo --- config/vufind/EDS.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/vufind/EDS.ini b/config/vufind/EDS.ini index b96665e688b..0b3fcdb9d3e 100644 --- a/config/vufind/EDS.ini +++ b/config/vufind/EDS.ini @@ -330,7 +330,7 @@ AU = None ; to that database's individual website. [Databases] -; Define the facet hierarcy path leading to each database. +; Define the facet hierarchy path leading to each database. ; For EDS (the databases are at ContentProvider/list): ;resultFacet[] = 'ContentProvider' ;resultFacet[] = 'list' From f6e36ef6071fe41979bac1926a044f6200a48f53 Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Wed, 8 Nov 2023 19:46:30 +0000 Subject: [PATCH 29/32] Log errors rather than raising exceptions --- .../VuFind/src/VuFind/Recommend/Databases.php | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/module/VuFind/src/VuFind/Recommend/Databases.php b/module/VuFind/src/VuFind/Recommend/Databases.php index a388a9b93fc..e8cfc236da2 100644 --- a/module/VuFind/src/VuFind/Recommend/Databases.php +++ b/module/VuFind/src/VuFind/Recommend/Databases.php @@ -49,9 +49,10 @@ * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org/wiki/development:plugins:recommendation_modules Wiki */ -class Databases implements RecommendInterface +class Databases implements RecommendInterface, \Laminas\Log\LoggerAwareInterface { use \VuFind\Cache\CacheTrait; + use \VuFind\Log\LoggerAwareTrait; /** * Results object @@ -212,20 +213,31 @@ public function process($results) public function getResults() { if (count($this->resultFacet) < 1) { - throw new \Exception('At least one facet key required.'); + $this->logError('At least one facet key is required.'); + return []; } $resultDatabasesTopFacet = array_shift($this->resultFacet); - $resultDatabases = $this->results->getFacetList([$resultDatabasesTopFacet => null])[$resultDatabasesTopFacet]; - while (count($this->resultFacet) && $resultDatabases) { - // Throw exception if the key is not found - $resultDatabases = $resultDatabases[array_shift($this->resultFacet)]; + try { + $resultDatabases = $this->results->getFacetList([$resultDatabasesTopFacet => null])[$resultDatabasesTopFacet]; + while (count($this->resultFacet) && $resultDatabases) { + $resultDatabases = $resultDatabases[array_shift($this->resultFacet)]; + } + } + catch (\Exception $ex) { + $this->logError('Error using configured facets to find list of result databases.'); + return []; } $nameToDatabase = $this->getDatabases(); $databases = []; foreach ($resultDatabases as $resultDatabase) { - // Throw exception if the name is not found - $name = $resultDatabase[$this->resultFacetNameKey]; + try { + $name = $resultDatabase[$this->resultFacetNameKey]; + } + catch (\Exception $ex) { + $this->logError("Name key '$this->resultFacetNameKey' not found for database."); + continue; + } $databaseInfo = $nameToDatabase[$name] ?? null; if ($databaseInfo) { $databases[$name] = $databaseInfo; From b1095adef064f21103476d2ead28fd310f6e7d19 Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Wed, 8 Nov 2023 19:54:32 +0000 Subject: [PATCH 30/32] Fix code styling --- module/VuFind/src/VuFind/Recommend/Databases.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/module/VuFind/src/VuFind/Recommend/Databases.php b/module/VuFind/src/VuFind/Recommend/Databases.php index e8cfc236da2..3100b064b80 100644 --- a/module/VuFind/src/VuFind/Recommend/Databases.php +++ b/module/VuFind/src/VuFind/Recommend/Databases.php @@ -219,12 +219,12 @@ public function getResults() $resultDatabasesTopFacet = array_shift($this->resultFacet); try { - $resultDatabases = $this->results->getFacetList([$resultDatabasesTopFacet => null])[$resultDatabasesTopFacet]; + $resultDatabases = + $this->results->getFacetList([$resultDatabasesTopFacet => null])[$resultDatabasesTopFacet]; while (count($this->resultFacet) && $resultDatabases) { $resultDatabases = $resultDatabases[array_shift($this->resultFacet)]; - } - } - catch (\Exception $ex) { + } + } catch (\Exception $ex) { $this->logError('Error using configured facets to find list of result databases.'); return []; } @@ -233,8 +233,7 @@ public function getResults() foreach ($resultDatabases as $resultDatabase) { try { $name = $resultDatabase[$this->resultFacetNameKey]; - } - catch (\Exception $ex) { + } catch (\Exception $ex) { $this->logError("Name key '$this->resultFacetNameKey' not found for database."); continue; } From 15e28c746b93c7955adde38b1484fee74b7bfa84 Mon Sep 17 00:00:00 2001 From: Maccabee Levine Date: Fri, 10 Nov 2023 13:32:00 +0000 Subject: [PATCH 31/32] Fix error if LibGuidesAPI not configured --- .../VuFind/src/VuFind/Recommend/Databases.php | 19 ++++++++++--------- .../src/VuFind/Recommend/DatabasesFactory.php | 8 +++++++- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/module/VuFind/src/VuFind/Recommend/Databases.php b/module/VuFind/src/VuFind/Recommend/Databases.php index 3100b064b80..b4fc58f6e54 100644 --- a/module/VuFind/src/VuFind/Recommend/Databases.php +++ b/module/VuFind/src/VuFind/Recommend/Databases.php @@ -112,26 +112,26 @@ class Databases implements RecommendInterface, \Laminas\Log\LoggerAwareInterface protected $useLibGuides; /** - * LibGuides connector + * Callable for LibGuides connector * - * @var LibGuides + * @var callable */ - protected $libGuides; + protected $libGuidesGetter; /** * Constructor * - * @param \VuFind\Config\PluginManager $configManager Config PluginManager - * @param LibGuides $libGuides LibGuides API connection - * @param CacheAdapter $cache Object cache + * @param \VuFind\Config\PluginManager $configManager Config PluginManager + * @param callable $libGuidesGetter Getter for LibGuides API connection + * @param CacheAdapter $cache Object cache */ public function __construct( \VuFind\Config\PluginManager $configManager, - LibGuides $libGuides, + callable $libGuidesGetter, CacheAdapter $cache ) { $this->configManager = $configManager; - $this->libGuides = $libGuides; + $this->libGuidesGetter = $libGuidesGetter; $this->setCacheStorage($cache); } @@ -274,7 +274,8 @@ protected function getLibGuidesDatabases() { $nameToDatabase = $this->getCachedData('libGuidesAZ-nameToDatabase'); if (empty($nameToDatabase)) { - $databases = $this->libGuides->getAZ(); + $libGuides = ($this->libGuidesGetter)(); + $databases = $libGuides->getAZ(); $nameToDatabase = []; foreach ($databases as $database) { diff --git a/module/VuFind/src/VuFind/Recommend/DatabasesFactory.php b/module/VuFind/src/VuFind/Recommend/DatabasesFactory.php index 3a11f21aeb1..f0cd8053048 100644 --- a/module/VuFind/src/VuFind/Recommend/DatabasesFactory.php +++ b/module/VuFind/src/VuFind/Recommend/DatabasesFactory.php @@ -66,9 +66,15 @@ public function __invoke( if (!empty($options)) { throw new \Exception('Unexpected options passed to factory.'); } + + // LibGuides connection should only be instantiated if used + $libGuidesGetter = function () use ($container) { + return $container->get(\VuFind\Connection\LibGuides::class); + }; + return new $requestedName( $container->get(\VuFind\Config\PluginManager::class), - $container->get(\VuFind\Connection\LibGuides::class), + $libGuidesGetter, $container->get(\VuFind\Cache\Manager::class) ->getCache('object'), ); From ee324be9295383abffa3585f93a7f75fe000c886 Mon Sep 17 00:00:00 2001 From: Demian Katz Date: Fri, 10 Nov 2023 12:55:01 -0500 Subject: [PATCH 32/32] Fix icon link styling. --- themes/bootstrap3/templates/Recommend/Databases.phtml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/themes/bootstrap3/templates/Recommend/Databases.phtml b/themes/bootstrap3/templates/Recommend/Databases.phtml index 69a38d2296d..39d338044e6 100644 --- a/themes/bootstrap3/templates/Recommend/Databases.phtml +++ b/themes/bootstrap3/templates/Recommend/Databases.phtml @@ -9,9 +9,9 @@ $database): ?>