Completed
Branch master (3c175d)
by Alfred
03:21 queued 01:31
created

ConfigManager.php (2 issues)

1
<?php
2
namespace Iriven;
3
use Exception;
4
/**
5
 * Created by PhpStorm.
6
 * User: IRIVEN FRANCE
7
 * Date: 21/11/2015
8
 * Time: 10:44
9
 */
10
class ConfigManager
11
{
12
const PHP_TAB = "\t";
13
    /**
14
    * Chemin complet du fichier de configuration
15
    */
16
    private $targetFile;
17
    private $Options = [];
18
    /**
19
    * tableau multidimensionnel contenant les donnée de configuration, initialement
20
    * chargées depuis le fichier
21
    */
22
    private $Config = [];
23
    /**
24
    * processeurs de fichier pris en charge par l'application
25
    */
26
    private $availableDrivers = array('JSON', 'PHP','INI','YML');
27
28
    private $defaultSection = 'runtime';
29
30
    /**
31
     * @param $filename
32
     * @param $location
33
     * @throws \Exception
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
            return $this;
45
        }
46
        catch(Exception $a)
47
        {
48
            trigger_error($a->getMessage(),E_USER_ERROR);
49
        }
50
    }
51
 /**
52
     * @param $section
53
     * @param $item
54
     * @return array|bool|mixed
55
     */
56
    public function get($section=null, $item=null)
57
    {
58
        if($item) $item = trim(strtolower($item));
59
        if($section) $section = trim(strtolower($section));
60
        if(!count($this->Config)) return false;
61
        if(!$section or !strlen($section)) return $this->Config;
62
        if($section AND $item)
63
        {
64
            if(!isset($this->Config[$section]))
65
            {
66
                $key = $item;
67
                $item = $section;
68
                $section = $this->defaultSection;
69
                if(!isset($this->Config[$section][$item][$key]))
70
                    return false;
71
                return $this->Config[$section][$item][$key];
72
            }
73
        }
74
        elseif(!$item or !strlen($item))
75
        {
76
            $item = $section;
77
            if(isset($this->Config[$item])) return $this->Config[$item];
78
            $section = $this->defaultSection;
79
        }
80
        if(!isset($this->Config[$section][$item])) return false;
81
        return $this->Config[$section][$item];
82
    }
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
     * @param $file
196
     * @param $location
197
     * @return array|bool
198
     */
199
    private function configureOptions($file,$location=null){
200
        if(!is_string($file) or ($location and !is_string($location)))
201
            throw new Exception('SETUP ERROR: configuration manager can accept string only parameters');
202
        $default=[
203
            'driver' => 'PHP',
204
            'filename' => null,
205
            'directory' => __DIR__,
206
        ];
207
        $Options = [];
208
        if($location)
209
            $Options['directory']=rtrim($this->normalize($location),DIRECTORY_SEPARATOR);
210
        else{
211
            if(basename($file)!==$file)
212
                $Options['directory']= rtrim($this->normalize(pathinfo($file,PATHINFO_DIRNAME)),DIRECTORY_SEPARATOR);
213
        }
214
        $Options['filename'] = basename($file);
215
        if(strpos($Options['filename'],'.')!==false)
216
            $Options['driver'] = strtoupper(pathinfo($Options['filename'], PATHINFO_EXTENSION));
217
        else
218
            $Options['filename']= $Options['filename'].'.'.strtolower($default['driver']);
219
	     if(!in_array($Options['driver'],$this->availableDrivers))
220
            throw new Exception('ERROR: driver "'.$Options['driver'].'" not supported');
221
	    $this->Options = array_merge($default,$Options);
222
        return $this->Options;
223
    }
224
    /**
225
     * @param $path
226
     * @param $relativeTo
227
     * @return string
228
     */
229
    private function normalize($path, $relativeTo = null) {
230
        $path = rtrim(preg_replace('#[/\\\\]+#', DIRECTORY_SEPARATOR, $path), DIRECTORY_SEPARATOR);
231
        $isAbsolute = stripos(PHP_OS, 'win')===0 ? preg_match('/^[A-Za-z]+:/', $path): !strncmp($path, DIRECTORY_SEPARATOR, 1);
232
        if (!$isAbsolute)
233
        {
234
            if (!$relativeTo) $relativeTo = getcwd();
235
            $path = $relativeTo.DIRECTORY_SEPARATOR.$path;
236
        }
237
        if (is_link($path) and ($parentPath = realpath(dirname($path))))
238
            return $parentPath.DIRECTORY_SEPARATOR.$path;
239
        if ($realpath = realpath($path))  return $realpath;
240
        $parts = explode(DIRECTORY_SEPARATOR, trim($path, DIRECTORY_SEPARATOR));
241
        while (end($parts) !== false)
242
        {
243
            array_pop($parts);
244
            $attempt = stripos(PHP_OS, 'win')===0 ? implode(DIRECTORY_SEPARATOR, $parts): DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $parts);
245
            if ($realpaths = realpath($attempt))
246
            {
247
                $path = $realpaths.substr($path, strlen($attempt));
248
                break;
249
            }
250
        }
251
        return $path;
252
    }
253
	  /**
254
     * @param array $options
255
     * @return mixed
256
     */
257
    private function parseConfiguration($options=[])
258
    {
259
260
        try
261
        {  $this->targetFile = $this->normalize($options['directory'].DIRECTORY_SEPARATOR.$options['filename']);
262
            if(!file_exists($this->targetFile))
263
                file_put_contents($this->targetFile,'',LOCK_EX);
264
            switch($this->Options['driver'])
265
            {
266
                case 'JSON':
267
                    $this->Config = unserialize(json_decode(file_get_contents($this->targetFile), true));
268
                    break;
269
                case 'INI':
270
                    $this->Config = parse_ini_file($this->targetFile, true);
271
                    break;
272
                case 'YML':
273
                    $ndocs=0;
274
                    $this->Config = yaml_parse_file($this->targetFile,0,$ndocs);
275
                    break;
276
                default:
277
                    if(!$this->Config = include $this->targetFile) $this->Config = [];
278
                    break;
279
            }
280
        }
281
        catch(Exception $b)
282
        {
283
            trigger_error($b->getMessage(),E_USER_ERROR);
284
        }
285
        return $this->Config;
286
    }
287
/**
288
     * @return bool
289
     */
290
     private function Save()
291
    {
292
        if( !is_writeable( $this->targetFile ) ) @chmod($this->targetFile,0775);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

292
        if( !is_writeable( $this->targetFile ) ) /** @scrutinizer ignore-unhandled */ @chmod($this->targetFile,0775);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
293
        $content = null;
294
        switch($this->Options['driver'])
295
        {
296
            case 'JSON':
297
                $content .= json_encode(serialize($this->Config));
298
                break;
299
            case 'INI':
300
                $content .= '; @file generator: Iriven France Php "'.get_class($this).'" Class'.PHP_EOL;
301
                $content .= '; @Last Update: '.date('Y-m-d H:i:s').PHP_EOL;
302
                $content .= PHP_EOL;
303
                foreach($this->Config as $section => $array)
304
                {
305
                    is_array($array) or $array = array($array);
306
                    $content .= '[' . $section . ']'.PHP_EOL;
307
                    foreach( $array as $key => $value )
308
                        $content .= PHP_TAB.$key.' = '.$value.PHP_EOL;
0 ignored issues
show
The constant Iriven\PHP_TAB was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
309
                    $content .= PHP_EOL;
310
                }
311
                break;
312
            case 'YML':
313
                $content .= yaml_emit ($this->Config, YAML_UTF8_ENCODING , YAML_LN_BREAK );
314
                break;
315
            default:
316
                $content .= '<?php'.PHP_EOL;
317
                $content .= 'return ';
318
                $content .= var_export($this->Config, true) . ';';
319
                $content = preg_replace('/array\s+\(/', '[', $content);
320
                $content = preg_replace('/,(\s+)\)/', '$1]', $content);
321
                break;
322
        }
323
        file_put_contents($this->targetFile, $content, LOCK_EX);
324
        @chmod($this->targetFile,0644);
325
        return true;
326
    }
327
    /**
328
     * fin de la classe
329
     */
330
331
}
332