Passed
Push — main ( 3ef0a0...535c71 )
by Sammy
01:39
created

Hopper::routeExists()   A

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
/**
4
* huppel konijntje huppel and wiebel
5
* Hommage to Grace Hopper, programmer & expert in *litteral* duck taping
6
***/
7
8
namespace HexMakina\Hopper;
9
10
class Hopper extends \AltoRouter implements RouterInterface
11
{
12
    private $match = null;
13
    private $file_root = null;
14
15
  //----------------------------------------------------------- INITIALISATION
16
17
    public function mapHomeRoute($route)
18
    {
19
        $this->map(self::REQUEST_GET, '', $route, self::ROUTE_HOME_NAME);
20
    }
21
22
    public function __debugInfo(): array
23
    {
24
        $dbg = get_object_vars($this);
25
        $dbg['routes'] = count($dbg['routes']);
26
        $dbg['namedRoutes'] = count($dbg['namedRoutes']);
27
        unset($dbg['matchTypes']);
28
        return $dbg;
29
    }
30
  // -- MATCHING REQUESTS
31
    public function match($requestUrl = null, $requestMethod = null)
32
    {
33
        $this->match = parent::match($requestUrl, $requestMethod);
34
35
        if ($this->match === false) {
36
            throw new RouterException('ROUTE_MATCH_FALSE');
37
        }
38
39
        $res = explode('::', $this->target());
40
41
        if ($res === false || !isset($res[1]) || isset($res[2])) {
42
            throw new RouterException('INVALID_TARGET_FORMAT');
43
        }
44
45
        $this->match['target_controller'] = $res[0];
46
        $this->match['target_method'] = $res[1];
47
48
        return [$res[0], $res[1]];
49
    }
50
51
    public function params($param_name = null)
52
    {
53
        return $this->extractFrom($this->match['params'] ?? [], $param_name);
54
    }
55
56
    public function submitted($param_name = null)
57
    {
58
        return $this->extractFrom($_POST, $param_name);
59
    }
60
61
62
63
    public function target()
64
    {
65
        return $this->match['target'];
66
    }
67
68
    public function targetController()
69
    {
70
        return $this->match['target_controller'];
71
    }
72
73
    public function targetMethod()
74
    {
75
        return $this->match['target_method'];
76
    }
77
78
    public function name()
79
    {
80
        return $this->match['name'];
81
    }
82
83
  // -- ROUTING TOOLS
84
    public function routeExists($route): bool
85
    {
86
        return isset($this->namedRoutes[$route]);
87
    }
88
89
    public function namedRoutes()
90
    {
91
        return $this->namedRoutes;
92
    }
93
94
  /* Generates HYPertext reference
95
   * @param route_name string  requires
96
   *  - a valid AltoRouter route name
97
   *  - OR a Descendant of Model
98
   * @route_params requires
99
   *  - an assoc_array of url params (strongly AltoRouter-based)
100
   * returns: something to put in a href="", action="" or header('Location:');
101
   */
102
    public function hyp($route, $route_params = [])
103
    {
104
        try {
105
            $url = $this->generate($route, $route_params);
106
        } catch (\Exception $e) {
107
            $url = $this->hyp(self::ROUTE_HOME_NAME);
108
        }
109
110
        return $url;
111
    }
112
113
114
115
  /*
116
   * @params $route is
117
   *    - empty: default is ROUTE_HOME_NAME
118
   *    - an existing route name: make url with optional [$route_params])
119
   *    - a url, go there
120
   * @params $route_params, assoc_data for url creation (i:id, a:format, ..)
121
   */
122
    public function hop($route = null, $route_params = [])
123
    {
124
        $url = null;
125
126
        if (is_null($route)) {
127
            $url = $this->hyp(self::ROUTE_HOME_NAME, $route_params);
128
        } elseif (is_string($route) && $this->routeExists($route)) {
129
            $url = $this->hyp($route, $route_params);
130
        } else {
131
            $url = $route;
132
        }
133
134
        $this->hopURL($url);
135
    }
136
137
    public function stay($url = null)
138
    {
139
        return $url ?? $_SERVER['REQUEST_URI'];
140
    }
141
142
  // hops back to previous page (referer()), or home if no referer
143
    public function hopBack()
144
    {
145
        if (!is_null($back = $this->referer())) {
146
            $this->hopURL($back);
147
        }
148
149
        $this->hop();
150
    }
151
152
    public function hopURL($url)
153
    {
154
        header('Cache-Control: no-cache, must-revalidate');
155
        header('Expires: Mon, 01 Jan 1970 00:00:00 GMT');
156
        header('Location: ' . $url);
157
        exit();
158
    }
159
160
  // returns full URL of the refering URL
161
  // returns null if same as current URL (prevents endless redirection loop)
162
    public function referer()
163
    {
164
        if (isset($_SERVER['HTTP_REFERER']) && $_SERVER['HTTP_REFERER'] != $this->webHost() . $_SERVER['REQUEST_URI']) {
165
            return $_SERVER['HTTP_REFERER'];
166
        }
167
168
        return null;
169
    }
170
171
    public function sendFile($file_path)
172
    {
173
        if (!file_exists($file_path)) {
174
            throw new RouterException('SENDING_NON_EXISTING_FILE');
175
        }
176
177
        $file_name = basename($file_path);
178
179
      //Get file type and set it as Content Type
180
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
181
182
        header('Content-Type: ' . finfo_file($finfo, $file_path));
183
184
        finfo_close($finfo);
185
186
      //Use Content-Disposition: attachment to specify the filename
187
        header('Content-Disposition: attachment; filename=' . $file_name);
188
189
      //No cache
190
        header('Expires: 0');
191
        header('Cache-Control: must-revalidate');
192
        header('Pragma: public');
193
194
      //Define file size
195
        header('Content-Length: ' . filesize($file_path));
196
197
        ob_clean();
198
        flush();
199
        readfile($file_path);
200
        // die; // might be useless after all
201
    }
202
203
  // -- PROCESSING REQUESTS
204
    public function requests(): bool
205
    {
206
        return $_SERVER['REQUEST_METHOD'] === self::REQUEST_GET;
207
    }
208
209
    public function submits(): bool
210
    {
211
        return $_SERVER['REQUEST_METHOD'] === self::REQUEST_POST;
212
    }
213
214
    public function webHost(): string
215
    {
216
        return $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'];
217
    }
218
219
    public function webRoot(): string
220
    {
221
        return $this->webHost() . $this->basePath();
222
    }
223
224
    // return web base
225
    public function basePath($setter = null): string
226
    {
227
        if (!is_null($setter)) {
228
            $this->basePath = $setter;
229
        }
230
231
        return $this->basePath ?? '';
232
    }
233
234
    // returns root filepath for project
235
    // default out of vendor/hexmakina/Hopper
236
    public function filePath($setter = null): string
237
    {
238
        if (!is_null($setter)) {
239
            $this->file_root = realpath($setter) . '/';
240
        }
241
242
        return $this->file_root ?? __DIR__ . '/../../';
243
    }
244
245
246
    private function extractFrom($dat_ass, $key = null)
247
    {
248
249
      // $key is null, returns $dat_ass or empty array
250
        if (is_null($key)) {
251
            return $dat_ass ?? [];
252
        }
253
254
      // $dat_ass[$key] not set, returns null
255
        if (!isset($dat_ass[$key])) {
256
            return null;
257
        }
258
259
      // $dat_ass[$key] is a string, returns decoded value
260
        if (is_string($dat_ass[$key])) {
261
            return urldecode($dat_ass[$key]);
262
        }
263
264
      // $dat_ass[$key] is not a string, return match[$key]
265
        return $dat_ass[$key];
266
    }
267
}
268