Merge pull request #57116 from nextcloud/php/8.5

ci(PHP): Test against 8.5 on CI
This commit is contained in:
Joas Schilling 2025-12-19 16:38:16 +01:00 committed by GitHub
commit aec12f5b51
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 72 additions and 62 deletions

View file

@ -47,7 +47,7 @@ jobs:
strategy:
matrix:
php-versions: [ '8.2', '8.3', '8.4' ]
php-versions: [ '8.2', '8.3', '8.4', '8.5' ]
name: php-lint

View file

@ -60,13 +60,15 @@ jobs:
fail-fast: false
matrix:
php-versions: ['8.2']
mariadb-versions: ['10.3', '10.6', '10.11', '11.4', '11.8']
mariadb-versions: ['10.6', '10.11', '11.4', '11.8']
include:
- php-versions: '8.3'
mariadb-versions: '10.11'
coverage: ${{ github.event_name != 'pull_request' }}
- php-versions: '8.4'
mariadb-versions: '11.8'
- php-versions: '8.5'
mariadb-versions: '11.8'
name: MariaDB ${{ matrix.mariadb-versions }} (PHP ${{ matrix.php-versions }}) - database tests

View file

@ -56,7 +56,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php-versions: ['8.3', '8.4']
php-versions: ['8.3', '8.4', '8.5']
include:
- php-versions: '8.2'
coverage: ${{ github.event_name != 'pull_request' }}

View file

@ -67,6 +67,8 @@ jobs:
coverage: ${{ github.event_name != 'pull_request' }}
- mysql-versions: '8.4'
php-versions: '8.4'
- mysql-versions: '8.4'
php-versions: '8.5'
name: MySQL ${{ matrix.mysql-versions }} (PHP ${{ matrix.php-versions }}) - database tests

View file

@ -59,7 +59,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php-versions: ['8.3', '8.4']
php-versions: ['8.3', '8.4', '8.5']
include:
- php-versions: '8.2'
coverage: ${{ github.event_name != 'pull_request' }}

View file

@ -69,6 +69,8 @@ jobs:
php-versions: '8.3'
- oracle-versions: '23'
php-versions: '8.4'
- oracle-versions: '23'
php-versions: '8.5'
name: Oracle ${{ matrix.oracle-versions }} (PHP ${{ matrix.php-versions }}) - database tests

View file

@ -68,6 +68,8 @@ jobs:
coverage: ${{ github.event_name != 'pull_request' }}
- php-versions: '8.4'
postgres-versions: '18'
- php-versions: '8.5'
postgres-versions: '18'
name: PostgreSQL ${{ matrix.postgres-versions }} (PHP ${{ matrix.php-versions }}) - database tests

View file

@ -59,7 +59,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php-versions: ['8.3', '8.4']
php-versions: ['8.3', '8.4', '8.5']
include:
- php-versions: '8.2'
coverage: ${{ github.event_name != 'pull_request' }}

View file

@ -375,7 +375,6 @@ class SharedMountTest extends TestCase {
$mountProvider = Server::get(MountProvider::class);
$reflectionClass = new \ReflectionClass($mountProvider);
$reflectionCacheFactory = $reflectionClass->getProperty('cacheFactory');
$reflectionCacheFactory->setAccessible(true);
$reflectionCacheFactory->setValue($mountProvider, $cacheFactory);
// share to user

View file

@ -88,12 +88,23 @@ class ConnectionFactory {
throw new \InvalidArgumentException("Unsupported type: $type");
}
$result = $this->defaultConnectionParams[$normalizedType];
// \PDO::MYSQL_ATTR_FOUND_ROWS may not be defined, e.g. when the MySQL
// driver is missing. In this case, we won't be able to connect anyway.
if ($normalizedType === 'mysql' && defined('\PDO::MYSQL_ATTR_FOUND_ROWS')) {
$result['driverOptions'] = [
\PDO::MYSQL_ATTR_FOUND_ROWS => true,
];
/**
* {@see \PDO::MYSQL_ATTR_FOUND_ROWS} may not be defined, e.g. when the MySQL
* driver is missing. In this case, we won't be able to connect anyway.
* In PHP 8.5 it's deprecated and {@see \Pdo\Mysql::ATTR_FOUND_ROWS} should be used,
* but that is only available since PHP 8.4
*/
if ($normalizedType === 'mysql') {
if (PHP_VERSION_ID >= 80500 && class_exists(\Pdo\Mysql::class)) {
/** @psalm-suppress UndefinedClass */
$result['driverOptions'] = [
\Pdo\Mysql::ATTR_FOUND_ROWS => true,
];
} elseif (PHP_VERSION_ID < 80500 && defined('\PDO::MYSQL_ATTR_FOUND_ROWS')) {
$result['driverOptions'] = [
\PDO::MYSQL_ATTR_FOUND_ROWS => true,
];
}
}
return $result;
}

View file

@ -44,7 +44,11 @@ class SQLiteSessionInit implements EventSubscriber {
/** @var \Doctrine\DBAL\Driver\PDO\Connection $connection */
$connection = $args->getConnection()->getWrappedConnection();
$pdo = $connection->getWrappedConnection();
$pdo->sqliteCreateFunction('md5', 'md5', 1);
if (PHP_VERSION_ID >= 80500 && method_exists($pdo, 'createFunction')) {
$pdo->createFunction('md5', 'md5', 1);
} else {
$pdo->sqliteCreateFunction('md5', 'md5', 1);
}
}
public function getSubscribedEvents() {

View file

@ -839,7 +839,6 @@ class Image implements IImage {
return false;
}
$result = $this->resizeNew($maxSize);
imagedestroy($this->resource);
$this->resource = $result;
return $this->valid();
}
@ -875,7 +874,6 @@ class Image implements IImage {
return false;
}
$result = $this->preciseResizeNew($width, $height);
imagedestroy($this->resource);
$this->resource = $result;
return $this->valid();
}

