Application::setDefaultController()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Kore : Simple And Minimal Framework
4
 *
5
 */
6
7
namespace Kore;
8
9
use Exception;
10
11
/**
12
 * Application class
13
 *
14
 * Running web and cli applications.
15
 */
16
class Application
17
{
18
    /**
19
     * Base path
20
     *
21
     * Excluded when parsing the controller namespace.
22
     * Used in running web applications.
23
     * @var string
24
     */
25
    protected $basePath = '';
26
    /**
27
     * Default controller
28
     *
29
     * Called if the controller is not specified.
30
     * If unspecified, the default is 'index'.
31
     * Used in running web applications.
32
     * @var string
33
     */
34
    protected $defaultController = 'index';
35
    /**
36
     * Not found handler
37
     *
38
     * Called when the controller is not found.
39
     * Used in running web applications.
40
     * @var callable
41
     */
42
    protected $notFound;
43
44
    /**
45
     * Set the base path
46
     *
47
     * @param string $basePath bath path ex. '/mybasepath'
48
     * @return void
49
     */
50
    public function setBasePath($basePath)
51
    {
52
        $this->basePath = trim($basePath, '/');
53
    }
54
55
    /**
56
     * Set the default controller
57
     *
58
     * @param string $defaultController default controller
59
     * @return void
60
     */
61
    public function setDefaultController($defaultController)
62
    {
63
        $this->defaultController = $defaultController;
64
    }
65
66
    /**
67
     * Set the not found handler
68
     *
69
     * @param callable $notFound not found handler
70
     * @return void
71
     */
72
    public function setNotFound($notFound)
73
    {
74
        if (is_callable($notFound)) {
75
            $this->notFound = $notFound;
76
        }
77
    }
78
    
79
    /**
80
     * Running web applications
81
     *
82
     * @param string|null $path request path
83
     * @return void
84
     */
85
    public function run($path = null)
86
    {
87
        if ($path === null) {
88
            $path = $_SERVER['REQUEST_URI'];
89
        }
90
        if (false !== $pos = strpos($path, '?')) {
91
            $path = substr($path, 0, $pos);
92
        }
93
        $path = rawurldecode($path);
94
        $path = trim($path, '/');
95
        if (!empty($this->basePath) && strpos($path, $this->basePath) === 0) {
96
            $path = substr($path, strlen($this->basePath));
97
            $path = trim($path, '/');
98
        }
99
100
        list($class, $controller, $args) = $this->parseController($path);
101
102
        if ($class === null) {
103
            http_response_code(404);
104
            if (is_callable($this->notFound)) {
105
                call_user_func($this->notFound);
106
            }
107
            return;
108
        }
109
110
        /** @phpstan-ignore-next-line */
111
        register_shutdown_function(array($class, 'handleShutdown'));
112
113
        $class->main($controller, $args);
114
    }
115
116
    /**
117
     * Parse the controller namespace from the request path
118
     *
119
     * @param string $path request path
120
     * @return array<mixed> controller information
121
     *                      array(
122
     *                          controller class instance,
123
     *                          controller namespace,
124
     *                          path arguments
125
     *                      )
126
     */
127
    protected function parseController($path)
128
    {
129
        $parray = explode('/', $path);
130
    
131
        $class = null;
132
        $controller = $this->defaultController;
133
        $args = array();
134
        foreach ($parray as $i => $p) {
135
            $tmpController = implode('\\', array_slice($parray, 0, $i+1));
136
            if ($tmpController !== '') {
137
                $controller = $tmpController;
138
            }
139
            $controller = CONTROLLERS_NS.'\\'.$controller;
140
            if (class_exists($controller)) {
141
                $class = new $controller();
142
                $args = array_slice($parray, $i+1);
143
                break;
144
            }
145
        }
146
        return array($class, $controller, $args);
147
    }
148
149
    /**
150
     * Running cli applications
151
     *
152
     * @param array<string> $argv command line argument
153
     * @return void
154
     * @throws Exception thrown when the command class is not found.
155
     */
156
    public function runCmd($argv)
157
    {
158
        if (!isset($argv[1])) {
159
            throw new Exception('Unable to find command name');
160
        }
161
162
        list($class, $command, $args, $opts) = $this->parseCommand($argv);
163
164
        if ($class === null) {
165
            throw new Exception('Unable to load command class ->' . $command);
166
        }
167
168
        /** @phpstan-ignore-next-line */
169
        register_shutdown_function(array($class, 'handleShutdown'));
170
171
        $class->main($command, $args, $opts);
172
    }
173
174
    /**
175
     * Parse the command namespace from the command line argument
176
     *
177
     * @param array<string> $argv command line argument
178
     * @return array<mixed> command information
179
     *                      array(
180
     *                          commadn class instance,
181
     *                          command namespace,
182
     *                          arguments,
183
     *                          options
184
     *                      )
185
     */
186
    protected function parseCommand($argv)
187
    {
188
        $class = null;
189
        $command = COMMANDS_NS.'\\'.str_replace('/', '\\', $argv[1]);
190
        $args = array();
191
        $opts = array();
192
193
        if (!class_exists($command)) {
194
            return array($class, $command, $args, $opts);
195
        }
196
197
        $class = new $command();
198
        foreach ($argv as $key => $value) {
199
            if ($key > 1) {
200
                if (preg_match('/^--[a-zA-Z0-9]+=[a-zA-Z0-9]+$/', $value)) {
201
                    $params = explode('=', $value);
202
                    $name = str_replace('--', '', $params[0]);
203
                    $opts[$name] = $params[1];
204
                } else {
205
                    $args[] = $value;
206
                }
207
            }
208
        }
209
        return array($class, $command, $args, $opts);
210
    }
211
}
212