From 83436367dfede884e82011fb415c4af658ad23da Mon Sep 17 00:00:00 2001
From: Christian Kuhn <lolli@schwarzbu.ch>
Date: Sun, 20 Aug 2017 13:24:05 +0200
Subject: [PATCH] [TASK] Install tool: Improve 'clear tables' view

Refactor the 'clear tables' view of the install tool:
* Main content is loaded on opening the card via ajax
* Tables with 0 rows are no longer shown
* Refresh view after 'clear this table' ajax action has been clicked

Change-Id: I8608e6561eaf9d0ae06da8e27b25c5ce879a5b62
Resolves: #82136
Related: #76084
Releases: master
Reviewed-on: https://review.typo3.org/53743
Tested-by: TYPO3com <no-reply@typo3.com>
Tested-by: Mona Muzaffar <mona.muzaffar@gmx.de>
Reviewed-by: Mona Muzaffar <mona.muzaffar@gmx.de>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Jan Stockfisch <jan.stockfisch@googlemail.com>
Tested-by: Jan Stockfisch <jan.stockfisch@googlemail.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
---
 .../{ClearTable.php => ClearTablesClear.php}  |   3 +-
 .../Action/Ajax/ClearTablesStats.php          |  39 ++++++
 .../Controller/Action/Tool/Maintenance.php    |   4 +-
 .../Classes/Controller/AjaxController.php     |   3 +-
 .../Action/Tool/Maintenance/ClearTables.html  |  42 +++---
 .../Templates/Action/Tool/Maintenance.html    |   4 +-
 .../Public/JavaScript/Modules/ClearTable.js   |  69 ---------
 .../Public/JavaScript/Modules/ClearTables.js  | 131 ++++++++++++++++++
 8 files changed, 200 insertions(+), 95 deletions(-)
 rename typo3/sysext/install/Classes/Controller/Action/Ajax/{ClearTable.php => ClearTablesClear.php} (96%)
 create mode 100644 typo3/sysext/install/Classes/Controller/Action/Ajax/ClearTablesStats.php
 delete mode 100644 typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTable.js
 create mode 100644 typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTables.js

diff --git a/typo3/sysext/install/Classes/Controller/Action/Ajax/ClearTable.php b/typo3/sysext/install/Classes/Controller/Action/Ajax/ClearTablesClear.php
similarity index 96%
rename from typo3/sysext/install/Classes/Controller/Action/Ajax/ClearTable.php
rename to typo3/sysext/install/Classes/Controller/Action/Ajax/ClearTablesClear.php
index f459823513ed..d4213e4e07f2 100644
--- a/typo3/sysext/install/Classes/Controller/Action/Ajax/ClearTable.php
+++ b/typo3/sysext/install/Classes/Controller/Action/Ajax/ClearTablesClear.php
@@ -21,7 +21,7 @@ use TYPO3\CMS\Install\Status\OkStatus;
 /**
  * Truncate a given table via ClearTableService
  */
