Completed
Push — master ( f7ee5f...7c37a7 )
by Oleg
08:25
created

Micro::sendSignal()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 2
1
<?php /** Micro */
2
3
namespace Micro;
4
5
use Micro\base\Container;
6
use Micro\base\Dispatcher;
7
use Micro\Base\Exception;
8
use Micro\Base\FatalError;
9
use Micro\base\IContainer;
10
use Micro\cli\Consoles\DefaultConsoleCommand;
11
use Micro\resolver\HMVCResolver;
12
use Micro\Resolver\IResolver;
13
use Micro\web\IOutput;
14
use Micro\web\IRequest;
15
use Micro\Web\IResponse;
16
use Micro\web\Response;
17
18
/**
19
 * Micro class file.
20
 *
21
 * Base class for initialize MicroPHP, used as bootstrap framework.
22
 *
23
 * @author Oleg Lunegov <[email protected]>
24
 * @link https://github.com/lugnsk/micro
25
 * @copyright Copyright &copy; 2013 Oleg Lunegov
26
 * @license /LICENSE
27
 * @package micro
28
 * @version 1.0
29
 * @since 1.0
30
 */
31
class Micro
32
{
33
    /** @const string VERSION Version framework */
34
    const VERSION = '1.1';
35
36
    /** @var IContainer $container Container is a container for components and options */
37
    protected $container;
38
    /** @var string $appDir */
39
    protected $appDir;
40
41
    /** @var bool $loaded Micro loaded flag */
42
    private $loaded;
43
    /** @var bool $debug Debug-mode flag */
44
    private $debug = true;
45
    /** @var string $environment Application environment */
46
    private $environment = 'devel';
47
    /** @var float $startTime Time of start framework */
48
    private $startTime;
49
50
51
    /**
52
     * Initialize application
53
     *
54
     * @access public
55
     *
56
     * @param string $environment Application environment: devel , production , test, other
57
     * @param bool $debug Debug-mode flag
58
     *
59
     * @result void
60
     */
61
    public function __construct($environment = 'devel', $debug = true)
62
    {
63
        $this->environment = (string)$environment;
64
        $this->debug = (bool)$debug;
65
        $this->loaded = false;
66
67
        ini_set('display_errors', $this->debug);
68
69
        FatalError::register();
70
71
        if ($this->debug) {
72
            $this->startTime = microtime(true);
73
        }
74
    }
75
76
    /**
77
     * Clone application
78
     *
79
     * @access public
80
     *
81
     * @return void
82
     */
83
    public function __clone()
84
    {
85
        if ($this->debug) { // start new timer
86
            $this->startTime = microtime(true);
87
        }
88
89
        $this->loaded = false; // deactivate loaded
90
        $this->container = null; // remove configured container
91
    }
92
93
    /**
94
     * Running application
95
     *
96
     * @access public
97
     *
98
     * @param IRequest $request Request object
99
     *
100
     * @return Response
101
     * @throws \Exception
102
     */
103
    public function run(IRequest $request)
104
    {
105
        try {
106
            return $this->doRun($request);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->doRun($request); of type Micro\Web\IResponse|string adds the type string to the return on line 106 which is incompatible with the return type documented by Micro\Micro::run of type Micro\Web\Response.
Loading history...
107
        } catch (\Exception $e) {
108
            if ($this->debug) {
109
                $this->container->dispatcher->signal('kernel.exception', ['exception' => $e]);
0 ignored issues
show
Bug introduced by
Accessing dispatcher on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
110
                throw $e;
111
            }
112
113
            return $this->doException($e); // run exception
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->doException($e); of type Micro\Cli\Consoles\Defau...mand|Micro\Web\Response adds the type Micro\Cli\Consoles\DefaultConsoleCommand to the return on line 113 which is incompatible with the return type documented by Micro\Micro::run of type Micro\Web\Response.
Loading history...
114
        }
115
    }
116
117
    /**
118
     * Initialization container
119
     *
120
     * @access protected
121
     * @return void
122
     */
123
    protected function initializeContainer()
124
    {
125
        $class = $this->getContainerClass();
126
        if ($class) {
127
            $class = new $class;
128
        }
129
130
        $this->container = ($class instanceof IContainer) ? $class : new Container;
131
        $this->container->kernel = $this;
0 ignored issues
show
Bug introduced by
Accessing kernel on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
132
        $this->container->load($this->getConfig());
133
134
        if (false === $this->container->dispatcher) {
0 ignored issues
show
Bug introduced by
Accessing dispatcher on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
135
            $this->container->dispatcher = new Dispatcher;
0 ignored issues
show
Bug introduced by
Accessing dispatcher on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
136
        }
137
138
        $this->addListener('kernel.kill', function (array $params) {
139
            if ($params['container']->kernel->isDebug() && !$params['container']->request->isCli()) {
140
                // Add timer into page
141
                echo '<div class=debug_timer>', (microtime(true) - $params['container']->kernel->getStartTime()), '</div>';
142
            }
143
        });
144
145
        $this->container->dispatcher->signal('kernel.boot', ['container' => $this->container]);
0 ignored issues
show
Bug introduced by
Accessing dispatcher on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
146
147
        $this->loaded = true;
148
    }
149
150
    /**
151
     * Get full class name
152
     * @return string
153
     */
154
    protected function getContainerClass()
155
    {
156
        return '';
157
    }
158
159
    /**
160
     * Default config path
161
     *
162
     * @return string
163
     */
164
    protected function getConfig()
165
    {
166
        return $this->getAppDir() . '/configs/index.php';
167
    }
168
169
    /**
170
     * Get application directory
171
     *
172
     * @return string
173
     */
174
    public function getAppDir()
175
    {
176
        if (!$this->appDir) {
177
            $this->appDir = dirname((new \ReflectionObject($this))->getFileName());
178
        }
179
180
        return $this->appDir;
181
    }
182
183
    /**
184
     * Add listener on event
185
     *
186
     * @access public
187
     *
188
     * @param string $listener listener name
189
     * @param mixed $event ['Object', 'method'] or callable
190
     * @param int|null $prior priority
191
     *
192
     * @return bool
193
     */
194
    protected function addListener($listener, $event, $prior = null)
195
    {
196
        if (!is_string($listener) || !$this->container) {
197
            return false;
198
        }
199
200
        $this->container->dispatcher->addListener($listener, $event, $prior);
0 ignored issues
show
Bug introduced by
Accessing dispatcher on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
201
202
        return true;
203
    }
204
205
    /**
206
     * Send signal to dispatcher
207
     *
208
     * @param $signal
209
     * @param $params
210
     * @return mixed
211
     */
212
    protected function sendSignal($signal, $params)
213
    {
214
        return $this->container->dispatcher->signal($signal, $params);
0 ignored issues
show
Bug introduced by
Accessing dispatcher on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
215
    }
216
217
    /**
218
     * Get start time
219
     *
220
     * @access public
221
     *
222
     * @return float|null
223
     */
224
    public function getStartTime()
225
    {
226
        return $this->startTime;
227
    }
228
229
    /**
230
     * Starting ...
231
     *
232
     * @access private
233
     *
234
     * @param IRequest $request
235
     *
236
     * @return Web\IResponse|Response|string
237
     * @throws \Micro\Base\Exception
238
     */
239
    private function doRun(IRequest $request)
240
    {
241
        if (!$this->loaded) {
242
            $this->initializeContainer();
243
        }
244
245
        $this->container->request = $request;
0 ignored issues
show
Bug introduced by
Accessing request on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
246
        if ($output = $this->sendSignal('kernel.request', ['container' => $this->container]) instanceof IResponse) {
247
            return $output;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $output; (boolean) is incompatible with the return type documented by Micro\Micro::doRun of type Micro\Web\IResponse|string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
248
        }
249
250
        $resolver = $this->getResolver();
251
        if ($output = $this->sendSignal('kernel.router', ['resolver' => $resolver]) instanceof IResponse) {
252
            return $output;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $output; (boolean) is incompatible with the return type documented by Micro\Micro::doRun of type Micro\Web\IResponse|string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
253
        }
254
255
        $app = $resolver->getApplication();
256
        if ($output = $this->sendSignal('kernel.controller', ['application' => $app]) instanceof IResponse) {
257
            return $output;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $output; (boolean) is incompatible with the return type documented by Micro\Micro::doRun of type Micro\Web\IResponse|string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
258
        }
259
260
        $output = $app->action($resolver->getAction());
261
        if (!$output instanceof IOutput) {
262
            $response = $this->container->response ?: new Response;
0 ignored issues
show
Bug introduced by
Accessing response on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
263
            $response->setBody($output);
264
            $output = $response;
265
        }
266
267
        $this->sendSignal('kernel.response', ['output' => $output]);
268
269
        return $output;
270
    }
271
272
    /**
273
     * Get resolver
274
     *
275
     * @access protected
276
     *
277
     * @return IResolver
278
     * @throws \Micro\Base\Exception
279
     */
280
    protected function getResolver()
281
    {
282
        if ($this->container->request->isCli()) {
0 ignored issues
show
Bug introduced by
Accessing request on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
283
            $resolver = $this->container->consoleResolver ?: '\Micro\resolver\ConsoleResolver';
0 ignored issues
show
Bug introduced by
Accessing consoleResolver on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
284
        } else {
285
            $resolver = $this->container->resolver ?: '\Micro\Resolver\HMVCResolver';
0 ignored issues
show
Bug introduced by
Accessing resolver on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
286
        }
287
288
        if (is_string($resolver) && is_subclass_of($resolver, '\Micro\Resolver\IResolver')) {
289
            $resolver = new $resolver($this->container);
290
        }
291
292
        if (!$resolver instanceof IResolver) {
293
            throw new Exception('Resolver is not implement an IReslover');
294
        }
295
296
        return $resolver;
297
    }
298
299
    /**
300
     * Do exception
301
     *
302
     * @access private
303
     *
304
     * @param \Exception $e Exception
305
     *
306
     * @return IOutput
307
     * @throws \Micro\base\Exception
308
     */
309
    private function doException(\Exception $e)
310
    {
311
        $output = $this->container->request->isCli() ? new DefaultConsoleCommand([]) : new Response();
0 ignored issues
show
Bug introduced by
Accessing request on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
312
313
        if ($this->container->request->isCli()) {
0 ignored issues
show
Bug introduced by
Accessing request on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
314
            $output->data = '"Error #' . $e->getCode() . ' - ' . $e->getMessage() . '"';
315
            $output->execute();
0 ignored issues
show
Bug introduced by
The method execute does only exist in Micro\Cli\Consoles\DefaultConsoleCommand, but not in Micro\Web\Response.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
316
317
            return $output;
318
        }
319
320
        if (!$this->container->errorController) {
0 ignored issues
show
Bug introduced by
Accessing errorController on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
321
            $output->setBody('Option `errorController` not configured');
0 ignored issues
show
Bug introduced by
The method setBody does only exist in Micro\Web\Response, but not in Micro\Cli\Consoles\DefaultConsoleCommand.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
322
323
            return $output;
324
        }
325
        if (!$this->container->errorAction) {
0 ignored issues
show
Bug introduced by
Accessing errorAction on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
326
            $output->setBody('Option `errorAction` not configured');
327
328
            return $output;
329
        }
330
331
        $controller = $this->container->errorController;
0 ignored issues
show
Bug introduced by
Accessing errorController on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
332
        $action = $this->container->errorAction;
0 ignored issues
show
Bug introduced by
Accessing errorAction on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
333
334
        $this->container->request->setPost('error', $e);
0 ignored issues
show
Bug introduced by
Accessing request on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
335
336
        /** @var \Micro\mvc\controllers\IController $result */
337
        $result = new $controller($this->container, false);
338
        $result = $result->action($action);
339
340
        if ($result instanceof IOutput) {
341
            return $result;
342
        }
343
344
        $output->setBody($result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by $result->action($action) on line 338 can also be of type object<Micro\Web\IResponse>; however, Micro\Web\Response::setBody() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
345
346
        return $output;
347
    }
348
349
    /**
350
     * Terminate application
351
     *
352
     * @access public
353
     *
354
     * @return void
355
     */
356
    public function terminate()
357
    {
358
        $this->container->dispatcher->signal('kernel.kill', ['container' => $this->container]);
0 ignored issues
show
Bug introduced by
Accessing dispatcher on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
359
360
        $this->unloader();
361
    }
362
363
    /**
364
     * Unloader subsystem
365
     *
366
     * @access public
367
     *
368
     * @return void
369
     */
370
    public function unloader()
371
    {
372
        if (false === $this->loaded) {
373
            return;
374
        }
375
376
        $this->container = null;
377
        $this->loaded = false;
378
    }
379
380
    /**
381
     * Get status of debug
382
     *
383
     * @access public
384
     *
385
     * @return bool
386
     */
387
    public function isDebug()
388
    {
389
        return $this->debug;
390
    }
391
392
    /**
393
     * Get components container
394
     *
395
     * @access public
396
     *
397
     * @return IContainer
398
     */
399
    public function getContainer()
400
    {
401
        return $this->container;
402
    }
403
404
    /**
405
     * Get character set
406
     *
407
     * @access public
408
     *
409
     * @return string
410
     */
411
    public function getCharset()
412
    {
413
        return 'UTF-8';
414
    }
415
416
    /**
417
     * Get logs directory
418
     *
419
     * @return string
420
     */
421
    public function getLogDir()
422
    {
423
        return $this->getAppDir() . '/logs';
424
    }
425
426
    /**
427
     * Get cache directory
428
     *
429
     * @return string
430
     */
431
    public function getCacheDir()
432
    {
433
        return $this->getAppDir() . '/cache/' . $this->getEnvironment();
434
    }
435
436
    /**
437
     * Get environment name
438
     *
439
     * @access public
440
     *
441
     * @return string
442
     */
443
    public function getEnvironment()
444
    {
445
        return $this->environment;
446
    }
447
}
448