Completed
Push — master ( b659c5...c65770 )
by Michael
10:22
created

YamlConfigFile::setSettings()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
crap 1
1
<?php
2
declare(strict_types = 1);
3
/**
4
 * Contains class YamlConfigFile.
5
 *
6
 * PHP version 7.0+
7
 *
8
 * LICENSE:
9
 * This file is part of Yet Another Php Eve Api Library also know as Yapeal
10
 * which can be used to access the Eve Online API data and place it into a
11
 * database.
12
 * Copyright (C) 2016-2017 Michael Cummings
13
 *
14
 * This program is free software: you can redistribute it and/or modify it
15
 * under the terms of the GNU Lesser General Public License as published by the
16
 * Free Software Foundation, either version 3 of the License, or (at your
17
 * option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful, but WITHOUT
20
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
22
 * for more details.
23
 *
24
 * You should have received a copy of the GNU Lesser General Public License
25
 * along with this program. If not, see
26
 * <http://spdx.org/licenses/LGPL-3.0.html>.
27
 *
28
 * You should be able to find a copy of this license in the COPYING-LESSER.md
29
 * file. A copy of the GNU GPL should also be available in the COPYING.md file.
30
 *
31
 * @author    Michael Cummings <[email protected]>
32
 * @copyright 2016-2017 Michael Cummings
33
 * @license   LGPL-3.0+
34
 */
35
namespace Yapeal\Configuration;
36
37
use Symfony\Component\Yaml\Dumper;
38
use Symfony\Component\Yaml\Exception\ParseException;
39
use Symfony\Component\Yaml\Parser;
40
use Yapeal\FileSystem\SafeFileHandlingTrait;
41
42
/**
43
 * Class YamlConfigFile.
44
 */
45
class YamlConfigFile implements ConfigFileInterface
46
{
47
    use SafeFileHandlingTrait;
48
    /**
49
     * YamlConfigFile constructor.
50
     *
51
     * @param string|null $pathFile File name with absolute path.
52
     * @param array $settings Contents as an associate array.
53
     */
54 17
    public function __construct(string $pathFile = null, array $settings = [])
55
    {
56 17
        $this->pathFile = $pathFile;
57 17
        $this->settings = $settings;
58
    }
59
    /**
60
     * @param array|null $yaml The array to be flattened. If null assumes $settings.
61
     *
62
     * @return array
63
     */
64 9
    public function flattenYaml(array $yaml = null): array
65
    {
66 9
        if (null === $yaml) {
67 9
            $yaml = $this->getSettings();
68
        }
69 9
        if (0 === count($yaml)) {
70
            return [];
71
        }
72 9
        $rItIt = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($yaml));
73 9
        $settings = [];
74 9
        foreach ($rItIt as $leafValue) {
75 9
            $keys = [];
76 9
            foreach (range(0, $rItIt->getDepth()) as $depth) {
77 9
                $keys[] = $rItIt->getSubIterator($depth)
78 9
                    ->key();
79
            }
80 9
            $settings[implode('.', $keys)] = $leafValue;
81
        }
82 9
        return $settings;
83
    }
84
    /**
85
     * @return string
86
     * @throws \LogicException
87
     */
88 14
    public function getPathFile(): string
89
    {
90 14
        if (null === $this->pathFile) {
91 1
            $mess = 'Trying to access $pathFile before it was set';
92 1
            throw new \LogicException($mess);
93
        }
94 13
        return $this->pathFile;
95
    }
96
    /**
97
     * @return array
98
     */
99 9
    public function getSettings(): array
100
    {
101 9
        return $this->settings;
102
    }
103
    /**
104
     * @return self Fluent interface.
105
     * @throws \LogicException
106
     */
107 13
    public function read(): self
108
    {
109 13
        $data = $this->safeFileRead($this->getPathFile());
110 13
        if (false === $data) {
111
            $this->setSettings([]);
112
            return $this;
113
        }
114
        try {
115 13
            $data = (new Parser())->parse($data, true, false);
116
        } catch (ParseException $exc) {
117
            $data = [];
118
        }
119 13
        $this->setSettings($data);
120 13
        return $this;
121
    }
122
    /**
123
     * @throws \LogicException
124
     */
125
    public function save()
126
    {
127
        $data = (new Dumper())->dump($this->getSettings());
128
        $this->safeDataWrite($this->getPathFile(), $data);
129
    }
130
    /**
131
     * @param string|null $value File name with absolute path.
132
     *
133
     * @return self Fluent interface.
134
     */
135 1
    public function setPathFile(string $value = null): self
136
    {
137 1
        $this->pathFile = $value;
138 1
        return $this;
139
    }
140
    /**
141
     * @param array $value
142
     *
143
     * @return self Fluent interface.
144
     */
145 14
    public function setSettings(array $value = []): self
146
    {
147 14
        $this->settings = $value;
148 14
        return $this;
149
    }
150
    /**
151
     * @param array|null $yaml The array to be unflattened. If null assumes $settings.
152
     *
153
     * @return array
154
     */
155
    public function unflattenYaml(array $yaml = null): array
156
    {
157
        if (null === $yaml) {
158
            $yaml = $this->getSettings();
159
        }
160
        if (0 === count($yaml)) {
161
            return [];
162
        }
163
        $output = [];
164
        foreach ((array)$yaml as $key => $value) {
165
            $this->arraySet($output, $key, $value);
166
            if (is_array($value) && false !== strpos($key, '.')) {
167
                $nested = $this->unflattenYaml($value);
168
                $output[$key] = $nested;
169
            }
170
        }
171
        return $output;
172
    }
173
    /**
174
     * @param array      $array
175
     * @param string|int $key
176
     * @param mixed      $value
177
     *
178
     * @return array
179
     */
180
    private function arraySet(array &$array, $key, $value): array
181
    {
182
        if (null === $key) {
183
            $array = $value;
184
            return $array;
185
        }
186
        if (is_int($key)) {
187
            $key = (string)$key;
188
        }
189
        $keys = explode('.', $key);
190
        while (1 < count($keys)) {
191
            $key = array_shift($keys);
192
            // If the key doesn't exist at this depth, we will just create an empty array
193
            // to hold the next value, allowing us to create the arrays to hold final
194
            // values at the correct depth. Then we'll keep digging into the array.
195
            if (!array_key_exists($key, $array) || !is_array($array[$key])) {
196
                $array[$key] = [];
197
            }
198
            $array = &$array[$key];
199
        }
200
        $array[array_shift($keys)] = $value;
201
        return $array;
202
    }
203
    /**
204
     * @var string $pathFile
205
     */
206
    private $pathFile;
207
    /**
208
     * @var array $settings
209
     */
210
    private $settings;
211
}
212