Passed
Push — master ( 5146e5...36d909 )
by Alfred
01:50
created

ConfigManager::Save()   B

Complexity

Conditions 8
Paths 18

Size

Total Lines 38
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 31
nc 18
nop 0
dl 0
loc 38
rs 8.1795
c 0
b 0
f 0
1
<?php
2
namespace Iriven;
3
4
/**
5
 * Created by PhpStorm.
6
 * User: IRIVEN FRANCE
7
 * Date: 21/11/2015
8
 * Time: 10:44
9
 */
10
use Exception;
11
12
class ConfigManager
13
{
14
    /**
15
     * Chemin complet du fichier de configuration
16
     */
17
    private $targetFile;
18
    private $Options = [];
19
    /**
20
     * tableau multidimensionnel contenant les donnée de configuration, initialement
21
     * chargées depuis le fichier
22
     */
23
    private $Config = [];
24
    /**
25
     * processeurs de fichier pris en charge par l'application
26
     */
27
    private $availableDrivers = array('JSON', 'PHP','INI','YML');
28
    private $defaultSection = 'runtime';
29
30
    /**
31
     * ConfigManager constructor.
32
     * @param $filename
33
     * @param $location
34
     */
35
    public function __construct( $filename, $location=null )
36
    {
37
        $numargs = func_num_args();
38
        try
39
        {
40
            if($numargs > 2)
41
                throw new Exception('SETUP ERROR: configuration manager can accept only up to 2 parameters,'.$numargs.' given!');
42
            $this->configureOptions($filename,$location);
43
            $this->parseConfiguration($this->Options);
44
        }
45
        catch(Exception $a)
46
        {
47
            trigger_error($a->getMessage(),E_USER_ERROR);
48
        }
49
        return $this;
50
    }
51
52
    /**
53
     * @param $section
54
     * @param $item
55
     * @return array|bool|mixed
56
     */
57
    public function get($section=null, $item=null)
58
    {
59
        if($item) $item = trim(strtolower($item));
60
        if($section) $section = trim(strtolower($section));
61
        if(!count($this->Config)) return false;
62
        if(!$section or !strlen($section)) return $this->Config;
63
        if($section AND $item)
64
        {
65
            if(!isset($this->Config[$section]))
66
            {
67
                $key = $item;
68
                $item = $section;
69
                $section = $this->defaultSection;
70
                if(!isset($this->Config[$section][$item][$key]))
71
                    return false;
72
                return $this->Config[$section][$item][$key];
73
            }
74
        }
75
        elseif(!$item or !strlen($item))
76
        {
77
            $item = $section;
78
            if(isset($this->Config[$item])) return $this->Config[$item];
79
            $section = $this->defaultSection;
80
        }
81
        if(!isset($this->Config[$section][$item])) return false;
82
        return $this->Config[$section][$item];
83
    }
84
    /**
85
     * @param $section
86
     * @param $item
87
     * @param $value
88
     * @return bool
89
     */
90
    public function set($section,$item=null,$value=null)
91
    {
92
        ob_start();
93
        $numarg = func_num_args();
94
        $arguments=func_get_args();
95
        switch($numarg)
96
        {
97
            case 1:
98
                if(!is_array($arguments[0])) return false;
99
                $item=array_change_key_case($arguments[0], CASE_LOWER); $section=null; $value=null;
100
                break;
101
            case 2:
102
                if(is_array($arguments[0])) return false;
103
                $_arg = strtolower(trim($arguments[0]));
104
                if(is_array($arguments[1])){ $section=$_arg; $item =array_change_key_case($arguments[1], CASE_LOWER);$value=null;}
105
                else {$item = $_arg;$value=$arguments[1];$section=null;}
106
                break;
107
            default:
108
                break;
109
        }
110
        $section = $section? trim(strtolower($section)) : $this->defaultSection;
111
        if(!is_array($item))
112
        {
113
            if(!$value) return false;
114
            $item=trim(strtolower($item));
115
            if(!isset($this->Config[$section][$item]) or !is_array($this->Config[$section][$item])):
116
                $this->Config[$section][$item]=$value;
117
            else:
118
                if(!is_array($value)) $value = array($value);
119
                $this->Config[$section][$item] = array_merge($this->Config[$section][$item],$value);
120
            endif;
121
        }
122
        else
123
        {
124
            if($value) return false;
125
            $item = array_change_key_case($item, CASE_LOWER);
126
            $sectionsize = count($this->Config[$section]);
127
            $itemsize = count($item);
128
            if($sectionsize)
129
            {
130
                if($itemsize=='1')
131
                {
132
                    if(isset($this->Config[$section][key($item)]))
133
                        $this->Config[$section][key($item)] = array_merge($this->Config[$section][key($item)],$item[key($item)]);
134
                    else if(!is_numeric(key($item))) $this->Config[$section][key($item)]=$item[key($item)];
135
                }
136
                else $this->Config[$section] = array_merge($this->Config[$section],$item);
137
            }
138
            else $this->Config[$section] = $item;
139
        }
140
        $re = $this->Save();
141
        ob_end_clean();
142
        return $re;
143
    }
144
    /**
145
     * @param $section
146
     * @param $item
147
     * @return bool
148
     */
149
    public function del($section, $item=null)
150
    {
151
        $section = trim(strtolower($section));
152
        if($item and strlen($item))
153
        {
154
            $item = trim(strtolower($item));
155
            if(!isset($this->Config[$section]))
156
            {
157
                $key = $item;
158
                $item = $section;
159
                $section = $this->defaultSection;
160
                if(isset($this->Config[$section][$item][$key]))
161
                {
162
                    $itemSize=count($this->Config[$section][$item]);
163
                    if($itemSize>1) unset($this->Config[$section][$item][$key]);
164
                    else unset($this->Config[$section]);
165
                }
166
            }
167
            else
168
            {
169
                $sectionSize=count($this->Config[$section]);
170
                if(isset($this->Config[$section][$item]))
171
                {
172
                    if($sectionSize>1) unset($this->Config[$section][$item]);
173
                    else unset($this->Config[$section]);
174
                }
175
            }
176
        }
177
        else
178
        {
179
            $item = $section;
180
            if(!isset($this->Config[$item]))
181
            {
182
                $section = $this->defaultSection;
183
                $defaultSectionSize = count($this->Config[$section]);
184
                if(isset($this->Config[$section][$item]))
185
                {
186
                    if($defaultSectionSize>1) unset($this->Config[$section][$item]);
187
                    else unset($this->Config[$section]);
188
                }
189
            }
190
            else unset($this->Config[$item]);
191
        }
192
        return $this->Save();
193
    }
194
195
    /**
196
     * @param $file
197
     * @param $location
198
     * @return array
199
     * @throws Exception
200
     */
201
    private function configureOptions($file,$location=null){
202
        if(!is_string($file) or ($location and !is_string($location)))
203
            throw new Exception('SETUP ERROR: configuration manager can accept string only parameters');
204
        $default=[
205
            'driver' => 'PHP',
206
            'filename' => null,
207
            'directory' => __DIR__,
208
        ];
209
        $Options = [];
210
        if($location)
211
            $Options['directory']=rtrim($this->normalize($location),DIRECTORY_SEPARATOR);
212
        else{
213
            if(basename($file)!==$file)
214
                $Options['directory']= rtrim($this->normalize(pathinfo($file,PATHINFO_DIRNAME)),DIRECTORY_SEPARATOR);
215
        }
216
        $Options['filename'] = basename($file);
217
        if(strpos($Options['filename'],'.')!==false)
218
            $Options['driver'] = strtoupper(pathinfo($Options['filename'], PATHINFO_EXTENSION));
219
        else
220
            $Options['filename']= $Options['filename'].'.'.strtolower($default['driver']);
221
        if(!in_array($Options['driver'],$this->availableDrivers))
222
            throw new Exception('ERROR: driver "'.$Options['driver'].'" not supported');
223
        $this->Options = array_merge($default,$Options);
224
        return $this->Options;
225
    }
226
227
    /**
228
     * @param $path
229
     * @param $relativeTo
230
     * @return bool|string
231
     */
232
    private function normalize($path, $relativeTo = null) {
233
        $path = rtrim(preg_replace('#[/\\\\]+#', DIRECTORY_SEPARATOR, $path), DIRECTORY_SEPARATOR);
234
        $isAbsolute = stripos(PHP_OS, 'win')===0 ? preg_match('/^[A-Za-z]+:/', $path): !strncmp($path, DIRECTORY_SEPARATOR, 1);
235
        if (!$isAbsolute)
236
        {
237
            if (!$relativeTo) $relativeTo = getcwd();
238
            $path = $relativeTo.DIRECTORY_SEPARATOR.$path;
239
        }
240
        if (is_link($path) and ($parentPath = realpath(dirname($path))))
241
            return $parentPath.DIRECTORY_SEPARATOR.$path;
242
        if ($realpath = realpath($path))  return $realpath;
243
        $parts = explode(DIRECTORY_SEPARATOR, trim($path, DIRECTORY_SEPARATOR));
244
        while (end($parts) !== false)
245
        {
246
            array_pop($parts);
247
            $attempt = stripos(PHP_OS, 'win')===0 ? implode(DIRECTORY_SEPARATOR, $parts): DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $parts);
248
            if ($realpaths = realpath($attempt))
249
            {
250
                $path = $realpaths.substr($path, strlen($attempt));
251
                break;
252
            }
253
        }
254
        return $path;
255
    }
