name))) { throw new \InvalidArgumentException('Argument name cannot be empty'); } if ($this->shortName !== null && strlen($this->shortName) !== 1) { throw new \InvalidArgumentException('Short name must be exactly one character'); } if ($this->required && $this->default !== null) { throw new \InvalidArgumentException('Required arguments cannot have default values'); } if ($this->type === ArgumentType::BOOLEAN && ! empty($this->allowedValues)) { throw new \InvalidArgumentException('Boolean arguments cannot have allowed values'); } } /** * Create a required string argument */ public static function required(string $name, string $description = ''): self { return new self($name, ArgumentType::STRING, required: true, description: $description); } /** * Create an optional string argument with default */ public static function optional(string $name, string $default = '', string $description = ''): self { return new self($name, ArgumentType::STRING, default: $default, description: $description); } /** * Create a boolean flag */ public static function flag(string $name, ?string $shortName = null, string $description = ''): self { return new self($name, ArgumentType::BOOLEAN, description: $description, shortName: $shortName); } /** * Create an email argument */ public static function email(string $name, bool $required = true, string $description = ''): self { return new self($name, ArgumentType::EMAIL, required: $required, description: $description); } /** * Create an integer argument */ public static function integer(string $name, bool $required = false, ?int $default = null, string $description = ''): self { return new self($name, ArgumentType::INTEGER, required: $required, default: $default, description: $description); } /** * Create a choice argument with allowed values */ public static function choice(string $name, array $allowedValues, bool $required = false, ?string $default = null, string $description = ''): self { return new self( $name, ArgumentType::STRING, required: $required, default: $default, description: $description, allowedValues: $allowedValues ); } /** * Get the display name for help text */ public function getDisplayName(): string { $display = $this->name; if ($this->shortName) { $display = "{$this->shortName}, {$display}"; } return $display; } /** * Get usage text for this argument */ public function getUsageText(): string { if ($this->type === ArgumentType::BOOLEAN) { return $this->required ? "--{$this->name}" : "[--{$this->name}]"; } $usage = "--{$this->name}"; if (! empty($this->allowedValues)) { $usage .= "=" . implode('|', $this->allowedValues); } else { $usage .= "={$this->type->getExample()}"; } return $this->required ? "<{$usage}>" : "[{$usage}]"; } /** * Validate a value against this argument definition */ public function validateValue(mixed $value): void { if ($this->required && ($value === null || $value === '')) { throw new \InvalidArgumentException("Required argument '{$this->name}' is missing"); } if (! empty($this->allowedValues) && ! in_array($value, $this->allowedValues, true)) { throw new \InvalidArgumentException( "Invalid value '{$value}' for argument '{$this->name}'. Allowed values: " . implode(', ', $this->allowedValues) ); } } }