Passed
Branch master (4422ce)
by Alfred
03:48
created

ConfigManager.php (2 issues)

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 null $section
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $section is correct as it would always require null to be passed?
Loading history...
54
     * @param null $item
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $item is correct as it would always require null to be passed?
Loading history...
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
                    if(!function_exists('json_decode')) 
272
                        throw new Exception('Error: The PHP-Json extension is missing');
273
                    $this->Config = unserialize(json_decode(file_get_contents($this->targetFile), true));
274
                    break;
275
                case 'INI':
276
                    $this->Config = parse_ini_file($this->targetFile, true);
277
                    break;
278
                case 'YML':
279
                    $ndocs=0;
280
                    if(!function_exists('yaml_parse_file'))
281
                        throw new Exception('Error: The PHP-Yaml extension is missing');
282
                    $this->Config = yaml_parse_file($this->targetFile,0,$ndocs);
283
                    break;
284
                default:
285
                    if(!$this->Config = include $this->targetFile) $this->Config = [];
286
                    break;
287
            }
288
        }
289
        catch(Exception $b)
290
        {
291
            trigger_error($b->getMessage(),E_USER_ERROR);
292
        }
293
        return $this->Config;
294
    }
295
296
    /**
297
     * @return bool
298
     */
299
    private function Save()
300
    {
301
        try {
302
            if( !is_writeable( $this->targetFile ) )
303
            {
304
                if(@chmod($this->targetFile,0775))
305
                    throw new Exception('Cant write to file: '.$this->targetFile);
306
            }
307
            $content = null;
308
            switch($this->Options['driver'])
309
            {
310
                case 'JSON':
311
                    if(!function_exists('json_encode'))
312
                        throw new Exception('Error: The PHP-Json extension is missing');
313
                    $content .= json_encode(serialize($this->Config));
314
                    break;
315
                case 'INI':
316
                    $content .= '; @file generator: Iriven France Php "'.get_class($this).'" Class'.PHP_EOL;
317
                    $content .= '; @Last Update: '.date('Y-m-d H:i:s').PHP_EOL;
318
                    $content .= PHP_EOL;
319
                    foreach($this->Config as $section => $array)
320
                    {
321
                        is_array($array) or $array = array($array);
322
                        $content .= '[' . $section . ']'.PHP_EOL;
323
                        foreach( $array as $key => $value )
324
                            $content .= $key.' = '.$value.PHP_EOL;
325
                        $content .= PHP_EOL;
326
                    }
327
                    break;
328
                case 'YML':
329
                    if(!function_exists('yaml_emit'))
330
                        throw new Exception('Error: The PHP-Yaml extension is missing');
331
                    $content .= yaml_emit ($this->Config, YAML_UTF8_ENCODING , YAML_LN_BREAK );
332
                    break;
333
                default:
334
                    $content .= '<?php'.PHP_EOL;
335
                    $content .= 'return ';
336
                    $content .= var_export($this->Config, true) . ';';
337
                    $content = preg_replace('/array\s+\(/', '[', $content);
338
                    $content = preg_replace('/,(\s+)\)/', '$1]', $content);
339
                    break;
340
            }
341
            file_put_contents($this->targetFile, $content, LOCK_EX);
342
            if(@chmod($this->targetFile,0644))
343
                throw new Exception('Cant write to file: '.$this->targetFile);
344
        }
345
        catch (Exception $e)
346
        {  trigger_error($e->getMessage(),E_USER_ERROR);}
347
        return true;
348
    }
349
    /**
350
     * fin de la classe
351
     */
352
}
353