Completed
Pull Request — master (#234)
by Дмитрий
07:51
created

AppInstance::__construct()   D

Complexity

Conditions 12
Paths 216

Size

Total Lines 51
Code Lines 30

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 12
dl 0
loc 51
rs 4.8739
eloc 30
nc 216
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace PHPDaemon\Core;
3
4
use PHPDaemon\Config;
5
use PHPDaemon\Core\Daemon;
6
use PHPDaemon\Request\Generic;
7
use PHPDaemon\Thread;
8
9
/**
10
 * Application instance
11
 * @package PHPDaemon\Core
12
 * @author  Vasily Zorin <[email protected]>
13
 */
14
class AppInstance
15
{
16
    use \PHPDaemon\Traits\ClassWatchdog;
17
    use \PHPDaemon\Traits\StaticObjectWatchdog;
18
19
    /**
20
     * Event: config updated
21
     */
22
    const EVENT_CONFIG_UPDATED = 1;
23
    
24
    /**
25
     * Event: graceful shutdown
26
     */
27
    const EVENT_GRACEFUL_SHUTDOWN = 2;
28
    
29
    /**
30
     * Event: shutdown
31
     */
32
    const EVENT_SHUTDOWN = 3;
33
    
34
    /**
35
     * @var boolean If true, it's allowed to be run without defined config section'
36
     */
37
    public static $runOnDemand = true;
38
    
39
    /**
40
     * @var string Optional passphrase
41
     */
42
    public $passphrase;
43
    
44
    /**
45
     * @var boolean Ready to run?
46
     */
47
    public $ready = false;
48
    
49
    /**
50
     * @var object Related config section
51
     */
52
    public $config;
53
    
54
    /**
55
     * @var boolean Is RPC enabled?
56
     */
57
    public $enableRPC = false;
58
    
59
    /**
60
     * @var null|string Default class of incoming requests
61
     */
62
    public $requestClass;
63
    
64
    /**
65
     * @var string Instance name
66
     */
67
    protected $name;
68
69
    /**
70
     * Application constructor
71
     * @param  string $name Instance name
72
     * @return void
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...
73
     */
74
    public function __construct($name = '')
75
    {
76
        $this->name = $name;
77
        $appName    = '\\' . get_class($this);
78
        $fullname   = Daemon::$appResolver->getAppFullName($appName, $this->name);
79
        //Daemon::$process->log($fullname . ' instantiated.');
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
80
81
        if ($this->requestClass === null) {
82
            $this->requestClass = get_class($this) . 'Request';
83
            if (!class_exists($this->requestClass)) {
84
                $this->requestClass = null;
85
            }
86
        }
87
88
        if (!isset(Daemon::$appInstances[$appName])) {
89
            Daemon::$appInstances[$appName] = [];
90
        }
91
        Daemon::$appInstances[$appName][$this->name] = $this;
92
93
        if (!isset(Daemon::$config->{$fullname})) {
94
            Daemon::$config->{$fullname} = new Config\Section;
95
        } else {
96
            if (
97
                    !isset(Daemon::$config->{$fullname}->enable)
98
                    && !isset(Daemon::$config->{$fullname}->disable)
99
            ) {
100
                Daemon::$config->{$fullname}->enable = new Config\Entry\Generic;
101
                Daemon::$config->{$fullname}->enable->setValue(true);
102
            }
103
        }
104
105
        $this->config = Daemon::$config->{$fullname};
106
        if ($this->isEnabled()) {
107
            Daemon::$process->log($appName . ($name ? ":{$name}" : '') . ' up.');
108
        }
109
110
        $defaults = $this->getConfigDefaults();
111
        if ($defaults) {
112
            /** @noinspection PhpUndefinedMethodInspection */
113
            $this->config->imposeDefault($defaults);
114
        }
115
116
        $this->init();
117
118
        if (Daemon::$process instanceof Thread\Worker) {
119
            if (!$this->ready) {
120
                $this->ready = true;
121
                $this->onReady();
122
            }
123
        }
124
    }
125
126
    /**
127
     * Returns whether if this application is enabled
128
     * @return boolean
129
     */
130
    public function isEnabled()
131
    {
132
        return isset($this->config->enable->value) && $this->config->enable->value;
133
    }
134
135
    /**
136
     * Function to get default config options from application
137
     * Override to set your own
138
     * @return boolean
139
     */
140
    protected function getConfigDefaults()
141
    {
142
        return false;
143
    }
144
145
    /**
146
     * Called when creates instance of the application
147
     * @return void
148
     */
149
    protected function init()
150
    {
151
    }
152
153
    /**
154
     * Called when the worker is ready to go
155
     * @return void
156
     */
157
    public function onReady()
158
    {
159
    }
160
161
    /**
162
     * @param  string  $name  Instance name
163
     * @param  boolean $spawn If true, we spawn an instance if absent
164
     * @return AppInstance
165
     */
166
    public static function getInstance($name, $spawn = true)
167
    {
168
        return Daemon::$appResolver->getInstanceByAppName('\\' . get_called_class(), $name, $spawn);
169
    }
170
171
    /**
172
     * Function handles incoming Remote Procedure Calls
173
     * You can override it
174
     * @param  string $method Method name
175
     * @param  array  $args   Arguments
176
     * @return mixed          Result
177
     */
178
    public function RPCall($method, $args)
179
    {
180
        if (!$this->enableRPC || !is_callable([$this, $method])) {
181
            return false;
182
        }
183
        $func = [$this, $method];
184
        return $func(...$args);
185
    }
186
187
    /**
188
     * Returns a config section
189
     * @return Config\Section
190
     */
191
    public function getConfig()
192
    {
193
        return $this->config;
194
    }
195
196
    /**
197
     * Returns the instance name
198
     * @return string
199
     */
200
    public function getName()
201
    {
202
        return $this->name;
203
    }
204
205
    /**
206
     * Send broadcast RPC
207
     * You can override it
208
     * @param  string   $method Method name
209
     * @param  array    $args   Arguments
210
     * @param  callable $cb     Callback
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

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...
211
     * @return boolean Success
212
     */
213 View Code Duplication
    public function broadcastCall($method, $args = [], $cb = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
214
    {
215
        return Daemon::$process->IPCManager->sendBroadcastCall(
216
            '\\' . get_class($this) . ($this->name !== '' ? ':' . $this->name : ''),
217
            $method,
218
            $args,
219
            $cb
220
        );
221
    }
222
223
    /**
224
     * Send RPC, executed once in any worker
225
     * You can override it
226
     * @param  string $method Method name
227
     * @param  array  $args   Arguments
228
     * @param  mixed  $cb     Callback
229
     * @return boolean Success
230
     */
231 View Code Duplication
    public function singleCall($method, $args = [], $cb = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
232
    {
233
        return Daemon::$process->IPCManager->sendSingleCall(
234
            '\\' . get_class($this) . ($this->name !== '' ? ':' . $this->name : ''),
235
            $method,
236
            $args,
237
            $cb
238
        );
239
    }
240
241
    /**
242
     * Send RPC, executed once in certain worker
243
     * You can override it
244
     * @param  integer $workerId Worker Id
245
     * @param  string  $method   Method name
246
     * @param  array   $args     Arguments
247
     * @param  mixed   $cb       Callback
248
     * @return boolean Success
249
     */
250 View Code Duplication
    public function directCall($workerId, $method, $args = [], $cb = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
251
    {
252
        return Daemon::$process->IPCManager->sendDirectCall(
253
            $workerId,
254
            '\\' . get_class($this) . ($this->name !== '' ? ':' . $this->name : ''),
255
            $method,
256
            $args,
257
            $cb
258
        );
259
    }
260
261
    /**
262
     * Log something
263
     * @param  string $message Message
264
     * @return void
265
     */
266
    public function log($message)
267
    {
268
        Daemon::log(get_class($this) . ': ' . $message);
269
    }
270
271
    /**
272
     * Handle the request
273
     * @param  object $parent   Parent request
274
     * @param  object $upstream Upstream application
275
     * @return object Request
276
     */
277
    public function handleRequest($parent, $upstream)
278
    {
279
        $req = $this->beginRequest($parent, $upstream);
280
        return $req ? : $parent;
281
    }
282
283
    /**
284
     * Create Request instance
285
     * @param  object $req      Generic
286
     * @param  object $upstream Upstream application instance
287
     * @return object Request
0 ignored issues
show
Documentation introduced by
Should the return type not be false|object?

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...
288
     */
289
    public function beginRequest($req, $upstream)
290
    {
291
        if (!$this->requestClass) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->requestClass of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
292
            return false;
293
        }
294
        $className = $this->requestClass;
295
        return new $className($this, $upstream, $req);
296
    }
297
298
    /**
299
     * Handle the worker status
300
     * @param  integer $ret Status code
301
     * @return boolean Result
302
     */
303
    public function handleStatus($ret)
304
    {
305
        if ($ret === self::EVENT_CONFIG_UPDATED) {
306
            $this->onConfigUpdated();
307
            return true;
308
        } elseif ($ret === self::EVENT_GRACEFUL_SHUTDOWN) {
309
            return $this->onShutdown(true);
310
        } elseif ($ret === self::EVENT_SHUTDOWN) {
311
            return $this->onShutdown();
312
        }
313
        return false;
314
    }
315
316
    /**
317
     * Called when worker is going to update configuration
318
     * @todo call it only when application section config is changed
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
319
     * @return void
320
     */
321
    public function onConfigUpdated()
322
    {
323
    }
324
325
    /**
326
     * Called when application instance is going to shutdown
327
     * @return boolean Ready to shutdown?
328
     */
329
    protected function onShutdown($graceful = false)
330
    {
331
        return true;
332
    }
333
}
334