diff --git a/apps/dav/lib/Connector/Sabre/Node.php b/apps/dav/lib/Connector/Sabre/Node.php
index 799a273aaf6..b2ecf9b2f6a 100644
--- a/apps/dav/lib/Connector/Sabre/Node.php
+++ b/apps/dav/lib/Connector/Sabre/Node.php
@@ -28,6 +28,7 @@ use OCP\Lock\LockedException;
use OCP\PreConditionNotMetException;
use OCP\Server;
use OCP\Share\Exceptions\ShareNotFound;
+use OCP\Share\IAttributes;
use OCP\Share\IManager;
use RuntimeException;
use Sabre\DAV\Exception;
@@ -297,7 +298,7 @@ abstract class Node implements INode {
$attributes = [];
if ($storage->instanceOfStorage(ISharedStorage::class)) {
$attributes = $storage->getShare()->getAttributes();
- if ($attributes === null) {
+ if (!$attributes instanceof IAttributes) {
return [];
}
diff --git a/build/rector-strict.php b/build/rector-strict.php
index 3bc07860bd3..c8b655cdb6f 100644
--- a/build/rector-strict.php
+++ b/build/rector-strict.php
@@ -25,6 +25,10 @@ return (require __DIR__ . '/rector-shared.php')
$nextcloudDir . '/lib/private/DB/QueryBuilder/TypedQueryBuilder.php',
$nextcloudDir . '/lib/public/DB/QueryBuilder/ITypedQueryBuilder.php',
])
+ ->withAutoloadPaths([
+ // ensure rector properly autoload the public interfaces
+ $nextcloudDir . '/lib/public',
+ ])
->withPreparedSets(
deadCode: true,
codeQuality: true,
diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php
index bb3f3840dd5..88a2f5a89a8 100644
--- a/lib/private/TemplateLayout.php
+++ b/lib/private/TemplateLayout.php
@@ -163,7 +163,8 @@ class TemplateLayout {
$page->assign('appid', $appId);
$page->assign('bodyid', 'body-public');
- $this->initialState->provideInitialState('core', 'apps', [$this->navigationManager->get($appId)]);
+ $currentAppData = $this->navigationManager->get($appId);
+ $this->initialState->provideInitialState('core', 'apps', $currentAppData === null ? [] : [$currentAppData]);
// Set logo link target
$logoUrl = $this->config->getSystemValueString('logo_url', '');
diff --git a/psalm-strict.xml b/psalm-strict.xml
index 95d52600434..d8f2488e2fa 100644
--- a/psalm-strict.xml
+++ b/psalm-strict.xml
@@ -15,6 +15,9 @@
findUnusedVariablesAndParams="true"
phpVersion="8.2"
>
+
+
+
@@ -34,7 +37,6 @@
-
@@ -43,6 +45,9 @@
+
+
+
diff --git a/psalm.xml b/psalm.xml
index 655aaa2625c..d3ef1770aca 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -20,6 +20,7 @@
+
diff --git a/tests/lib/TestCase.php b/tests/lib/TestCase.php
index 8944ad148ce..4b4497a070b 100644
--- a/tests/lib/TestCase.php
+++ b/tests/lib/TestCase.php
@@ -27,6 +27,7 @@ use OC\User\Session;
use OCP\Command\IBus;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\IRootFolder;
+use OCP\IAppConfig;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IUserManager;
@@ -195,6 +196,22 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase {
call_user_func([$this, $methodName]);
}
}
+
+ // Clean up encryption state to prevent test pollution
+ // This ensures encryption_enabled is reset after each test, preventing
+ // MultiKeyEncryptException failures in subsequent tests when encryption
+ // is left enabled but user keys don't exist
+ try {
+ $appConfig = Server::get(IAppConfig::class);
+ $currentValue = $appConfig->getValueBool('core', 'encryption_enabled', false);
+ if ($currentValue) {
+ $appConfig->setValueBool('core', 'encryption_enabled', false);
+ $appConfig->deleteKey('core', 'default_encryption_module');
+ $appConfig->deleteKey('encryption', 'useMasterKey');
+ }
+ } catch (\Throwable $e) {
+ // Ignore - may be called before bootstrap completes
+ }
}
/**
diff --git a/vendor-bin/psalm/composer.json b/vendor-bin/psalm/composer.json
index 78da32f7fb6..ea55244560f 100644
--- a/vendor-bin/psalm/composer.json
+++ b/vendor-bin/psalm/composer.json
@@ -1,7 +1,4 @@
{
- "require": {
- "vimeo/psalm": "^6.16"
- },
"config": {
"platform": {
"php": "8.2.27"
@@ -9,5 +6,9 @@
"allow-plugins": {
"composer/package-versions-deprecated": true
}
+ },
+ "require": {
+ "psalm/plugin-phpunit": "^0.19.7",
+ "vimeo/psalm": "^6.16"
}
}
diff --git a/vendor-bin/psalm/composer.lock b/vendor-bin/psalm/composer.lock
index 0e9b269c8ea..9798c9cee16 100644
--- a/vendor-bin/psalm/composer.lock
+++ b/vendor-bin/psalm/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": "7591b157e86a8c10c3360618317e822c",
+ "content-hash": "305efadf319961c090d8cd0b425471b1",
"packages": [
{
"name": "amphp/amp",
@@ -1915,6 +1915,64 @@
},
"time": "2026-01-25T14:56:51+00:00"
},
+ {
+ "name": "psalm/plugin-phpunit",
+ "version": "0.19.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/psalm/psalm-plugin-phpunit.git",
+ "reference": "143f9d5e049fffcdbc0da3fbb99f6149f9d3e2dc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/psalm/psalm-plugin-phpunit/zipball/143f9d5e049fffcdbc0da3fbb99f6149f9d3e2dc",
+ "reference": "143f9d5e049fffcdbc0da3fbb99f6149f9d3e2dc",
+ "shasum": ""
+ },
+ "require": {
+ "ext-simplexml": "*",
+ "php": ">=8.1",
+ "vimeo/psalm": "dev-master || ^6.10.0"
+ },
+ "conflict": {
+ "phpspec/prophecy": "<1.20.0",
+ "phpspec/prophecy-phpunit": "<2.3.0",
+ "phpunit/phpunit": "<8.5.1"
+ },
+ "require-dev": {
+ "php": "^7.3 || ^8.0",
+ "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0",
+ "squizlabs/php_codesniffer": "^3.3.1",
+ "weirdan/prophecy-shim": "^1.0 || ^2.0"
+ },
+ "type": "psalm-plugin",
+ "extra": {
+ "psalm": {
+ "pluginClass": "Psalm\\PhpUnitPlugin\\Plugin"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psalm\\PhpUnitPlugin\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Matt Brown",
+ "email": "github@muglug.com"
+ }
+ ],
+ "description": "Psalm plugin for PHPUnit",
+ "support": {
+ "issues": "https://github.com/psalm/psalm-plugin-phpunit/issues",
+ "source": "https://github.com/psalm/psalm-plugin-phpunit/tree/0.19.7"
+ },
+ "time": "2025-03-31T18:49:55+00:00"
+ },
{
"name": "psr/container",
"version": "2.0.2",
diff --git a/version.php b/version.php
index 54d45acc85f..b046ba22664 100644
--- a/version.php
+++ b/version.php
@@ -11,10 +11,10 @@ declare(strict_types=1);
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patch level
// when updating major/minor version number.
-$OC_Version = [34, 0, 0, 2];
+$OC_Version = [34, 0, 0, 3];
// The human-readable string
-$OC_VersionString = '34.0.0 beta 1';
+$OC_VersionString = '34.0.0 beta 2';
$OC_VersionCanBeUpgradedFrom = [
'nextcloud' => [