View file

@ -342,14 +342,14 @@ class Log implements ILogger, IDataLogger {
$this->error('Failed to load ExceptionSerializer serializer while trying to log ' . $exception->getMessage());
return;
}
$context = array_map($this->normalizer->format(...), $context);
$data = $context;
unset($data['app']);
unset($data['level']);
unset($data['app'], $data['level']);
$data = array_merge($serializer->serializeException($exception), $data);
$data = $this->interpolateMessage($data, isset($context['message']) && $context['message'] !== '' ? $context['message'] : ('Exception thrown: ' . get_class($exception)), 'CustomMessage');
array_walk($context, [$this->normalizer, 'format']);
$this->eventDispatcher?->dispatchTyped(new BeforeMessageLoggedEvent($app, $level, $data));
try {
@ -374,8 +374,7 @@ class Log implements ILogger, IDataLogger {
$level = $context['level'] ?? ILogger::ERROR;
$minLevel = $this->getLogLevel($context, $message);
array_walk($context, [$this->normalizer, 'format']);
$data = array_map($this->normalizer->format(...), $data);
try {
if ($level >= $minLevel) {
@ -385,8 +384,6 @@ class Log implements ILogger, IDataLogger {
}
$this->writeLog($app, $data, $level);
}
$context['level'] = $level;
} catch (Throwable $e) {
// make sure we dont hard crash if logging fails
error_log('Error when trying to log exception: ' . $e->getMessage() . ' ' . $e->getTraceAsString());

View file

@ -5,7 +5,7 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
// Show warning if a PHP version below 8.1 is used,
// Show warning if a PHP version below 8.2 is used,
if (PHP_VERSION_ID < 80200) {
http_response_code(500);
echo 'This version of Nextcloud requires at least PHP 8.2<br/>';
@ -13,10 +13,10 @@ if (PHP_VERSION_ID < 80200) {
exit(1);
}
// Show warning if >= PHP 8.5 is used as Nextcloud is not compatible with >= PHP 8.5 for now
if (PHP_VERSION_ID >= 80500) {
// Show warning if >= PHP 8.6 is used as Nextcloud is not compatible with >= PHP 8.6 for now
if (PHP_VERSION_ID >= 80600) {
http_response_code(500);
echo 'This version of Nextcloud is not compatible with PHP>=8.5.<br/>';
echo 'This version of Nextcloud is not compatible with PHP>=8.6.<br/>';
echo 'You are currently running ' . PHP_VERSION . '.';
exit(1);
}

View file

@ -1811,13 +1811,13 @@ class ViewTest extends \Test\TestCase {
['touch', ['test.txt'], 'test.txt', 'touch', null, null, null],
// ---- no hooks, no locks ---
['is_dir', ['dir'], 'dir', null],
['is_file', ['dir'], 'dir', null],
['is_dir', ['dir'], 'dir', ''],
['is_file', ['dir'], 'dir', ''],
[
'stat',
['dir'],
'dir',
null,
'',
ILockingProvider::LOCK_SHARED,
ILockingProvider::LOCK_SHARED,
ILockingProvider::LOCK_SHARED,
@ -1828,7 +1828,7 @@ class ViewTest extends \Test\TestCase {
'filetype',
['dir'],
'dir',
null,
'',
ILockingProvider::LOCK_SHARED,
ILockingProvider::LOCK_SHARED,
ILockingProvider::LOCK_SHARED,
@ -1839,7 +1839,7 @@ class ViewTest extends \Test\TestCase {
'filesize',
['dir'],
'dir',
null,
'',
ILockingProvider::LOCK_SHARED,
ILockingProvider::LOCK_SHARED,
ILockingProvider::LOCK_SHARED,
@ -1847,17 +1847,17 @@ class ViewTest extends \Test\TestCase {
/* Return an int */
100
],
['isCreatable', ['dir'], 'dir', null],
['isReadable', ['dir'], 'dir', null],
['isUpdatable', ['dir'], 'dir', null],
['isDeletable', ['dir'], 'dir', null],
['isSharable', ['dir'], 'dir', null],
['file_exists', ['dir'], 'dir', null],
['isCreatable', ['dir'], 'dir', ''],
['isReadable', ['dir'], 'dir', ''],
['isUpdatable', ['dir'], 'dir', ''],
['isDeletable', ['dir'], 'dir', ''],
['isSharable', ['dir'], 'dir', ''],
['file_exists', ['dir'], 'dir', ''],
[
'filemtime',
['dir'],
'dir',
null,
'',
ILockingProvider::LOCK_SHARED,
ILockingProvider::LOCK_SHARED,
ILockingProvider::LOCK_SHARED,
@ -1875,23 +1875,23 @@ class ViewTest extends \Test\TestCase {
* @param array $operationArgs arguments for the operation
* @param string $lockedPath path of the locked item to check
* @param string $hookType hook type
* @param int $expectedLockBefore expected lock during pre hooks
* @param int $expectedLockDuring expected lock during operation
* @param int $expectedLockAfter expected lock during post hooks
* @param int $expectedStrayLock expected lock after returning, should
* be null (unlock) for most operations
* @param ?int $expectedLockBefore expected lock during pre hooks
* @param ?int $expectedLockDuring expected lock during operation
* @param ?int $expectedLockAfter expected lock during post hooks
* @param ?int $expectedStrayLock expected lock after returning, should
* be null (unlock) for most operations
*/
#[\PHPUnit\Framework\Attributes\DataProvider('basicOperationProviderForLocks')]
public function testLockBasicOperation(
$operation,
$operationArgs,
$lockedPath,
$hookType,
$expectedLockBefore = ILockingProvider::LOCK_SHARED,
$expectedLockDuring = ILockingProvider::LOCK_SHARED,
$expectedLockAfter = ILockingProvider::LOCK_SHARED,
$expectedStrayLock = null,
$returnValue = true,
string $operation,
array $operationArgs,
string $lockedPath,
string $hookType,
?int $expectedLockBefore = ILockingProvider::LOCK_SHARED,
?int $expectedLockDuring = ILockingProvider::LOCK_SHARED,
?int $expectedLockAfter = ILockingProvider::LOCK_SHARED,
?int $expectedStrayLock = null,
mixed $returnValue = true,
): void {
$view = new View('/' . $this->user . '/files/');
@ -1931,7 +1931,7 @@ class ViewTest extends \Test\TestCase {
// do operation
call_user_func_array([$view, $operation], $operationArgs);
if ($hookType !== null) {
if ($hookType !== '') {
$this->assertEquals($expectedLockBefore, $lockTypePre, 'File locked properly during pre-hook');
$this->assertEquals($expectedLockAfter, $lockTypePost, 'File locked properly during post-hook');
$this->assertEquals($expectedLockDuring, $lockTypeDuring, 'File locked properly during operation');
@ -2530,7 +2530,7 @@ class ViewTest extends \Test\TestCase {
}
);
if ($hookType !== null) {
if ($hookType !== '') {
Util::connectHook(
Filesystem::CLASSNAME,
$hookType,

View file

@ -102,14 +102,12 @@ class HelperStorageTest extends \Test\TestCase {
private function getIncludeExternalStorage(): bool {
$class = new \ReflectionClass(\OC_Helper::class);
$prop = $class->getProperty('quotaIncludeExternalStorage');
$prop->setAccessible(true);
return $prop->getValue(null) ?? false;
}
private function setIncludeExternalStorage(bool $include) {
$class = new \ReflectionClass(\OC_Helper::class);
$prop = $class->getProperty('quotaIncludeExternalStorage');
$prop->setAccessible(true);
$prop->setValue(null, $include);
}

View file

@ -248,15 +248,10 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase {
if ($reflection->hasMethod($methodName)) {
$method = $reflection->getMethod($methodName);
$method->setAccessible(true);
return $method->invokeArgs($object, $parameters);
} elseif ($reflection->hasProperty($methodName)) {
$property = $reflection->getProperty($methodName);
$property->setAccessible(true);
if (!empty($parameters)) {
if ($property->isStatic()) {
$property->setValue(null, array_pop($parameters));