From b8aa20c3659275dbf18e5260791f142c4de19868 Mon Sep 17 00:00:00 2001
From: Georg Ringer <georg.ringer@gmail.com>
Date: Thu, 12 Oct 2017 13:20:24 +0200
Subject: [PATCH] [FEATURE] Show user who deleted a record in recycler

Add the user who deleted a record to the recycler information and also
show the avatar of the user.

Resolves: #69340
Releases: master
Change-Id: Id7d86d737b2759c6746baefa4b60659b6e9527eb
Reviewed-on: https://review.typo3.org/54379
Tested-by: TYPO3com <no-reply@typo3.com>
Tested-by: Riccardo De Contardi <erredeco@gmail.com>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
Reviewed-by: Joerg Boesche <typo3@joergboesche.de>
Tested-by: Joerg Boesche <typo3@joergboesche.de>
---
 ...-69340-ShowBackendUserWhoDeletedRecord.rst | 14 ++++
 .../Controller/DeletedRecordsController.php   | 70 ++++++++++++++++++-
 .../Resources/Private/Language/locallang.xlf  |  3 +
 .../Partials/RecordsTable/DeletedRecord.html  |  6 +-
 4 files changed, 90 insertions(+), 3 deletions(-)
 create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Feature-69340-ShowBackendUserWhoDeletedRecord.rst

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-69340-ShowBackendUserWhoDeletedRecord.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-69340-ShowBackendUserWhoDeletedRecord.rst
new file mode 100644
index 000000000000..419eec4ce35e
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-69340-ShowBackendUserWhoDeletedRecord.rst
@@ -0,0 +1,14 @@
+.. include:: ../../Includes.txt
+
+======================================================
+Feature: #69340 - Show backend user who deleted record
+======================================================
+
+See :issue:`69340`
+
+Description
+===========
+
+Improve the recycler output by showing also the backend user who deleted the record. Furthermore the avatar of the creator and the remover are shown.
+
+.. index:: Backend
diff --git a/typo3/sysext/recycler/Classes/Controller/DeletedRecordsController.php b/typo3/sysext/recycler/Classes/Controller/DeletedRecordsController.php
index 7c25727deb37..09b9e65ddb3e 100644
--- a/typo3/sysext/recycler/Classes/Controller/DeletedRecordsController.php
+++ b/typo3/sysext/recycler/Classes/Controller/DeletedRecordsController.php
@@ -1,4 +1,5 @@
 <?php
+
 namespace TYPO3\CMS\Recycler\Controller;
 
 /*
@@ -15,7 +16,9 @@ namespace TYPO3\CMS\Recycler\Controller;
  */
 
 use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\DataHandling\DataHandler;
+use TYPO3\CMS\Core\History\RecordHistoryStore;
 use TYPO3\CMS\Core\Imaging\Icon;
 use TYPO3\CMS\Core\Imaging\IconFactory;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -64,7 +67,10 @@ class DeletedRecordsController
                 $total += count($deletedRowsArray[$table]);
                 foreach ($rows as $row) {
                     $pageTitle = $this->getPageTitle((int)$row['pid']);
-                    $backendUser = BackendUtility::getRecord('be_users', $row[$GLOBALS['TCA'][$table]['ctrl']['cruser_id']], 'username', '', false);
+                    $backendUserName = $this->getBackendUser((int)$row[$GLOBALS['TCA'][$table]['ctrl']['cruser_id']]);
+
+                    $userIdWhoDeleted = $this->getUserWhoDeleted($table, (int)$row['uid']);
+
                     $jsonArray['rows'][] = [
                         'uid' => $row['uid'],
                         'pid' => $row['pid'],
@@ -73,11 +79,13 @@ class DeletedRecordsController
                         'table' => $table,
                         'crdate' => BackendUtility::datetime($row[$GLOBALS['TCA'][$table]['ctrl']['crdate']]),
                         'tstamp' => BackendUtility::datetime($row[$GLOBALS['TCA'][$table]['ctrl']['tstamp']]),
-                        'owner' => htmlspecialchars($backendUser['username']),
+                        'owner' => htmlspecialchars($backendUserName),
                         'owner_uid' => $row[$GLOBALS['TCA'][$table]['ctrl']['cruser_id']],
                         'tableTitle' => $lang->sL($GLOBALS['TCA'][$table]['ctrl']['title']),
                         'title' => htmlspecialchars(BackendUtility::getRecordTitle($table, $row)),
                         'path' => RecyclerUtility::getRecordPath($row['pid']),
+                        'delete_user_uid' => $userIdWhoDeleted,
+                        'delete_user' => $this->getBackendUser($userIdWhoDeleted),
                         'isParentDeleted' => $table === 'pages' ? RecyclerUtility::isParentPageDeleted($row['pid']) : false
                     ];
                 }
@@ -110,6 +118,64 @@ class DeletedRecordsController
         return $pageTitle;
     }
 
