Failed Conditions
Push — master ( 767168...ebb773 )
by Mathieu
08:50 queued 06:17
created

Links   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 175
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 36
lcom 1
cbo 1
dl 0
loc 175
rs 8.8
c 0
b 0
f 0

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A offsetExists() 0 3 1
A offsetGet() 0 3 1
A offsetSet() 0 3 1
A offsetUnset() 0 3 1
A count() 0 4 1
A current() 0 3 1
A key() 0 3 1
A next() 0 3 1
A rewind() 0 3 1
A valid() 0 3 1
B withEnv() 0 27 4
A buildFrom() 0 4 1
A links() 0 10 3
A iterator() 0 6 2
A envs() 0 19 4
A prefixes() 0 4 2
A uniquePrefixes() 0 14 4
A prefixesWithPorts() 0 6 1
A allPrefixes() 0 15 4
1
<?php
2
3
namespace TH\Docker;
4
5
use ArrayAccess;
6
use ArrayIterator;
7
use Countable;
8
use Iterator;
9
10
class Links implements ArrayAccess, Countable, Iterator
11
{
12
    private $env;
13
    private $unique;
14
15
    private $links;
16
    private $iterator;
17
18
    public function __construct($env, $unique)
19
    {
20
        $this->env = $env;
21
        $this->unique = $unique;
22
    }
23
24
    public function offsetExists($name) {
25
        return isset($this->links()[strtoupper($name)]);
26
    }
27
28
    public function offsetGet($name) {
29
        return $this->links()[strtoupper($name)];
30
    }
31
32
    public function offsetSet($name, $value) {
33
        throw new \Exception('\TH\Docker\Links is read only');
34
    }
35
36
    public function offsetUnset($name) {
37
        throw new \Exception('\TH\Docker\Links is read only');
38
    }
39
40
    public function count()
41
    {
42
        return count($this->links());
43
    }
44
45
    public function current() {
46
        return $this->iterator()->current();
47
    }
48
49
    public function key() {
50
        return $this->iterator()->key();
51
    }
52
53
    public function next() {
54
        return $this->iterator()->next();
55
    }
56
57
    public function rewind() {
58
        return $this->iterator()->rewind();
59
    }
60
61
    public function valid() {
62
        return $this->iterator()->valid();
63
    }
64
65
    public function withEnv($name, $value = null)
66
    {
67
        $suffix = "_ENV_".strtoupper($name);
68
        $n = strlen($suffix);
69
70
        $filteredEnv = array_filter($this->env, function ($key) use ($suffix, $n) {
71
            return substr_compare($key, $suffix, -$n) === 0;
72
        }, ARRAY_FILTER_USE_KEY);
73
        if ($value !== null) {
74
            $filteredEnv = array_filter($filteredEnv, function ($envValue) use ($value) {
75
                return $envValue === $value;
76
            });
77
        }
78
        $prefixes = array_map(function ($key) use ($n) {
79
            return substr($key, 0, -$n);
80
        }, array_keys($filteredEnv));
81
        $prefixes = array_combine($prefixes, array_map("strlen", $prefixes));
82
        $env = array_filter($this->env, function ($key) use ($prefixes) {
83
            foreach ($prefixes as $prefix => $prefixLength) {
84
                if (substr_compare($key, $prefix, 0, $prefixLength) === 0) {
85
                    return true;
86
                }
87
            }
88
            return false;
89
        }, ARRAY_FILTER_USE_KEY);
90
        return new self($env, $this->unique);
91
    }
92
93
    public static function buildFrom(Array $env, $unique = true)
94
    {
95
        return new self($env, $unique);
96
    }
97
98
    private function links() {
99
        if ($this->links === null) {
100
            $this->links = [];
101
            foreach (self::envs($this->env, $this->unique) as $prefixEnv) {
102
                $link = Link::build($prefixEnv);
103
                $this->links[strtoupper($link->name())] = $link;
104
            }
105
        }
106
        return $this->links;
107
    }
108
109
    private function iterator() {
110
        if ($this->iterator === null) {
111
            $this->iterator = new ArrayIterator($this->links());
112
        }
113
        return $this->iterator;
114
    }
115
116
    /**
117
     * @param  boolean $unique
118
     */
119
    private static function envs(Array $env, $unique)
120
    {
121
        ksort($env);
122
        $envs = [];
123
        reset($env);
124
        foreach (self::prefixes($env, $unique) as $prefix) {
125
            while (strpos(key($env), $prefix) === false) {
126
                next($env);
127
            }
128
            $prefixLength = strlen($prefix) + 1;
129
            $prefixEnv = [];
130
            do {
131
                $prefixEnv[substr(key($env), $prefixLength)] = current($env);
132
                next($env);
133
            } while (strpos(key($env), $prefix) === 0);
134
            $envs[] = $prefixEnv;
135
        }
136
        return $envs;
137
    }
138
139
    /**
140
     * @param  boolean $unique
141
     */
142
    private static function prefixes(Array $env, $unique)
143
    {
144
        return $unique ? self::uniquePrefixes($env) : self::prefixesWithPorts($env);
145
    }
146
147
    private static function uniquePrefixes(Array $env)
148
    {
149
        $prefixes = self::prefixesWithPorts($env);
150
        sort($prefixes);
151
        return array_reduce($prefixes, function($uniquePrefixes, $prefix) {
152
            foreach ($uniquePrefixes as $uniqueprefix) {
153
                if (strpos($prefix, $uniqueprefix) !== false || strpos($uniqueprefix, $prefix) !== false) {
154
                    return $uniquePrefixes;
155
                }
156
            }
157
            $uniquePrefixes[] = $prefix;
158
            return $uniquePrefixes;
159
        }, []);
160
    }
161
162
    private static function prefixesWithPorts(Array $env)
163
    {
164
        return array_filter(self::allPrefixes($env), function($prefix) use ($env) {
165
            return array_key_exists("{$prefix}_PORT", $env);
166
        });
167
    }
168
169
    private static function allPrefixes(Array $env)
170
    {
171
        $prefixes = [];
172
        foreach ($env as $key => $value) {
173
            $keyLength = strlen($key);
174
            if ($keyLength < 6) {
175
                continue;
176
            }
177
            $pos = strrpos($key, '_NAME');
178
            if ($pos + 5 === $keyLength) {
179
                $prefixes[] = substr($key, 0, $pos);
180
            }
181
        }
182
        return $prefixes;
183
    }
184
}
185