Completed
Pull Request — master (#243)
by Дмитрий
05:05
created

Object::onLoad()   B

Complexity

Conditions 9
Paths 9

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 2 Features 0
Metric Value
cc 9
eloc 9
c 2
b 2
f 0
nc 9
nop 0
dl 0
loc 16
rs 7.756
1
<?php
2
namespace PHPDaemon\Config;
3
4
use PHPDaemon\Config\Entry\ConfigFile;
5
use PHPDaemon\Config\Entry\Number;
6
use PHPDaemon\Config\Entry\Size;
7
use PHPDaemon\Config\Entry\Time;
8
use PHPDaemon\Config\Parser;
9
use PHPDaemon\Core\Daemon;
10
11
/**
12
 * Config class
13
 *
14
 * @package    Core
15
 * @subpackage Config
16
 *
17
 * @author     Vasily Zorin <[email protected]>
18
 * @dynamic_fields
19
 */
20
class Object implements \ArrayAccess
21
{
22
    use \PHPDaemon\Traits\ClassWatchdog;
23
24
    /**
25
     * Maximum memory usage
26
     * @var size
27
     */
28
    public $maxmemoryusage = '0b';
29
30
    /**
31
     * Maximum idle time
32
     * @var time
33
     */
34
    public $maxidle = '0s';
35
36
    /**
37
     * PID file
38
     * @var string|Entry\Generic
39
     */
40
    public $pidfile = '/var/run/phpd.pid';
41
42
    /**
43
     * Default namespace
44
     * @var path
45
     */
46
    public $defaultns = 'PHPDaemon';
47
48
    /**
49
     * Default PID file
50
     * @var path
51
     */
52
    public $defaultpidfile = '/var/run/phpd.pid';
53
54
    /**
55
     * Config file
56
     * @var string|Entry\ConfigFile
57
     */
58
    public $configfile = '/etc/phpdaemon/phpd.conf;/etc/phpd/phpd.conf;./conf/phpd.conf';
59
60
    /**
61
     * Application resolver
62
     * @var string|Entry\Generic
63
     */
64
    public $path = '/etc/phpdaemon/AppResolver.php;./conf/AppResolver.php';
65
66
    /**
67
     * Additional include path
68
     * @var string|Entry\Generic
69
     */
70
    public $addincludepath = null;
71
72
    /**
73
     * Multi-Process Manager delay
74
     * @var time
75
     */
76
    public $mpmdelay = '0.1s';
77
78
    /**
79
     * Max. requests before worker restart
80
     * @var int|Entry\Number
81
     */
82
    public $maxrequests = '10k';
83
84
    /**
85
     * Start workers
86
     * @var int|Entry\Number
87
     */
88
    public $startworkers = 4;
89
90
    /**
91
     * Minimum number of workers
92
     * @var int|Entry\Number
93
     */
94
    public $minworkers = 4;
95
96
    /**
97
     * Maximum number of workers
98
     * @var int|Entry\Number
99
     */
100
    public $maxworkers = 8;
101
102
    /**
103
     * Minimum number of spare workes
104
     * @var int|Entry\Number
105
     */
106
    public $minspareworkers = 2;
107
108
    /**
109
     * Maximum number of spare workes
110
     * @var int|Entry\Number
111
     */
112
    public $maxspareworkers = 0;
113
114
    /**
115
     * Master thread priority
116
     * @var integer
117
     */
118
    public $masterpriority = 100;
119
120
    /**
121
     * IPC thread priority
122
     * @var integer
123
     */
124
    public $ipcthreadpriority = 100;
125
126
    /**
127
     * IPC thread priority
128
     * @var boolean
129
     */
130
    public $obfilterauto = 1;
131
132
    /**
133
     * System user (setuid)
134
     * @var string|Entry\Generic
135
     */
136
    public $user = null;
137
138
    /**
139
     * System group (setgid)
140
     * @var string|Entry\Generic
141
     */
142
    public $group = null;
143
144
    /**
145
     * Automatic garbage collector, number of iterations between GC call
146
     * @var int|Entry\Number
147
     */
148
    public $autogc = '1k';
149
150
    /**
151
     * Chroot
152
     * @var string|Entry\Generic
153
     */
154
    public $chroot = '/';
155
156
    /**
157
     * Current directory
158
     * @var string
159
     */
160
    public $cwd = '.';
161
162
    /**
163
     * Autoreload interval. Time interval between checks.
164
     * @var time
165
     */
166
    public $autoreload = '0s';
167
168
    /**
169
     * Try to import updated code (runkit required)
170
     * @var boolean|Entry\Generic
171
     */
172
    public $autoreimport = 0;
173
174
    /**
175
     * Worker thread priority
176
     * @var integer
177
     */
178
    public $workerpriority = 4;
179
180
    /**
181
     * Lambda cache size
182
     * @var integer
183
     */
184
    public $lambdacachemaxsize = 128;
185
186
    /**
187
     * Lambda cache cap window
188
     * @var integer
189
     */
190
    public $lambdacachecapwindow = 32;
191
192
    /**
193
     * Lambda cache ttl
194
     * @var integer
195
     */
196
    public $lambdacachettl = 0;
197
198
    /**
199
     * Throw exception on shutdown?
200
     * @var boolean
201
     */
202
    public $throwexceptiononshutdown = 0;
203
204
    /**
205
     * Comma-separated list of locales
206
     * @var string|Entry\Generic
207
     */
208
    public $locale = '';
209
210
    /**
211
     * Restrict usage of error-control functions (like @ operator), useful in debugging
212
     * @var boolean
213
     */
214
    public $restricterrorcontrol = false;
215
216
    // Logging-related
217
218
    /**
219
     * Logging?
220
     * @var boolean
221
     */
222
    public $logging = 1;
223
224
    /**
225
     * Log storage
226
     * @var boolean|Entry\Generic
227
     */
228
    public $logstorage = '/var/log/phpdaemon.log';
229
230
    /**
231
     * Log format
232
     * @var string
233
     */
234
    public $logformat = '[D, j M Y H:i:s.u O] %msg%';
235
236
    /**
237
     * Log errors?
238
     * @var boolean
239
     */
240
    public $logerrors = 1;
241
242
    /**
243
     * Log Worker->setState() ?
244
     * @var boolean
245
     */
246
    public $logworkersetstate = 0;
247
248
    /**
249
     * Log events?
250
     * @var boolean
251
     */
252
    public $logevents = 0;
253
254
    /**
255
     * Log signals?
256
     * @var boolean
257
     */
258
    public $logsignals = 0;
259
260
    /**
261
     * Do not close STDOUT and STDERR pipes and send log messages there
262
     * @var boolean
263
     */
264
    public $verbosetty = 0;
265
266
    /**
267
     * EIO enabled?
268
     * @var boolean
269
     */
270
    public $eioenabled = 1;
271
272
    /**
273
     * EIO maximum idle time
274
     * @var time
275
     */
276
    public $eiosetmaxidle = null;
277
278
    /**
279
     * EIO maximum parallel threads
280
     * @var int|Entry\Number
281
     */
282
    public $eiosetmaxparallel = null;
283
284
    /**
285
     * EIO maximum poll requests
286
     * @var int|Entry\Number
287
     */
288
    public $eiosetmaxpollreqs = null;
289
290
    /**
291
     * EIO maximum poll time
292
     * @var time
293
     */
294
    public $eiosetmaxpolltime = null;
295
296
    /**
297
     * EIO minimum parallel threads
298
     * @var int|Entry\Number
299
     */
300
    public $eiosetminparallel = null;
301
302
    /** @var int */
303
    public static $lastRevision = 0;
304
305
    /**
306
     * Constructor
307
     * @return object
308
     */
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
309
310
    public function __construct()
311
    {
312
        static $sizes = ['maxmemoryusage'];
313
        static $times = ['maxidle', 'autoreload', 'mpmdelay', 'eiosetmaxpolltime', 'lambdacachettl'];
314
        static $numbers = [
315
            'maxrequests',
316
            'autogc',
317
            'startworkers',
318
            'workerpriority',
319
            'minworkers',
320
            'maxworkers',
321
            'minspareworkers',
322
            'maxspareworkers',
323
            'masterpriority',
324
            'ipcthreadpriority',
325
            'eiosetmaxidle',
326
            'eiosetmaxparallel',
327
            'eiosetmaxpollreqs',
328
            'eiosetminparallel',
329
            'verbose',
330
            'verbosetty',
331
            'lambdacachemaxsize',
332
            'lambdacachecapwindow',
333
        ];
334
335
        foreach ($this as $name => $value) {
0 ignored issues
show
Bug introduced by
The expression $this of type this<PHPDaemon\Config\Object> is not traversable.
Loading history...
336
            if (in_array($name, $sizes)) {
337
                $entry = new Size;
338
            } elseif (in_array($name, $times)) {
339
                $entry = new Time;
340
            } elseif (in_array($name, $numbers)) {
341
                $entry = new Number;
342
            } elseif ($name === 'configfile') {
343
                $entry = new ConfigFile;
344
            } else {
345
                $entry = new Entry\Generic;
346
            }
347
348
            if ($name === 'addincludepath') {
349
                $entry->setStackable();
350
            }
351
352
            $entry->setDefaultValue($value);
353
            $entry->setHumanValue($value);
354
            $this->{$name} = $entry;
355
        }
356
    }
357
358
    /**
359
     * Renames section
360
     * @param string $old
361
     * @param string $new
362
     * @param booelan $log Log?
0 ignored issues
show
Documentation introduced by
Should the type for parameter $log not be false|booelan?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
363
     * @return void
364
     */
365
    public function renameSection($old, $new, $log = false)
366
    {
367
        Daemon::$config->{$new} = Daemon::$config->{$old};
368
        unset(Daemon::$config->{$old});
369
        if ($log) {
370
            Daemon::log('Config section \'' . $old . '\' -> \'' . $new . '\'');
371
        }
372
    }
373
374
    /**
375
     * Load config file
376
     * @param string Path
377
     * @return boolean Success
378
     */
379
    public function loadFile($path)
380
    {
381
        $parser = Parser::parse($path, $this);
382
        $this->onLoad();
383
        return !$parser->isErroneous();
384
    }
385
386
    /**
387
     * Called when config is loaded
388
     * @return void
389
     */
390
    protected function onLoad()
391
    {
392
        if (isset($this->minspareworkers->value) && $this->minspareworkers->value > 0
393
            && isset($this->maxspareworkers->value) && $this->maxspareworkers->value > 0) {
394
            if ($this->minspareworkers->value > $this->maxspareworkers->value) {
395
                Daemon::log('\'minspareworkers\' (' . $this->minspareworkers->value . ')  cannot be greater than \'maxspareworkers\' (' . $this->maxspareworkers->value . ').');
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 176 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
396
                $this->minspareworkers->value = $this->maxspareworkers->value;
397
            }
398
        }
399
400
        if (isset($this->minworkers->value) && isset($this->maxworkers->value)) {
401
            if ($this->minworkers->value > $this->maxworkers->value) {
402
                $this->minworkers->value = $this->maxworkers->value;
403
            }
404
        }
405
    }
406
407
    /**
408
     * Get real property name
409
     * @param string Property name
410
     * @return string Real property name
411
     */
412
    public function getRealPropertyName($prop)
413
    {
414
        return str_replace('-', '', strtolower($prop));
415
    }
416
417
    /**
418
     * Checks if property exists
419
     * @param string Property name
420
     * @return boolean Exists?
421
     */
422
423
    public function offsetExists($prop)
424
    {
425
        $prop = $this->getRealPropertyName($prop);
426
        return property_exists($this, $prop);
427
    }
428
429
    /**
430
     * Get property by name
431
     * @param string Property name
432
     * @return mixed
433
     */
434
    public function offsetGet($prop)
435
    {
436
        $prop = $this->getRealPropertyName($prop);
437
        return isset($this->{$prop}) ? $this->{$prop}->value : null;
438
    }
439
440
    /**
441
     * Set property
442
     * @param string Property name
443
     * @param mixed  Value
444
     * @return void
445
     */
446
    public function offsetSet($prop, $value)
447
    {
448
        $prop = $this->getRealPropertyName($prop);
449
        $this->{$prop} = $value;
450
    }
451
452
    /**
453
     * Unset property
454
     * @param string Property name
455
     * @return void
456
     */
457
    public function offsetUnset($prop)
458
    {
459
        $prop = $this->getRealPropertyName($prop);
460
        unset($this->{$prop});
461
    }
462
463
    /**
464
     * Checks if property exists
465
     * @param string Property name
466
     * @return boolean Exists?
0 ignored issues
show
Documentation introduced by
Should the return type not be array<string,string>|false?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
467
     */
468
    public static function parseCfgUri($uri, $source = null)
0 ignored issues
show
Unused Code introduced by
The parameter $source is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
469
    {
470
        if (mb_orig_strpos($uri, '://') === false) {
471
            if (strncmp($uri, 'unix:', 5) === 0) {
472
                $e = explode(':', $uri);
473
                if (sizeof($e) === 4) {
474
                    $uri = 'unix://' . $e[1] . ':' . $e[2] . '@localhost' . $e[3];
475
                } elseif (sizeof($e) === 3) {
476
                    $uri = 'unix://' . $e[1] . '@localhost' . $e[2];
477
                } else {
478
                    $uri = 'unix://localhost' . $e[1];
479
                }
480
            } else {
481
                $uri = 'tcp://' . $uri;
482
            }
483
        }
484
        if (stripos($uri, 'unix:///') === 0) {
485
            $uri = 'unix://localhost/' . substr($uri, 8);
486
        }
487
        $zeroPortNum = false;
488
        $uri = preg_replace_callback('~:0(?:$|/)~', function () use (&$zeroPortNum) {
489
            $zeroPortNum = true;
490
            return '';
491
        }, $uri);
492
        $u = parse_url($uri);
493
        $u['host'] = trim($u['host'], '][');
494
        $u['uri'] = $uri;
495
        if ($zeroPortNum) {
496
            $u['port'] = 0;
497
        }
498
        if (!isset($u['scheme'])) {
499
            $u['scheme'] = '';
500
        }
501
        $u['params'] = [];
502
        if (!isset($u['fragment'])) {
503
            return $u;
504
        }
505
        $hash = '#' . $u['fragment'];
506
        $error = false;
507
        preg_replace_callback('~(#+)(.+?)(?=#|$)|(.+)~', function ($m) use (&$u, &$error, $uri) {
508
            if ($error) {
509
                return;
510
            }
511
            list(, $type, $value) = $m;
512
            if ($type === '#') { // standard value
513
                $e = explode('=', $value, 2);
514
                if (sizeof($e) === 2) {
515
                    list($key, $value) = $e;
516
                } else {
517
                    $key = $value;
518
                    $value = true;
519
                }
520
                $u['params'][$key] = $value;
521
            } elseif ($type === '##') { // Context name
522
                $u['params']['ctxname'] = $value;
523
            } else {
524
                Daemon::log('Malformed URI: ' . var_export($uri, true) . ', unexpected token \'' . $type . '\'');
525
                $error = true;
526
            }
527
        }, $hash);
528
        return $error ? false : $u;
529
    }
530
531
    /**
532
     * Imports parameters from command line args
533
     * @param array Settings.
534
     * @return boolean - Success.
535
     */
536
    public static function loadCmdLineArgs($settings)
537
    {
538
        $error = false;
539
540
        static $ktr = [
541
            '-' => '',
542
        ];
543
544
        foreach ($settings as $k => $v) {
545
            $k = strtolower(strtr($k, $ktr));
546
547
            if ($k === 'config') {
548
                $k = 'configfile';
549
            }
550
551
            if (($k === 'user') || ($k === 'group')) {
552
                if ($v === '') {
553
                    $v = null;
554
                }
555
            }
556
            if (isset(Daemon::$config->{$k})) {
557
                Daemon::$config->{$k}->setHumanValue($v);
558
                Daemon::$config->{$k}->source = 'cmdline';
559
            } else {
560
                Daemon::log('Unrecognized parameter \'' . $k . '\'');
561
                $error = true;
562
            }
563
        }
564
565
        return !$error;
566
    }
567
}
568