From 995daee56ff04e67f47904fb5f2522b575914aee Mon Sep 17 00:00:00 2001
From: Lidiya Gelemeev <l_gele02@uni-muenster.de>
Date: Tue, 4 Feb 2025 20:25:44 +0100
Subject: [PATCH 1/6] Changing the DB requests

---
 ...eferencesMapper.php => AccountsMapper.php} |  99 ++++++---------
 lib/Db/OC/FilecacheMapper.php                 |   4 +-
 lib/SessionStatistics.php                     |  74 +++++++++++
 lib/ShareStatistics.php                       |  82 ++++++++++++
 lib/Stats/Collector/UsersCountCollector.php   |   4 +-
 lib/Stats/Collector/UsersQuotaCollector.php   |   4 +-
 lib/Stats/Collector/UsersStorageCollector.php |   4 +-
 lib/StorageStatistic.php                      | 117 ++++++++++++++++++
 8 files changed, 317 insertions(+), 71 deletions(-)
 rename lib/Db/OC/{PreferencesMapper.php => AccountsMapper.php} (58%)
 create mode 100644 lib/SessionStatistics.php
 create mode 100644 lib/ShareStatistics.php
 create mode 100644 lib/StorageStatistic.php

diff --git a/lib/Db/OC/PreferencesMapper.php b/lib/Db/OC/AccountsMapper.php
similarity index 58%
rename from lib/Db/OC/PreferencesMapper.php
rename to lib/Db/OC/AccountsMapper.php
index 1c0588a..20933aa 100644
--- a/lib/Db/OC/PreferencesMapper.php
+++ b/lib/Db/OC/AccountsMapper.php
@@ -5,81 +5,54 @@ namespace OCA\SccuotNC\Db\OC;
 use OCA\SccuotNC\Db\ExtMapper;
 use OCA\SccuotNC\Util\FileSize;
 
+use OCP\DB\Exception;
+use OCP\IConfig;
 use OCP\IDBConnection;
 use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCA\SccuotNC\Service\ConfigService;
 
