Completed
Push — 2.1 ( 68dd3d...1f97e0 )
by Alexander
11:18
created

ServeController::isAddressTaken()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 0
cts 0
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 7
nc 2
nop 1
crap 6
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 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)) {
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);
118
        if ($fp === false) {
119
            return false;
120
        }
121
        fclose($fp);
122
        return true;
123
    }
124
}
125