256
257
    /**
258
     * @param array $options
259
     * @return array|bool|mixed
260
     */
261
    
262
    private function parseConfiguration($options=[])
263
    {
264
        try
265
        {  $this->targetFile = $this->normalize($options['directory'].DIRECTORY_SEPARATOR.$options['filename']);
266
            if(!file_exists($this->targetFile))
267
                file_put_contents($this->targetFile,'',LOCK_EX);
268
            switch($this->Options['driver'])
269
            {
270
                case 'JSON':
271
                    $this->Config = unserialize(json_decode(file_get_contents($this->targetFile), true));
272
                    break;
273
                case 'INI':
274
                    $this->Config = parse_ini_file($this->targetFile, true);
275
                    break;
276
                case 'YML':
277
                    $ndocs=0;
278
                    $this->Config = yaml_parse_file($this->targetFile,0,$ndocs);
279
                    break;
280
                default:
281
                    if(!$this->Config = include $this->targetFile) $this->Config = [];
282
                    break;
283
            }
284
        }
285
        catch(Exception $b)
286
        {
287
            trigger_error($b->getMessage(),E_USER_ERROR);
288
        }
289
        return $this->Config;
290
    }
291
292
    /**
293
     * @return bool
294
     */
295
    private function Save()
296
    {
297
        try {
298
            $content = null;
299
            switch($this->Options['driver'])
300
            {
301
                case 'JSON':
302
                    $content .= json_encode(serialize($this->Config));
303
                    break;
304
                case 'INI':
305
                    $content .= '; @file generator: Iriven France Php "'.get_class($this).'" Class'.PHP_EOL;
306
                    $content .= '; @Last Update: '.date('Y-m-d H:i:s').PHP_EOL;
307
                    $content .= PHP_EOL;
308
                    foreach($this->Config as $section => $array)
309
                    {
310
                        is_array($array) or $array = array($array);
311
                        $content .= '[' . $section . ']'.PHP_EOL;
312
                        foreach( $array as $key => $value )
313
                            $content .= $key.' = '.$value.PHP_EOL;
314
                        $content .= PHP_EOL;
315
                    }
316
                    break;
317
                case 'YML':
318
                    $content .= yaml_emit ($this->Config, YAML_UTF8_ENCODING , YAML_LN_BREAK );
319
                    break;
320
                default:
321
                    $content .= '<?php'.PHP_EOL;
322
                    $content .= 'return ';
323
                    $content .= var_export($this->Config, true) . ';';
324
                    $content = preg_replace('/array\s+\(/', '[', $content);
325
                    $content = preg_replace('/,(\s+)\)/', '$1]', $content);
326
                    break;
327
            }
328
            file_put_contents($this->targetFile, $content, LOCK_EX);
329
        }
330
        catch (Exception $e)
331
        {  trigger_error($e->getMessage(),E_USER_ERROR);}
332
        return true;
333
    }
334
    /**
335
     * fin de la classe
336
     */
337
}
338