-
-class PreferencesMapper extends ExtMapper {
+class AccountsMapper extends ExtMapper {
     const PREFERENCES_TABLE = 'preferences';
+	private ConfigService $configService;
 
-    public function __construct(IDBConnection $db, int $chunkSize = 10) {
-        parent::__construct($db, self::PREFERENCES_TABLE,  10);
+    public function __construct(IDBConnection $db, int $chunkSize, ConfigService $configService ) {
+        parent::__construct($db, self::PREFERENCES_TABLE,  $chunkSize);
+		$this->configService = $configService;
     }
 
-	public function queryTotalCount(string $state) {
-		$data = [
-			'state' => $state,
-			'count' => 0
-		];
-		$this->chunkedQuery('userid', array($this, 'queryTotalCountCallback'), $data, true);
-		return $data['count'];
-	}
-
-    protected function queryTotalCountCallback(IQueryBuilder $query, $offset, &$data): string {
-		$state = $data['state'];
-
-		$qb = $this->getQueryBuilder();
-		$qb->selectDistinct('userid')
-			->from(self::PREFERENCES_TABLE)
-			->where($qb->expr()->eq('configkey', $qb->expr()->literal('enabled')))
-			->andWhere($qb->expr()->eq('configvalue', $qb->expr()->literal('false')));
-
-		if ($state == 'true') {
-			$query
-				->selectAlias($query->createFunction('COUNT(DISTINCT userid)'), 'c')
-				->selectAlias($query->createFunction('MAX(userid)'), 'm')
-				->from(self::PREFERENCES_TABLE)
-				->where($query->expr()->notIn('userid', $query->createFunction($qb->getSQL())));
-		} else {
-			$query->selectAlias($query->createFunction('COUNT(DISTINCT userid)'), 'c')
-				->selectAlias($query->createFunction('MAX(userid)'), 'm')
-				->from(self::PREFERENCES_TABLE)
-				->where($query->expr()->in('userid', $query->createFunction($qb->getSQL())));
+	public function queryTotalCount(string $state): int {
+		$users = $this->configService->config()->getUsersForUserValue('core', 'enabled', 'false');			
+		if ($state === 'false'){
+			return count($users);
 		}
-
-		$this->addAlphabeticalChunkCondition($query,'userid', $offset);
-
-	    // Query values and add up count
-	    $values = $this->queryValues($query, ['c', 'm']);
-	    $data['count'] += $values['c'];
-	    return $values['m'] == NULL ? '' : $values['m'];
-    }
-
-	public function queryActiveCount(int $since): int {
-		$data = [
-			'since' => $since,
-			'count' => 0
-		];
-		$this->chunkedQuery('userid', array($this, 'queryActiveCountCallback'), $data, true);
-		return $data['count'];
+	
+                $qb = $this->db->getQueryBuilder();
+                $qb->selectAlias($qb->createFunction('COUNT(DISTINCT uid)'), 'c')
+                         ->from('accounts');
+                $stmt = $qb->execute();
+                $result = $stmt->fetch();
+                $stmt->closeCursor();
+
+		$count =  (int)$result['c'] - count($users);
+		return $count;
 	}
 
-    protected function queryActiveCountCallback(IQueryBuilder $query, $offset, &$data): string {
-        $since = $data['since'];
+	/**
+	 * @throws Exception
+	 */
+	public function queryActiveCount(int $since): int {
+		$qb = $this->db->getQueryBuilder();
 
-        $query->selectAlias($query->createFunction('COUNT(*)'), 'c')
-	        ->selectAlias($query->createFunction('MAX(userid)'), 'm')
-            ->from(self::PREFERENCES_TABLE)
-            ->where($query->expr()->eq('configkey',  $query->createPositionalParameter('lastLogin')))
-			->andWhere($query->expr()->gte('configvalue',$query->createPositionalParameter($since)));
-	    $this->addAlphabeticalChunkCondition($query,'userid', $offset);
+		$qb->selectAlias($qb->createFunction('COUNT(DISTINCT uid)'), 'c')
+			->from('authtoken')
+			->where($qb->expr()->gte('last_activity',  $qb->createPositionalParameter($since)));
 
-	    // Query values and add up count
-	    $values = $this->queryValues($query, ['c', 'm']);
-	    $data['count'] += $values['c'];
+		$stmt = $qb->execute();
+		$result = $stmt->fetch();
+		$stmt->closeCursor();
 
-	    return $values['m'] == NULL ? '' : $values['m'];
-    }
+		return (int) $result['c'];
+	}
 
 	public function queryUserStorages(): array {
 		$data = [
@@ -109,7 +82,7 @@ class PreferencesMapper extends ExtMapper {
 		$this->addAlphabeticalChunkCondition($query,'p.userid', $offset);
 
 		// Add storages and get highest ID
-		$highestID = 'A';
+		$highestID = '0';
 		foreach ($this->queryRows($query) as $row) {
 			$storages[] = intval($row['s']);
 			$highestID = max($row['i'], $highestID);
diff --git a/lib/Db/OC/FilecacheMapper.php b/lib/Db/OC/FilecacheMapper.php
index f143689..f816bbc 100644
--- a/lib/Db/OC/FilecacheMapper.php
+++ b/lib/Db/OC/FilecacheMapper.php
@@ -130,7 +130,7 @@ class FilecacheMapper extends ExtMapper {
 	private function joinUserAccounts(IQueryBuilder $query) {
 		if ($this->accountsState != '') {
 			$query->join('fc', StoragesMapper::STORAGES_TABLE, 's', 's.numeric_id = fc.storage')
-				->join('s', PreferencesMapper::PREFERENCES_TABLE, 'p', "CONCAT('home::', p.userid) = s.id");
+				->join('s', AccountsMapper::PREFERENCES_TABLE, 'p', "CONCAT('home::', p.userid) = s.id");
 		}
 	}
 
@@ -139,7 +139,7 @@ class FilecacheMapper extends ExtMapper {
 
 			$qb = $this->getQueryBuilder();
 			$qb->selectDistinct('userid')
-				->from(PreferencesMapper::PREFERENCES_TABLE)
+				->from(AccountsMapper::PREFERENCES_TABLE)
 				->where($qb->expr()->eq('configkey', $qb->expr()->literal('enabled')))
 				->andWhere($qb->expr()->eq('configvalue', $qb->expr()->literal('false')));
 
diff --git a/lib/SessionStatistics.php b/lib/SessionStatistics.php
new file mode 100644
index 0000000..f1bf3eb
--- /dev/null
+++ b/lib/SessionStatistics.php
@@ -0,0 +1,74 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\SccuotNC;
+
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\IDBConnection;
+
+/**
+ * Class SessionStatistics
+ *
+ * get active users
+ *
+ * @group DB
+ * @package OCA\ServerInfo
+ */
+class SessionStatistics {
+	private const OFFSET_5MIN = 300;
+	private const OFFSET_1HOUR = 3600;
+	private const OFFSET_1DAY = 86400;
+	private const OFFSET_7DAYS = 604800;
+	private const OFFSET_1MONTH = 2592000;
+	private const OFFSET_3MONTHS = 7776000;
+	private const OFFSET_6MONTHS = 15552000;
+	private const OFFSET_1YEAR = 31536000;
+
+	private IDBConnection $connection;
+	private ITimeFactory $timeFactory;
+
+	public function __construct(IDBConnection $connection, ITimeFactory $timeFactory) {
+		$this->connection = $connection;
+		$this->timeFactory = $timeFactory;
+	}
+
+	public function getSessionStatistics(): array {
+		return [
+			'last5minutes' => $this->getNumberOfActiveUsers(self::OFFSET_5MIN),
+			'last1hour' => $this->getNumberOfActiveUsers(self::OFFSET_1HOUR),
+			'last24hours' => $this->getNumberOfActiveUsers(self::OFFSET_1DAY),
+			'last7days' => $this->getNumberOfActiveUsers(self::OFFSET_7DAYS),
+			'last1month' => $this->getNumberOfActiveUsers(self::OFFSET_1MONTH),
+			'last3months' => $this->getNumberOfActiveUsers(self::OFFSET_3MONTHS),
+			'last6months' => $this->getNumberOfActiveUsers(self::OFFSET_6MONTHS),
+			'lastyear' => $this->getNumberOfActiveUsers(self::OFFSET_1YEAR),
+		];
+	}
+
+	/**
+	 * get number of active user in a given time span
+	 *
+	 * @param int $offset seconds
+	 */
+	private function getNumberOfActiveUsers(int $offset): int {
+		$query = $this->connection->getQueryBuilder();
+		$query->select('uid')
+			->from('authtoken')
+			->where($query->expr()->gte(
+				'last_activity',
+				$query->createNamedParameter($this->timeFactory->getTime() - $offset)
+			))->groupBy('uid');
+
+		$result = $query->executeQuery();
+		$activeUsers = $result->fetchAll();
+		$result->closeCursor();
+
+		return count($activeUsers);
+	}
+}
diff --git a/lib/ShareStatistics.php b/lib/ShareStatistics.php
new file mode 100644
index 0000000..4ffe3e1
--- /dev/null
+++ b/lib/ShareStatistics.php
@@ -0,0 +1,82 @@
+<?php
+declare(strict_types=1);
+namespace OCA\SccuotNC;
+
+use OCP\IDBConnection;
+use OCP\Share\IShare;
+
+class ShareStatistics {
+	protected IDBConnection $connection;
+
+	public function __construct(IDBConnection $connection) {
+		$this->connection = $connection;
+	}
+
+	/**
+	 * @return array (string => string|int)
+	 */
+	public function getShareStatistics(): array {
+		$query = $this->connection->getQueryBuilder();
+		$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
+			->addSelect(['permissions', 'share_type'])
+			->from('share')
+			->addGroupBy('permissions')
+			->addGroupBy('share_type');
+		$result = $query->executeQuery();
+
+		$data = [
+			'num_shares' => $this->countEntries('share'),
+			'num_shares_user' => $this->countShares(IShare::TYPE_USER),
+			'num_shares_groups' => $this->countShares(IShare::TYPE_GROUP),
+			'num_shares_link' => $this->countShares(IShare::TYPE_LINK),
+			'num_shares_mail' => $this->countShares(IShare::TYPE_EMAIL),
+			'num_shares_room' => $this->countShares(IShare::TYPE_ROOM),
+			'num_shares_link_no_password' => $this->countShares(IShare::TYPE_LINK, true),
+			'num_fed_shares_sent' => $this->countShares(IShare::TYPE_REMOTE),
+			'num_fed_shares_received' => $this->countEntries('share_external'),
+		];
+		while ($row = $result->fetch()) {
+			$data['permissions_' . $row['share_type'] . '_' . $row['permissions']] = $row['num_entries'];
+		}
+		$result->closeCursor();
+
+		return $data;
+	}
+
+	/**
+	 * @param string $tableName
+	 * @return int
+	 */
+	protected function countEntries(string $tableName): int {
+		$query = $this->connection->getQueryBuilder();
+		$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
+			->from($tableName);
+		$result = $query->executeQuery();
+		$row = $result->fetch();
+		$result->closeCursor();
+
+		return (int)$row['num_entries'];
+	}
+
+	/**
+	 * @param int $type
+	 * @param bool $noPassword
+	 * @return int
+	 */
+	protected function countShares(int $type, bool $noPassword = false): int {
+		$query = $this->connection->getQueryBuilder();
+		$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
+			->from('share')
+			->where($query->expr()->eq('share_type', $query->createNamedParameter($type)));
+
+		if ($noPassword) {
+			$query->andWhere($query->expr()->isNull('password'));
+		}
+
+		$result = $query->executeQuery();
+		$row = $result->fetch();
+		$result->closeCursor();
+
+		return (int)$row['num_entries'];
+	}
+}
diff --git a/lib/Stats/Collector/UsersCountCollector.php b/lib/Stats/Collector/UsersCountCollector.php
index c0b8728..15f9aa5 100644
--- a/lib/Stats/Collector/UsersCountCollector.php
+++ b/lib/Stats/Collector/UsersCountCollector.php
@@ -2,7 +2,7 @@
 
 namespace OCA\SccuotNC\Stats\Collector;
 
-use OCA\SccuotNC\Db\OC\PreferencesMapper;
+use OCA\SccuotNC\Db\OC\AccountsMapper;
 use OCA\SccuotNC\Misc\TimePeriods;
 use OCA\SccuotNC\Service\ConfigService;
 use OCA\SccuotNC\Stats\Value\UsersCountValue;
@@ -11,7 +11,7 @@ use OCP\IDBConnection;
 
 class UsersCountCollector extends BaseCollector {
     protected function collectData(IDBConnection $db, int $timestamp, int $chunkSize, ConfigService $config): array {
-        $mapper = new PreferencesMapper($db, $chunkSize);
+        $mapper = new AccountsMapper($db, $chunkSize, $config);
 		$activeUsers = $mapper->queryTotalCount(self::STATE_ENABLED);
 		$closedUsers = $mapper->queryTotalCount(self::STATE_DISABLED);
         $values = [UsersCountValue::TOTAL_COUNT => $activeUsers + $closedUsers, UsersCountValue::CLOSED_COUNT => $closedUsers];
diff --git a/lib/Stats/Collector/UsersQuotaCollector.php b/lib/Stats/Collector/UsersQuotaCollector.php
index b67fa53..b44dbc0 100644
--- a/lib/Stats/Collector/UsersQuotaCollector.php
+++ b/lib/Stats/Collector/UsersQuotaCollector.php
@@ -2,7 +2,7 @@
 
 namespace OCA\SccuotNC\Stats\Collector;
 
-use OCA\SccuotNC\Db\OC\PreferencesMapper;
+use OCA\SccuotNC\Db\OC\AccountsMapper;
 use OCA\SccuotNC\Db\OC\StoragesMapper;
 use OCA\SccuotNC\Service\ConfigService;
 use OCA\SccuotNC\Util\FileSize;
@@ -11,7 +11,7 @@ use OCP\IDBConnection;
 
 class UsersQuotaCollector extends BaseCollector {
     protected function collectData(IDBConnection $db, int $timestamp, int $chunkSize, ConfigService $config) {
-        $accMapper = new PreferencesMapper($db, $chunkSize);
+        $accMapper = new AccountsMapper($db, $chunkSize, $config);
 		$storeMapper = new StoragesMapper($db, $chunkSize);
 		$userQuotas = $accMapper->queryUserQuotas($this->getDefaultQuotas($config));
 		$quotaUsages = [];
diff --git a/lib/Stats/Collector/UsersStorageCollector.php b/lib/Stats/Collector/UsersStorageCollector.php
index cf81af8..837ba18 100644
--- a/lib/Stats/Collector/UsersStorageCollector.php
+++ b/lib/Stats/Collector/UsersStorageCollector.php
@@ -2,14 +2,14 @@
 
 namespace OCA\SccuotNC\Stats\Collector;
 
-use OCA\SccuotNC\Db\OC\PreferencesMapper;
+use OCA\SccuotNC\Db\OC\AccountsMapper;
 use OCA\SccuotNC\Service\ConfigService;
 
 use OCP\IDBConnection;
 
 class UsersStorageCollector extends BaseCollector {
     protected function collectData(IDBConnection $db, int $timestamp, int $chunkSize, ConfigService $config) {
-		$mapper = new PreferencesMapper($db, $chunkSize);
+		$mapper = new AccountsMapper($db, $chunkSize, $config);
 		$filesSizes = $mapper->queryUserStorages();
         sort($filesSizes);
         return $filesSizes;
diff --git a/lib/StorageStatistic.php b/lib/StorageStatistic.php
new file mode 100644
index 0000000..95b67a5
--- /dev/null
+++ b/lib/StorageStatistic.php
@@ -0,0 +1,117 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+
+namespace OCA\SccuotNC\Db\OC;
+
+use OCP\Files\IRootFolder;
+use OCP\IAppConfig;
+use OCP\IDBConnection;
+
+class StorageStatistics {
+
+	public function __construct(
+		private IDBConnection $connection,
+		private IRootFolder $rootFolder,
+		private IAppConfig $appConfig,
+	) {
+	}
+
+	public function getStorageStatistics(): array {
+		return [
+			'num_users' => $this->countUserEntries(),
+			'num_files' => $this->getCountOf('filecache'),
+			'num_storages' => $this->getCountOf('storages'),
+			'num_storages_local' => $this->countStorages('local'),
+			'num_storages_home' => $this->countStorages('home'),
+			'num_storages_other' => $this->countStorages('other'),
+			'size_appdata_storage' => $this->appConfig->getValueFloat('serverinfo', 'size_appdata_storage'),
+			'num_files_appdata' => $this->getCountOf('appdata_files'),
+		];
+	}
+
+	/**
+	 * count number of users
+	 */
+	protected function countUserEntries(): int {
+		$query = $this->connection->getQueryBuilder();
+		$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
+			->from('preferences')
+			->where($query->expr()->eq('configkey', $query->createNamedParameter('lastLogin')));
+		$result = $query->executeQuery();
+		$row = $result->fetch();
+		$result->closeCursor();
+		return (int)$row['num_entries'];
+	}
+
+	protected function getCountOf(string $table): int {
+		return $this->appConfig->getValueInt('serverinfo', 'cached_count_' . $table);
+	}
+
+	public function updateStorageCounts(): void {
+		$storageCount = 0;
+		$fileCount = 0;
+
+		$fileQuery = $this->connection->getQueryBuilder();
+		$fileQuery->select($fileQuery->func()->count())
+			->from('filecache')
+			->where($fileQuery->expr()->eq('storage', $fileQuery->createParameter('storageId')));
+
+		$storageQuery = $this->connection->getQueryBuilder();
+		$storageQuery->selectAlias('numeric_id', 'id')
+			->from('storages');
+		$storageResult = $storageQuery->executeQuery();
+		while ($storageRow = $storageResult->fetch()) {
+			$storageCount++;
+			$fileQuery->setParameter('storageId', $storageRow['id']);
+			$fileResult = $fileQuery->executeQuery();
+			$fileCount += (int)$fileResult->fetchOne();
+			$fileResult->closeCursor();
+		}
+		$storageResult->closeCursor();
+
+		$this->updateAppDataStorageStats();
+
+		$this->appConfig->setValueInt('serverinfo', 'cached_count_filecache', $fileCount);
+		$this->appConfig->setValueInt('serverinfo', 'cached_count_storages', $storageCount);
+	}
+
+	protected function countStorages(string $type): int {
+		$query = $this->connection->getQueryBuilder();
+		$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
+			->from('storages');
+		if ($type === 'home') {
+			$query->where($query->expr()->like('id', $query->createNamedParameter('home::%')));
+		} elseif ($type === 'local') {
+			$query->where($query->expr()->like('id', $query->createNamedParameter('local::%')));
+		} elseif ($type === 'other') {
+			$query->where($query->expr()->notLike('id', $query->createNamedParameter('home::%')));
+			$query->andWhere($query->expr()->notLike('id', $query->createNamedParameter('local::%')));
+		}
+		$result = $query->executeQuery();
+		$row = $result->fetch();
+		$result->closeCursor();
+		return (int)$row['num_entries'];
+	}
+
+	public function updateAppDataStorageStats(): void {
+		$appDataPath = $this->rootFolder->getAppDataDirectoryName();
+		$appDataFolder = $this->rootFolder->get($appDataPath);
+		$this->appConfig->setValueFloat('serverinfo', 'size_appdata_storage', $appDataFolder->getSize());
+
+		$query = $this->connection->getQueryBuilder();
+		$query->select($query->func()->count())
+			->from('filecache')
+			->where($query->expr()->like('path', $query->createNamedParameter($appDataPath . '%')));
+		$fileResult = $query->executeQuery();
+		$fileCount = (int)$fileResult->fetchOne();
+		$fileResult->closeCursor();
+		$this->appConfig->setValueInt('serverinfo', 'cached_count_appdata_files', $fileCount);
+	}
+}
-- 
GitLab


From afcf6fac0eb4c6b2a17d5826463f9bafffc00559 Mon Sep 17 00:00:00 2001
From: Lidiya Gelemeev <l_gele02@uni-muenster.de>
Date: Thu, 6 Feb 2025 15:13:59 +0100
Subject: [PATCH 2/6] Controller modification

---
 lib/Db/ExtMapper.php         | 54 ++++++++------------
 lib/Db/OC/AccountsMapper.php | 98 ++++++++++++++++++++----------------
 2 files changed, 76 insertions(+), 76 deletions(-)

diff --git a/lib/Db/ExtMapper.php b/lib/Db/ExtMapper.php
index f25b9b9..e5ee27d 100644
--- a/lib/Db/ExtMapper.php
+++ b/lib/Db/ExtMapper.php
@@ -34,19 +34,33 @@ abstract class ExtMapper extends QBMapper {
 		return $this->queryValue($query, $field);
 	}
 
-    protected function chunkedQuery(string $idField, callable $callback, &$data, $alphabetic = false) {
-		$alphabetic ? $offset = 'A' : $offset = 0;
+    protected function chunkedQuery(string $idField, callable $callback, &$data) {
+		$offset = 0;
 		$highestEntityID = $this->getHighestEntityID($idField);
 		while ($offset < $highestEntityID) {
 			$query = $this->getQueryBuilder();
 
 			// The provided callback performs the actual query; afterwards, advance the offset
 			$maxEntityID = call_user_func_array($callback, array($query, $offset, &$data));
-			if (!$alphabetic) {
-				$offset = max($maxEntityID, $this->advanceOffset($offset));
-			} else {
-				$offset = max($maxEntityID, $this->advanceAlphabeticOffset($offset));
+			$offset = max($maxEntityID, $this->advanceOffset($offset));
+		}
+	}
+
+	protected function chunkedQueryArray(callable $callback, &$data, $activeUsers): void {
+
+		$offset = 0;
+		$totalUsers = count($activeUsers); // Total number of users
+
+		while ($offset < $totalUsers) {
+			$query = $this->getQueryBuilder();
+
+			$userChunk = array_slice($activeUsers, $offset, $this->chunkSize);
+			if (empty($userChunk)) {
+				break;
 			}
+			$callback($query, $userChunk, $data);
+
+			$offset += $this->chunkSize;
 		}
 	}
 
@@ -64,23 +78,6 @@ abstract class ExtMapper extends QBMapper {
 		}
 	}
 
-	protected function addAlphabeticalChunkCondition(IQueryBuilder $query, string $field, string $offset, bool $firstWhereClause = false): void {
-		//Changed chunkSize to a string that can define the size of a chunk
-		if ($this->chunkSize > 0) {
-			$endOffset = $this->advanceAlphabeticOffset($offset);
-
-			$expr = $query->expr()->gt($field, $query->createPositionalParameter($offset));
-			if ($firstWhereClause) {
-				$query->where($expr);
-			} else {
-				$query->andWhere($expr);
-			}
-			$expr = $query->expr()->lte($field, $query->createPositionalParameter($endOffset));
-			$query->andWhere($expr);
-			$query->orderBy($field, 'ASC');
-		}
-	}
-
     protected function getQueryBuilder() : IQueryBuilder {
         return $this->db->getQueryBuilder();
     }
@@ -115,6 +112,7 @@ abstract class ExtMapper extends QBMapper {
         $stmt = $query->execute();
         $rows = [];
         while ($row = $stmt->fetch()) {
+			echo "Row fetched: " . json_encode($row) . PHP_EOL;
             $rows[] = $row;
         }
         $stmt->closeCursor();
@@ -160,14 +158,4 @@ abstract class ExtMapper extends QBMapper {
 		}
 		return $offset;
 	}
-
-	private function advanceAlphabeticOffset(string $offset): string {
-		if ($this->chunkSize > 0) {
-			$offset = chr(ord($offset) + $this->chunkSize);
-		} else {
-			$offset = '{';
-		}
-		return $offset;
-	}
-
 }
diff --git a/lib/Db/OC/AccountsMapper.php b/lib/Db/OC/AccountsMapper.php
index 20933aa..028b095 100644
--- a/lib/Db/OC/AccountsMapper.php
+++ b/lib/Db/OC/AccountsMapper.php
@@ -6,14 +6,15 @@ use OCA\SccuotNC\Db\ExtMapper;
 use OCA\SccuotNC\Util\FileSize;
 
 use OCP\DB\Exception;
-use OCP\IConfig;
 use OCP\IDBConnection;
 use OCP\DB\QueryBuilder\IQueryBuilder;
 use OCA\SccuotNC\Service\ConfigService;
+use PDO;
 
 class AccountsMapper extends ExtMapper {
     const PREFERENCES_TABLE = 'preferences';
 	private ConfigService $configService;
+	private string $activeUsersFile = '/tmp/active_users.txt';
 
     public function __construct(IDBConnection $db, int $chunkSize, ConfigService $configService ) {
         parent::__construct($db, self::PREFERENCES_TABLE,  $chunkSize);
@@ -21,20 +22,23 @@ class AccountsMapper extends ExtMapper {
     }
 
 	public function queryTotalCount(string $state): int {
-		$users = $this->configService->config()->getUsersForUserValue('core', 'enabled', 'false');			
+		$deactivatedUsers = array_map('strval', $this->configService->config()->getUsersForUserValue('core', 'enabled', 'false'));
 		if ($state === 'false'){
-			return count($users);
+			return count($deactivatedUsers);
 		}
-	
                 $qb = $this->db->getQueryBuilder();
-                $qb->selectAlias($qb->createFunction('COUNT(DISTINCT uid)'), 'c')
+                $qb->select('uid')
                          ->from('accounts');
                 $stmt = $qb->execute();
-                $result = $stmt->fetch();
+                $result = $stmt->fetchAll(PDO::FETCH_COLUMN);
                 $stmt->closeCursor();
+		$result = array_map('strval', $result);
 
-		$count =  (int)$result['c'] - count($users);
-		return $count;
+		$activerUsers = array_diff($result, $deactivatedUsers);
+		$fileContent = implode(PHP_EOL, $activerUsers);
+		file_put_contents($this->activeUsersFile, $fileContent);
+
+		return count($result) - count($deactivatedUsers);
 	}
 
 	/**
@@ -54,79 +58,74 @@ class AccountsMapper extends ExtMapper {
 		return (int) $result['c'];
 	}
 
+	/**
+	 * @throws \Exception
+	 */
 	public function queryUserStorages(): array {
+		$activeUsers = $this->getActiveUsersFromFile($this->activeUsersFile);
 		$data = [
 			'storages' => []
 		];
-		$this->chunkedQuery('userid', array($this, 'queryUserStoragesCallback'), $data, true);
+		$this->chunkedQueryArray(function ($query, $userChunk, &$data) use ($activeUsers) {
+			return $this->queryUserStoragesCallback($query, $userChunk, $data);
+		}, $data, $activeUsers);
+
 		return $data['storages'];
 	}
 
-	protected function queryUserStoragesCallback(IQueryBuilder $query, $offset, &$data): string {
+	protected function queryUserStoragesCallback(IQueryBuilder $query, array $userChunk, &$data): string {
 		$storages = &$data['storages'];
-
-		$qb = $this->getQueryBuilder();
-		$qb->selectDistinct('userid')
-			->from(self::PREFERENCES_TABLE)
-			->where($qb->expr()->eq('configkey', $qb->expr()->literal('enabled')))
-			->andWhere($qb->expr()->eq('configvalue', $qb->expr()->literal('false')));
-
+		if (empty($userChunk)) {
+			return '0';
+		}
 		$query->selectAlias('fc.size', 's')
-			->selectAlias('p.userid', 'i')
-			->from(self::PREFERENCES_TABLE, 'p')
-			->join('p', StoragesMapper::STORAGES_TABLE, 's', "s.id = CONCAT('home::', p.userid)")
+			->selectAlias('a.uid', 'i')
+			->from('accounts', 'a')
+			->join('a', StoragesMapper::STORAGES_TABLE, 's', "s.id = CONCAT('home::', a.uid)")
 			->join('s', FilecacheMapper::FILECACHE_TABLE, 'fc', 'fc.storage = s.numeric_id')
-			->where($query->expr()->notIn('p.userid', $query->createFunction($qb->getSQL())))
-			->where($query->expr()->eq('p.configkey', $query->createPositionalParameter('quota')))
-			->andWhere($query->expr()->eq('fc.path', $query->createPositionalParameter('files')));
-		$this->addAlphabeticalChunkCondition($query,'p.userid', $offset);
+			->where($query->expr()->eq('fc.path', $query->createPositionalParameter('files')))
+			->andWhere($query->expr()->in('a.uid', $query->createPositionalParameter($userChunk, IQueryBuilder::PARAM_STR_ARRAY)));
 
-		// Add storages and get highest ID
-		$highestID = '0';
 		foreach ($this->queryRows($query) as $row) {
 			$storages[] = intval($row['s']);
-			$highestID = max($row['i'], $highestID);
 		}
-		return $highestID;
+		return '';
 	}
 
 	public function queryUserQuotas($defaultQuotas) {
+		$activeUsers = $this->getActiveUsersFromFile($this->activeUsersFile);
 		$data = [
 			'defaultQuotas' => $defaultQuotas,
 			'quotas' => []
 		];
-		$this->chunkedQuery('userid', array($this, 'queryUserQuotasCallback'), $data, true);
+		$this->chunkedQueryArray(function ($query, $userChunk, &$data) use ($activeUsers) {
+
+			return $this->queryUserQuotasCallback($query, $userChunk, $data);
+		}, $data, $activeUsers);
 		return $data['quotas'];
 	}
 
-	protected function queryUserQuotasCallback(IQueryBuilder $query, $offset, &$data): string {
+	protected function queryUserQuotasCallback(IQueryBuilder $query, $userChunk, &$data): string {
 		$defaultQuotas = $data['defaultQuotas'];
 		$quotas = &$data['quotas'];
-
-		$qb = $this->getQueryBuilder();
-		$qb->selectDistinct('userid')
-			->from(self::PREFERENCES_TABLE)
-			->where($qb->expr()->eq('configkey', $qb->expr()->literal('enabled')))
-			->andWhere($qb->expr()->eq('configvalue', $qb->expr()->literal('false')));
+		if (empty($userChunk)) {
+			return '0';
+		}
 
 		$query->selectDistinct('p.userid')
 			->selectAlias('p1.configvalue', 'quota')
 			->from(self::PREFERENCES_TABLE, 'p')
 			->join('p', self::PREFERENCES_TABLE, 'p1', 'p1.userid = p.userid')
-			->where($query->expr()->notIn('p.userid', $query->createFunction($qb->getSQL())))
-			->andWhere($query->expr()->eq('p1.configkey', $query->createPositionalParameter('quota')));
-		$this->addAlphabeticalChunkCondition($query,'p.userid', $offset);
+			->andWhere($query->expr()->eq('p1.configkey', $query->createPositionalParameter('quota')))
+			->andWhere($query->expr()->in('p.userid', $query->createPositionalParameter($userChunk, IQueryBuilder::PARAM_STR_ARRAY)));
 
-		// Add quotas and get highest ID
-		$highestID = '';
 		foreach ($this->queryRows($query) as $row) {
 			$defaultQuota = $this->findDefaultQuota($defaultQuotas, $row['quota']);
 			if (($quota = FileSize::ParseQuotaString($row['quota'], $defaultQuota)) !== false) {
 				$quotas[$row['userid']] = $quota;
 			}
-			$highestID = max($row['userid'], $highestID);
 		}
-		return $highestID;
+		return '';
 	}
 
 	private function findDefaultQuota($defaultQuotas, $backend) {
@@ -138,4 +137,17 @@ class AccountsMapper extends ExtMapper {
 		}
 		return false;
 	}
+
+	/**
+	 * @throws \Exception
+	 */
+	protected function getActiveUsersFromFile(string $filePath): array {
+		if (!file_exists($filePath)) {
+			throw new \Exception("Active users file not found at: {$filePath}");
+		}
+
+		$activeUsers = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
+
+		return array_map('trim', $activeUsers); // Ensure no extra whitespace
+	}
 }
-- 
GitLab


From c396c8f8dd70ed2457c8f9d48acc64565a546f20 Mon Sep 17 00:00:00 2001
From: Lidiya Gelemeev <l_gele02@uni-muenster.de>
Date: Mon, 10 Feb 2025 13:17:38 +0100
Subject: [PATCH 3/6] Adjust the user fetching

---
 lib/Db/ExtMapper.php          |  7 +++----
 lib/Db/OC/AccountsMapper.php  | 37 ++++-------------------------------
 lib/Db/OC/FilecacheMapper.php |  9 +--------
 3 files changed, 8 insertions(+), 45 deletions(-)

diff --git a/lib/Db/ExtMapper.php b/lib/Db/ExtMapper.php
index e5ee27d..2086674 100644
--- a/lib/Db/ExtMapper.php
+++ b/lib/Db/ExtMapper.php
@@ -46,15 +46,15 @@ abstract class ExtMapper extends QBMapper {
 		}
 	}
 
-	protected function chunkedQueryArray(callable $callback, &$data, $activeUsers): void {
+	protected function chunkedQueryArray(callable $callback, &$data, $users): void {
 
 		$offset = 0;
-		$totalUsers = count($activeUsers); // Total number of users
+		$totalUsers = count($users); // Total number of users
 
 		while ($offset < $totalUsers) {
 			$query = $this->getQueryBuilder();
 
-			$userChunk = array_slice($activeUsers, $offset, $this->chunkSize);
+			$userChunk = array_slice($users, $offset, $this->chunkSize);
 			if (empty($userChunk)) {
 				break;
 			}
@@ -112,7 +112,6 @@ abstract class ExtMapper extends QBMapper {
         $stmt = $query->execute();
         $rows = [];
         while ($row = $stmt->fetch()) {
-			echo "Row fetched: " . json_encode($row) . PHP_EOL;
             $rows[] = $row;
         }
         $stmt->closeCursor();
diff --git a/lib/Db/OC/AccountsMapper.php b/lib/Db/OC/AccountsMapper.php
index 028b095..2383f42 100644
--- a/lib/Db/OC/AccountsMapper.php
+++ b/lib/Db/OC/AccountsMapper.php
@@ -9,12 +9,10 @@ use OCP\DB\Exception;
 use OCP\IDBConnection;
 use OCP\DB\QueryBuilder\IQueryBuilder;
 use OCA\SccuotNC\Service\ConfigService;
-use PDO;
 
 class AccountsMapper extends ExtMapper {
     const PREFERENCES_TABLE = 'preferences';
 	private ConfigService $configService;
-	private string $activeUsersFile = '/tmp/active_users.txt';
 
     public function __construct(IDBConnection $db, int $chunkSize, ConfigService $configService ) {
         parent::__construct($db, self::PREFERENCES_TABLE,  $chunkSize);
@@ -22,23 +20,8 @@ class AccountsMapper extends ExtMapper {
     }
 
 	public function queryTotalCount(string $state): int {
-		$deactivatedUsers = array_map('strval', $this->configService->config()->getUsersForUserValue('core', 'enabled', 'false'));
-		if ($state === 'false'){
-			return count($deactivatedUsers);
-		}
-                $qb = $this->db->getQueryBuilder();
-                $qb->select('uid')
-                         ->from('accounts');
-                $stmt = $qb->execute();
-                $result = $stmt->fetchAll(PDO::FETCH_COLUMN);
-                $stmt->closeCursor();
-		$result = array_map('strval', $result);
-
-		$activerUsers = array_diff($result, $deactivatedUsers);
-		$fileContent = implode(PHP_EOL, $activerUsers);
-		file_put_contents($this->activeUsersFile, $fileContent);
-
-		return count($result) - count($deactivatedUsers);
+		$users = $this->configService->config()->getUsersForUserValue('core', 'enabled', $state);
+		return count($users);
 	}
 
 	/**
@@ -62,7 +45,7 @@ class AccountsMapper extends ExtMapper {
 	 * @throws \Exception
 	 */
 	public function queryUserStorages(): array {
-		$activeUsers = $this->getActiveUsersFromFile($this->activeUsersFile);
+		$activeUsers = $this->configService->config()->getUsersForUserValue('core', 'enabled', 'true');
 		$data = [
 			'storages' => []
 		];
@@ -93,7 +76,7 @@ class AccountsMapper extends ExtMapper {
 	}
 
 	public function queryUserQuotas($defaultQuotas) {
-		$activeUsers = $this->getActiveUsersFromFile($this->activeUsersFile);
+		$activeUsers = $this->configService->config()->getUsersForUserValue('core', 'enabled', 'true');
 		$data = [
 			'defaultQuotas' => $defaultQuotas,
 			'quotas' => []
@@ -138,16 +121,4 @@ class AccountsMapper extends ExtMapper {
 		return false;
 	}
 
-	/**
-	 * @throws \Exception
-	 */
-	protected function getActiveUsersFromFile(string $filePath): array {
-		if (!file_exists($filePath)) {
-			throw new \Exception("Active users file not found at: {$filePath}");
-		}
-
-		$activeUsers = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
-
-		return array_map('trim', $activeUsers); // Ensure no extra whitespace
-	}
 }
diff --git a/lib/Db/OC/FilecacheMapper.php b/lib/Db/OC/FilecacheMapper.php
index f816bbc..a7d9080 100644
--- a/lib/Db/OC/FilecacheMapper.php
+++ b/lib/Db/OC/FilecacheMapper.php
@@ -141,14 +141,7 @@ class FilecacheMapper extends ExtMapper {
 			$qb->selectDistinct('userid')
 				->from(AccountsMapper::PREFERENCES_TABLE)
 				->where($qb->expr()->eq('configkey', $qb->expr()->literal('enabled')))
-				->andWhere($qb->expr()->eq('configvalue', $qb->expr()->literal('false')));
-
-			$query->andWhere($query->expr()->like('configkey', $query->expr()->literal('%quota%')));
-			if ($this->accountsState == 'true') {
-				$query->andWhere($query->expr()->notIn('p.userid', $query->createFunction($qb->getSQL())));
-			} else {
-				$query->andWhere($query->expr()->in('p.userid', $query->createFunction($qb->getSQL())));
-			}
+				->andWhere($qb->expr()->eq('configvalue', $qb->expr()->literal($this->accountsState)));
 		}
 	}
 
-- 
GitLab


From 169f3f54bfeb70ab3e7d439df9d7791f51e62bfd Mon Sep 17 00:00:00 2001
From: Lidiya Gelemeev <l_gele02@uni-muenster.de>
Date: Mon, 10 Feb 2025 13:42:10 +0100
Subject: [PATCH 4/6] Remove the callback by simple count

---
 lib/Db/OC/ExternalSharesMapper.php | 30 ++++-------
 lib/Db/OC/SharesMapper.php         | 82 ++++++++----------------------
 2 files changed, 32 insertions(+), 80 deletions(-)

diff --git a/lib/Db/OC/ExternalSharesMapper.php b/lib/Db/OC/ExternalSharesMapper.php
index d683bfd..011edce 100644
--- a/lib/Db/OC/ExternalSharesMapper.php
+++ b/lib/Db/OC/ExternalSharesMapper.php
@@ -15,23 +15,15 @@ class ExternalSharesMapper extends ExtMapper {
     }
 
 	public function queryTotalCount() {
-		$data = [
-			'count' => 0
-		];
-		$this->chunkedQuery('id', array($this, 'queryTotalCountCallback'), $data);
-		return $data['count'];
-	}
-
-    protected function queryTotalCountCallback(IQueryBuilder $query, $offset, &$data): int {
-        $query->selectAlias($query->createFunction('COUNT(*)'), 'c')
-	        ->selectAlias($query->createFunction('MAX(id)'), 'm')
-            ->from(self::EXTERNAL_SHARES_TABLE);
-	    $this->addChunkCondition($query,'id', $offset, true);
-
-	    // Query values and add up count
-	    $values = $this->queryValues($query, ['c', 'm']);
-        $data['count'] += $values['c'];
-
-		return $values['m'] == NULL ? 0 : $values['m'];
-    }
+		$query = $this->db->getQueryBuilder();
+
+		// Create a query to count all rows in the EXTERNAL_SHARES_TABLE
+		$query->selectAlias($query->createFunction('COUNT(*)'), 'count')
+			->from(self::EXTERNAL_SHARES_TABLE);
+
+		// Execute the query and fetch the result
+		$result = $query->execute()->fetch();
+
+		// Return the total count as an integer
+		return (int) $result['count'];
 }
diff --git a/lib/Db/OC/SharesMapper.php b/lib/Db/OC/SharesMapper.php
index 039db00..219c1aa 100644
--- a/lib/Db/OC/SharesMapper.php
+++ b/lib/Db/OC/SharesMapper.php
@@ -17,89 +17,49 @@ class SharesMapper extends ExtMapper {
     }
 
 	public function queryTotalCount(): int {
-		$data = [
-			'count' => 0
-		];
-		$this->chunkedQuery('id', array($this, 'queryTotalCountCallback'), $data);
-		return $data['count'];
-	}
+		$query = $this->db->getQueryBuilder();
 
-    protected function queryTotalCountCallback(IQueryBuilder $query, $offset, &$data): int {
-        $query->selectAlias($query->createFunction('COUNT(*)'), 'c')
-	        ->selectAlias($query->createFunction('MAX(id)'), 'm')
-            ->from(self::SHARES_TABLE);
-	    $this->addChunkCondition($query,'id', $offset, true);
+		$query->selectAlias($query->createFunction('COUNT(*)'), 'count')
+			->from(self::SHARES_TABLE);
 
-	    // Query values and add up count
-	    $values = $this->queryValues($query, ['c', 'm']);
-	    $data['count'] += $values['c'];
+		$result = $query->execute()->fetch();
 
-	    return $values['m'] == NULL ? 0 : $values['m'];
+		return (int) $result['count'];
     }
 
 	public function queryFilesCount(): int {
-		$data = [
-			'count' => 0
-		];
-		$this->chunkedQuery('id', array($this, 'queryFilesCountCallback'), $data);
-		return $data['count'];
-	}
+		$query = $this->db->getQueryBuilder();
 
-    protected function queryFilesCountCallback(IQueryBuilder $query, $offset, &$data): int {
-        $query->selectAlias($query->createFunction('COUNT(*)'), 'c')
-	        ->selectAlias($query->createFunction('MAX(id)'), 'm')
-            ->from(self::SHARES_TABLE)
-            ->where($query->expr()->like('item_type', $query->createPositionalParameter('file')));
-	    $this->addChunkCondition($query,'id', $offset);
+		$query->selectAlias($query->createFunction('COUNT(*)'), 'count')
+			->from(self::SHARES_TABLE)
+			->where($query->expr()->like('item_type', $query->createPositionalParameter('file')));
 
-	    // Query values and add up count
-	    $values = $this->queryValues($query, ['c', 'm']);
-	    $data['count'] += $values['c'];
+		$result = $query->execute()->fetch();
 
-	    return $values['m'] == NULL ? 0 : $values['m'];
+		return (int) $result['count'];
     }
 
 	public function queryFoldersCount(): int {
-		$data = [
-			'count' => 0
-		];
-		$this->chunkedQuery('id', array($this, 'queryFoldersCountCallback'), $data);
-		return $data['count'];
-	}
+		$query = $this->db->getQueryBuilder();
 
-    protected function queryFoldersCountCallback(IQueryBuilder $query, $offset, &$data): int {
-        $query->selectAlias($query->createFunction('COUNT(*)'), 'c')
-	        ->selectAlias($query->createFunction('MAX(id)'), 'm')
-            ->from(self::SHARES_TABLE)
-            ->where($query->expr()->like('item_type', $query->createPositionalParameter('folder')));
-	    $this->addChunkCondition($query,'id', $offset);
+		$query->selectAlias($query->createFunction('COUNT(*)'), 'count')
+			->from(self::SHARES_TABLE)
+			->where($query->expr()->like('item_type', $query->createPositionalParameter('folder')));
 
-	    // Query values and add up count
-	    $values = $this->queryValues($query, ['c', 'm']);
-	    $data['count'] += $values['c'];
+		$result = $query->execute()->fetch();
 
-	    return $values['m'] == NULL ? 0 : $values['m'];
+		return (int) $result['count'];
     }
 
 	public function queryPublicLinksCount(): int {
-		$data = [
-			'count' => 0
-		];
-		$this->chunkedQuery('id', array($this, 'queryPublicLinksCountCallback'), $data);
-		return $data['count'];
-	}
+		$query = $this->db->getQueryBuilder();
 
-	protected function queryPublicLinksCountCallback(IQueryBuilder $query, $offset, &$data): int {
-		$query->selectAlias($query->createFunction('COUNT(*)'), 'c')
-			->selectAlias($query->createFunction('MAX(id)'), 'm')
+		$query->selectAlias($query->createFunction('COUNT(*)'), 'count')
 			->from(self::SHARES_TABLE)
 			->where($query->expr()->eq('share_type', $query->createPositionalParameter(IShare::TYPE_LINK, IQueryBuilder::PARAM_INT)));
-		$this->addChunkCondition($query,'id', $offset);
 
-		// Query values and add up count
-		$values = $this->queryValues($query, ['c', 'm']);
-		$data['count'] += $values['c'];
+		$result = $query->execute()->fetch();
 
-		return $values['m'] == NULL ? 0 : $values['m'];
+		return (int) $result['count'];
 	}
 }
-- 
GitLab


From d9e1383a6d5842f268c1c3c950149bfc130e70ad Mon Sep 17 00:00:00 2001
From: Lidiya Gelemeev <l_gele02@uni-muenster.de>
Date: Mon, 10 Feb 2025 13:42:39 +0100
Subject: [PATCH 5/6] fix

---
 lib/Db/OC/ExternalSharesMapper.php | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/lib/Db/OC/ExternalSharesMapper.php b/lib/Db/OC/ExternalSharesMapper.php
index 011edce..a1d7377 100644
--- a/lib/Db/OC/ExternalSharesMapper.php
+++ b/lib/Db/OC/ExternalSharesMapper.php
@@ -8,11 +8,11 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
 use OCP\IDBConnection;
 
 class ExternalSharesMapper extends ExtMapper {
-    const EXTERNAL_SHARES_TABLE = 'share_external';
+	const EXTERNAL_SHARES_TABLE = 'share_external';
 
-    public function __construct(IDBConnection $db, int $chunkSize) {
-        parent::__construct($db, self::EXTERNAL_SHARES_TABLE, $chunkSize);
-    }
+	public function __construct(IDBConnection $db, int $chunkSize) {
+		parent::__construct($db, self::EXTERNAL_SHARES_TABLE, $chunkSize);
+	}
 
 	public function queryTotalCount() {
 		$query = $this->db->getQueryBuilder();
@@ -25,5 +25,6 @@ class ExternalSharesMapper extends ExtMapper {
 		$result = $query->execute()->fetch();
 
 		// Return the total count as an integer
-		return (int) $result['count'];
+		return (int)$result['count'];
+	}
 }
-- 
GitLab


From de281b1ff4ba8bdeba492acd51a217ed5ad26404 Mon Sep 17 00:00:00 2001
From: Lidiya Gelemeev <l_gele02@uni-muenster.de>
Date: Mon, 10 Feb 2025 14:36:02 +0100
Subject: [PATCH 6/6] fix

---
 lib/SessionStatistics.php |  74 ------------------------
 lib/ShareStatistics.php   |  82 --------------------------
 lib/StorageStatistic.php  | 117 --------------------------------------
 3 files changed, 273 deletions(-)
 delete mode 100644 lib/SessionStatistics.php
 delete mode 100644 lib/ShareStatistics.php
 delete mode 100644 lib/StorageStatistic.php

diff --git a/lib/SessionStatistics.php b/lib/SessionStatistics.php
deleted file mode 100644
index f1bf3eb..0000000
--- a/lib/SessionStatistics.php
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-namespace OCA\SccuotNC;
-
-use OCP\AppFramework\Utility\ITimeFactory;
-use OCP\IDBConnection;
-
-/**
- * Class SessionStatistics
- *
- * get active users
- *
- * @group DB
- * @package OCA\ServerInfo
- */
-class SessionStatistics {
-	private const OFFSET_5MIN = 300;
-	private const OFFSET_1HOUR = 3600;
-	private const OFFSET_1DAY = 86400;
-	private const OFFSET_7DAYS = 604800;
-	private const OFFSET_1MONTH = 2592000;
-	private const OFFSET_3MONTHS = 7776000;
-	private const OFFSET_6MONTHS = 15552000;
-	private const OFFSET_1YEAR = 31536000;
-
-	private IDBConnection $connection;
-	private ITimeFactory $timeFactory;
-
-	public function __construct(IDBConnection $connection, ITimeFactory $timeFactory) {
-		$this->connection = $connection;
-		$this->timeFactory = $timeFactory;
-	}
-
-	public function getSessionStatistics(): array {
-		return [
-			'last5minutes' => $this->getNumberOfActiveUsers(self::OFFSET_5MIN),
-			'last1hour' => $this->getNumberOfActiveUsers(self::OFFSET_1HOUR),
-			'last24hours' => $this->getNumberOfActiveUsers(self::OFFSET_1DAY),
-			'last7days' => $this->getNumberOfActiveUsers(self::OFFSET_7DAYS),
-			'last1month' => $this->getNumberOfActiveUsers(self::OFFSET_1MONTH),
-			'last3months' => $this->getNumberOfActiveUsers(self::OFFSET_3MONTHS),
-			'last6months' => $this->getNumberOfActiveUsers(self::OFFSET_6MONTHS),
-			'lastyear' => $this->getNumberOfActiveUsers(self::OFFSET_1YEAR),
-		];
-	}
-
-	/**
-	 * get number of active user in a given time span
-	 *
-	 * @param int $offset seconds
-	 */
-	private function getNumberOfActiveUsers(int $offset): int {
-		$query = $this->connection->getQueryBuilder();
-		$query->select('uid')
-			->from('authtoken')
-			->where($query->expr()->gte(
-				'last_activity',
-				$query->createNamedParameter($this->timeFactory->getTime() - $offset)
-			))->groupBy('uid');
-
-		$result = $query->executeQuery();
-		$activeUsers = $result->fetchAll();
-		$result->closeCursor();
-
-		return count($activeUsers);
-	}
-}
diff --git a/lib/ShareStatistics.php b/lib/ShareStatistics.php
deleted file mode 100644
index 4ffe3e1..0000000
--- a/lib/ShareStatistics.php
+++ /dev/null
@@ -1,82 +0,0 @@
-<?php
-declare(strict_types=1);
-namespace OCA\SccuotNC;
-
-use OCP\IDBConnection;
-use OCP\Share\IShare;
-
-class ShareStatistics {
-	protected IDBConnection $connection;
-
-	public function __construct(IDBConnection $connection) {
-		$this->connection = $connection;
-	}
-
-	/**
-	 * @return array (string => string|int)
-	 */
-	public function getShareStatistics(): array {
-		$query = $this->connection->getQueryBuilder();
-		$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
-			->addSelect(['permissions', 'share_type'])
-			->from('share')
-			->addGroupBy('permissions')
-			->addGroupBy('share_type');
-		$result = $query->executeQuery();
-
-		$data = [
-			'num_shares' => $this->countEntries('share'),
-			'num_shares_user' => $this->countShares(IShare::TYPE_USER),
-			'num_shares_groups' => $this->countShares(IShare::TYPE_GROUP),
-			'num_shares_link' => $this->countShares(IShare::TYPE_LINK),
-			'num_shares_mail' => $this->countShares(IShare::TYPE_EMAIL),
-			'num_shares_room' => $this->countShares(IShare::TYPE_ROOM),
-			'num_shares_link_no_password' => $this->countShares(IShare::TYPE_LINK, true),
-			'num_fed_shares_sent' => $this->countShares(IShare::TYPE_REMOTE),
-			'num_fed_shares_received' => $this->countEntries('share_external'),
-		];
-		while ($row = $result->fetch()) {
-			$data['permissions_' . $row['share_type'] . '_' . $row['permissions']] = $row['num_entries'];
-		}
-		$result->closeCursor();
-
-		return $data;
-	}
-
-	/**
-	 * @param string $tableName
-	 * @return int
-	 */
-	protected function countEntries(string $tableName): int {
-		$query = $this->connection->getQueryBuilder();
-		$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
-			->from($tableName);
-		$result = $query->executeQuery();
-		$row = $result->fetch();
-		$result->closeCursor();
-
-		return (int)$row['num_entries'];
-	}
-
-	/**
-	 * @param int $type
-	 * @param bool $noPassword
-	 * @return int
-	 */
-	protected function countShares(int $type, bool $noPassword = false): int {
-		$query = $this->connection->getQueryBuilder();
-		$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
-			->from('share')
-			->where($query->expr()->eq('share_type', $query->createNamedParameter($type)));
-
-		if ($noPassword) {
-			$query->andWhere($query->expr()->isNull('password'));
-		}
-
-		$result = $query->executeQuery();
-		$row = $result->fetch();
-		$result->closeCursor();
-
-		return (int)$row['num_entries'];
-	}
-}
diff --git a/lib/StorageStatistic.php b/lib/StorageStatistic.php
deleted file mode 100644
index 95b67a5..0000000
--- a/lib/StorageStatistic.php
+++ /dev/null
@@ -1,117 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-
-namespace OCA\SccuotNC\Db\OC;
-
-use OCP\Files\IRootFolder;
-use OCP\IAppConfig;
-use OCP\IDBConnection;
-
-class StorageStatistics {
-
-	public function __construct(
-		private IDBConnection $connection,
-		private IRootFolder $rootFolder,
-		private IAppConfig $appConfig,
-	) {
-	}
-
-	public function getStorageStatistics(): array {
-		return [
-			'num_users' => $this->countUserEntries(),
-			'num_files' => $this->getCountOf('filecache'),
-			'num_storages' => $this->getCountOf('storages'),
-			'num_storages_local' => $this->countStorages('local'),
-			'num_storages_home' => $this->countStorages('home'),
-			'num_storages_other' => $this->countStorages('other'),
-			'size_appdata_storage' => $this->appConfig->getValueFloat('serverinfo', 'size_appdata_storage'),
-			'num_files_appdata' => $this->getCountOf('appdata_files'),
-		];
-	}
-
-	/**
-	 * count number of users
-	 */
-	protected function countUserEntries(): int {
-		$query = $this->connection->getQueryBuilder();
-		$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
-			->from('preferences')
-			->where($query->expr()->eq('configkey', $query->createNamedParameter('lastLogin')));
-		$result = $query->executeQuery();
-		$row = $result->fetch();
-		$result->closeCursor();
-		return (int)$row['num_entries'];
-	}
-
-	protected function getCountOf(string $table): int {
-		return $this->appConfig->getValueInt('serverinfo', 'cached_count_' . $table);
-	}
-
-	public function updateStorageCounts(): void {
-		$storageCount = 0;
-		$fileCount = 0;
-
-		$fileQuery = $this->connection->getQueryBuilder();
-		$fileQuery->select($fileQuery->func()->count())
-			->from('filecache')
-			->where($fileQuery->expr()->eq('storage', $fileQuery->createParameter('storageId')));
-
-		$storageQuery = $this->connection->getQueryBuilder();
-		$storageQuery->selectAlias('numeric_id', 'id')
-			->from('storages');
-		$storageResult = $storageQuery->executeQuery();
-		while ($storageRow = $storageResult->fetch()) {
-			$storageCount++;
-			$fileQuery->setParameter('storageId', $storageRow['id']);
-			$fileResult = $fileQuery->executeQuery();
-			$fileCount += (int)$fileResult->fetchOne();
-			$fileResult->closeCursor();
-		}
-		$storageResult->closeCursor();
-
-		$this->updateAppDataStorageStats();
-
-		$this->appConfig->setValueInt('serverinfo', 'cached_count_filecache', $fileCount);
-		$this->appConfig->setValueInt('serverinfo', 'cached_count_storages', $storageCount);
-	}
-
-	protected function countStorages(string $type): int {
-		$query = $this->connection->getQueryBuilder();
-		$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
-			->from('storages');
-		if ($type === 'home') {
-			$query->where($query->expr()->like('id', $query->createNamedParameter('home::%')));
-		} elseif ($type === 'local') {
-			$query->where($query->expr()->like('id', $query->createNamedParameter('local::%')));
-		} elseif ($type === 'other') {
-			$query->where($query->expr()->notLike('id', $query->createNamedParameter('home::%')));
-			$query->andWhere($query->expr()->notLike('id', $query->createNamedParameter('local::%')));
-		}
-		$result = $query->executeQuery();
-		$row = $result->fetch();
-		$result->closeCursor();
-		return (int)$row['num_entries'];
-	}
-
-	public function updateAppDataStorageStats(): void {
-		$appDataPath = $this->rootFolder->getAppDataDirectoryName();
-		$appDataFolder = $this->rootFolder->get($appDataPath);
-		$this->appConfig->setValueFloat('serverinfo', 'size_appdata_storage', $appDataFolder->getSize());
-
-		$query = $this->connection->getQueryBuilder();
-		$query->select($query->func()->count())
-			->from('filecache')
-			->where($query->expr()->like('path', $query->createNamedParameter($appDataPath . '%')));
-		$fileResult = $query->executeQuery();
-		$fileCount = (int)$fileResult->fetchOne();
-		$fileResult->closeCursor();
-		$this->appConfig->setValueInt('serverinfo', 'cached_count_appdata_files', $fileCount);
-	}
-}
-- 
GitLab