1: <?php declare(strict_types=1);
2:
3: namespace Salient\Core\Exception;
4:
5: use Salient\Core\Process;
6: use Salient\Utility\Get;
7: use Throwable;
8:
9: /**
10: * @api
11: */
12: class ProcessException extends Exception
13: {
14: /**
15: * Creates a new exception
16: *
17: * To get a message for the exception, `$format` and `$values` are passed to
18: * {@see sprintf()} after any {@see Process} instances in `$values` are
19: * replaced with the command they spawn.
20: *
21: * {@see sprintf()} is not called if `$values` is empty or `null`.
22: *
23: * @internal
24: *
25: * @param array<Process|string|int|bool|float|null>|null $values
26: */
27: public function __construct(
28: string $format = '',
29: ?array $values = null,
30: ?Throwable $previous = null,
31: ?int $exitStatus = null
32: ) {
33: $message = $values
34: ? sprintf($format, ...$this->filterValues($values))
35: : $format;
36:
37: parent::__construct($message, $previous, $exitStatus);
38: }
39:
40: /**
41: * @param non-empty-array<Process|string|int|bool|float|null> $values
42: * @return list<string|int|bool|float|null>
43: */
44: private function filterValues(array $values): array
45: {
46: foreach ($values as $value) {
47: $filtered[] = $value instanceof Process
48: ? Get::code($value->getCommand())
49: : $value;
50: }
51: return $filtered;
52: }
53: }
54: