Completed
Push — master ( 7b302a...d24209 )
by Tristan
04:27
created

Config::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 4
nc 1
nop 2
1
<?php
2
3
namespace Enzyme\Axiom\Console;
4
5
use Enzyme\Parrot\File;
6
use Symfony\Component\Yaml\Parser;
7
use Symfony\Component\Yaml\Exception\ParseException;
8
9
class Config
10
{
11
    /**
12
     * Reference to the Symfony YAML parser.
13
     *
14
     * @var Symfony\Component\Yaml\Parser
15
     */
16
    protected $parser;
17
18
    /**
19
     * Reference to a parrot file wrapper.
20
     *
21
     * @var Enzyme\Parrot\File
22
     */
23
    protected $file_dispatch;
24
25
    /**
26
     * The local configuration store.
27
     *
28
     * @var array
29
     */
30
    protected $store;
31
32
    /**
33
     * The parsed YAML configuration.
34
     *
35
     * @var array
36
     */
37
    protected $config;
38
39
    /**
40
     * Create a new configuration manager.
41
     *
42
     * @param Parser $parser
43
     * @param File   $file_dispatch
44
     */
45
    public function __construct(Parser $parser, File $file_dispatch)
46
    {
47
        $this->parser = $parser;
0 ignored issues
show
Documentation Bug introduced by
It seems like $parser of type object<Symfony\Component\Yaml\Parser> is incompatible with the declared type object<Enzyme\Axiom\Cons...\Component\Yaml\Parser> of property $parser.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
48
        $this->file_dispatch = $file_dispatch;
0 ignored issues
show
Documentation Bug introduced by
It seems like $file_dispatch of type object<Enzyme\Parrot\File> is incompatible with the declared type object<Enzyme\Axiom\Console\Enzyme\Parrot\File> of property $file_dispatch.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
49
        $this->store = [];
50
    }
51
52
    /**
53
     * Parse the given YAML file.
54
     *
55
     * @param string $file The path to the file.
56
     */
57
    public function parse($file)
58
    {
59
        if (false === $this->file_dispatch->exists($file)) {
60
            return;
61
        }
62
63
        try {
64
            $this->config = $this->parser->parse(
65
                $this->file_dispatch->getContents($file)
66
            );
67
        } catch (ParseException $e) {
68
            throw new InvalidArgumentException(
69
                "The yaml configuration file [$file] is invalid."
70
            );
71
        }
72
    }
73
74
    /**
75
     * Get the value associated with the given key, if the key does not
76
     * exist, return null.
77
     *
78
     * @param string $key
79
     *
80
     * @return null|string
81
     */
82
    public function get($key)
83
    {
84
        return $this->dotGet($this->config, $key);
85
    }
86
87
    /**
88
     * This funky little method will get the value from a multidimensional
89
     * array using a dot-path notation. Eg: 'foo.bar' will return the value 'ok'
90
     * from the example array below. If the key cannot be found, it will return
91
     * null instead.
92
     * $arr = [
93
     *    'foo' => [
94
     *        'bar' => 'ok'
95
     *    ]
96
     * ];
97
     *
98
     * @param array  $array
99
     * @param string $path
100
     *
101
     * @return null|mixed
102
     */
103
    protected function dotGet(array $array, $path)
104
    {
105
        $parts = explode('.', $path);
106
        $top = count($parts) - 1;
107
        $current = $array;
0 ignored issues
show
Unused Code introduced by
$current is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
108
        $index = 0;
109
110
        foreach ($array as $key => $value) {
111
            // If we have only one path item left and this array key matches
112
            // it, let's immediately return its value.
113
            if ($key === $parts[0] && $index === $top) {
114
                return $value;
115
            }
116
117
            // If this array key matches the path item we're currently on,
118
            // let's dig in deeper and hope to find the full path.
119
            if ($key === $parts[0]) {
120
                // The next iteration will continue on the next available path
121
                // item chain. Eg: if we were on 'foo.bar.xzy', we'll be passing
122
                // in 'bar.xyz' to the recursive call.
123
                $new_path = array_slice($parts, 1);
124
                $new_path = implode('.', $new_path);
125
126
                return $this->dotGet($value, $new_path, 1);
0 ignored issues
show
Unused Code introduced by
The call to Config::dotGet() has too many arguments starting with 1.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
127
            }
128
129
            // If we're currently sitting on a numerical key, let's dig in
130
            // deeper in hopes to find some string keys to work with.
131
            if (true === is_int($key)) {
132
                // Keep our current path chain.
133
                $new_path = implode('.', $parts);
134
                $hit = $this->dotGet($value, $new_path, 1);
0 ignored issues
show
Unused Code introduced by
The call to Config::dotGet() has too many arguments starting with 1.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
135
136
                // If we found a match futher down the rabbit hole, let's
137
                // return that value here, otherwise let's do another iteration.
138
                if (null !== $hit) {
139
                    return $hit;
140
                }
141
            }
142
        }
143
144
        return null;
145
    }
146
}
147