Skip to content

Commit

Permalink
feat: Add possibility to recursive merge data in Context
Browse files Browse the repository at this point in the history
  • Loading branch information
Theo D committed Mar 3, 2024
1 parent 82f4710 commit 32fc721
Show file tree
Hide file tree
Showing 13 changed files with 77 additions and 13 deletions.
30 changes: 26 additions & 4 deletions examples/context.php
Expand Up @@ -21,17 +21,38 @@ function defaultContext(): Context
'name' => 'my_default',
'production' => false,
'foo' => 'bar',
'nested' => [
'merge' => [
'key' => [
'value' => 'should keep this',
'replaced' => 'should be replaced',
],
'another' => 'should keep',
],
'another' => 'should keep',
],
]);
}

#[AsContext(name: 'production')]
function productionContext(): Context
{
return defaultContext()
->withData([
'name' => 'production',
'production' => true,
])
->withData(
[
'name' => 'production',
'production' => true,
'nested' => [
'merge' => [
'key' => [
'replaced' => 'replaced value',
'new' => 'new value',
],
],
],
],
recursive: true
)
;
}

Expand Down Expand Up @@ -83,6 +104,7 @@ function contextInfo(): void
echo 'Production? ' . (variable('production', false) ? 'yes' : 'no') . "\n";
echo "verbosity: {$context->verbosityLevel->value}\n";
echo 'context: ' . variable('foo', 'N/A') . "\n";
echo 'nested merge recursive: ' . json_encode(variable('nested', []), \JSON_THROW_ON_ERROR) . "\n";
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Attribute/AsCommandArgument.php
Expand Up @@ -5,7 +5,7 @@
abstract class AsCommandArgument
{
public function __construct(
public readonly string|null $name = null,
public readonly ?string $name = null,
) {
}
}
2 changes: 1 addition & 1 deletion src/Attribute/AsOption.php
Expand Up @@ -12,7 +12,7 @@ class AsOption extends AsCommandArgument
public function __construct(
?string $name = null,
public readonly string|array|null $shortcut = null,
public readonly int|null $mode = null,
public readonly ?int $mode = null,
public readonly string $description = '',
public readonly array $suggestedValues = [],
) {
Expand Down
2 changes: 1 addition & 1 deletion src/Attribute/AsTask.php
Expand Up @@ -11,7 +11,7 @@ class AsTask
*/
public function __construct(
public string $name = '',
public string|null $namespace = null,
public ?string $namespace = null,
public string $description = '',
public array $aliases = [],
public array $onSignals = [],
Expand Down
45 changes: 40 additions & 5 deletions src/Context.php
Expand Up @@ -17,7 +17,7 @@ public function __construct(
?string $currentDirectory = null,
public readonly bool $tty = false,
public readonly bool $pty = true,
public readonly float|null $timeout = null,
public readonly ?float $timeout = null,
public readonly bool $quiet = false,
public readonly bool $allowFailure = false,
public readonly bool $notify = false,
Expand Down Expand Up @@ -45,11 +45,25 @@ public function __debugInfo()
];
}

/** @param array<(int|string), mixed> $data */
public function withData(array $data, bool $keepExisting = true): self
/**
* @param array<(int|string), mixed> $data
*
* @throws \Exception
*/
public function withData(array $data, bool $keepExisting = true, bool $recursive = true): self
{
if ($keepExisting) {
if ($recursive) {
/* @var array<(int|string), mixed> */
$data = $this->arrayMergeRecursiveDistinct($this->data, $data);
} else {
/* @var array<(int|string), mixed> */
$data = array_merge($this->data, $data);
}
}

return new self(
$keepExisting ? array_merge($this->data, $data) : $data,
$data,
$this->environment,
$this->currentDirectory,
$this->tty,
Expand Down Expand Up @@ -132,7 +146,7 @@ public function withPty(bool $pty = true): self
);
}

public function withTimeout(float|null $timeout): self
public function withTimeout(?float $timeout): self
{
return new self(
$this->data,
Expand Down Expand Up @@ -257,4 +271,25 @@ public function offsetUnset(mixed $offset): void
{
throw new \LogicException('Context is immutable');
}

/**
* @param array<(int|string), mixed> $array1
* @param array<(int|string), mixed> $array2
*
* @return array<(int|string), mixed>
*/
private function arrayMergeRecursiveDistinct(array $array1, array $array2): array
{
/** @var array<(int|string), mixed> $merged */
$merged = $array1;
foreach ($array2 as $key => $value) {
if (\is_array($value) && isset($merged[$key]) && \is_array($merged[$key])) {
$merged[$key] = $this->arrayMergeRecursiveDistinct($merged[$key], $value);
} else {
$merged[$key] = $value;
}
}

return $merged;
}
}
2 changes: 1 addition & 1 deletion src/SectionOutput.php
Expand Up @@ -14,7 +14,7 @@ class SectionOutput

private OutputInterface|ConsoleSectionOutput $consoleOutput;

private ConsoleOutput|null $mainOutput;
private ?ConsoleOutput $mainOutput;

/** @var \SplObjectStorage<Process, SectionDetails> */
private \SplObjectStorage $sections;
Expand Down
Expand Up @@ -2,3 +2,4 @@ context name: dynamic
Production? no
verbosity: 1
context: baz
nested merge recursive: []
Expand Up @@ -2,3 +2,4 @@ context name: my_default
Production? no
verbosity: 2
context: bar
nested merge recursive: {"merge":{"key":{"value":"should keep this","replaced":"should be replaced"},"another":"should keep"},"another":"should keep"}
Expand Up @@ -2,3 +2,4 @@ context name: path
Production? yes
verbosity: 1
context: bar
nested merge recursive: []
Expand Up @@ -2,3 +2,4 @@ context name: production
Production? yes
verbosity: 1
context: bar
nested merge recursive: {"merge":{"key":{"value":"should keep this","replaced":"replaced value","new":"new value"},"another":"should keep"},"another":"should keep"}
Expand Up @@ -2,3 +2,4 @@ context name: run
Production? no
verbosity: 1
context: no defined
nested merge recursive: []
1 change: 1 addition & 0 deletions tests/Examples/Generated/ContextContextTest.php.output.txt
Expand Up @@ -2,3 +2,4 @@ context name: my_default
Production? no
verbosity: 1
context: bar
nested merge recursive: {"merge":{"key":{"value":"should keep this","replaced":"should be replaced"},"another":"should keep"},"another":"should keep"}
Expand Up @@ -2,4 +2,5 @@ context name: dynamic
Production? no
verbosity: -1
context: bar
nested merge recursive: []
bar

0 comments on commit 32fc721

Please sign in to comment.