+    /**
+     * Gets the username of a given backend user
+     *
+     * @param int $userId uid of user
+     * @return string
+     */
+    protected function getBackendUser(int $userId): string
+    {
+        if ($userId === 0) {
+            return '';
+        }
+        $cacheId = 'recycler-user-' . $userId;
+        if ($this->runtimeCache->has($cacheId)) {
+            $username = $this->runtimeCache->get($cacheId);
+        } else {
+            $backendUser = BackendUtility::getRecord('be_users', $userId, 'username', '', false);
+            $username = $backendUser['username'];
+            $this->runtimeCache->set($cacheId, $username);
+        }
+        return $username;
+    }
+
+    /**
+     * Get the user uid of the user who deleted the record
+     *
+     * @param string $table table name
+     * @param int $uid uid of record
+     * @return int
+     */
+    protected function getUserWhoDeleted(string $table, int $uid): int
+    {
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getQueryBuilderForTable('sys_history');
+        $queryBuilder->select('userid')
+            ->from('sys_history')
+            ->where(
+                $queryBuilder->expr()->eq(
+                    'tablename',
+                    $queryBuilder->createNamedParameter($table, \PDO::PARAM_STR)
+                ),
+                $queryBuilder->expr()->eq(
+                    'usertype',
+                    $queryBuilder->createNamedParameter('BE', \PDO::PARAM_STR)
+                ),
+                $queryBuilder->expr()->eq(
+                    'recuid',
+                    $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
+                ),
+                $queryBuilder->expr()->eq(
+                    'actiontype',
+                    $queryBuilder->createNamedParameter(RecordHistoryStore::ACTION_DELETE, \PDO::PARAM_INT)
+                )
+            )
+            ->setMaxResults(1);
+
+        return (int)$queryBuilder->execute()->fetchColumn(0);
+    }
+
     /**
      * Returns an instance of LanguageService
      *
diff --git a/typo3/sysext/recycler/Resources/Private/Language/locallang.xlf b/typo3/sysext/recycler/Resources/Private/Language/locallang.xlf
index df7279921d39..e0812d710c31 100644
--- a/typo3/sysext/recycler/Resources/Private/Language/locallang.xlf
+++ b/typo3/sysext/recycler/Resources/Private/Language/locallang.xlf
@@ -117,6 +117,9 @@
 			<trans-unit id="table.header.owner">
 				<source>Owner</source>
 			</trans-unit>
+			<trans-unit id="table.header.deletedBy">
+				<source>Deleted by</source>
+			</trans-unit>
 			<trans-unit id="table.header.path">
 				<source>Path</source>
 			</trans-unit>
diff --git a/typo3/sysext/recycler/Resources/Private/Partials/RecordsTable/DeletedRecord.html b/typo3/sysext/recycler/Resources/Private/Partials/RecordsTable/DeletedRecord.html
index c42383d4f975..2f84bfafa79f 100644
--- a/typo3/sysext/recycler/Resources/Private/Partials/RecordsTable/DeletedRecord.html
+++ b/typo3/sysext/recycler/Resources/Private/Partials/RecordsTable/DeletedRecord.html
@@ -1,3 +1,4 @@
+<html xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers" data-namespace-typo3-fluid="true">
 <tr data-uid="{record.uid}" data-table="{record.table}" data-recordtitle="{record.title}" data-parent-deleted="{record.isParentDeleted}">
 	<td class="nowrap">
 		<label class="btn btn-default btn-checkbox">
@@ -36,6 +37,7 @@
 					<th><f:translate key="LLL:EXT:recycler/Resources/Private/Language/locallang.xlf:table.header.recordtype" /></th>
 					<th><f:translate key="LLL:EXT:recycler/Resources/Private/Language/locallang.xlf:table.header.crdate" /></th>
 					<th><f:translate key="LLL:EXT:recycler/Resources/Private/Language/locallang.xlf:table.header.owner" /></th>
+					<th><f:translate key="LLL:EXT:recycler/Resources/Private/Language/locallang.xlf:table.header.deletedBy" /></th>
 					<th><f:translate key="LLL:EXT:recycler/Resources/Private/Language/locallang.xlf:table.header.path" /></th>
 				</tr>
 			</thead>
@@ -43,10 +45,12 @@
 				<tr>
 					<td>{record.table}</td>
 					<td>{record.crdate}</td>
-					<td>{record.owner} ({record.owner_uid})</td>
+					<td><be:avatar backendUser="{record.owner_uid}" showIcon="true" />{record.owner} ({record.owner_uid})</td>
+					<td><f:if condition="{record.delete_user}"><be:avatar backendUser="{record.delete_user_uid}" showIcon="true" />{record.delete_user} ({record.delete_user_uid})</f:if></td>
 					<td><f:format.html>{record.path}</f:format.html></td>
 				</tr>
 			</tbody>
 		</table>
 	</td>
 </tr>
+</html>
-- 
GitLab