diff --git a/lib/ACL/ACLManager.php b/lib/ACL/ACLManager.php
index 3aad0ad80..539708c27 100644
--- a/lib/ACL/ACLManager.php
+++ b/lib/ACL/ACLManager.php
@@ -64,7 +64,7 @@ private function getRules(int $storageId, array $paths, bool $cache = true): arr
$nonCachedPaths = array_filter($paths, fn (string $path): bool => !isset($rules[$path]));
- if (!empty($nonCachedPaths)) {
+ if ($nonCachedPaths !== []) {
$newRules = $this->ruleManager->getRulesForFilesByPath($this->user, $storageId, $nonCachedPaths);
foreach ($newRules as $path => $rulesForPath) {
if ($cache) {
diff --git a/lib/ACL/Rule.php b/lib/ACL/Rule.php
index 874be5a8d..125602216 100644
--- a/lib/ACL/Rule.php
+++ b/lib/ACL/Rule.php
@@ -140,7 +140,7 @@ public static function xmlDeserialize(Reader $reader): Rule {
throw new \RuntimeException(self::MAPPING_TYPE . ' is not a string.');
}
- if (!in_array($mappingType, ['user', 'group', 'circle'])) {
+ if (!in_array($mappingType, ['user', 'group', 'circle'], true)) {
throw new \RuntimeException(self::MAPPING_TYPE . ' does not have a valid value.');
}
diff --git a/lib/ACL/RuleManager.php b/lib/ACL/RuleManager.php
index 268ec0b12..d1f635fd4 100644
--- a/lib/ACL/RuleManager.php
+++ b/lib/ACL/RuleManager.php
@@ -29,7 +29,7 @@ public function __construct(
* @param array{mapping_type?: 'user'|'group'|'dummy'|'circle'|null, mapping_id: string, fileid: int|string, mask: int|string, permissions: int|string} $data
*/
private function createRule(array $data): ?Rule {
- if (empty($data['mapping_type'])) {
+ if (!isset($data['mapping_type'])) {
return null;
}
$mapping = $this->userMappingManager->mappingFromId($data['mapping_type'], $data['mapping_id']);
@@ -116,7 +116,7 @@ public function getRulesForFilesByPath(IUser $user, int $storageId, array $fileP
*/
public function getRulesForFilesByIds(IUser $user, array $fileIds): array {
$userMappings = $this->userMappingManager->getMappingsForUser($user);
- if (empty($userMappings)) {
+ if ($userMappings === []) {
return [];
}
@@ -144,7 +144,7 @@ public function getRulesForFilesByIds(IUser $user, array $fileIds): array {
*/
public function getRulesForFilesByParent(IUser $user, int $storageId, int $parentId): array {
$userMappings = $this->userMappingManager->getMappingsForUser($user);
- if (empty($userMappings)) {
+ if ($userMappings === []) {
return [];
}
@@ -312,7 +312,7 @@ public function getAllRulesForPrefix(int $storageId, string $prefix): array {
*/
public function getRulesForPrefix(IUser $user, int $storageId, string $prefix): array {
$userMappings = $this->userMappingManager->getMappingsForUser($user);
- if (empty($userMappings)) {
+ if ($userMappings === []) {
return [];
}
diff --git a/lib/Command/Create.php b/lib/Command/Create.php
index a8c56c029..31f84dfec 100644
--- a/lib/Command/Create.php
+++ b/lib/Command/Create.php
@@ -40,7 +40,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$name = $this->folderManager->trimMountpoint($name);
// Check if the folder name is valid
- if (empty($name)) {
+ if ($name === '') {
$output->writeln('Folder name cannot be empty');
return 1;
}
diff --git a/lib/Command/Rename.php b/lib/Command/Rename.php
index dccf76309..7bff3675e 100644
--- a/lib/Command/Rename.php
+++ b/lib/Command/Rename.php
@@ -38,7 +38,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
// Check if the new name is valid
$name = $this->folderManager->trimMountpoint($name);
- if (empty($name)) {
+ if ($name === '') {
$output->writeln('Folder name cannot be empty');
return 1;
}
diff --git a/lib/Folder/FolderManager.php b/lib/Folder/FolderManager.php
index 46853da25..9f394115a 100644
--- a/lib/Folder/FolderManager.php
+++ b/lib/Folder/FolderManager.php
@@ -528,7 +528,7 @@ public function canManageACL(int $folderId, IUser $user, bool $excludeAdmins = f
}
private function computeCanManageACL(int $folderId, IUser $user, bool $excludeAdmins): bool {
- $userId = $user->getUId();
+ $userId = $user->getUID();
if (!$excludeAdmins && $this->groupManager->isAdmin($userId)) {
return true;
}
@@ -1536,12 +1536,12 @@ public function updateOverwriteHomeFolders(): void {
$appIdsList = $this->appConfig->getValueArray('files', 'overwrites_home_folders');
if ($this->hasHomeFolderOverwriteMount()) {
- if (!in_array(Application::APP_ID, $appIdsList)) {
+ if (!in_array(Application::APP_ID, $appIdsList, true)) {
$appIdsList[] = Application::APP_ID;
$this->appConfig->setValueArray('files', 'overwrites_home_folders', $appIdsList);
}
} else {
- if (in_array(Application::APP_ID, $appIdsList)) {
+ if (in_array(Application::APP_ID, $appIdsList, true)) {
$appIdsList = array_values(array_filter($appIdsList, fn ($v): bool => $v !== Application::APP_ID));
$this->appConfig->setValueArray('files', 'overwrites_home_folders', $appIdsList);
}
diff --git a/lib/Mount/GroupMountPoint.php b/lib/Mount/GroupMountPoint.php
index c3493be4d..a6e56b663 100644
--- a/lib/Mount/GroupMountPoint.php
+++ b/lib/Mount/GroupMountPoint.php
@@ -54,7 +54,7 @@ public function getSourcePath(): string {
$storage = $this->storage;
if ($storage && $storage->instanceOfStorage(Jail::class)) {
/** @var Jail $storage */
- return $storage->getUnJailedPath('');
+ return $storage->getUnjailedPath('');
}
return '';
diff --git a/lib/Mount/MountProvider.php b/lib/Mount/MountProvider.php
index a84777dc2..60227986f 100644
--- a/lib/Mount/MountProvider.php
+++ b/lib/Mount/MountProvider.php
@@ -72,7 +72,7 @@ public function getMountsForUser(IUser $user, IStorageFactory $loader): array {
return array_map(function (FolderDefinitionWithPermissions $folder) use ($user, $loader, $conflicts, $aclManager, $rootRules): IMountPoint {
// check for existing files in the user home and rename them if needed
$originalFolderName = $folder->mountPoint;
- if (in_array($originalFolderName, $conflicts)) {
+ if (in_array($originalFolderName, $conflicts, true)) {
/** @var IStorage $userStorage */
$userStorage = $this->mountProviderCollection->getHomeMountForUser($user)->getStorage();
$userCache = $userStorage->getCache();
diff --git a/lib/Service/ApplicationService.php b/lib/Service/ApplicationService.php
index a5cffcae2..ebdd5b2e6 100644
--- a/lib/Service/ApplicationService.php
+++ b/lib/Service/ApplicationService.php
@@ -24,6 +24,6 @@ public function __construct(
public function checkAppsInstalled(): bool {
$diffApps = array_diff(Application::APPS_USE_GROUPFOLDERS, $this->appManager->getEnabledApps());
- return empty($diffApps);
+ return $diffApps === [];
}
}
diff --git a/lib/Service/FoldersFilter.php b/lib/Service/FoldersFilter.php
index 6bfba5585..b0e12fd03 100644
--- a/lib/Service/FoldersFilter.php
+++ b/lib/Service/FoldersFilter.php
@@ -35,10 +35,10 @@ public function getForApiUser(array $folders): array {
return array_filter($folders, function (array $folder) use ($user): bool {
foreach ($folder['manage'] as $manager) {
if ($manager['type'] === 'group') {
- if ($this->groupManager->isInGroup($user->getUid(), $manager['id'])) {
+ if ($this->groupManager->isInGroup($user->getUID(), $manager['id'])) {
return true;
}
- } elseif ($manager['id'] === $user->getUid()) {
+ } elseif ($manager['id'] === $user->getUID()) {
return true;
}
}
diff --git a/lib/Versions/VersionsBackend.php b/lib/Versions/VersionsBackend.php
index 2d6f58a15..c232f7f8e 100644
--- a/lib/Versions/VersionsBackend.php
+++ b/lib/Versions/VersionsBackend.php
@@ -112,7 +112,7 @@ public function getVersionsForFile(IUser $user, FileInfo $file): array {
throw new RuntimeException('Failed to get id of file.');
}
$versionEntity->setFileId($fileId);
- $versionEntity->setTimestamp($file->getMTime());
+ $versionEntity->setTimestamp($file->getMtime());
$versionEntity->setSize($file->getSize());
$versionEntity->setMimetype($this->mimeTypeLoader->getId($file->getMimetype()));
$versionEntity->setDecodedMetadata([]);
@@ -135,7 +135,7 @@ public function getVersionsForFile(IUser $user, FileInfo $file): array {
// This means that the name of some versions is the exact mtime of the next version. This behavior is now fixed.
// To prevent occasional conflicts between the last version and the current one, we decrement the last version mtime.
$mtime = (int)$version->getName();
- if ($mtime === $file->getMTime()) {
+ if ($mtime === $file->getMtime()) {
$versionEntity->setTimestamp($mtime - 1);
$version->move($version->getParent()->getPath() . '/' . ($mtime - 1));
} else {
@@ -427,7 +427,7 @@ public function createVersionEntity(File $file): null {
$versionEntity->setFileId($fileId);
$versionEntity->setTimestamp($timestamp);
$versionEntity->setSize($file->getSize());
- $versionEntity->setMimetype($this->mimeTypeLoader->getId($file->getMimetype()));
+ $versionEntity->setMimetype($this->mimeTypeLoader->getId($file->getMimeType()));
$versionEntity->setDecodedMetadata([]);
$this->groupVersionsMapper->insert($versionEntity);
}
@@ -494,7 +494,7 @@ public function importVersionsForFile(IUser $user, Node $source, Node $target, a
$versionEntity->setFileId($target->getId());
$versionEntity->setTimestamp($version->getTimestamp());
$versionEntity->setSize($version->getSize());
- $versionEntity->setMimetype($this->mimeTypeLoader->getId($version->getMimetype()));
+ $versionEntity->setMimetype($this->mimeTypeLoader->getId($version->getMimeType()));
if ($version instanceof IMetadataVersion) {
$versionEntity->setDecodedMetadata($version->getMetadata());
}
diff --git a/phpstan.neon b/phpstan.neon
index e746422c4..50bad73ae 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -1,5 +1,8 @@
# SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: AGPL-3.0-or-later
+includes:
+ - vendor-bin/phpstan/vendor/phpstan/phpstan-strict-rules/rules.neon
+
parameters:
level: 10
phpVersion:
@@ -9,6 +12,12 @@ parameters:
- lib
- templates
- tests
+ strictRules:
+ allRules: false
+ strictFunctionCalls: true
+ disallowedLooseComparison: true
+ disallowedEmpty: true
+ disallowedImplicitArrayCreation: true
excludePaths:
- tests/stubs
scanDirectories:
diff --git a/tests/ACL/ACLManagerTest.php b/tests/ACL/ACLManagerTest.php
index c78382e11..f526119e1 100644
--- a/tests/ACL/ACLManagerTest.php
+++ b/tests/ACL/ACLManagerTest.php
@@ -48,7 +48,7 @@ protected function setUp(): void {
/** @var string[] $paths */
$this->requestedPaths = array_values(array_merge($this->requestedPaths, $paths));
$rules = array_fill_keys($paths, []);
- $actualRules = array_filter($this->rules, fn (string $path): bool => array_search($path, $paths) !== false, ARRAY_FILTER_USE_KEY);
+ $actualRules = array_filter($this->rules, fn (string $path): bool => array_search($path, $paths, true) !== false, ARRAY_FILTER_USE_KEY);
return array_merge($rules, $actualRules);
});
diff --git a/vendor-bin/phpstan/composer.json b/vendor-bin/phpstan/composer.json
index 5111129c6..602e266b1 100644
--- a/vendor-bin/phpstan/composer.json
+++ b/vendor-bin/phpstan/composer.json
@@ -1,5 +1,6 @@
{
"require-dev": {
- "phpstan/phpstan": "^2.2"
+ "phpstan/phpstan": "^2.2",
+ "phpstan/phpstan-strict-rules": "^2.0"
}
}
diff --git a/vendor-bin/phpstan/composer.lock b/vendor-bin/phpstan/composer.lock
index 53d98e585..b2bf85268 100644
--- a/vendor-bin/phpstan/composer.lock
+++ b/vendor-bin/phpstan/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "a51b3f39b291c98954d42def89bce21e",
+ "content-hash": "1e46f1af4fc47e311cc3d5016311ba28",
"packages": [],
"packages-dev": [
{
@@ -70,6 +70,58 @@
}
],
"time": "2026-08-22T07:38:16+00:00"
+ },
+ {
+ "name": "phpstan/phpstan-strict-rules",
+ "version": "2.0.12",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpstan/phpstan-strict-rules.git",
+ "reference": "2bc5ae19ae965663b62ac907ee6342c3903ec93b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/2bc5ae19ae965663b62ac907ee6342c3903ec93b",
+ "reference": "2bc5ae19ae965663b62ac907ee6342c3903ec93b",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4 || ^8.0",
+ "phpstan/phpstan": "^2.1.52"
+ },
+ "require-dev": {
+ "php-parallel-lint/php-parallel-lint": "^1.2",
+ "phpstan/phpstan-deprecation-rules": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.6",
+ "shipmonk/name-collision-detector": "^2.1"
+ },
+ "type": "phpstan-extension",
+ "extra": {
+ "phpstan": {
+ "includes": [
+ "rules.neon"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PHPStan\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Extra strict and opinionated rules for PHPStan",
+ "keywords": [
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
+ "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.12"
+ },
+ "time": "2026-07-19T07:24:06+00:00"
}
],
"aliases": [],