Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
"cs:check": "php-cs-fixer fix --dry-run --diff",
"cs:fix": "php-cs-fixer fix",
"test:unit": "phpunit -c tests/phpunit.xml",
"psalm": "psalm --no-cache --threads=$(nproc)"
"psalm": "psalm --no-cache --threads=$(nproc)",
"rector:check": "rector --dry-run --clear-cache",
"rector:fix": "rector && php-cs-fixer fix"
},
"autoload-dev": {
"psr-4": {
Expand Down
4 changes: 1 addition & 3 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ public function register(IRegistrationContext $context): void {
if (defined('OC_CONSOLE') && \OC_CONSOLE) {
$context->registerEventListener(BeforeMessageLoggedEvent::class, LogListener::class);
}
$context->registerService(Formatter::class, function () {
return new Formatter(\OC::$SERVERROOT);
});
$context->registerService(Formatter::class, fn () => new Formatter(\OC::$SERVERROOT));

$context->registerSetupCheck(LogErrors::class);
}
Expand Down
24 changes: 10 additions & 14 deletions lib/Command/Tail.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,11 @@
class Tail extends Base {
public const LEVELS = ['Debug', 'Info', 'Warning', 'Error', 'Fatal'];

private $formatter;
private $logIteratorFactory;

public function __construct(Formatter $formatter, LogIteratorFactory $logIteratorFactory) {
public function __construct(
private readonly Formatter $formatter,
private readonly LogIteratorFactory $logIteratorFactory,
) {
parent::__construct();
$this->formatter = $formatter;
$this->logIteratorFactory = $logIteratorFactory;
}

#[\Override]
Expand Down Expand Up @@ -64,14 +62,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
// 8 level, 18 for app, 26 for time, 6 for formatting
$messageWidth = $totalWidth - 8 - 18 - 26 - 6;

$tableItems = array_map(function (array $logItem) use ($messageWidth) {
return [
self::LEVELS[$logItem['level']],
wordwrap($logItem['app'], 18),
$this->formatter->formatMessage($logItem, $messageWidth) . "\n",
$logItem['time'],
];
}, $logItems);
$tableItems = array_map(fn (array $logItem) => [
self::LEVELS[$logItem['level']],
wordwrap($logItem['app'], 18),
$this->formatter->formatMessage($logItem, $messageWidth) . "\n",
$logItem['time'],
], $logItems);
$io->table([
'Level',
'App',
Expand Down
34 changes: 10 additions & 24 deletions lib/Command/Watch.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,11 @@ class Watch extends Base {
public const LEVELS = ['Debug', 'Info', 'Warning', 'Error', 'Fatal'];
public const ALL_LEVELS = [0, 1, 2, 3, 4];

private $formatter;
private $logIteratorFactory;

public function __construct(Formatter $formatter, LogIteratorFactory $logIteratorFactory) {
public function __construct(
private readonly Formatter $formatter,
private readonly LogIteratorFactory $logIteratorFactory,
) {
parent::__construct();
$this->formatter = $formatter;
$this->logIteratorFactory = $logIteratorFactory;
}

#[\Override]
Expand Down Expand Up @@ -66,7 +64,7 @@ public function watch(bool $raw, OutputInterface $output): int {
usleep(100 * 1000);
try {
$this->abortIfInterrupted();
} catch (InterruptedException $e) {
} catch (InterruptedException) {
break;
}

Expand Down Expand Up @@ -116,24 +114,12 @@ private function printItem(array $logItem, OutputInterface $output, int $message
$logItem['time'],
];

$partLines = array_map(function ($part) {
return explode("\n", $part);
}, $parts);
$lineCount = array_reduce($partLines, function (int $count, array $lines) {
return max($count, count($lines));
}, 0);
$partLines = array_map(function (array $lines) use ($lineCount) {
return array_pad($lines, $lineCount, '');
}, $partLines);
$partLines = array_map(function (array $lines, int $width) {
return array_map(function (string $line) use ($width) {
return str_pad($line, $width);
}, $lines);
}, $partLines, $widths);
$partLines = array_map(fn ($part) => explode("\n", $part), $parts);
$lineCount = array_reduce($partLines, fn (int $count, array $lines) => max($count, count($lines)), 0);
$partLines = array_map(fn (array $lines) => array_pad($lines, $lineCount, ''), $partLines);
$partLines = array_map(fn (array $lines, int $width) => array_map(fn (string $line) => str_pad($line, $width), $lines), $partLines, $widths);
$lines = array_map(function (int $lineNumber) use ($partLines) {
$partsForLine = array_map(function (array $lines) use ($lineNumber) {
return $lines[$lineNumber];
}, $partLines);
$partsForLine = array_map(fn (array $lines) => $lines[$lineNumber], $partLines);
return implode(' ', $partsForLine);
}, range(0, $lineCount - 1));

Expand Down
6 changes: 3 additions & 3 deletions lib/Controller/LogController.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ class LogController extends Controller {
public function __construct(
$appName,
IRequest $request,
private LogIteratorFactory $logIteratorFactory,
private SettingsService $settingsService,
private LoggerInterface $logger,
private readonly LogIteratorFactory $logIteratorFactory,
private readonly SettingsService $settingsService,
private readonly LoggerInterface $logger,
) {
parent::__construct($appName, $request);
}
Expand Down
7 changes: 3 additions & 4 deletions lib/Controller/PageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,15 @@
class PageController extends Controller {

public function __construct(
private IInitialState $initialState,
private SettingsService $settingsService,
private readonly IInitialState $initialState,
private readonly SettingsService $settingsService,
) {
}

/**
* @NoCSRFRequired
*
* @return TemplateResponse
*/
#[\OCP\AppFramework\Http\Attribute\NoCSRFRequired]
public function index() {
Util::addScript($this->appName, 'logreader-main');
Util::addStyle($this->appName, 'logreader-main');
Expand Down
6 changes: 3 additions & 3 deletions lib/Controller/SettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ class SettingsController extends ApiController {
public function __construct(
string $appName,
IRequest $request,
private SettingsService $settingsService,
private IConfig $config,
private LoggerInterface $logger,
private readonly SettingsService $settingsService,
private readonly IConfig $config,
private readonly LoggerInterface $logger,
) {
parent::__construct($appName, $request);
}
Expand Down
35 changes: 15 additions & 20 deletions lib/Log/Console.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@
* Utility to write log messages to the console as they are emitted
*/
class Console extends LogDetails {
private int $level;
private int $terminalWidth;
private Formatter $formatter;
private readonly int $level;

public function __construct(Formatter $formatter, SystemConfig $config, string $level, int $terminalWidth) {
public function __construct(
private readonly Formatter $formatter,
SystemConfig $config,
string $level,
private readonly int $terminalWidth,
) {
parent::__construct($config);
$this->formatter = $formatter;
$this->level = self::parseLogLevel($level);
$this->terminalWidth = $terminalWidth;
}

public function log(int $level, string $app, array $entry) {
Expand Down Expand Up @@ -54,19 +55,13 @@ private static function parseLogLevel(string $level): int {
return (int)$level;
}

switch (strtoupper($level)) {
case 'DEBUG':
return 0;
case 'INFO':
return 1;
case 'WARN':
return 2;
case 'ERROR':
return 3;
case 'FATAL':
return 4;
default:
throw new \Exception("Unknown log level $level");
}
return match (strtoupper($level)) {
'DEBUG' => 0,
'INFO' => 1,
'WARN' => 2,
'ERROR' => 3,
'FATAL' => 4,
default => throw new \Exception("Unknown log level $level"),
};
}
}
25 changes: 8 additions & 17 deletions lib/Log/Formatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@
namespace OCA\LogReader\Log;

class Formatter {
private $root;

public function __construct(string $root) {
$this->root = $root;
public function __construct(
private readonly string $root,
) {
}

public function formatMessage($logItem, int $width) {
Expand All @@ -29,9 +28,7 @@ private function formatException(array $e, int $width) {
$largestIndex = count($e['Trace']) - 1;
$largestIndexWidth = strlen((string)$largestIndex);
$message = wordwrap($e['Exception'] . ': ' . $e['Message'] . ' at ' . $this->getFileAndLine($e), $width) . "\n\n";
$message .= implode("\n", array_map(function ($index, $trace) use ($largestIndexWidth, $width) {
return $this->formatTraceLine($index, $trace, $largestIndexWidth, $width);
}, array_keys($e['Trace']), array_values($e['Trace'])));
$message .= implode("\n", array_map(fn ($index, $trace) => $this->formatTraceLine($index, $trace, $largestIndexWidth, $width), array_keys($e['Trace']), array_values($e['Trace'])));

if (isset($e['Previous'])) {
$message .= "\n\n" . 'Caused by ' . $this->formatException($e['Previous'], $width);
Expand All @@ -58,9 +55,7 @@ private function formatTraceLine(int $index, array $trace, int $largestIndexWidt
} else {
return $whiteSpace . $index . '. ' . $this->getFileAndLine($trace, $argumentWidth) . "\n"
. $argumentWhiteSpace . $method . "(\n"
. implode(",\n", array_map(function ($argumentLine) use ($argumentWhiteSpace) {
return $argumentWhiteSpace . ' ' . trim($argumentLine);
}, $arguments)) . "\n"
. implode(",\n", array_map(fn ($argumentLine) => $argumentWhiteSpace . ' ' . trim($argumentLine), $arguments)) . "\n"
. $argumentWhiteSpace . ')';
}
}
Expand All @@ -80,14 +75,10 @@ private function formatArgument($argument, int $whiteSpace, int $depth = 0, bool
if ($isObject) {
$keyWhitespace = str_repeat(' ', $whiteSpace * ($depth + 1));
return $leadingSpace . "{\n"
. implode($glue, array_map(function ($key, $value) use ($whiteSpace, $depth, $keyWhitespace) {
return $keyWhitespace . $key . ':' . trim($this->formatArgument($value, $whiteSpace, $depth + 1));
}, array_keys($argument), array_values($argument))) . ($whiteSpace ? "\n" : '') . $leadingSpace . '}';
. implode($glue, array_map(fn ($key, $value) => $keyWhitespace . $key . ':' . trim($this->formatArgument($value, $whiteSpace, $depth + 1)), array_keys($argument), array_values($argument))) . ($whiteSpace ? "\n" : '') . $leadingSpace . '}';
} else {
return $leadingSpace . "[\n"
. implode($glue, array_map(function ($value) use ($whiteSpace, $depth) {
return $this->formatArgument($value, $whiteSpace, $depth + 1);
}, $argument)) . ($whiteSpace ? "\n" : '') . $leadingSpace . ']';
. implode($glue, array_map(fn ($value) => $this->formatArgument($value, $whiteSpace, $depth + 1), $argument)) . ($whiteSpace ? "\n" : '') . $leadingSpace . ']';
}
} else {
$value = json_encode($argument, $whiteSpace ? JSON_PRETTY_PRINT : 0);
Expand All @@ -106,7 +97,7 @@ private function getFileAndLine(array $item, int $width = 64): string {
$fileWidth = $width - strlen($postFix) - 4;
$prefix = '';
$count = 0;
while (strlen($file) > $fileWidth && strpos($file, '/') !== false && $count < 20) {
while (strlen($file) > $fileWidth && str_contains($file, '/') && $count < 20) {
$file = substr($file, strpos($file, '/') + 1);
$prefix = '.../';
$count++;
Expand Down
15 changes: 6 additions & 9 deletions lib/Log/LogIterator.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,7 @@
* @template-implements \Iterator<int,array>
*/
class LogIterator implements \Iterator {
/**
* @var resource
*/
private $handle;
private string $dateFormat;
private \DateTimeZone $timezone;
private readonly \DateTimeZone $timezone;

private string $buffer = '';
private string $lastLine = '';
Expand All @@ -31,9 +26,11 @@ class LogIterator implements \Iterator {
* @param string $dateFormat
* @param string $timezone
*/
public function __construct($handle, string $dateFormat, string $timezone) {
$this->handle = $handle;
$this->dateFormat = $dateFormat;
public function __construct(
private $handle,
private readonly string $dateFormat,
string $timezone,
) {
$this->timezone = new \DateTimeZone($timezone);
$this->rewind();
}
Expand Down
8 changes: 3 additions & 5 deletions lib/Log/LogIteratorFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
*/
class LogIteratorFactory {
public function __construct(
private IConfig $config,
private ILogFactory $logFactory,
private readonly IConfig $config,
private readonly ILogFactory $logFactory,
) {
}

Expand All @@ -40,9 +40,7 @@ public function getLogIterator(array $levels): \Iterator {
$handle = fopen($log->getLogFilePath(), 'rb');
if ($handle) {
$iterator = new LogIterator($handle, $dateFormat, $timezone);
return new \CallbackFilterIterator($iterator, function ($logItem) use ($levels) {
return $logItem && in_array($logItem['level'], $levels);
});
return new \CallbackFilterIterator($iterator, fn ($logItem) => $logItem && in_array($logItem['level'], $levels));
} else {
throw new \Exception('Error while opening ' . $log->getLogFilePath());
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Log/SearchFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function __construct(\Iterator $iterator, string $query) {
}

private function formatLevel(int $level): string {
return isset($this->levels[$level]) ? $this->levels[$level] : 'Unknown';
return $this->levels[$level] ?? 'Unknown';
}

#[\Override]
Expand Down
6 changes: 3 additions & 3 deletions lib/Settings/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
class Admin implements IDelegatedSettings {

public function __construct(
private string $appName,
private IInitialState $initialState,
private SettingsService $settingsService,
private readonly string $appName,
private readonly IInitialState $initialState,
private readonly SettingsService $settingsService,
) {
}

Expand Down
12 changes: 6 additions & 6 deletions lib/SetupChecks/LogErrors.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
* @psalm-api
*/
class LogErrors implements ISetupCheck {
private const LEVEL_WARNING = 2;
private const LEVEL_ERROR = 3;
private const LEVEL_FATAL = 4;
private const int LEVEL_WARNING = 2;
private const int LEVEL_ERROR = 3;
private const int LEVEL_FATAL = 4;

public function __construct(
private IL10N $l10n,
private IDateTimeFormatter $dateFormatter,
private LogIteratorFactory $logIteratorFactory,
private readonly IL10N $l10n,
private readonly IDateTimeFormatter $dateFormatter,
private readonly LogIteratorFactory $logIteratorFactory,
) {
}

Expand Down
28 changes: 28 additions & 0 deletions rector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

use Nextcloud\Rector\Rector\ReplaceInjectedMethodCallRector;
use Nextcloud\Rector\Set\NextcloudSets;
use Rector\Config\RectorConfig;

return RectorConfig::configure()
->withPaths([
__DIR__ . '/appinfo',
__DIR__ . '/lib',
__DIR__ . '/templates',
__DIR__ . '/tests/Unit',
])
->withPhpSets(php83: true)
->withSets([
NextcloudSets::NEXTCLOUD_35,
])
->withSkip([
// Rewrites to untyped IAppConfig::getValue()/setValue(); OCP only has typed getters/setters, so the type must be picked per call site
ReplaceInjectedMethodCallRector::class,
])
->withTypeCoverageLevel(0);
Loading
Loading