Args
In questo esempio vedremo la costruzione della classe Args
, la quale, data in input una stringa di formattazione e degli argomenti, e poi possibile interrogarla chiedendole il valore degli argomenti.
ArgumentMarshaler
<?php
interface ArgumentMarshaler
{
/**
* @param ArgumentMarshaler $am
* @return mixed
*/
public static function getValue(ArgumentMarshaler $am);
/**
* @param mixed $currentArgument
* @return void
*/
public function set($currentArgument): void;
}
BooleanArgumentMarshaler
<?php
include_once('ArgumentMarshaler.php');
class BooleanArgumentMarshaler implements ArgumentMarshaler
{
/** @var bool */
private $value = false;
/**
* @param ArgumentMarshaler $am
* @return bool
*/
public static function getValue(ArgumentMarshaler $am)
{
if ($am instanceof BooleanArgumentMarshaler) {
return $am->value;
}
return false;
}
/**
* {@inheritDoc}
*/
public function set($currentArgument): void
{
$this->value = true;
}
}
FloatArgumentMarshaler
<?php
include_once('ArgumentMarshaler.php');
class FloatArgumentMarshaler implements ArgumentMarshaler
{
public const SYMBOL = '##';
/** @var float */
private $value = 0.0;
/**
* @param ArgumentMarshaler $am
* @return float
*/
public static function getValue(ArgumentMarshaler $am)
{
if ($am instanceof FloatArgumentMarshaler) {
return $am->value;
}
return 0.0;
}
/**
* {@inheritDoc}
*/
public function set($currentArgument): void
{
$this->value = (float)$currentArgument;
}
}
IntegerArgumentMarshaler
<?php
include_once('ArgumentMarshaler.php');
class IntegerArgumentMarshaler implements ArgumentMarshaler
{
public const SYMBOL = '#';
/** @var int */
private $value = 0;
/**
* @param ArgumentMarshaler $am
* @return int
*/
public static function getValue(ArgumentMarshaler $am)
{
if ($am instanceof IntegerArgumentMarshaler) {
return $am->value;
}
return 0;
}
/**
* {@inheritDoc}
*/
public function set($currentArgument): void
{
$this->value = (int)$currentArgument;
}
}
StringArgumentMarshaler
<?php
include_once('ArgumentMarshaler.php');
class StringArgumentMarshaler implements ArgumentMarshaler
{
public const SYMBOL = '*';
/** @var string */
private $value = '';
/**
* @param ArgumentMarshaler $am
* @return string
*/
public static function getValue(ArgumentMarshaler $am)
{
if ($am instanceof StringArgumentMarshaler) {
return $am->value;
}
return '';
}
/**
* {@inheritDoc}
*/
public function set($currentArgument): void
{
$this->value = (string)$currentArgument;
}
}
ArgumentMarshalerCollection
<?php
include_once('ArgsException.php');
include_once('ArgumentMarshaler.php');
class ArgumentMarshalerCollection
{
/** @var array */
private $array = [];
/**
* @param string $elementId
* @return ArgumentMarshaler
* @throws ArgsException
*/
public function get(string $elementId): ArgumentMarshaler
{
if (!isset($this->array[$elementId])) {
throw new ArgsException(ArgsException::UNEXPECTED_ARGUMENT, $elementId);
}
return $this->array[$elementId];
}
/**
* @param string $elementId
* @param ArgumentMarshaler $am
* @return void
*/
public function put(string $elementId, ArgumentMarshaler $am): void
{
$this->array[$elementId] = $am;
}
}
ArgsException
<?php
class ArgsException extends Exception
{
public const INVALID_ARGUMENT_FORMAT = 1;
public const UNEXPECTED_ARGUMENT = 2;
public const INVALID_ARGUMENT_NAME = 3;
/** @var string|null */
private $argumentId;
/** @var string|null */
private $parameter;
/**
* ArgsException constructor.
* @param int $code
* @param string|null $argumentId
* @param string|null $parameter
*/
public function __construct(int $code, string $argumentId = null, string $parameter = null)
{
$this->code = $code;
$this->argumentId = $argumentId;
$this->parameter = $parameter;
parent::__construct($this->formatErrorMessage(), $code);
}
/**
* @return string|null
*/
public function getArgumentId(): ?string
{
return $this->argumentId;
}
/**
* @return string|null
*/
public function getParameter(): ?string
{
return $this->parameter;
}
/**
* @return string
*/
private function formatErrorMessage(): string
{
switch ($this->code) {
case self::INVALID_ARGUMENT_FORMAT:
return sprintf('`%s` is not a valid argument format.', $this->parameter);
case self::UNEXPECTED_ARGUMENT:
return sprintf('Argument -%s unexpected.', $this->argumentId);
case self::INVALID_ARGUMENT_NAME:
return sprintf('`%s` is not a valid argument name.', $this->argumentId);
default:
return 'TILT: Should not get here.';
}
}
}
Args
<?php
include_once('ArgsException.php');
include_once('ArgumentMarshaler/ArgumentMarshalerCollection.php');
include_once('ArgumentMarshaler/BooleanArgumentMarshaler.php');
include_once('ArgumentMarshaler/FloatArgumentMarshaler.php');
include_once('ArgumentMarshaler/IntegerArgumentMarshaler.php');
include_once('ArgumentMarshaler/StringArgumentMarshaler.php');
class Args
{
private const SCHEMA_SEPARATOR = ',';
/** @var ArgumentMarshalerCollection */
private $marshalers;
/** @var string[] */
private $args = [];
/** @var string[] */
private $argsFound = [];
/**
* Args constructor.
* @param string $schema
* @param string[] $args
* @throws ArgsException
*/
public function __construct(string $schema, array $args)
{
$this->marshalers = new ArgumentMarshalerCollection();
$this->args = $args;
$this->parseSchema($schema);
$this->parseArgumentStrings();
}
/**
* @param string $schema
* @return void
* @throws ArgsException
*/
private function parseSchema(string $schema): void
{
$elements = explode(self::SCHEMA_SEPARATOR, $schema);
foreach ($elements as $element) {
if (strlen($element) > 0) {
$this->parseSchemaElement(trim($element));
}
}
}
/**
* @param string $element
* @return void
* @throws ArgsException
*/
private function parseSchemaElement(string $element): void
{
$elementId = $element[0];
$elementTail = substr($element, 1);
$this->validateSchemaElementId($elementId);
if (strlen($elementTail) === 0) {
$this->marshalers->put($elementId, new BooleanArgumentMarshaler());
} elseif ($elementTail === StringArgumentMarshaler::SYMBOL) {
$this->marshalers->put($elementId, new StringArgumentMarshaler());
} elseif ($elementTail === IntegerArgumentMarshaler::SYMBOL) {
$this->marshalers->put($elementId, new IntegerArgumentMarshaler());
} elseif ($elementTail === FloatArgumentMarshaler::SYMBOL) {
$this->marshalers->put($elementId, new FloatArgumentMarshaler());
} else {
throw new ArgsException(ArgsException::INVALID_ARGUMENT_FORMAT, $elementId, $elementTail);
}
}
/**
* @param string $elementId
* @return void
* @throws ArgsException
*/
private function validateSchemaElementId(string $elementId): void
{
if (!ctype_alpha($elementId)) {
throw new ArgsException(ArgsException::INVALID_ARGUMENT_NAME, $elementId);
}
}
/**
* @return void
* @throws ArgsException
*/
private function parseArgumentStrings(): void
{
foreach ($this->args as $arg) {
if (substr($arg, 0, 1) === '-') {
$this->parseArgumentCharacters(substr($arg, 1));
}
}
}
/**
* @param string $argChars
* @return void
* @throws ArgsException
*/
private function parseArgumentCharacters(string $argChars): void
{
for ($i = 0; $i < strlen($argChars); $i++) {
$this->parseArgumentCharacter($argChars[$i]);
}
}
/**
* @param string $argChar
* @return void
* @throws ArgsException
*/
private function parseArgumentCharacter(string $argChar): void
{
$am = $this->marshalers->get($argChar);
$am->set(next($this->args));
$this->argsFound[] = $argChar;
}
/**
* @param string $arg
* @return bool
*/
public function has(string $arg): bool
{
return in_array($arg, $this->argsFound);
}
/**
* @param string $arg
* @return bool
* @throws ArgsException
*/
public function getBoolean(string $arg): bool
{
return BooleanArgumentMarshaler::getValue($this->marshalers->get($arg));
}
/**
* @param string $arg
* @return string
* @throws ArgsException
*/
public function getString(string $arg): string
{
return StringArgumentMarshaler::getValue($this->marshalers->get($arg));
}
/**
* @param string $arg
* @return int
* @throws ArgsException
*/
public function getInteger(string $arg): int
{
return IntegerArgumentMarshaler::getValue($this->marshalers->get($arg));
}
/**
* @param string $arg
* @return float
* @throws ArgsException
*/
public function getFloat(string $arg): float
{
return FloatArgumentMarshaler::getValue($this->marshalers->get($arg));
}
}
Index
<?php
include_once('Args.php');
try {
$args = new Args('l,p#,d*,x##', ['-lpdx', true, 42, 'param', 16.5]);
var_dump($args->getBoolean('l'));
var_dump($args->getInteger('p'));
var_dump($args->getString('d'));
var_dump($args->getFloat('x'));
} catch (ArgsException $e) {
var_dump($e->getMessage());
}
Last updated