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

ArgumentParser   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 148
Duplicated Lines 8.11 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 87.5%

Importance

Changes 0
Metric Value
wmc 24
lcom 1
cbo 3
dl 12
loc 148
ccs 49
cts 56
cp 0.875
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A setDescription() 0 4 1
A setFooter() 0 4 1
A addToOptionArray() 0 8 4
A addOption() 0 8 2
B parseLongArgument() 6 22 5
B parseShortArgument() 6 21 5
B parse() 0 20 5
A getHelp() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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