src/CLI.php
protected function parseParam(array &$args, \DateTimeZone $timezone)
    {
        if (!count($args)) {
            throw new \Exception('Not enough arguments.');
        }

        $type = strtolower(array_shift($args));
        $parseFunc = null;
        switch ($type) {
            case 'null':
            case 'nil':
            case 'n':
                return null;
                break;

            case 'boolean':
            case 'bool':
            case 'b':
                $parseFunc = array($this, 'parseBool');
                break;

            case 'integer':
            case 'int':
            case 'i4':
            case 'i':
                $parseFunc = 'intval';
                break;

            case 'double':
            case 'float':
            case 'f':
                $parseFunc = 'floatval';
                break;

            case 'string':
            case 'str':
            case 's':
                $parseFunc = 'strval';
                break;

            case 'file':
            case '@':
                $parseFunc = array($this, 'parseFile');
                break;

            case 'timestamp':
            case 'datetime':
            case 'date':
            case 'time':
            case 'ts':
            case 'dt':
            case 't':
            case 'd':
                $parseFunc = array($this, 'parseTimestamp');
                break;

            case 'hash':
            case 'h':
                $result = array();
                while (true) {
                    if (!count($args)) {
                        throw new \Exception('Not enough arguments for "hash".');
                    }

                    if (in_array(strtolower($args[0]), array('endhash', 'eh'))) {
                        break;
                    }

                    $key = $this->parseParam($args, $timezone);
                    if (!is_int($key) && !is_string($key)) {
                        throw new \Exception(
                            'Invalid type "'.gettype($key).'" for hash key. '.
                            'Only integer and string keys may be used.'
                        );
                    }
                    $value = $this->parseParam($args, $timezone);
                    $result[$key] = $value;
                }
                // Pop the ending "endhash".
                array_shift($args);
                return $result;

            case 'list':
            case 'l':
                $result = array();
                while (true) {
                    if (!count($args)) {
                        throw new \Exception('Not enough arguments for "list".');
                    }

                    if (in_array(strtolower($args[0]), array('endlist', 'el'))) {
                        break;
                    }

                    $result[] = $this->parseParam($args, $timezone);
                }
                // Pop the ending "endlist".
                array_shift($args);
                return $result;

            default:
                throw new \Exception('Unknown type "'.$type.'".');
        }

        if (!count($args)) {
            throw new \Exception('Not enough arguments.');
        }

        $value = array_shift($args);
        $value = call_user_func($parseFunc, $value);
        if ($value instanceof \DateTime) {
            $value->setTimezone($timezone);
        }
        return $value;
    }
protected function parseParam(array &$args, \DateTimeZone $timezone)
    {
        if (!count($args)) {
            throw new \Exception('Not enough arguments.');
        }

        $type = strtolower(array_shift($args));
        $parseFunc = null;
        switch ($type) {
            case 'null':
            case 'nil':
            case 'n':
                return null;
                break;

            case 'boolean':
            case 'bool':
            case 'b':
                $parseFunc = array($this, 'parseBool');
                break;

            case 'integer':
            case 'int':
            case 'i4':
            case 'i':
                $parseFunc = 'intval';
                break;

            case 'double':
            case 'float':
            case 'f':
                $parseFunc = 'floatval';
                break;

            case 'string':
            case 'str':
            case 's':
                $parseFunc = 'strval';
                break;

            case 'file':
            case '@':
                $parseFunc = array($this, 'parseFile');
                break;

            case 'timestamp':
            case 'datetime':
            case 'date':
            case 'time':
            case 'ts':
            case 'dt':
            case 't':
            case 'd':
                $parseFunc = array($this, 'parseTimestamp');
                break;

            case 'hash':
            case 'h':
                $result = array();
                while (true) {
                    if (!count($args)) {
                        throw new \Exception('Not enough arguments for "hash".');
                    }

                    if (in_array(strtolower($args[0]), array('endhash', 'eh'))) {
                        break;
                    }

                    $key = $this->parseParam($args, $timezone);
                    if (!is_int($key) && !is_string($key)) {
                        throw new \Exception(
                            'Invalid type "'.gettype($key).'" for hash key. '.
                            'Only integer and string keys may be used.'
                        );
                    }
                    $value = $this->parseParam($args, $timezone);
                    $result[$key] = $value;
                }
                // Pop the ending "endhash".
                array_shift($args);
                return $result;

            case 'list':
            case 'l':
                $result = array();
                while (true) {
                    if (!count($args)) {
                        throw new \Exception('Not enough arguments for "list".');
                    }

                    if (in_array(strtolower($args[0]), array('endlist', 'el'))) {
                        break;
                    }

                    $result[] = $this->parseParam($args, $timezone);
                }
                // Pop the ending "endlist".
                array_shift($args);
                return $result;

            default:
                throw new \Exception('Unknown type "'.$type.'".');
        }

        if (!count($args)) {
            throw new \Exception('Not enough arguments.');
        }

        $value = array_shift($args);
        $value = call_user_func($parseFunc, $value);
        if ($value instanceof \DateTime) {
            $value->setTimezone($timezone);
        }
        return $value;
    }
Parse this script's arguments and extract
parameters.

\param array $args
Arguments that contain parameters for an XML-RPC
request, using the notation this script expects.

\param DateTimeZone $timezone
Timezone information (used to parse date/times).

\retval array
The parameters for an XML-RPC request that were
parsed by this method.

\throw Exception
Some error occurred during the parsing.
See the exception's message for more information.

\note
The list of arguments passed to this method
is modified as it is parsed.