-
Notifications
You must be signed in to change notification settings - Fork 402
Create a new cover loader for EDS to proxy the image provided from the EDS API #5542
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
caf6bef
1a02004
f8b2f8e
ae7073e
6647e7a
7dde2dd
4d1e0c7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * EDS cover content loader. | ||
| * | ||
| * PHP version 8 | ||
| * | ||
| * Copyright (C) Michigan State University Board of Trustees 2026. | ||
| * | ||
| * 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, see | ||
| * <https://www.gnu.org/licenses/>. | ||
| * | ||
| * @category VuFind | ||
| * @package Content | ||
| * @author Megan Schanz <schamzme@msu.edu> | ||
| * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License | ||
| * @link https://vufind.org/wiki/development Wiki | ||
| */ | ||
|
|
||
| namespace VuFind\Content\Covers; | ||
|
|
||
| use Laminas\Cache\Storage\StorageInterface; | ||
|
|
||
| /** | ||
| * EDS cover content loader. | ||
| * | ||
| * @category VuFind | ||
| * @package Content | ||
| * @author Megan Schanz <schamzme@msu.edu> | ||
| * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License | ||
| * @link https://vufind.org/wiki/development Wiki | ||
| */ | ||
| class EDS extends \VuFind\Content\AbstractCover implements \Psr\Log\LoggerAwareInterface | ||
| { | ||
| use \VuFind\Log\LoggerAwareTrait; | ||
| use \VuFind\Cache\CacheTrait; | ||
|
|
||
| /** | ||
| * Constructor. | ||
| * | ||
| * @param StorageInterface $cache Cache | ||
| */ | ||
| public function __construct(StorageInterface $cache) | ||
| { | ||
| $this->supportsRecordid = true; | ||
| $this->setCacheStorage($cache); | ||
| } | ||
|
|
||
| /** | ||
| * Set the key to store in the cache to share between EDS cover loader and record driver. | ||
| * | ||
| * @param string $key Key to put in the cache | ||
| * | ||
| * @return string The determined key | ||
| */ | ||
| protected function getCacheKey($key = '') | ||
| { | ||
| return 'EDS_Shared_' . md5($key); | ||
| } | ||
|
|
||
| /** | ||
| * Determine if this handler supports the provided identifiers. | ||
| * | ||
| * In this case, we look for the recordid and source keys | ||
| * that are required for proxying the image and making sure the source | ||
| * is EDS. | ||
| * | ||
| * @param array $ids Array of identifiers (recordid, isbn, etc.) | ||
| * | ||
| * @return bool | ||
| */ | ||
| public function supports($ids) | ||
| { | ||
| return isset($ids['recordid']) | ||
| && isset($ids['source']) | ||
| && $ids['source'] === 'EDS'; | ||
| } | ||
|
|
||
| /** | ||
| * Get an image URL for the specific record. | ||
| * | ||
| * This is the primary method used by the Cover Loader manager. | ||
| * | ||
| * @param string $key Cover provider key (e.g. 'eds') | ||
| * @param string $size Size of image requested | ||
| * @param array $ids Array of identifiers | ||
| * | ||
| * @return string|bool URL of the image or false if unavailable | ||
| */ | ||
| public function getUrl($key, $size, $ids) | ||
| { | ||
| $recordId = $ids['recordid'] ?? ''; | ||
| $url = $this->getCachedData($recordId); | ||
|
|
||
| if (filter_var($url, FILTER_VALIDATE_URL)) { | ||
| $this->debug('Returning EDS cover image URL: ' . $url); | ||
| return $url; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * EDS cover loader factory. | ||
| * | ||
| * PHP version 8 | ||
| * | ||
| * Copyright (C) Michigan State University Board of Trustees 2026. | ||
| * | ||
| * 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, see | ||
| * <https://www.gnu.org/licenses/>. | ||
| * | ||
| * @category VuFind | ||
| * @package Content | ||
| * @author Megan Schanz <schamzme@msu.edu> | ||
| * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License | ||
| * @link https://vufind.org/wiki/development:plugins:record_drivers Wiki | ||
| */ | ||
|
|
||
| namespace VuFind\Content\Covers; | ||
|
|
||
| use Interop\Container\ContainerInterface; | ||
| use Laminas\ServiceManager\Factory\FactoryInterface; | ||
|
|
||
| /** | ||
| * Factory for EDS cover loader. | ||
| * | ||
| * PHP version 8 | ||
| * | ||
| * @category VuFind | ||
| * @package Content | ||
| * @author Megan Schanz <schamzme@msu.edu> | ||
| * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License | ||
| * @link https://vufind.org/vufind/ Main page | ||
| */ | ||
| class EDSFactory implements 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 | ||
| */ | ||
| 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\Cache\Manager::class)->getCache('object')); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,8 @@ | |
|
|
||
| namespace VuFind\RecordDriver; | ||
|
|
||
| use Laminas\Cache\Storage\StorageInterface; | ||
|
|
||
| use function count; | ||
| use function floatval; | ||
| use function in_array; | ||
|
|
@@ -48,6 +50,8 @@ | |
| class EDS extends DefaultRecord | ||
| { | ||
| use Feature\IlsAwareTrait; | ||
| use \VuFind\Http\CachingDownloaderAwareTrait; | ||
| use \VuFind\Cache\CacheTrait; | ||
|
|
||
| /** | ||
| * Document types that are treated as ePub links. | ||
|
|
@@ -63,6 +67,33 @@ class EDS extends DefaultRecord | |
| */ | ||
| protected $pdfTypes = ['ebook-pdf', 'pdflink']; | ||
|
|
||
| /** | ||
| * Constructor. | ||
| * | ||
| * @param \VuFind\Config\Config $mainConfig VuFind main configuration (omit | ||
| * for built-in defaults) | ||
| * @param StorageInterface $cache Cache | ||
| */ | ||
| public function __construct( | ||
| $mainConfig = null, | ||
| StorageInterface $cache = null, | ||
| ) { | ||
| $this->setCacheStorage($cache); | ||
| parent::__construct($mainConfig); | ||
| } | ||
|
|
||
| /** | ||
| * Set the key to store in the cache to share between EDS cover loader and record driver. | ||
| * | ||
| * @param string $key Key to put in the cache | ||
| * | ||
| * @return string The determined key | ||
| */ | ||
| protected function getCacheKey($key = '') | ||
| { | ||
| return 'EDS_Shared_' . md5($key); | ||
| } | ||
|
|
||
| /** | ||
| * Return the unique identifier of this record within EDS API; | ||
| * As Accession Numbers (AN) could be repetitive, we use Database ID | ||
|
|
@@ -653,6 +684,7 @@ function ($data) { | |
| */ | ||
| public function getThumbnail($size = 'small') | ||
| { | ||
| $thumbnail = null; | ||
| // Create a ranked list of sizes so we can use "best available" when appropriate. | ||
| // Note that "thumb" is a value used by EBSCO, not by VuFind; it is included so | ||
| // it can be matched up with requests for "small." | ||
|
|
@@ -665,7 +697,8 @@ public function getThumbnail($size = 'small') | |
| $target = $image['Target'] ?? ''; | ||
| if ($target) { | ||
| if ($currentFit === $desiredFit) { | ||
| return $target; | ||
| $thumbnail = $target; | ||
| break; | ||
| } | ||
| // Aim for the best match that is smaller than the requested size; we | ||
| // don't want to overflow, but something small is better than nothing. | ||
|
|
@@ -676,10 +709,25 @@ public function getThumbnail($size = 'small') | |
| } | ||
| } | ||
|
|
||
| if (!$thumbnail && $closestMatch) { | ||
| $thumbnail = $closestMatch; | ||
| } | ||
|
|
||
| // If EDS actually returned cover image data, use it. EDS only provides this data | ||
| // for certain ebook packages. | ||
| if ($closestMatch) { | ||
| return $closestMatch; | ||
| if ($thumbnail) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would there be value in adding an EDS.ini setting to control whether thumbnails are returned directly or through the cache? Some might prefer the old approach, and it doesn't look like adding flexibility would be too difficult.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea. I made a new setting under |
||
| // Determine if we are using the cover loader method or direct load | ||
| $loadDirectly = $this->recordConfig?->Cover?->loadDirectly ?? true; | ||
| if ($loadDirectly) { | ||
| return $thumbnail; | ||
| } else { | ||
| $this->putCachedData($this->getUniqueID(), $thumbnail); | ||
| return [ | ||
| 'recordid' => $this->getUniqueID(), | ||
| 'size' => $size, | ||
| 'source' => 'EDS', | ||
| ]; | ||
| } | ||
| } | ||
|
|
||
| // Optionally use VuFind's default cover loader | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * EDS factory for record drivers. | ||
| * | ||
| * PHP version 8 | ||
| * | ||
| * Copyright (C) Michigan State University Board of Trustees 2026. | ||
| * | ||
| * 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, see | ||
| * <https://www.gnu.org/licenses/>. | ||
| * | ||
| * @category VuFind | ||
| * @package RecordDrivers | ||
| * @author Megan Schanz <schanzme@msu.edu> | ||
| * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License | ||
| * @link https://vufind.org/wiki/development Wiki | ||
| */ | ||
|
|
||
| namespace VuFind\RecordDriver; | ||
|
|
||
| use Interop\Container\ContainerInterface; | ||
| use Laminas\ServiceManager\Factory\FactoryInterface; | ||
|
|
||
| /** | ||
| * Factory for EDS RecordDriver. | ||
| * | ||
| * PHP version 8 | ||
| * | ||
| * @category VuFind | ||
| * @package RecordDrivers | ||
| * @author Megan Schanz <schanzme@msu.edu> | ||
| * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License | ||
| * @link https://vufind.org/vufind/ Main page | ||
| */ | ||
| class EDSFactory implements 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 | ||
| */ | ||
| public function __invoke( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if this factory should be simplified or made to extend one of the other existing driver factories -- but the best approach may depend on the answer to the EPF issue.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It didn't seem like any of the existing driver factories injected the |
||
| ContainerInterface $container, | ||
| $requestedName, | ||
| ?array $options = null | ||
| ) { | ||
| $parts = explode('\\', $requestedName); | ||
| $configName = array_pop($parts); | ||
| $config = $container->get(\VuFind\Config\ConfigManagerInterface::class)->getConfigObject($configName); | ||
| $cache = $container->get(\VuFind\Cache\Manager::class)->getCache('object'); | ||
| return new $requestedName($config, $cache); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're not using the caching downloader, so why are you using this trait?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not; good catch. That was leftover from when I was experimenting with caching the images. I removed it.