diff --git a/application/Thumbnailer.php b/application/Thumbnailer.php
index 314baf0d..5aec23c8 100644
--- a/application/Thumbnailer.php
+++ b/application/Thumbnailer.php
@@ -4,7 +4,6 @@ namespace Shaarli;
use Shaarli\Config\ConfigManager;
use WebThumbnailer\Application\ConfigManager as WTConfigManager;
-use WebThumbnailer\Exception\WebThumbnailerException;
use WebThumbnailer\WebThumbnailer;
/**
@@ -90,7 +89,7 @@ class Thumbnailer
try {
return $this->wt->thumbnail($url);
- } catch (WebThumbnailerException $e) {
+ } catch (\Throwable $e) {
// Exceptions are only thrown in debug mode.
error_log(get_class($e) . ': ' . $e->getMessage());
}
diff --git a/application/front/controller/admin/ConfigureController.php b/application/front/controller/admin/ConfigureController.php
index 44971c43..201a859b 100644
--- a/application/front/controller/admin/ConfigureController.php
+++ b/application/front/controller/admin/ConfigureController.php
@@ -99,7 +99,7 @@ class ConfigureController extends ShaarliAdminController
) {
$this->saveWarningMessage(t(
'You have enabled or changed thumbnails mode. '
- .'Please synchronize them.'
+ .'Please synchronize them.'
));
}
$this->container->conf->set('thumbnails.mode', $thumbnailsMode);
diff --git a/application/front/controller/admin/ThumbnailsController.php b/application/front/controller/admin/ThumbnailsController.php
new file mode 100644
index 00000000..e5308510
--- /dev/null
+++ b/application/front/controller/admin/ThumbnailsController.php
@@ -0,0 +1,79 @@
+container->bookmarkService->search() as $bookmark) {
+ // A note or not HTTP(S)
+ if ($bookmark->isNote() || !startsWith(strtolower($bookmark->getUrl()), 'http')) {
+ continue;
+ }
+
+ $ids[] = $bookmark->getId();
+ }
+
+ $this->assignView('ids', $ids);
+ $this->assignView(
+ 'pagetitle',
+ t('Thumbnails update') .' - '. $this->container->conf->get('general.title', 'Shaarli')
+ );
+
+ return $response->write($this->render('thumbnails'));
+ }
+
+ /**
+ * PATCH /admin/shaare/{id}/thumbnail-update - Route for AJAX calls
+ */
+ public function ajaxUpdate(Request $request, Response $response, array $args): Response
+ {
+ $id = $args['id'] ?? null;
+
+ if (false === ctype_digit($id)) {
+ return $response->withStatus(400);
+ }
+
+ try {
+ $bookmark = $this->container->bookmarkService->get($id);
+ } catch (BookmarkNotFoundException $e) {
+ return $response->withStatus(404);
+ }
+
+ $bookmark->setThumbnail($this->container->thumbnailer->get($bookmark->getUrl()));
+ $this->container->bookmarkService->set($bookmark);
+
+ return $response->withJson($this->container->formatterFactory->getFormatter('raw')->format($bookmark));
+ }
+
+ /**
+ * @param mixed[] $data Variables passed to the template engine
+ *
+ * @return mixed[] Template data after active plugins render_picwall hook execution.
+ */
+ protected function executeHooks(array $data): array
+ {
+ $this->container->pluginManager->executeHooks(
+ 'render_tools',
+ $data
+ );
+
+ return $data;
+ }
+}
diff --git a/application/legacy/LegacyUpdater.php b/application/legacy/LegacyUpdater.php
index 8d5cd071..cbf6890f 100644
--- a/application/legacy/LegacyUpdater.php
+++ b/application/legacy/LegacyUpdater.php
@@ -534,7 +534,7 @@ class LegacyUpdater
if ($thumbnailsEnabled) {
$this->session['warnings'][] = t(
- 'You have enabled or changed thumbnails mode. Please synchronize them.'
+ 'You have enabled or changed thumbnails mode. Please synchronize them.'
);
}
diff --git a/assets/common/js/thumbnails-update.js b/assets/common/js/thumbnails-update.js
index b37a32f3..3cd4c2a7 100644
--- a/assets/common/js/thumbnails-update.js
+++ b/assets/common/js/thumbnails-update.js
@@ -17,7 +17,7 @@
*/
function updateThumb(basePath, ids, i, elements) {
const xhr = new XMLHttpRequest();
- xhr.open('POST', `${basePath}/?do=ajax_thumb_update`);
+ xhr.open('PATCH', `${basePath}/admin/shaare/${ids[i]}/update-thumbnail`);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.responseType = 'json';
xhr.onload = () => {
@@ -30,14 +30,14 @@ function updateThumb(basePath, ids, i, elements) {
elements.current.innerHTML = i;
elements.title.innerHTML = response.title;
if (response.thumbnail !== false) {
- elements.thumbnail.innerHTML = ``;
+ elements.thumbnail.innerHTML = `
`;
}
if (i < ids.length) {
updateThumb(basePath, ids, i, elements);
}
}
};
- xhr.send(`id=${ids[i]}`);
+ xhr.send();
}
(() => {
diff --git a/index.php b/index.php
index 9202cb84..a07de74d 100644
--- a/index.php
+++ b/index.php
@@ -603,38 +603,14 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM
// -------- Thumbnails Update
if ($targetPage == Router::$PAGE_THUMBS_UPDATE) {
- $ids = [];
- foreach ($bookmarkService->search() as $bookmark) {
- // A note or not HTTP(S)
- if ($bookmark->isNote() || ! startsWith(strtolower($bookmark->getUrl()), 'http')) {
- continue;
- }
- $ids[] = $bookmark->getId();
- }
- $PAGE->assign('ids', $ids);
- $PAGE->assign('pagetitle', t('Thumbnails update') .' - '. $conf->get('general.title', 'Shaarli'));
- $PAGE->renderPage('thumbnails');
+ header('Location: ./admin/thumbnails');
exit;
}
// -------- Single Thumbnail Update
if ($targetPage == Router::$AJAX_THUMB_UPDATE) {
- if (! isset($_POST['id']) || ! ctype_digit($_POST['id'])) {
- http_response_code(400);
- exit;
- }
- $id = (int) $_POST['id'];
- if (! $bookmarkService->exists($id)) {
- http_response_code(404);
- exit;
- }
- $thumbnailer = new Thumbnailer($conf);
- $bookmark = $bookmarkService->get($id);
- $bookmark->setThumbnail($thumbnailer->get($bookmark->getUrl()));
- $bookmarkService->set($bookmark);
-
- $factory = new FormatterFactory($conf, $loginManager->isLoggedIn());
- echo json_encode($factory->getFormatter('raw')->format($bookmark));
+ // This route is no longer supported in legacy mode
+ http_response_code(404);
exit;
}
@@ -971,6 +947,10 @@ $app->group('', function () {
$this->get('/admin/shaare/delete', '\Shaarli\Front\Controller\Admin\ManageShaareController:deleteBookmark');
$this->get('/admin/shaare/visibility', '\Shaarli\Front\Controller\Admin\ManageShaareController:changeVisibility');
$this->get('/admin/shaare/{id:[0-9]+}/pin', '\Shaarli\Front\Controller\Admin\ManageShaareController:pinBookmark');
+ $this->patch(
+ '/admin/shaare/{id:[0-9]+}/update-thumbnail',
+ '\Shaarli\Front\Controller\Admin\ThumbnailsController:ajaxUpdate'
+ );
$this->get('/admin/export', '\Shaarli\Front\Controller\Admin\ExportController:index');
$this->post('/admin/export', '\Shaarli\Front\Controller\Admin\ExportController:export');
$this->get('/admin/import', '\Shaarli\Front\Controller\Admin\ImportController:index');
@@ -978,6 +958,7 @@ $app->group('', function () {
$this->get('/admin/plugins', '\Shaarli\Front\Controller\Admin\PluginsController:index');
$this->post('/admin/plugins', '\Shaarli\Front\Controller\Admin\PluginsController:save');
$this->get('/admin/token', '\Shaarli\Front\Controller\Admin\TokenController:getToken');
+ $this->get('/admin/thumbnails', '\Shaarli\Front\Controller\Admin\ThumbnailsController:index');
$this->get('/links-per-page', '\Shaarli\Front\Controller\Admin\SessionFilterController:linksPerPage');
$this->get('/visibility/{visibility}', '\Shaarli\Front\Controller\Admin\SessionFilterController:visibility');
diff --git a/tests/front/controller/admin/ThumbnailsControllerTest.php b/tests/front/controller/admin/ThumbnailsControllerTest.php
new file mode 100644
index 00000000..0c0c8a83
--- /dev/null
+++ b/tests/front/controller/admin/ThumbnailsControllerTest.php
@@ -0,0 +1,154 @@
+createContainer();
+
+ $this->controller = new ThumbnailsController($this->container);
+ }
+
+ /**
+ * Test displaying the thumbnails update page
+ * Note that only non-note and HTTP bookmarks should be returned.
+ */
+ public function testIndex(): void
+ {
+ $assignedVariables = [];
+ $this->assignTemplateVars($assignedVariables);
+
+ $request = $this->createMock(Request::class);
+ $response = new Response();
+
+ $this->container->bookmarkService
+ ->expects(static::once())
+ ->method('search')
+ ->willReturn([
+ (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'),
+ (new Bookmark())->setId(2)->setUrl('?abcdef')->setTitle('Note 1'),
+ (new Bookmark())->setId(3)->setUrl('http://url2.tld')->setTitle('Title 2'),
+ (new Bookmark())->setId(4)->setUrl('ftp://domain.tld', ['ftp'])->setTitle('FTP'),
+ ])
+ ;
+
+ $result = $this->controller->index($request, $response);
+
+ static::assertSame(200, $result->getStatusCode());
+ static::assertSame('thumbnails', (string) $result->getBody());
+
+ static::assertSame('Thumbnails update - Shaarli', $assignedVariables['pagetitle']);
+ static::assertSame([1, 3], $assignedVariables['ids']);
+ }
+
+ /**
+ * Test updating a bookmark thumbnail with valid parameters
+ */
+ public function testAjaxUpdateValid(): void
+ {
+ $request = $this->createMock(Request::class);
+ $response = new Response();
+
+ $bookmark = (new Bookmark())
+ ->setId($id = 123)
+ ->setUrl($url = 'http://url1.tld')
+ ->setTitle('Title 1')
+ ->setThumbnail(false)
+ ;
+
+ $this->container->thumbnailer = $this->createMock(Thumbnailer::class);
+ $this->container->thumbnailer
+ ->expects(static::once())
+ ->method('get')
+ ->with($url)
+ ->willReturn($thumb = 'http://img.tld/pic.png')
+ ;
+
+ $this->container->bookmarkService
+ ->expects(static::once())
+ ->method('get')
+ ->with($id)
+ ->willReturn($bookmark)
+ ;
+ $this->container->bookmarkService
+ ->expects(static::once())
+ ->method('set')
+ ->willReturnCallback(function (Bookmark $bookmark) use ($thumb) {
+ static::assertSame($thumb, $bookmark->getThumbnail());
+ })
+ ;
+
+ $result = $this->controller->ajaxUpdate($request, $response, ['id' => (string) $id]);
+
+ static::assertSame(200, $result->getStatusCode());
+
+ $payload = json_decode((string) $result->getBody(), true);
+
+ static::assertSame($id, $payload['id']);
+ static::assertSame($url, $payload['url']);
+ static::assertSame($thumb, $payload['thumbnail']);
+ }
+
+ /**
+ * Test updating a bookmark thumbnail - Invalid ID
+ */
+ public function testAjaxUpdateInvalidId(): void
+ {
+ $request = $this->createMock(Request::class);
+ $response = new Response();
+
+ $result = $this->controller->ajaxUpdate($request, $response, ['id' => 'nope']);
+
+ static::assertSame(400, $result->getStatusCode());
+ }
+
+ /**
+ * Test updating a bookmark thumbnail - No ID
+ */
+ public function testAjaxUpdateNoId(): void
+ {
+ $request = $this->createMock(Request::class);
+ $response = new Response();
+
+ $result = $this->controller->ajaxUpdate($request, $response, []);
+
+ static::assertSame(400, $result->getStatusCode());
+ }
+
+ /**
+ * Test updating a bookmark thumbnail with valid parameters
+ */
+ public function testAjaxUpdateBookmarkNotFound(): void
+ {
+ $id = 123;
+ $request = $this->createMock(Request::class);
+ $response = new Response();
+
+ $this->container->bookmarkService
+ ->expects(static::once())
+ ->method('get')
+ ->with($id)
+ ->willThrowException(new BookmarkNotFoundException())
+ ;
+
+ $result = $this->controller->ajaxUpdate($request, $response, ['id' => (string) $id]);
+
+ static::assertSame(404, $result->getStatusCode());
+ }
+}
diff --git a/tpl/default/configure.html b/tpl/default/configure.html
index fa1f7aa6..bb2564af 100644
--- a/tpl/default/configure.html
+++ b/tpl/default/configure.html
@@ -35,7 +35,7 @@
php-gd
to use thumbnails.'|t}
{elseif="$thumbnails_enabled"}
- {'Synchronize thumbnails'|t}
+ {'Synchronize thumbnails'|t}
{/if}
diff --git a/tpl/default/linklist.html b/tpl/default/linklist.html
index b0a5fdf2..8c1c2036 100644
--- a/tpl/default/linklist.html
+++ b/tpl/default/linklist.html
@@ -140,7 +140,7 @@
php-gd
to use thumbnails.'|t}
{elseif="$thumbnails_enabled"}
- {'Synchonize thumbnails'|t}
+ {'Synchonize thumbnails'|t}
{/if}