From d8a9d4fa87d2271cd838a8f86ee413205720667f Mon Sep 17 00:00:00 2001 From: domerz <merz@ub.uni-leipzig.de> Date: Thu, 10 Sep 2020 13:54:21 +0200 Subject: [PATCH] Optionally allow rendering of a custom template for unavailable covers (#1679) --- config/vufind/config.ini | 5 ++ .../src/VuFind/AjaxHandler/GetRecordCover.php | 48 +++++++++++++++---- .../AjaxHandler/GetRecordCoverFactory.php | 8 +++- module/VuFind/src/VuFind/Cover/Loader.php | 31 ++++++++++++ module/VuFind/src/VuFind/Cover/Router.php | 19 +++++++- themes/bootstrap3/js/covers.js | 9 +++- .../templates/record/coverReplacement.phtml | 1 + 7 files changed, 109 insertions(+), 12 deletions(-) create mode 100644 themes/bootstrap3/templates/record/coverReplacement.phtml diff --git a/config/vufind/config.ini b/config/vufind/config.ini index 1f522830d1e..8bff5f8b935 100644 --- a/config/vufind/config.ini +++ b/config/vufind/config.ini @@ -852,6 +852,11 @@ coverimagesCache = true ; default; to enable it, just uncomment the line below. ;ajaxcovers = true +; When ajaxcovers is set to true, this setting controls whether the AJAX Handler +; GetRecordCover renders a fallback template (record/coverReplacement.phtml) in case +; no cover image could be loaded. +;useCoverFallbacksOnFail = false + ; These settings control the image to display when no book cover is available. ; If makeDynamicCovers is not false and the GD library is installed, VuFind will draw ; cover images on the fly. See [DynamicCovers] below for more settings. If set to diff --git a/module/VuFind/src/VuFind/AjaxHandler/GetRecordCover.php b/module/VuFind/src/VuFind/AjaxHandler/GetRecordCover.php index c49a7fd39f9..9d4d3814d14 100644 --- a/module/VuFind/src/VuFind/AjaxHandler/GetRecordCover.php +++ b/module/VuFind/src/VuFind/AjaxHandler/GetRecordCover.php @@ -28,6 +28,7 @@ namespace VuFind\AjaxHandler; use Laminas\Mvc\Controller\Plugin\Params; +use Laminas\View\Renderer\PhpRenderer; use VuFind\Cover\Router as CoverRouter; use VuFind\Exception\RecordMissing as RecordMissingException; use VuFind\ILS\Driver\CacheTrait; @@ -60,17 +61,40 @@ class GetRecordCover extends AbstractBase implements AjaxHandlerInterface */ protected $coverRouter; + /** + * PHP renderer + * + * @var PhpRenderer + */ + protected $renderer; + + /** + * If true we will render a fallback html template in case no image could be + * loaded + * + * @var bool + */ + protected $useCoverFallbacksOnFail = false; + /** * GetRecordCover constructor. * - * @param RecordLoader $recordLoader Record loader - * @param CoverRouter $coverRouter Cover router + * @param RecordLoader $recordLoader Record loader + * @param CoverRouter $coverRouter Cover router + * @param PhpRenderer $renderer PHP renderer (only required if + * $userCoverFallbacksOnFail is set to true) + * @param bool $useCoverFallbacksOnFail If true we will render a + * fallback html template in case no image could be loaded */ public function __construct(RecordLoader $recordLoader, - CoverRouter $coverRouter + CoverRouter $coverRouter, + ?PhpRenderer $renderer = null, + $useCoverFallbacksOnFail = false ) { $this->recordLoader = $recordLoader; $this->coverRouter = $coverRouter; + $this->renderer = $renderer; + $this->useCoverFallbacksOnFail = $useCoverFallbacksOnFail; } /** @@ -102,11 +126,19 @@ class GetRecordCover extends AbstractBase implements AjaxHandlerInterface ); } - return $this->formatResponse( - [ - 'url' => $this->coverRouter->getUrl($record, $size ?? 'small'), - 'size' => $size, - ] + $url = $this->coverRouter->getUrl( + $record, $size ?? 'small', true, $this->useCoverFallbacksOnFail ); + + return ($url || !$this->renderer || !$this->useCoverFallbacksOnFail) + ? $this->formatResponse(compact('url', 'size')) + : $this->formatResponse( + [ + 'html' => $this->renderer->render( + 'record/coverReplacement', + ['driver' => $record] + ) + ] + ); } } diff --git a/module/VuFind/src/VuFind/AjaxHandler/GetRecordCoverFactory.php b/module/VuFind/src/VuFind/AjaxHandler/GetRecordCoverFactory.php index ba99980495c..b66289308b0 100644 --- a/module/VuFind/src/VuFind/AjaxHandler/GetRecordCoverFactory.php +++ b/module/VuFind/src/VuFind/AjaxHandler/GetRecordCoverFactory.php @@ -63,9 +63,15 @@ class GetRecordCoverFactory implements FactoryInterface public function __invoke(ContainerInterface $container, $requestedName, array $options = null ) { + $config + = $container->get(\VuFind\Config\PluginManager::class)->get('config'); + $useFallbacks = $config->Content->useCoverFallbacksOnFail ?? false; return new $requestedName( $container->get(\VuFind\Record\Loader::class), - $container->get(\VuFind\Cover\Router::class) + $container->get(\VuFind\Cover\Router::class), + // We only need the view renderer if we're going to use fallbacks: + $useFallbacks ? $container->get('ViewRenderer') : null, + $useFallbacks ); } } diff --git a/module/VuFind/src/VuFind/Cover/Loader.php b/module/VuFind/src/VuFind/Cover/Loader.php index 3ebcd631988..d4c04ad43d7 100644 --- a/module/VuFind/src/VuFind/Cover/Loader.php +++ b/module/VuFind/src/VuFind/Cover/Loader.php @@ -164,6 +164,13 @@ class Loader extends \VuFind\ImageLoader */ protected $type; + /** + * Flag denoting the last loaded image was a FailImage + * + * @var bool + */ + protected $hasLoadedUnavailable = false; + /** * Constructor * @@ -315,6 +322,8 @@ class Loader extends \VuFind\ImageLoader */ public function loadImage($settings = []) { + // reset to normal + $this->hasLoadedUnavailable = false; // Load settings from legacy function parameters if they are not passed // in as an array: $settings = is_array($settings) @@ -343,6 +352,28 @@ class Loader extends \VuFind\ImageLoader } } + /** + * {@inheritdoc} + * Adds @see self::$hasLoadedUnavailable flag + * + * @return void + */ + public function loadUnavailable() + { + $this->hasLoadedUnavailable = true; + return parent::loadUnavailable(); + } + + /** + * Returns true if the last loaded image was the FailImage + * + * @return bool + */ + public function hasLoadedUnavailable() + { + return $this->hasLoadedUnavailable; + } + /** * Support method for fetchFromAPI() -- set the localFile property. * diff --git a/module/VuFind/src/VuFind/Cover/Router.php b/module/VuFind/src/VuFind/Cover/Router.php index b96bfa4e10b..fdeabb53619 100644 --- a/module/VuFind/src/VuFind/Cover/Router.php +++ b/module/VuFind/src/VuFind/Cover/Router.php @@ -78,11 +78,13 @@ class Router implements \Laminas\Log\LoggerAwareInterface * small is default). * @param bool $resolveDynamic Should we resolve dynamic cover data into * a URL (true) or simply return false (false)? + * @param bool $testLoadImage If true the function will try to load the + * cover image in advance and returns false in case no image could be loaded * * @return string|bool */ public function getUrl(RecordDriver $driver, $size = 'small', - $resolveDynamic = true + $resolveDynamic = true, $testLoadImage = false ) { // Try to build thumbnail: $thumb = $driver->tryMethod('getThumbnail', [$size]); @@ -127,6 +129,19 @@ class Router implements \Laminas\Log\LoggerAwareInterface ); } } - return $directUrl ?? $dynamicUrl ?? false; + + if (isset($directUrl)) { + return $directUrl; + } elseif (isset($dynamicUrl)) { + if ($testLoadImage) { + $this->coverLoader->loadImage($settings); + if ($this->coverLoader->hasLoadedUnavailable()) { + return false; + } + } + return $dynamicUrl; + } + + return false; } } diff --git a/themes/bootstrap3/js/covers.js b/themes/bootstrap3/js/covers.js index fa8b46f1dfb..4a9b58c1fab 100644 --- a/themes/bootstrap3/js/covers.js +++ b/themes/bootstrap3/js/covers.js @@ -7,9 +7,16 @@ function loadCoverByElement(data, element) { function coverCallback(response) { spinner.hide(); container.show(); - if (response.data.url !== false) { + if (typeof response.data.url !== 'undefined' && response.data.url !== false) { img.attr("src", response.data.url); container.children().not("img").hide(); + } else { + img.remove(); + if (typeof response.data.html !== 'undefined') { + container.html(response.data.html); + } else { + container.html(); + } } } $.ajax({ diff --git a/themes/bootstrap3/templates/record/coverReplacement.phtml b/themes/bootstrap3/templates/record/coverReplacement.phtml new file mode 100644 index 00000000000..6abe01a3db6 --- /dev/null +++ b/themes/bootstrap3/templates/record/coverReplacement.phtml @@ -0,0 +1 @@ +<i class="fa fa-question"></i> \ No newline at end of file -- GitLab