Completed
Push — dev ( f23975...304c3a )
by James Ekow Abaka
02:03
created

ArgumentParser   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 114
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 68.08%

Importance

Changes 0
Metric Value
wmc 18
lcom 1
cbo 3
dl 0
loc 114
ccs 32
cts 47
cp 0.6808
rs 10
c 0
b 0
f 0

7 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() 0 22 4
B parse() 0 20 5
A getHelp() 0 4 1
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
     * @param $key
24
     * @param $value
25
     * @throws OptionExistsException
26
     */
27 1
    private function addToOptionArray($key, $value)
28
    {
29 1
        if(isset($value[$key]) && !isset($this->options[$value[$key]])) {
30 1
            $this->options[$value[$key]] = $value;
31
        } else if(isset($value[$key])) {
32
            throw new OptionExistsException("An argument option with name {$value['name']} already exists.");
33
        }
34 1
    }
35
36
    /**
37
     * Add an option to be parsed.
38
     * Arguments are presented as a structured array with the following possible keys.
39
     *
40
     *  name: The name of the option prefixed with a double dash --
41
     *  short_name: A shorter single character option prefixed with a single dash -
42
     *  type: Required for all options that take values. An option specified without a type is considered to be a boolean flag.
43
     *  help: A help message for the option
44
     *
45
     * @param $option
46
     * @throws OptionExistsException
47
     * @throws InvalidArgumentDescriptionException
48
     */
49 1
    public function addOption($option)
50
    {
51 1
        if(!isset($option['name'])) {
52
            throw new InvalidArgumentDescriptionException("Argument must have a name");
53
        }
54 1
        $this->addToOptionArray('name', $option);
55 1
        $this->addToOptionArray('short_name', $option);
56 1
    }
57
58
    /**
59
     * @param $arguments
60
     * @param $argPointer
61
     * @return array
62
     * @throws InvalidValueException
63
     */
64 1
    private function parseLongArgument($arguments, &$argPointer)
65
    {
66 1
        $name = substr($arguments[$argPointer], 2);
67 1
        $option = $this->options[$name];
68 1
        preg_match("/(?<option>[a-zA-Z_0-9-]+)(?<equal>=?)(?<value>.*)/", $name, $matches);
69
70 1
        if(isset($option['type'])) {
71 1
            $nextArgument = $arguments[$argPointer + 1];
72 1
            if($matches['equal'] === '=') {
73
                $value = $matches['value'];
74 1
            } else if ($nextArgument[0] != '-') {
75 1
                $value = $nextArgument;
76 1
                $argPointer++;
77
            } else {
78 1
                throw new InvalidValueException("A value must be passed along with argument $name.");
79
            }
80
        } else {
81 1
            $value = true;
82
        }
83
84 1
        return [$name => $value];
85
    }
86
87
    /**
88
     * Parses command line arguments and return a structured array of options and their associated values.
89
     *
90
     * @param array $arguments An optional array of arguments that would be parsed instead of those passed to the CLI.
91
     * @return array
92
     * @throws InvalidValueException
93
     */
94 1
    public function parse($arguments = null)
95
    {
96 1
        global $argv;
1 ignored issue
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
97 1
        $arguments = $arguments ?? $argv;
98 1
        $numArguments = count($arguments);
99 1
        $output = [];
100
101 1
        for($argPointer = 1; $argPointer < $numArguments; $argPointer++) {
102 1
            $arg = $arguments[$argPointer];
103 1
            if(substr($arg, 0, 2) == "--") {
104 1
                $output = array_merge($output, $this->parseLongArgument($arguments, $argPointer));
105
            } else if ($arg[0] == '-') {
106
                $output = array_merge($output, $this->parseShortArgument($arguments, $argPointer));
0 ignored issues
show
Bug introduced by
The method parseShortArgument() does not seem to exist on object<clearice\argparser\ArgumentParser>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
107
            } else {
108
                $output['__args'] = isset($output['__args']) ? $output['__args'] + [$arg] : [$arg];
109
            }
110
        }
111
112 1
        return $output;
113
    }
114
115
    public function getHelp()
116
    {
117
118
    }
119
}
120