-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVariableBuilderAbstract.php
More file actions
190 lines (153 loc) · 6.83 KB
/
VariableBuilderAbstract.php
File metadata and controls
190 lines (153 loc) · 6.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
<?php
declare(strict_types=1);
namespace MagicPush\CliToolkit\Parametizer\Config\Builder;
use MagicPush\CliToolkit\Parametizer\Exception\ConfigException;
use MagicPush\CliToolkit\Parametizer\HelpFormatter;
abstract class VariableBuilderAbstract extends BuilderAbstract {
protected ?bool $manualIsRequired = null;
protected mixed $manualDefault = null;
/** @var callable|string|null */
protected $manualValidator = null;
/** @var callable|string[]|null */
protected $manualCompletion = null;
/** @var string[]|null[] */
protected array $manualAllowedValues = [];
// === Parameter settings ===
public function required(bool $isRequired = true): static {
$this->manualIsRequired = $isRequired;
$this->ensureNotRequiredAndHasDefaultSimultaneously();
$this->param->require($isRequired);
return $this;
}
/**
* PCRE regexp as a parameter value validator (null = no validation).
*
* If a parameter can have multiple values, the validator runs on each value separately.
*/
public function validatorPattern(?string $pattern, ?string $validatorCustomMessage = null): static {
return $this->validator($pattern, $validatorCustomMessage);
}
/**
* Validator callback (null = no validation).
*
* Validator will be executed immediately when a value is scanned from input parameters.
* If a parameter can have multiple values, the validator runs on each value separately.
*
* Validator callback has such a signature: `(&$value): bool`.
* The callback may modify the value (e.g. trim, canonicalize, etc).
* * If the value is modified in validator, but then an exception occurs,
* the error message will contain the original value before its modification.
* * If your callback declares `$value` argument without reference, `$value` will be passed by a reference anyway!
*
* Validator also runs during completion. Make sure the callback is not throwing errors or exits the process,
* otherwise use {@see BuilderAbstract::callback()} instead.
*/
public function validatorCallback(?callable $callback, ?string $validatorCustomMessage = null): static {
return $this->validator($callback, $validatorCustomMessage);
}
protected function validator(callable|string|null $validator, ?string $validatorCustomMessage = null): static {
$this->manualValidator = $validator;
$this->ensureNotAllowedValuesSetWithValidatorOrCompletionSimultaneously();
$this->param->validator($validator, $validatorCustomMessage);
return $this;
}
/**
* Complete values list.
*
* @param string[] $values
*/
public function completionList(array $values): static {
return $this->completion($values);
}
/**
* Callback to provide values for completion (null = no values to complete).
*
* Callback should have this signature: `($enteredValue): string[]`.
*/
public function completionCallback(?callable $callback): static {
return $this->completion($callback);
}
/**
* @param callable|string[]|null $completion
*/
protected function completion(callable|array|null $completion): static {
$this->manualCompletion = $completion;
$this->ensureNotAllowedValuesSetWithValidatorOrCompletionSimultaneously();
$this->param->completion($completion);
return $this;
}
/**
* Allowed values for a parameter.
*
* This will automatically set {@see validatorCallback()} and {@see completionList()}.
*
* @param mixed[] $allowedValues
* @param bool $areHiddenForHelp If the list should not be shown on a generated help page.
* Useful for really long lists.
*/
public function allowedValues(array $allowedValues, bool $areHiddenForHelp = false): static {
$allowedValues = array_fill_keys(array_values($allowedValues), null);
return $this->setAllowedValues($allowedValues, $areHiddenForHelp);
}
/**
* Allowed values for a parameter with descriptions: value => 'description for the help'|null
* (`null` means no description).
*
* This will automatically set {@see validatorCallback()} and {@see completionList()}.
*
* Examples:
* 1. Descriptions for all values: ['up' => 'moves token up', 'down' => 'moves token down']
* 2. Mixed list: ['brother' => null, 'sister' => null, 'cousin' => 'anything other than brother or sister']
*
* @param string[]|null[] $allowedValues
*/
public function allowedValuesDescribed(array $allowedValues): static {
return $this->setAllowedValues($allowedValues, false);
}
/**
* Default value for a parameter.
* If the default is provided, parameter is no longer required (same as calling {@see required()} with `false`).
*/
public function default(mixed $default): static {
$this->manualDefault = $default;
$this->ensureNotRequiredAndHasDefaultSimultaneously();
$this->param->default($default);
// Default is set == param is not required
if (null !== $this->param->getDefault() && $this->param->isRequired()) {
$this->param->require(false);
}
return $this;
}
// === Misc ===
protected function setAllowedValues(array $allowedValues, bool $areHiddenForHelp): static {
$this->manualAllowedValues = $allowedValues;
$this->ensureNotAllowedValuesSetWithValidatorOrCompletionSimultaneously();
$this->param->allowedValues($allowedValues, $areHiddenForHelp);
return $this;
}
protected function ensureNotRequiredAndHasDefaultSimultaneously(): void {
// We do not allow to require a param and simultaneously have a default value for it.
if (
!empty($this->manualIsRequired)
&& isset($this->manualDefault)
) {
throw new ConfigException(
"'" . HelpFormatter::createForStdErr()->paramTitle($this->param->getName())
. "' >>> Config error: a parameter can't be required and have a default value simultaneously.",
);
}
}
protected function ensureNotAllowedValuesSetWithValidatorOrCompletionSimultaneously(): void {
if (empty($this->manualAllowedValues)) {
return;
}
$errorMessagePrefix = "'" . HelpFormatter::createForStdErr()->paramTitle($this->param->getName())
. "' >>> Config error:";
if (isset($this->manualValidator)) {
throw new ConfigException("{$errorMessagePrefix} do not set allowed values and validation simultaneously.");
}
if (isset($this->manualCompletion)) {
throw new ConfigException("{$errorMessagePrefix} do not set allowed values and completion simultaneously.");
}
}
}