Passed
Branch feature/testserver (9727dc)
by Pieter van der
08:04
created

TestServerApp   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 109
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 18
eloc 42
c 1
b 0
f 0
dl 0
loc 109
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A getSERVER() 0 3 1
A log_error() 0 3 1
A log_warning() 0 3 1
A log_info() 0 3 1
A getBODY() 0 3 1
B HandleHTTPRequest() 0 31 7
A error_exit() 0 5 1
A __construct() 0 12 3
A getGET() 0 3 1
A getPOST() 0 3 1
1
<?php
2
3
/*
4
@license New BSD License - See LICENSE file for details.
5
@copyright (C) 2022 SURF BV
6
*/
7
8
namespace TestServer;
9
10
use Exception;
11
12
abstract class App
13
{
14
    // Log error, return HTTP message and die
15
    abstract public static function error_exit(int $http_code, string $message);
16
17
    // Log
18
    abstract public static function log_info($message);
19
20
    abstract public static function log_warning($message);
21
22
    abstract public static function log_error($message);
23
24
    // Get HTTP SERVER, GET, POST and BODY parameter arrays
25
    abstract public function getSERVER(): array;
26
27
    abstract public function getGET(): array;
28
29
    abstract public function getPOST(): array;
30
31
    abstract public function getBODY(): string;
32
}
33
34
class TestServerApp extends App
35
{
36
    private $SERVER = array();
37
    private $GET = array();
38
    private $POST = array();
39
    private $BODY = '';
40
    private $router;
41
42
    public final function __construct($router)
43
    {
44
        $this->SERVER = $_SERVER;
45
        $this->GET = $_GET;
46
        $this->POST = $_POST;
47
        $this->BODY = file_get_contents('php://input');
48
49
        if (!is_object($router) || !method_exists($router, 'Route')) {
50
            self::error_exit(500, 'TestServerApp : $router must be object with Route($app, $uri) method');
51
        }
52
53
        $this->router = $router;
54
    }
55
56
    function HandleHTTPRequest()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
57
    {
58
        self::log_info("--== START ==--");
59
        $uri = $this->SERVER["REQUEST_URI"];
60
        $method = $this->SERVER["REQUEST_METHOD"];
61
        self::log_info("$method $uri");
62
        // Print HTTP headers from the request
63
        foreach ($this->SERVER as $k => $v) {
64
            if (strpos($k, "HTTP_") === 0) {
65
                // Transform back to HTTP header style
66
                $k = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($k, 5)))));
67
                self::log_info("$k: $v");
68
            }
69
        }
70
        if ($method == 'POST') {
71
            self::log_info($this->BODY);
72
        }
73
        if (strlen($uri) == 0) {
74
            self::error_exit(500, 'Empty REQUEST_URI');
75
        }
76
        if ($uri[0] != '/') {
77
            self::error_exit(500, 'REQUEST_URI must start with "/"');
78
        }
79
        self::log_info('--');   // End of the HTTP dump
80
81
        $path = parse_url($uri, PHP_URL_PATH);
82
83
        try {
84
            $this->router->Route($this, $path);
85
        } catch (Exception $e) {
86
            self::error_exit(500, 'Exception: ' . $e->getMessage() . "\n\n" . $e->getTraceAsString());
87
        }
88
    }
89
90
91
    static function error_exit(int $http_code, string $message): void
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
92
    {
93
        self::log_error($message);
94
        header("HTTP/1.1 $http_code");
95
        die(htmlentities($message));
96
    }
97
98
    static function log_info($message)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
99
    {
100
        error_log("INFO: $message");
101
    }
102
103
    static function log_warning($message)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
104
    {
105
        error_log("WARNING: $message");
106
    }
107
108
    static function log_error($message)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
109
    {
110
        error_log("ERROR: $message");
111
    }
112
113
    /**
114
     * @return array
115
     */
116
    public function getSERVER(): array
117
    {
118
        return $this->SERVER;
119
    }
120
121
    /**
122
     * @return array
123
     */
124
    public function getGET(): array
125
    {
126
        return $this->GET;
127
    }
128
129
    /**
130
     * @return array
131
     */
132
    public function getPOST(): array
133
    {
134
        return $this->POST;
135
    }
136
137
    /**
138
     * @return string
139
     */
140
    public function getBODY(): string
141
    {
142
        return $this->BODY;
143
    }
144
145
}