Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 4 additions & 141 deletions wcfsetup/install/files/acp/templates/attachmentList.tpl
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
{include file='header' pageTitle='wcf.acp.attachment.list'}

{include file='shared_imageViewer'}
<script data-relocate="true">
require(['WoltLabSuite/Core/Ui/User/Search/Input'], (UiUserSearchInput) => {
new UiUserSearchInput(document.getElementById('username'));
});
</script>

<header class="contentHeader">
<div class="contentHeaderTitle">
<h1 class="contentTitle">{lang}wcf.acp.attachment.list{/lang}{if $items} <span class="badge badgeInverse">{#$items}</span>{/if}</h1>
<h1 class="contentTitle">{lang}wcf.acp.attachment.list{/lang}</h1>
<p class="contentHeaderDescription">{lang}wcf.acp.attachment.stats{/lang}</p>
</div>

Expand All @@ -22,140 +17,8 @@
{/hascontent}
</header>

{include file='shared_formError'}

<form method="post" action="{link controller='AttachmentList'}{/link}">
<section class="section">
<h2 class="sectionTitle">{lang}wcf.global.filter{/lang}</h2>

<div class="row rowColGap formGrid">
<dl class="col-xs-12 col-md-3">
<dt></dt>
<dd>
<input type="number" id="attachmentID" name="attachmentID" value="{if $attachmentID}{$attachmentID}{/if}" placeholder="{lang}wcf.global.objectID{/lang}" class="long">
</dd>
</dl>

<dl class="col-xs-12 col-md-3">
<dt></dt>
<dd>
<input type="text" id="username" name="username" value="{$username}" placeholder="{lang}wcf.user.username{/lang}" class="long">
</dd>
</dl>

<dl class="col-xs-12 col-md-3">
<dt></dt>
<dd>
<input type="text" id="filename" name="filename" value="{$filename}" placeholder="{lang}wcf.attachment.filename{/lang}" class="long">
</dd>
</dl>

{if $availableFileTypes|count > 1}
<dl class="col-xs-12 col-md-3">
<dt></dt>
<dd>
<select name="fileType" id="fileType">
<option value="">{lang}wcf.attachment.fileType{/lang}</option>
{htmlOptions options=$availableFileTypes selected=$fileType}
</select>
</dd>
</dl>
{/if}

{event name='filterFields'}
</div>

<div class="formSubmit">
<input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
{csrfToken}
</div>
</section>
</form>

{hascontent}
<div class="paginationTop">
{content}
{assign var='linkParameters' value=''}
{if $username}{capture append=linkParameters}&username={@$username|rawurlencode}{/capture}{/if}
{if $filename}{capture append=linkParameters}&filename={@$filename|rawurlencode}{/capture}{/if}
{if $fileType}{capture append=linkParameters}&fileType={@$fileType|rawurlencode}{/capture}{/if}

{pages print=true assign=pagesLinks controller="AttachmentList" link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder$linkParameters"}
{/content}
</div>
{/hascontent}

{if $objects|count}
<div class="section tabularBox">
<table class="table jsObjectActionContainer" data-object-action-class-name="wcf\data\attachment\AttachmentAction"
<thead>
<tr>
<th class="columnID columnAttachmentID{if $sortField == 'attachmentID'} active {@$sortOrder}{/if}" colspan="2"><a href="{link controller='AttachmentList'}pageNo={@$pageNo}&sortField=attachmentID&sortOrder={if $sortField == 'attachmentID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$linkParameters}{/link}">{lang}wcf.global.objectID{/lang}</a></th>
<th class="columnTitle columnFilename{if $sortField == 'filename'} active {@$sortOrder}{/if}"><a href="{link controller='AttachmentList'}pageNo={@$pageNo}&sortField=filename&sortOrder={if $sortField == 'filename' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$linkParameters}{/link}">{lang}wcf.attachment.filename{/lang}</a></th>
<th class="columnDate columnUploadTime{if $sortField == 'uploadTime'} active {@$sortOrder}{/if}"><a href="{link controller='AttachmentList'}pageNo={@$pageNo}&sortField=uploadTime&sortOrder={if $sortField == 'uploadTime' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$linkParameters}{/link}">{lang}wcf.attachment.uploadTime{/lang}</a></th>
<th class="columnDigits columnFilesize{if $sortField == 'filesize'} active {@$sortOrder}{/if}"><a href="{link controller='AttachmentList'}pageNo={@$pageNo}&sortField=filesize&sortOrder={if $sortField == 'filesize' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$linkParameters}{/link}">{lang}wcf.attachment.filesize{/lang}</a></th>
<th class="columnDigits columnDownloads{if $sortField == 'downloads'} active {@$sortOrder}{/if}"><a href="{link controller='AttachmentList'}pageNo={@$pageNo}&sortField=downloads&sortOrder={if $sortField == 'downloads' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$linkParameters}{/link}">{lang}wcf.attachment.downloads{/lang}</a></th>
<th class="columnDate columnLastDownloadTime{if $sortField == 'lastDownloadTime'} active {@$sortOrder}{/if}"><a href="{link controller='AttachmentList'}pageNo={@$pageNo}&sortField=lastDownloadTime&sortOrder={if $sortField == 'lastDownloadTime' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{@$linkParameters}{/link}">{lang}wcf.attachment.lastDownloadTime{/lang}</a></th>

{event name='columnHeads'}
</tr>
</thead>

<tbody class="jsReloadPageWhenEmpty">
{foreach from=$objects item=attachment}
<tr class="jsAttachmentRow jsObjectActionObject" data-object-id="{@$attachment->getObjectID()}">
<td class="columnIcon">
{objectAction action="delete" objectTitle=$attachment->filename|tableWordwrap}

{event name='rowButtons'}
</td>
<td class="columnID columnAttachmentID">{@$attachment->attachmentID}</td>
<td class="columnTitle columnFilename">
<div class="box64">
<a href="{$attachment->getLink()}"{if $attachment->isImage} data-fancybox="attachments" data-caption="{$attachment->filename}"{/if}>
{if $attachment->tinyThumbnailType}
<img src="{$attachment->getThumbnailLink('tiny')}" class="attachmentTinyThumbnail" alt="">
{else}
{icon size=64 name=$attachment->getIconName()}
{/if}
</a>

<div>
<p><a href="{$attachment->getLink()}">{$attachment->filename|tableWordwrap}</a></p>
<p><small>{if $attachment->userID}{if $__wcf->session->getPermission('admin.user.canEditUser')}<a href="{link controller='UserEdit' id=$attachment->userID}{/link}">{$attachment->username}</a>{else}{$attachment->username}{/if}{else}{lang}wcf.user.guest{/lang}{/if}</small></p>
{if $attachment->getContainerObject()}<p><small><a href="{$attachment->getContainerObject()->getLink()}">{$attachment->getContainerObject()->getTitle()|tableWordwrap}</a></small></p>{/if}
</div>
</div>
</td>
<td class="columnDate columnUploadTime">{@$attachment->uploadTime|time}</td>
<td class="columnDigits columnFilesize">{@$attachment->filesize|filesize}</td>
<td class="columnDigits columnDownloads">{if $attachment->downloads}{#$attachment->downloads}{/if}</td>
<td class="columnDate columnLastDownloadTime">{if $attachment->lastDownloadTime}{@$attachment->lastDownloadTime|time}{/if}</td>

{event name='columns'}
</tr>
{/foreach}
</tbody>
</table>
</div>

<footer class="contentFooter">
{hascontent}
<div class="paginationBottom">
{content}{@$pagesLinks}{/content}
</div>
{/hascontent}

{hascontent}
<nav class="contentFooterNavigation">
<ul>
{content}{event name='contentFooterNavigation'}{/content}
</ul>
</nav>
{/hascontent}
</footer>
{else}
<woltlab-core-notice type="info">{lang}wcf.global.noItems{/lang}</woltlab-core-notice>
{/if}
<div class="section">
{unsafe:$gridView->render()}
</div>

{include file='footer'}
161 changes: 26 additions & 135 deletions wcfsetup/install/files/lib/acp/page/AttachmentListPage.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,20 @@

namespace wcf\acp\page;

use wcf\data\attachment\AdministrativeAttachmentList;
use wcf\data\object\type\ObjectTypeCache;
use wcf\data\user\User;
use wcf\page\SortablePage;
use wcf\page\AbstractGridViewPage;
use wcf\system\gridView\admin\AttachmentGridView;
use wcf\system\WCF;
use wcf\util\StringUtil;

/**
* Shows a list of attachments.
*
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @author Olaf Braun, Marcel Werk
* @copyright 2001-2025 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
*
* @property AdministrativeAttachmentList $objectList
* @property AttachmentGridView $gridView
*/
class AttachmentListPage extends SortablePage
class AttachmentListPage extends AbstractGridViewPage
{
/**
* @inheritDoc
Expand All @@ -30,139 +27,33 @@ class AttachmentListPage extends SortablePage
*/
public $neededPermissions = ['admin.attachment.canManageAttachment'];

/**
* @inheritDoc
*/
public $defaultSortField = 'uploadTime';

/**
* @inheritDoc
*/
public $defaultSortOrder = 'DESC';

/**
* @inheritDoc
*/
public $validSortFields = ['attachmentID', 'filename', 'filesize', 'downloads', 'uploadTime', 'lastDownloadTime'];

/**
* @inheritDoc
*/
public $objectListClassName = AdministrativeAttachmentList::class;

/**
* username
* @var string
*/
public $username = '';

/**
* filename
* @var string
*/
public $filename = '';

/**
* file type
* @var string
*/
public $fileType = '';

/**
* available file types
* @var string[]
*/
public $availableFileTypes = [];

/**
* @var int
*/
public $attachmentID = 0;

/**
* attachment stats
* @var array
*/
public $stats = [];

/**
* @inheritDoc
*/
public function readParameters()
#[\Override]
protected function createGridViewController(): AttachmentGridView
{
parent::readParameters();

if (!empty($_REQUEST['username'])) {
$this->username = StringUtil::trim($_REQUEST['username']);
}
if (!empty($_REQUEST['filename'])) {
$this->filename = StringUtil::trim($_REQUEST['filename']);
}
if (!empty($_REQUEST['fileType'])) {
$this->fileType = $_REQUEST['fileType'];
}
if (!empty($_REQUEST['attachmentID'])) {
$this->attachmentID = \intval($_REQUEST['attachmentID']);
}
return new AttachmentGridView();
}

/**
* @inheritDoc
*/
protected function initObjectList()
{
parent::initObjectList();

$objectTypeIDs = [];
foreach (ObjectTypeCache::getInstance()->getObjectTypes('com.woltlab.wcf.attachment.objectType') as $objectType) {
if (!$objectType->private) {
$objectTypeIDs[] = $objectType->objectTypeID;
}
}

if (!empty($objectTypeIDs)) {
$this->objectList->getConditionBuilder()->add('attachment.objectTypeID IN (?)', [$objectTypeIDs]);
} else {
$this->objectList->getConditionBuilder()->add('1 = 0');
}
$this->objectList->getConditionBuilder()->add("attachment.tmpHash = ''");

// get data
$this->stats = $this->objectList->getStats();
$this->availableFileTypes = $this->objectList->getAvailableFileTypes();

// filter
if (!empty($this->username)) {
$user = User::getUserByUsername($this->username);
if ($user->userID) {
$this->objectList->getConditionBuilder()->add('attachment.userID = ?', [$user->userID]);
}
}
if (!empty($this->filename)) {
$this->objectList->getConditionBuilder()->add('attachment.filename LIKE ?', [$this->filename . '%']);
}
if (!empty($this->fileType)) {
$this->objectList->getConditionBuilder()->add('attachment.fileType LIKE ?', [$this->fileType]);
}
if ($this->attachmentID) {
$this->objectList->getConditionBuilder()->add('attachment.attachmentID = ?', [$this->attachmentID]);
}
}

/**
* @inheritDoc
*/
#[\Override]
public function assignVariables()
{
parent::assignVariables();

WCF::getTPL()->assign([
'stats' => $this->stats,
'username' => $this->username,
'filename' => $this->filename,
'fileType' => $this->fileType,
'availableFileTypes' => $this->availableFileTypes,
'attachmentID' => $this->attachmentID,
'stats' => $this->getAttachmentStats()
]);
}

private function getAttachmentStats(): array
{
$sql = "SELECT COUNT(*) AS count,
COALESCE(SUM(file.fileSize), 0) AS size,
COALESCE(SUM(downloads), 0) AS downloads
FROM wcf1_attachment attachment
LEFT JOIN wcf1_file file
ON (file.fileID = attachment.fileID)";
$statement = WCF::getDB()->prepare($sql);
$statement->execute();

return $statement->fetchArray();
}
}
1 change: 1 addition & 0 deletions wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ static function (\wcf\event\endpoint\ControllerCollecting $event) {
$event->register(new \wcf\system\endpoint\controller\core\articles\RestoreArticle());
$event->register(new \wcf\system\endpoint\controller\core\articles\PublishArticle());
$event->register(new \wcf\system\endpoint\controller\core\articles\UnpublishArticle());
$event->register(new \wcf\system\endpoint\controller\core\attachments\DeleteAttachment());
}
);

Expand Down
Loading