Skip to content

Commit 259974d

Browse files
authored
Add finder depth configuration option (#15)
1 parent 413f33e commit 259974d

File tree

11 files changed

+118
-34
lines changed

11 files changed

+118
-34
lines changed

dev/config/config.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,5 @@ monolog:
5050
fd_log_viewer:
5151
log_files:
5252
monolog:
53-
type: monolog
54-
name: Monolog
55-
finder:
56-
in: "%kernel.logs_dir%"
57-
name: "*.log"
5853
downloadable: true
5954
deletable: true

docs/configuration.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ fd_log_viewer:
1414
finder:
1515
in: "%kernel.logs_dir%"
1616
name: "*.log"
17+
depth: '== 0'
1718
ignoreUnreadableDirs: true
1819
followLinks: false
1920
downloadable: false
@@ -60,6 +61,16 @@ Example:
6061
*.log,*.txt
6162
```
6263

64+
### log_files.finder.depth <small>`int|string|string[]|null`</small>
65+
66+
The maximum depth of directories to search for log files. If set to null all subdirectories will be added. Default: `== 0`
67+
68+
Example:
69+
- `'== 0'` will only search in the specified directory.
70+
- `'>= 0'` will search in the specified directory and all subdirectories.
71+
- `['>= 0', '< 3]` will search in the specified directory and all subdirectories up to a depth of 2.
72+
73+
6374
### log_files.finder.ignoreUnreadableDirs <small>`boolean`</small>
6475

6576
Should unreadable directories by ignored. Default: `true`

src/DependencyInjection/Configuration.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ public function getConfigTreeBuilder(): TreeBuilder
4343
->info("The symfony/finder pattern to filter files. Example: *.log")
4444
->defaultNull()
4545
->end()
46+
->scalarNode('depth')
47+
->info("The symfony/finder directory depth to search files for. Example: > 0")
48+
->defaultNull()
49+
->end()
4650
->scalarNode('ignoreUnreadableDirs')
4751
->info("Whether to ignore unreadable directories")
4852
->defaultTrue()

src/DependencyInjection/Extension.php

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
use FD\LogViewer\Entity\Config\FinderConfig;
77
use FD\LogViewer\Entity\Config\LogFilesConfig;
8+
use FD\LogViewer\Util\Arrays;
89
use Symfony\Component\Config\FileLocator;
910
use Symfony\Component\DependencyInjection\ContainerBuilder;
1011
use Symfony\Component\DependencyInjection\Extension\Extension as BaseExtension;
@@ -18,6 +19,24 @@
1819
*/
1920
final class Extension extends BaseExtension
2021
{
22+
private const DEFAULT_MONOLOG_CONFIG = [
23+
'log_files' => [
24+
'monolog' => [
25+
'type' => 'monolog',
26+
'name' => 'Monolog',
27+
'downloadable' => false,
28+
'deletable' => false,
29+
'finder' => [
30+
'in' => '%kernel.logs_dir%',
31+
'name' => '*.log',
32+
'depth' => '== 0',
33+
'ignoreUnreadableDirs' => true,
34+
'followLinks' => false,
35+
],
36+
]
37+
]
38+
];
39+
2140
/**
2241
* @inheritDoc
2342
* @throws Throwable
@@ -31,14 +50,15 @@ public function load(array $configs, ContainerBuilder $container): void
3150

3251
// add defaults
3352
if ($mergedConfigs['enable_default_monolog']) {
34-
$mergedConfigs = self::addMonologDefault($mergedConfigs);
53+
$mergedConfigs = Arrays::merge($mergedConfigs, self::DEFAULT_MONOLOG_CONFIG);
3554
}
3655

3756
foreach ($mergedConfigs['log_files'] as $key => $config) {
3857
$container->register('fd.symfony.log.viewer.log_files_config.finder.' . $key, FinderConfig::class)
3958
->setPublic(false)
4059
->setArgument('$inDirectories', $config['finder']['in'])
4160
->setArgument('$fileName', $config['finder']['name'])
61+
->setArgument('$depth', $config['finder']['depth'])
4262
->setArgument('$ignoreUnreadableDirs', $config['finder']['ignoreUnreadableDirs'])
4363
->setArgument('$followLinks', $config['finder']['followLinks']);
4464

@@ -61,27 +81,4 @@ public function getAlias(): string
6181
{
6282
return 'fd_log_viewer';
6383
}
64-
65-
/**
66-
* @template T of array
67-
* @phpstan-param T $configs
68-
*
69-
* @phpstan-return T
70-
*/
71-
private static function addMonologDefault(array $configs): array
72-
{
73-
// monolog
74-
$configs['log_files']['monolog']['type'] ??= 'monolog';
75-
$configs['log_files']['monolog']['name'] ??= 'Monolog';
76-
$configs['log_files']['monolog']['downloadable'] ??= false;
77-
$configs['log_files']['monolog']['deletable'] ??= false;
78-
79-
// finder
80-
$configs['log_files']['monolog']['finder']['in'] ??= '%kernel.logs_dir%';
81-
$configs['log_files']['monolog']['finder']['name'] ??= '*.log';
82-
$configs['log_files']['monolog']['finder']['ignoreUnreadableDirs'] ??= true;
83-
$configs['log_files']['monolog']['finder']['followLinks'] ??= false;
84-
85-
return $configs;
86-
}
8784
}

src/Entity/Config/FinderConfig.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ class FinderConfig
77
{
88
/**
99
* @codeCoverageIgnore Simple DTO
10+
*
11+
* @param int|string|string[]|null $depth
1012
*/
1113
public function __construct(
1214
public readonly string $inDirectories,
1315
public readonly ?string $fileName,
16+
public readonly int|string|array|null $depth,
1417
public readonly bool $ignoreUnreadableDirs,
1518
public readonly bool $followLinks
1619
) {

src/Service/FinderFactory.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ public function createForConfig(FinderConfig $config): Finder
2020
$finder->followLinks();
2121
}
2222

23+
if ($config->depth !== null) {
24+
$finder->depth($config->depth);
25+
}
26+
2327
$finder->files()->in(array_map('trim', explode(',', $config->inDirectories)));
2428

2529
if ($config->fileName !== null) {

src/Util/Arrays.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace FD\LogViewer\Util;
5+
6+
class Arrays
7+
{
8+
/**
9+
* @param array<int|string, mixed> $target
10+
* @param array<int|string, mixed> $source
11+
*
12+
* @return array<int|string, mixed>
13+
*/
14+
public static function merge(array $target, array $source): array
15+
{
16+
foreach ($source as $key => $value) {
17+
// if target key is not set, assign source value
18+
if (array_key_exists($key, $target) === false) {
19+
$target[$key] = $value;
20+
continue;
21+
}
22+
23+
// recursively merge (non-list) arrays
24+
if (is_array($value)
25+
&& is_array($target[$key])
26+
&& array_is_list($value) === false
27+
&& (count($target[$key]) === 0 || array_is_list($target[$key]) === false)
28+
) {
29+
$target[$key] = self::merge($target[$key], $value);
30+
}
31+
}
32+
33+
return $target;
34+
}
35+
}

tests/Unit/Service/File/LogFileServiceTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class LogFileServiceTest extends TestCase
3030
protected function setUp(): void
3131
{
3232
parent::setUp();
33-
$this->finderConfig = new FinderConfig(__DIR__, null, false, false);
33+
$this->finderConfig = new FinderConfig(__DIR__, null, null, false, false);
3434
$this->config = $this->createLogFileConfig(['finderConfig' => $this->finderConfig]);
3535

3636
$this->folderService = $this->createMock(FinderFactory::class);

tests/Unit/Service/FinderFactoryTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@ protected function setUp(): void
2222

2323
public function testFindFilesMinimal(): void
2424
{
25-
$config = new FinderConfig(__DIR__, null, false, false);
25+
$config = new FinderConfig(__DIR__, null, null, false, false);
2626
$expected = (new Finder())->files()->in([__DIR__])->sortByName();
2727

2828
static::assertEquals($expected, $this->service->createForConfig($config));
2929
}
3030

3131
public function testFindFilesFull(): void
3232
{
33-
$config = new FinderConfig(__DIR__, '*.php', true, true);
34-
$expected = (new Finder())->ignoreUnreadableDirs()->followLinks()->files()->in([__DIR__])->name(['*.php'])->sortByName();
33+
$config = new FinderConfig(__DIR__, '*.php', 2, true, true);
34+
$expected = (new Finder())->ignoreUnreadableDirs()->followLinks()->depth(2)->files()->in([__DIR__])->name(['*.php'])->sortByName();
3535

3636
static::assertEquals($expected, $this->service->createForConfig($config));
3737
}

tests/Unit/Util/ArraysTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace FD\LogViewer\Tests\Unit\Util;
5+
6+
use FD\LogViewer\Util\Arrays;
7+
use PHPUnit\Framework\Attributes\CoversClass;
8+
use PHPUnit\Framework\TestCase;
9+
10+
#[CoversClass(Arrays::class)]
11+
class ArraysTest extends TestCase
12+
{
13+
public function testMergeSingleDepth(): void
14+
{
15+
static::assertSame(['foo' => 'bar'], Arrays::merge([], ['foo' => 'bar']));
16+
static::assertSame(['foo' => 'bar'], Arrays::merge(['foo' => 'bar'], []));
17+
static::assertSame(['foo' => 'bar'], Arrays::merge(['foo' => 'bar'], ['foo' => 'baz']));
18+
}
19+
20+
public function testMergeMultiDepth(): void
21+
{
22+
static::assertSame(
23+
['foo' => ['bar' => ['baz' => 'qux']]],
24+
Arrays::merge(['foo' => []], ['foo' => ['bar' => ['baz' => 'qux']]])
25+
);
26+
}
27+
28+
public function testMergeMultiDepthLists(): void
29+
{
30+
static::assertSame(
31+
['foo' => ['foo' => 'foo', 'bar' => ['baz', 'qux']]],
32+
Arrays::merge(['foo' => ['foo' => 'foo']], ['foo' => ['bar' => ['baz', 'qux']]])
33+
);
34+
}
35+
}

0 commit comments

Comments
 (0)