From 736dc129a2497eb4b9cfc07c4c9feafa665e4e84 Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Wed, 8 May 2024 11:30:03 +0200 Subject: [PATCH] Add support for download tracking This partially reverts the changes made in bde83e6b8fc090654deaac827b342cea0b69695d --- .../files/acp/templates/attachmentList.tpl | 4 ++++ .../lib/acp/page/AttachmentListPage.class.php | 2 +- .../lib/action/FileDownloadAction.class.php | 2 ++ .../lib/data/attachment/Attachment.class.php | 24 +++++++++++-------- .../files/lib/data/file/File.class.php | 7 +++++- .../processor/AbstractFileProcessor.class.php | 6 +++++ .../AttachmentFileProcessor.class.php | 14 +++++++++++ .../file/processor/IFileProcessor.class.php | 6 +++++ wcfsetup/install/lang/de.xml | 2 ++ wcfsetup/install/lang/en.xml | 2 ++ 10 files changed, 57 insertions(+), 12 deletions(-) diff --git a/wcfsetup/install/files/acp/templates/attachmentList.tpl b/wcfsetup/install/files/acp/templates/attachmentList.tpl index b5a71d5d76..df3f858bc3 100644 --- a/wcfsetup/install/files/acp/templates/attachmentList.tpl +++ b/wcfsetup/install/files/acp/templates/attachmentList.tpl @@ -95,6 +95,8 @@ {lang}wcf.attachment.filename{/lang} {lang}wcf.attachment.uploadTime{/lang} {lang}wcf.attachment.filesize{/lang} + {lang}wcf.attachment.downloads{/lang} + {lang}wcf.attachment.lastDownloadTime{/lang} {event name='columnHeads'} @@ -128,6 +130,8 @@ {@$attachment->uploadTime|time} {@$attachment->filesize|filesize} + {if $attachment->downloads}{#$attachment->downloads}{/if} + {if $attachment->lastDownloadTime}{@$attachment->lastDownloadTime|time}{/if} {event name='columns'} diff --git a/wcfsetup/install/files/lib/acp/page/AttachmentListPage.class.php b/wcfsetup/install/files/lib/acp/page/AttachmentListPage.class.php index 71b4ebf810..4bd75017b9 100644 --- a/wcfsetup/install/files/lib/acp/page/AttachmentListPage.class.php +++ b/wcfsetup/install/files/lib/acp/page/AttachmentListPage.class.php @@ -43,7 +43,7 @@ class AttachmentListPage extends SortablePage /** * @inheritDoc */ - public $validSortFields = ['attachmentID', 'filename', 'filesize', 'uploadTime']; + public $validSortFields = ['attachmentID', 'filename', 'filesize', 'downloads', 'uploadTime', 'lastDownloadTime']; /** * @inheritDoc diff --git a/wcfsetup/install/files/lib/action/FileDownloadAction.class.php b/wcfsetup/install/files/lib/action/FileDownloadAction.class.php index efc42466bc..c699957c2f 100644 --- a/wcfsetup/install/files/lib/action/FileDownloadAction.class.php +++ b/wcfsetup/install/files/lib/action/FileDownloadAction.class.php @@ -49,6 +49,8 @@ final class FileDownloadAction implements RequestHandlerInterface throw new PermissionDeniedException(); } + $processor->trackDownload($file); + $filename = $file->getPathname(); $response = new Response( new Stream($filename), diff --git a/wcfsetup/install/files/lib/data/attachment/Attachment.class.php b/wcfsetup/install/files/lib/data/attachment/Attachment.class.php index 6ede598500..e601e96de9 100644 --- a/wcfsetup/install/files/lib/data/attachment/Attachment.class.php +++ b/wcfsetup/install/files/lib/data/attachment/Attachment.class.php @@ -38,6 +38,8 @@ use wcf\util\FileUtil; * @property-read int $tinyThumbnailHeight height of the tiny thumbnail file for the attachment if `$isImage` is `1`, otherwise `0` * @property-read string $thumbnailType type of the thumbnail file for the attachment if `$isImage` is `1`, otherwise empty * @property-read int $thumbnailSize size of the thumbnail file for the attachment if `$isImage` is `1`, otherwise `0` + * @property-read int $downloads number of times the attachment has been downloaded + * @property-read int $lastDownloadTime timestamp at which the attachment has been downloaded the last time * @property-read int $thumbnailWidth width of the thumbnail file for the attachment if `$isImage` is `1`, otherwise `0` * @property-read int $thumbnailHeight height of the thumbnail file for the attachment if `$isImage` is `1`, otherwise `0` * @property-read int $uploadTime timestamp at which the attachment has been uploaded @@ -386,21 +388,23 @@ class Attachment extends DatabaseObject implements ILinkableObject, IRouteContro #[\Override] public function __get($name) { - // Deprecated attributes that are no longer supported. - $value = match ($name) { - 'downloads' => 0, - 'lastDownloadTime' => 0, - default => null, - }; - if ($value !== null) { - return $value; - } - $file = $this->getFile(); if ($file === null) { return parent::__get($name); } + if ($name === 'downloads' || $name === 'lastDownloadTime') { + // Static files are no longer served through PHP but the web server + // instead, therefore we can no longer report any meaningful numbers. + // + // For existing files the stored value is suppressed because it is + // not going to be increased ever, possibly creating a false + // impression when the historic stored value is being reported. + if ($file->isStaticFile()) { + return 0; + } + } + return match ($name) { 'filename' => $file->filename, 'filesize' => $file->fileSize, diff --git a/wcfsetup/install/files/lib/data/file/File.class.php b/wcfsetup/install/files/lib/data/file/File.class.php index 8dd234f83d..4e5b8d02a4 100644 --- a/wcfsetup/install/files/lib/data/file/File.class.php +++ b/wcfsetup/install/files/lib/data/file/File.class.php @@ -78,7 +78,7 @@ class File extends DatabaseObject return \sprintf( \WCF_DIR . '_data/%s/files/%s/%s/', - $this->fileExtension === 'bin' ? 'private' : 'public', + $this->isStaticFile() ? 'public' : 'private', $folderA, $folderB, ); @@ -113,6 +113,11 @@ class File extends DatabaseObject }; } + public function isStaticFile(): bool + { + return $this->fileExtension !== 'bin'; + } + public function canDelete(): bool { $processor = $this->getProcessor(); diff --git a/wcfsetup/install/files/lib/system/file/processor/AbstractFileProcessor.class.php b/wcfsetup/install/files/lib/system/file/processor/AbstractFileProcessor.class.php index 305631583f..6511fed16d 100644 --- a/wcfsetup/install/files/lib/system/file/processor/AbstractFileProcessor.class.php +++ b/wcfsetup/install/files/lib/system/file/processor/AbstractFileProcessor.class.php @@ -49,4 +49,10 @@ abstract class AbstractFileProcessor implements IFileProcessor // There is usually no need for meta data to be sent to the client. return []; } + + #[\Override] + public function trackDownload(File $file): void + { + // Do not track downloads. + } } diff --git a/wcfsetup/install/files/lib/system/file/processor/AttachmentFileProcessor.class.php b/wcfsetup/install/files/lib/system/file/processor/AttachmentFileProcessor.class.php index 98afb972f6..a849b49115 100644 --- a/wcfsetup/install/files/lib/system/file/processor/AttachmentFileProcessor.class.php +++ b/wcfsetup/install/files/lib/system/file/processor/AttachmentFileProcessor.class.php @@ -193,6 +193,20 @@ final class AttachmentFileProcessor extends AbstractFileProcessor (new AttachmentAction($fileIDs, 'delete'))->executeAction(); } + #[\Override] + public function trackDownload(File $file): void + { + $attachment = Attachment::findByFileID($file->fileID); + if ($attachment === null) { + return; + } + + (new AttachmentEditor($attachment))->update([ + 'downloads' => $attachment->downloads, + 'lastDownloadTime' => \TIME_NOW, + ]); + } + private function getAttachmentHandlerFromContext(array $context): ?AttachmentHandler { try { diff --git a/wcfsetup/install/files/lib/system/file/processor/IFileProcessor.class.php b/wcfsetup/install/files/lib/system/file/processor/IFileProcessor.class.php index d23496ebaa..0fdb5ae120 100644 --- a/wcfsetup/install/files/lib/system/file/processor/IFileProcessor.class.php +++ b/wcfsetup/install/files/lib/system/file/processor/IFileProcessor.class.php @@ -98,4 +98,10 @@ interface IFileProcessor * the client. */ public function getUploadResponse(File $file): array; + + /** + * Invoked whenever a file is being downloaded. This does not work for some + * file types that are served by the web server itself. + */ + public function trackDownload(File $file): void; } diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml index 5b3a865e2c..ea5ff65282 100644 --- a/wcfsetup/install/lang/de.xml +++ b/wcfsetup/install/lang/de.xml @@ -3351,6 +3351,8 @@ Erlaubte Dateiendungen: {', '|implode:$attachmentHandler->getFormattedAllowedExt + + diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml index d5c418662b..01bf3ba4c0 100644 --- a/wcfsetup/install/lang/en.xml +++ b/wcfsetup/install/lang/en.xml @@ -3276,6 +3276,8 @@ Allowed extensions: {', '|implode:$attachmentHandler->getFormattedAllowedExtensi + + -- 2.20.1