Completed
Push — dev ( 153efe...0bf02b )
by James Ekow Abaka
01:18
created

ArgumentParser::addToOptionArray()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 6
cts 6
cp 1
rs 9.2
c 0
b 0
f 0
cc 4
eloc 5
nc 3
nop 2
crap 4
1
<?php
2
3
namespace clearice\argparser;
4
5
6
class ArgumentParser
7
{
8
    private $description;
9
    private $footer;
10
    private $options = [];
11
12
    public function setDescription($description)
13
    {
14
        $this->description = $description;
15
    }
16
17
    public function setFooter($footer)
18
    {
19
        $this->footer = $footer;
20
    }
21
22
    /**
23
     * Add a value to the available possible options for later parsing.
24
     * @param $key
25
     * @param $value
26
     * @throws OptionExistsException
27
     */
28 3
    private function addToOptionArray($key, $value)
29
    {
30 3
        if(isset($value[$key]) && !isset($this->options[$value[$key]])) {
31 3
            $this->options[$value[$key]] = $value;
32 2
        } else if(isset($value[$key])) {
33 2
            throw new OptionExistsException("An argument option with $key {$value[$key]} already exists.");
34
        }
35 3
    }
36
37
    /**
38
     * Add an option to be parsed.
39
     * Arguments are presented as a structured array with the following possible keys.
40
     *
41
     *  name: The name of the option prefixed with a double dash --
42
     *  short_name: A shorter single character option prefixed with a single dash -
43
     *  type: Required for all options that take values. An option specified without a type is considered to be a
44
     *        boolean flag.
45
     *  help: A help message for the option
46
     *
47
     * @param $option
48
     * @throws OptionExistsException
49
     * @throws InvalidArgumentDescriptionException
50
     */
51 4
    public function addOption($option)
52
    {
53 4
        if(!isset($option['name'])) {
54 1
            throw new InvalidArgumentDescriptionException("Argument must have a name");
55
        }
56 3
        $this->addToOptionArray('name', $option);
57 3
        $this->addToOptionArray('short_name', $option);
58 3
    }
59
60 1
    private function getNextValueOrFail($arguments, &$argPointer)
61
    {
62 1
        if (isset($arguments[$argPointer + 1]) && $arguments[$argPointer + 1][0] != '-') {
63 1
            $argPointer++;
64 1
            return $arguments[$argPointer];
65
        } else {
66
            throw new InvalidValueException("A value must be passed along with argument $name.");
67
        }
68
    }
69
70
    /**
71
     * Parse a long argument that is prefixed with a double dash "--"
72
     *
73
     * @param $arguments
74
     * @param $argPointer
75
     * @return array
76
     * @throws InvalidValueException
77
     */
78 1
    private function parseLongArgument($arguments, &$argPointer)
79
    {
80 1
        $string = substr($arguments[$argPointer], 2);
81 1
        preg_match("/(?<name>[a-zA-Z_0-9-]+)(?<equal>=?)(?<value>.*)/", $string, $matches);
82 1
        $name = $matches['name'];
83 1
        $option = $this->options[$name];
84 1
        $value = true;
85
86 1
        if(isset($option['type'])) {
87 1
            if($matches['equal'] === '=') {
88 1
                $value = $matches['value'];
89
            } else {
90 1
                $value = $this->getNextValueOrFail($arguments, $argPointer);
91
            }
92
        }
93
94 1
        return [$name => $value];
95
    }
96
97
    /**
98
     * Parse a short argument that is prefixed with a single dash '-'
99
     *
100
     * @param $arguments
101
     * @param $argPointer
102
     * @return array
103
     * @throws InvalidValueException
104
     */
105 1
    public function parseShortArgument($arguments, &$argPointer)
106
    {
107 1
        $argument = $arguments[$argPointer];
108 1
        $key = substr($argument, 1, 1);
109 1
        $option = $this->options[$key];
110 1
        $value = true;
111
112 1
        if(isset($option['type'])) {
113 1
            if(substr($argument, 2) != "") {
114 1
                $value = substr($argument, 2);
115
            } else {
116 1
                $value = $this->getNextValueOrFail($arguments, $argPointer);
117
            }
118
        }
119
120 1
        return [$option['name'] => $value];
121
    }
122
123
    /**
124
     * Parses command line arguments and return a structured array of options and their associated values.
125
     *
126
     * @param array $arguments An optional array of arguments that would be parsed instead of those passed to the CLI.
127
     * @return array
128
     * @throws InvalidValueException
129
     */
130 1
    public function parse($arguments = null)
131
    {
132 1
        global $argv;
133 1
        $arguments = $arguments ?? $argv;
134 1
        $numArguments = count($arguments);
135 1
        $output = [];
136
137 1
        for($argPointer = 1; $argPointer < $numArguments; $argPointer++) {
138 1
            $arg = $arguments[$argPointer];
139 1
            if(substr($arg, 0, 2) == "--") {
140 1
                $output = array_merge($output, $this->parseLongArgument($arguments, $argPointer));
141 1
            } else if ($arg[0] == '-') {
142 1
                $output = array_merge($output, $this->parseShortArgument($arguments, $argPointer));
143
            } else {
144 1
                $output['__args'] = isset($output['__args']) ? array_merge($output['__args'], [$arg]) : [$arg];
145
            }
146
        }
147
148 1
        return $output;
149
    }
150
151
    public function getHelp()
152
    {
153
154
    }
155
}
156