Passed
Push — master ( 9dbdd9...d5a428 )
by Alexander
04:15
created

framework/console/controllers/ServeController.php (2 issues)

1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\console\controllers;
9
10
use Yii;
11
use yii\console\Controller;
12
use yii\helpers\Console;
13
14
/**
15
 * Runs PHP built-in web server.
16
 *
17
 * In order to access server from remote machines use 0.0.0.0:8000. That is especially useful when running server in
18
 * a virtual machine.
19
 *
20
 * @author Alexander Makarov <[email protected]>
21
 * @since 2.0.7
22
 */
23
class ServeController extends Controller
24
{
25
    const EXIT_CODE_NO_DOCUMENT_ROOT = 2;
26
    const EXIT_CODE_NO_ROUTING_FILE = 3;
27
    const EXIT_CODE_ADDRESS_TAKEN_BY_ANOTHER_SERVER = 4;
28
    const EXIT_CODE_ADDRESS_TAKEN_BY_ANOTHER_PROCESS = 5;
29
30
    /**
31
     * @var int port to serve on.
32
     */
33
    public $port = 8080;
34
    /**
35
     * @var string path or [path alias](guide:concept-aliases) to directory to serve
36
     */
37
    public $docroot = '@app/web';
38
    /**
39
     * @var string path to router script.
40
     * See https://secure.php.net/manual/en/features.commandline.webserver.php
41
     */
42
    public $router;
43
44
45
    /**
46
     * Runs PHP built-in web server.
47
     *
48
     * @param string $address address to serve on. Either "host" or "host:port".
49
     *
50
     * @return int
51
     */
52
    public function actionIndex($address = 'localhost')
53
    {
54
        $documentRoot = Yii::getAlias($this->docroot);
55
56
        if (strpos($address, ':') === false) {
57
            $address = $address . ':' . $this->port;
58
        }
59
60
        if (!is_dir($documentRoot)) {
0 ignored issues
show
It seems like $documentRoot can also be of type false; however, parameter $filename of is_dir() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

60
        if (!is_dir(/** @scrutinizer ignore-type */ $documentRoot)) {
Loading history...
61
            $this->stdout("Document root \"$documentRoot\" does not exist.\n", Console::FG_RED);
62
            return self::EXIT_CODE_NO_DOCUMENT_ROOT;
63
        }
64
65
        if ($this->isAddressTaken($address)) {
66
            $this->stdout("http://$address is taken by another process.\n", Console::FG_RED);
67
            return self::EXIT_CODE_ADDRESS_TAKEN_BY_ANOTHER_PROCESS;
68
        }
69
70
        if ($this->router !== null && !file_exists($this->router)) {
71
            $this->stdout("Routing file \"$this->router\" does not exist.\n", Console::FG_RED);
72
            return self::EXIT_CODE_NO_ROUTING_FILE;
73
        }
74
75
        $this->stdout("Server started on http://{$address}/\n");
76
        $this->stdout("Document root is \"{$documentRoot}\"\n");
77
        if ($this->router) {
78
            $this->stdout("Routing file is \"$this->router\"\n");
79
        }
80
        $this->stdout("Quit the server with CTRL-C or COMMAND-C.\n");
81
82
        passthru('"' . PHP_BINARY . '"' . " -S {$address} -t \"{$documentRoot}\" $this->router");
83
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88 1
    public function options($actionID)
89
    {
90 1
        return array_merge(parent::options($actionID), [
91 1
            'docroot',
92
            'router',
93
            'port',
94
        ]);
95
    }
96
97
    /**
98
     * {@inheritdoc}
99
     * @since 2.0.8
100
     */
101 1
    public function optionAliases()
102
    {
103 1
        return array_merge(parent::optionAliases(), [
104 1
            't' => 'docroot',
105
            'p' => 'port',
106
            'r' => 'router',
107
        ]);
108
    }
109
110
    /**
111
     * @param string $address server address
112
     * @return bool if address is already in use
113
     */
114
    protected function isAddressTaken($address)
115
    {
116
        list($hostname, $port) = explode(':', $address);
117
        $fp = @fsockopen($hostname, $port, $errno, $errstr, 3);
0 ignored issues
show
$port of type string is incompatible with the type integer expected by parameter $port of fsockopen(). ( Ignorable by Annotation )

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

117
        $fp = @fsockopen($hostname, /** @scrutinizer ignore-type */ $port, $errno, $errstr, 3);
Loading history...
118
        if ($fp === false) {
119
            return false;
120
        }
121
        fclose($fp);
122
        return true;
123
    }
124
}
125