-class ClearTable extends AbstractAjaxAction
+class ClearTablesClear extends AbstractAjaxAction
 {
     /**
      * Executes the action
@@ -47,7 +47,6 @@ class ClearTable extends AbstractAjaxAction
             'success' => true,
             'status' => $messages,
         ]);
-
         return $this->view->render();
     }
 }
diff --git a/typo3/sysext/install/Classes/Controller/Action/Ajax/ClearTablesStats.php b/typo3/sysext/install/Classes/Controller/Action/Ajax/ClearTablesStats.php
new file mode 100644
index 000000000000..8724e6b3c274
--- /dev/null
+++ b/typo3/sysext/install/Classes/Controller/Action/Ajax/ClearTablesStats.php
@@ -0,0 +1,39 @@
+<?php
+declare(strict_types=1);
+namespace TYPO3\CMS\Install\Controller\Action\Ajax;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Install\Service\ClearTableService;
+
+/**
+ * Get "clear table" stats
+ */
+class ClearTablesStats extends AbstractAjaxAction
+{
+    /**
+     * Executes the action
+     *
+     * @return array Rendered content
+     * @throws \RuntimeException
+     */
+    protected function executeAction(): array
+    {
+        $this->view->assignMultiple([
+            'success' => true,
+            'stats' => (new ClearTableService())->getTableStatistics(),
+        ]);
+        return $this->view->render();
+    }
+}
diff --git a/typo3/sysext/install/Classes/Controller/Action/Tool/Maintenance.php b/typo3/sysext/install/Classes/Controller/Action/Tool/Maintenance.php
index 19767e387f2b..3b3520bb479c 100644
--- a/typo3/sysext/install/Classes/Controller/Action/Tool/Maintenance.php
+++ b/typo3/sysext/install/Classes/Controller/Action/Tool/Maintenance.php
@@ -19,7 +19,6 @@ use TYPO3\CMS\Core\FormProtection\FormProtectionFactory;
 use TYPO3\CMS\Core\FormProtection\InstallToolFormProtection;
 use TYPO3\CMS\Core\Service\OpcodeCacheService;
 use TYPO3\CMS\Install\Controller\Action\AbstractAction;
-use TYPO3\CMS\Install\Service\ClearTableService;
 use TYPO3\CMS\Install\Service\Typo3tempFileService;
 
 /**
@@ -37,8 +36,7 @@ class Maintenance extends AbstractAction
         $formProtection = FormProtectionFactory::get(InstallToolFormProtection::class);
         $this->view->assignMultiple([
             'clearAllCacheOpcodeCaches' => (new OpcodeCacheService())->getAllActive(),
-            'clearTableStats' => (new ClearTableService())->getTableStatistics(),
-            'clearTableToken' => $formProtection->generateToken('installTool', 'clearTable'),
+            'clearTablesClearToken' => $formProtection->generateToken('installTool', 'clearTablesClear'),
             'clearTypo3tempFilesStats' => (new Typo3tempFileService())->getDirectoryStatistics(),
             'clearTypo3tempFilesToken' => $formProtection->generateToken('installTool', 'clearTypo3tempFiles'),
             'createAdminToken' => $formProtection->generateToken('installTool', 'createAdmin'),
diff --git a/typo3/sysext/install/Classes/Controller/AjaxController.php b/typo3/sysext/install/Classes/Controller/AjaxController.php
index 16f828eda5ad..ccf2b6a0d5d7 100644
--- a/typo3/sysext/install/Classes/Controller/AjaxController.php
+++ b/typo3/sysext/install/Classes/Controller/AjaxController.php
@@ -32,7 +32,8 @@ class AjaxController extends AbstractController
     protected $authenticationActions = [
         'changeInstallToolPassword',
         'clearAllCache',
-        'clearTable',
+        'clearTablesClear',
+        'clearTablesStats',
         'clearTypo3tempFiles',
 
         'coreUpdateActivate',
diff --git a/typo3/sysext/install/Resources/Private/Partials/Action/Tool/Maintenance/ClearTables.html b/typo3/sysext/install/Resources/Private/Partials/Action/Tool/Maintenance/ClearTables.html
index 6db6faf56a3e..8a45f3a0fe0e 100644
--- a/typo3/sysext/install/Resources/Private/Partials/Action/Tool/Maintenance/ClearTables.html
+++ b/typo3/sysext/install/Resources/Private/Partials/Action/Tool/Maintenance/ClearTables.html
@@ -8,26 +8,32 @@
 	Use with care! Clearing tables here can have a negative impact on your site functionality.
 	You could log out all users, delete all their basket data, and lose logging information!
 </p>
+
+<div class="t3js-clearTables-output"></div>
+
+<button
+	class="btn btn-default t3js-clearTables-stats"
+	type="button"
+>
+	Scan again
+</button>
 <hr>
 
-<div style="display:none;">
-	<div id="t3js-clearTable-token">{clearTableToken}</div>
+<div class="form-group">
+	<div class="t3js-clearTables-stat-container"></div>
 </div>
 
-<div class="form-group">
-	<f:for each="{clearTableStats}" as="clearTableStatistic" iteration="iterator">
-		<div class="t3js-clearTable-container t3js-clearTable-container-{clearTableStatistic.name}">
-			<p>{clearTableStatistic.description}</p>
-			<div class="t3js-clearTable-output"></div>
-			<button
-				class="btn btn-default t3js-clearTable-clear" data-table="{clearTableStatistic.name}"
-				type="button"
-			>
-				Delete {clearTableStatistic.rowCount} rows from "{clearTableStatistic.name}" table
-			</button>
-			<f:if condition="!{iterator.isLast}">
-				<hr>
-			</f:if>
-		</div>
-	</f:for>
+<div style="display:none;">
+	<div id="t3js-clearTables-clear-token">{clearTablesClearToken}</div>
+	<div class="t3js-clearTables-stat-template">
+		<p class="t3js-clearTables-stat-description">{clearTableStatistic.description}</p>
+		<button
+			class="btn btn-default t3js-clearTables-clear"
+			type="button"
+		>
+			Delete <span class="t3js-clearTables-stat-rows"></span> rows
+			from table "<span class="t3js-clearTables-stat-name"></span>" table
+		</button>
+		<hr class="t3js-clearTables-stat-lastRuler">
+	</div>
 </div>
diff --git a/typo3/sysext/install/Resources/Private/Templates/Action/Tool/Maintenance.html b/typo3/sysext/install/Resources/Private/Templates/Action/Tool/Maintenance.html
index 5d9cc8681688..a20da8a98f39 100644
--- a/typo3/sysext/install/Resources/Private/Templates/Action/Tool/Maintenance.html
+++ b/typo3/sysext/install/Resources/Private/Templates/Action/Tool/Maintenance.html
@@ -37,8 +37,8 @@
 			description: 'Verify and update database status.'
 		},
 		4: {partial: 'Action/Tool/Maintenance/ClearTables',
-			require: 'TYPO3/CMS/Install/ClearTable',
-			baseClass: 't3js-clearTable',
+			require: 'TYPO3/CMS/Install/ClearTables',
+			baseClass: 't3js-clearTables',
 			title: 'Clear Tables',
 			category: 'Database',
 			description: 'Clears semi-temporary data from database tables.'
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTable.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTable.js
deleted file mode 100644
index eb99ecb8a437..000000000000
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTable.js
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * Module: TYPO3/CMS/Install/ClearTable
- */
-define(['jquery', 'TYPO3/CMS/Install/FlashMessage', 'TYPO3/CMS/Install/ProgressBar', 'TYPO3/CMS/Install/InfoBox', 'TYPO3/CMS/Install/Severity'], function($, FlashMessage, ProgressBar, InfoBox, Severity) {
-	'use strict';
-
-	return {
-		selectorClearToken: '#t3js-clearTable-token',
-		selectorClearTrigger: '.t3js-clearTable-clear',
-		selectorOutputContainer: '.t3js-clearTable-output',
-
-		initialize: function() {
-			var self = this;
-			$(document).on('click', this.selectorClearTrigger, function(e) {
-				var table = $(e.target).data('table');
-				e.preventDefault();
-				self.clear(table);
-			});
-		},
-
-		clear: function(table) {
-			var token = $(this.selectorClearToken).text();
-			var url = location.href + '&install[controller]=ajax';
-			var postData = {
-				'install': {
-					'action': 'clearTable',
-					'token': token,
-					'table': table
-				}
-			};
-			var $container = $('.t3js-clearTable-container-' + table);
-			var $outputContainer = $container.find(this.selectorOutputContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().html(message);
-			$.ajax({
-				method: 'POST',
-				data: postData,
-				url: url,
-				cache: false,
-				success: function(data) {
-					$outputContainer.empty();
-					if (data.success === true && Array.isArray(data.status)) {
-						data.status.forEach(function(element) {
-							var message = InfoBox.render(element.severity, element.title, element.message);
-							$outputContainer.html(message);
-						});
-					}
-				},
-				error: function () {
-					var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-					$outputContainer.empty().html(message);
-				}
-			});
-		}
-	};
-});
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTables.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTables.js
new file mode 100644
index 000000000000..b751a15b44e2
--- /dev/null
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTables.js
@@ -0,0 +1,131 @@
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * Module: TYPO3/CMS/Install/ClearTable
+ */
+define([
+	'jquery',
+	'TYPO3/CMS/Install/FlashMessage',
+	'TYPO3/CMS/Install/ProgressBar',
+	'TYPO3/CMS/Install/InfoBox',
+	'TYPO3/CMS/Install/Severity'
+], function($, FlashMessage, ProgressBar, InfoBox, Severity) {
+	'use strict';
+
+	return {
+		selectorGridderOpener: '.t3js-clearTables-open',
+		selectorClearToken: '#t3js-clearTables-clear-token',
+		selectorClearTrigger: '.t3js-clearTables-clear',
+		selectorStatsTrigger: '.t3js-clearTables-stats',
+		selectorOutputContainer: '.t3js-clearTables-output',
+		selectorStatContainer: 't3js-clearTables-stat-container',
+		selectorStatTemplate: '.t3js-clearTables-stat-template',
+		selectorStatDescription: '.t3js-clearTables-stat-description',
+		selectorStatRows: '.t3js-clearTables-stat-rows',
+		selectorStatName: '.t3js-clearTables-stat-name',
+		selectorStatLastRuler: '.t3js-clearTables-stat-lastRuler',
+
+		initialize: function() {
+			var self = this;
+
+			// Load stats on first open
+			$(document).on('click', this.selectorGridderOpener, function(event) {
+				var $element = $(event.target).closest(self.selectorGridderOpener);
+				if (!$element.data('isInitialized')) {
+					$element.data('isInitialized', true);
+					self.getStats();
+				}
+			});
+
+			$(document).on('click', this.selectorStatsTrigger, function(e) {
+				e.preventDefault();
+				$(self.selectorOutputContainer).empty();
+				self.getStats();
+			});
+
+			$(document).on('click', this.selectorClearTrigger, function(e) {
+				var table = $(e.target).closest(self.selectorClearTrigger).data('table');
+				e.preventDefault();
+				self.clear(table);
+				self.getStats();
+			});
+		},
+
+		getStats: function() {
+			var self = this;
+			var url = location.href + '&install[controller]=ajax&install[action]=clearTablesStats';
+			var $outputContainer = $(this.selectorOutputContainer);
+			var $statContainer = $('.' + this.selectorStatContainer);
+			$statContainer.empty();
+			var $statTemplate = $(this.selectorStatTemplate);
+			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+			$outputContainer.append(message);
+			$.ajax({
+				url: url,
+				cache: false,
+				success: function (data) {
+					if (data.success === true) {
+						$outputContainer.find('.alert-loading').remove();
+						if (Array.isArray(data.stats) && data.stats.length > 0) {
+							data.stats.forEach(function(element) {
+								if (element.rowCount > 0) {
+									var $aStat = $statTemplate.clone();
+									$aStat.find(self.selectorStatDescription).text(element.description);
+									$aStat.find(self.selectorStatName).text(element.name);
+									$aStat.find(self.selectorStatRows).text(element.rowCount);
+									$aStat.find(self.selectorClearTrigger).data('table', element.name);
+									$statContainer.append($aStat);
+								}
+							});
+							$statContainer.find(self.selectorStatLastRuler + ':last').remove();
+						}
+					}
+				}
+			});
+		},
+
+		clear: function(table) {
+			var url = location.href + '&install[controller]=ajax';
+			var postData = {
+				'install': {
+					'action': 'clearTablesClear',
+					'token': $(this.selectorClearToken).text(),
+					'table': table
+				}
+			};
+			var $outputContainer = $(this.selectorOutputContainer);
+			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+			$outputContainer.empty().append(message);
+			$.ajax({
+				method: 'POST',
+				data: postData,
+				url: url,
+				cache: false,
+				success: function(data) {
+					$outputContainer.empty();
+					if (data.success === true && Array.isArray(data.status)) {
+						data.status.forEach(function(element) {
+							var message = InfoBox.render(element.severity, element.title, element.message);
+							$outputContainer.append(message);
+						});
+					}
+				},
+				error: function () {
+					var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+					$outputContainer.append(message);
+				}
+			});
+		}
+	};
+});
-- 
GitLab