Passed
Push — main ( f4f617...3ef0a0 )
by Sammy
01:46
created

hopper::filePath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
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->extract_request($this->match['params'] ?? [], $param_name);
54
    }
55
56
    public function submitted($param_name = null)
57
    {
58
        return $this->extract_request($_POST, $param_name);
59
    }
60
61
    private function extract_request($dat_ass, $key = null)
62
    {
63
64
      // $key is null, returns $dat_ass or empty array
65
        if (is_null($key)) {
66
            return $dat_ass ?? [];
67
        }
68
69
      // $dat_ass[$key] not set, returns null
70
        if (!isset($dat_ass[$key])) {
71
            return null;
72
        }
73
74
      // $dat_ass[$key] is a string, returns decoded value
75
        if (is_string($dat_ass[$key])) {
76
            return urldecode($dat_ass[$key]);
77
        }
78
79
      // $dat_ass[$key] is not a string, return match[$key]
80
        return $dat_ass[$key];
81
    }
82
83
    public function target()
84
    {
85
        return $this->match['target'];
86
    }
87
88
    public function target_controller()
89
    {
90
        return $this->match['target_controller'];
91
    }
92
93
    public function target_method()
94
    {
95
        return $this->match['target_method'];
96
    }
97
98
    public function name()
99
    {
100
        return $this->match['name'];
101
    }
102
103
  // -- ROUTING TOOLS
104
    public function route_exists($route): bool
105
    {
106
        return isset($this->namedRoutes[$route]);
107
    }
108
109
    public function named_routes()
110
    {
111
        return $this->namedRoutes;
112
    }
113
114
  /*
115
   * @param route_name string  requires
116
   *  - a valid AltoRouter route name
117
   *  - OR a Descendant of Model
118
   * @route_params requires
119
   *  - an assoc_array of url params (strongly AltoRouter-based)
120
   * returns: something to put in a href="", action="" or header('Location:');
121
   */
122
    public function prehop($route, $route_params = [])
123
    {
124
        try {
125
            $url = $this->generate($route, $route_params);
126
        } catch (\Exception $e) {
127
            $url = $this->prehop(self::ROUTE_HOME_NAME);
128
        }
129
130
        return $url;
131
    }
132
133
    public function prehop_here($url = null)
134
    {
135
        return $url ?? $_SERVER['REQUEST_URI'];
136
    }
137
138
  /*
139
   * @params $route is
140
   *    - empty: default is ROUTE_HOME_NAME
141
   *    - an existing route name: make url with optional [$route_params])
142
   *    - a url, go there
143
   * @params $route_params, assoc_data for url creation (i:id, a:format, ..)
144
   */
145
    public function hop($route = null, $route_params = [])
146
    {
147
        $url = null;
148
149
        if (is_null($route)) {
150
            $url = $this->prehop(self::ROUTE_HOME_NAME, $route_params);
151
        } elseif (is_string($route) && $this->route_exists($route)) {
152
            $url = $this->prehop($route, $route_params);
153
        } else {
154
            $url = $route;
155
        }
156
157
        $this->hop_url($url);
158
    }
159
160
  // hops back to previous page (referer()), or home if no referer
161
    public function hop_back()
162
    {
163
        if (!is_null($back = $this->referer())) {
164
            $this->hop_url($back);
165
        }
166
167
        $this->hop();
168
    }
169
170
    public function hop_url($url)
171
    {
172
        header('Cache-Control: no-cache, must-revalidate');
173
        header('Expires: Mon, 01 Jan 1970 00:00:00 GMT');
174
        header('Location: ' . $url);
175
        exit();
176
    }
177
178
  // returns full URL of the refering URL
179
  // returns null if same as current URL (prevents endless redirection loop)
180
    public function referer()
181
    {
182
        if (isset($_SERVER['HTTP_REFERER']) && $_SERVER['HTTP_REFERER'] != $this->web_host() . $_SERVER['REQUEST_URI']) {
183
            return $_SERVER['HTTP_REFERER'];
184
        }
185
186
        return null;
187
    }
188
189
    public function send_file($file_path)
190
    {
191
        if (!file_exists($file_path)) {
192
            throw new RouterException('SENDING_NON_EXISTING_FILE');
193
        }
194
195
        $file_name = basename($file_path);
196
197
      //Get file type and set it as Content Type
198
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
199
200
        header('Content-Type: ' . finfo_file($finfo, $file_path));
201
202
        finfo_close($finfo);
203
204
      //Use Content-Disposition: attachment to specify the filename
205
        header('Content-Disposition: attachment; filename=' . $file_name);
206
207
      //No cache
208
        header('Expires: 0');
209
        header('Cache-Control: must-revalidate');
210
        header('Pragma: public');
211
212
      //Define file size
213
        header('Content-Length: ' . filesize($file_path));
214
215
        ob_clean();
216
        flush();
217
        readfile($file_path);
218
        // die; // might be useless after all
219
    }
220
221
  // -- PROCESSING REQUESTS
222
    public function requests(): bool
223
    {
224
        return $_SERVER['REQUEST_METHOD'] === self::REQUEST_GET;
225
    }
226
227
    public function submits(): bool
228
    {
229
        return $_SERVER['REQUEST_METHOD'] === self::REQUEST_POST;
230
    }
231
232
    public function web_host(): string
233
    {
234
        return $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'];
235
    }
236
237
    public function web_root(): string
238
    {
239
        return $this->web_host() . $this->basePath();
240
    }
241
242
    // return web base
243
    public function basePath(): string
244
    {
245
      return $this->basePath ?? '';
246
    }
247
248
    // returns root filepath for project
249
    // default out of vendor/hexmakina/Hopper
250
    public function filePath(): string
251
    {
252
      return $this->file_root ?? __DIR__.'/../../';
253
    }
254
255
    public function setFilePath($setter)
256
    {
257
        $this->file_root = realpath($setter) . '/';
258
    }
259
}
260