Completed
Push — dev ( c8d9f4...b17824 )
by James Ekow Abaka
01:23
created

ArgumentParser::parseLongArgument()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 22
Code Lines 16

Duplication

Lines 6
Ratio 27.27 %

Code Coverage

Tests 14
CRAP Score 5

Importance

Changes 0
Metric Value
dl 6
loc 22
ccs 14
cts 14
cp 1
rs 8.6737
c 0
b 0
f 0
cc 5
eloc 16
nc 4
nop 2
crap 5
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
    /**
61
     * Parse a long argument that is prefixed with a double dash "--"
62
     *
63
     * @param $arguments
64
     * @param $argPointer
65
     * @return array
66
     * @throws InvalidValueException
67
     */
68 1
    private function parseLongArgument($arguments, &$argPointer)
69
    {
70 1
        $string = substr($arguments[$argPointer], 2);
71 1
        preg_match("/(?<name>[a-zA-Z_0-9-]+)(?<equal>=?)(?<value>.*)/", $string, $matches);
72 1
        $name = $matches['name'];
73 1
        $option = $this->options[$name];
74
75 1
        if(isset($option['type'])) {
76 1
            if($matches['equal'] === '=') {
77 1
                $value = $matches['value'];
78 1 View Code Duplication
            } else if (isset($arguments[$argPointer + 1]) && $arguments[$argPointer + 1][0] != '-') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
79 1
                $value = $arguments[$argPointer + 1];
80 1
                $argPointer++;
81
            } else {
82 1
                throw new InvalidValueException("A value must be passed along with argument $name.");
83
            }
84
        } else {
85 1
            $value = true;
86
        }
87
88 1
        return [$name => $value];
89
    }
90
91
    /**
92
     * Parse a short argument that is prefixed with a single dash '-'
93
     *
94
     * @param $arguments
95
     * @param $argPointer
96
     * @return array
97
     * @throws InvalidValueException
98
     */
99 1
    public function parseShortArgument($arguments, &$argPointer)
100
    {
101 1
        $argument = $arguments[$argPointer];
102 1
        $key = substr($argument, 1, 1);
103 1
        $option = $this->options[$key];
104
105 1
        if(isset($option['type'])) {
106 1
            if(substr($argument, 2) != "") {
107 1
                $value = substr($argument, 2);
108 1 View Code Duplication
            } else if(isset($arguments[$argPointer + 1]) && $arguments[$argPointer + 1][0] != '-') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
109 1
                $value = $arguments[$argPointer + 1];
110 1
                $argPointer++;
111
            } else {
112 1
                throw new InvalidValueException("A value must be passed along with argument ${option['name']}");
113
            }
114
        } else {
115
            $value = true;
116
        }
117
118
        return [$option['name'] => $value];
119
    }
120
121
    /**
122
     * Parses command line arguments and return a structured array of options and their associated values.
123
     *
124
     * @param array $arguments An optional array of arguments that would be parsed instead of those passed to the CLI.
125
     * @return array
126
     * @throws InvalidValueException
127
     */
128
    public function parse($arguments = null)
129
    {
130 1
        global $argv;
131 1
        $arguments = $arguments ?? $argv;
132 1
        $numArguments = count($arguments);
133 1
        $output = [];
134
135 1
        for($argPointer = 1; $argPointer < $numArguments; $argPointer++) {
136 1
            $arg = $arguments[$argPointer];
137 1
            if(substr($arg, 0, 2) == "--") {
138 1
                $output = array_merge($output, $this->parseLongArgument($arguments, $argPointer));
139 1
            } else if ($arg[0] == '-') {
140 1
                $output = array_merge($output, $this->parseShortArgument($arguments, $argPointer));
141
            } else {
142 1
                $output['__args'] = isset($output['__args']) ? array_merge($output['__args'], [$arg]) : [$arg];
143
            }
144
        }
145
146 1
        return $output;
147
    }
148
149
    public function getHelp()
150
    {
151
152
    }
153
}
154