Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
33.87% |
21 / 62 |
|
40.00% |
2 / 5 |
CRAP | |
0.00% |
0 / 1 |
HttpUtils | |
33.87% |
21 / 62 |
|
40.00% |
2 / 5 |
221.49 | |
0.00% |
0 / 1 |
countRequest | |
0.00% |
0 / 23 |
|
0.00% |
0 / 1 |
210 | |||
dieWithHttpError | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
redirect | |
100.00% |
15 / 15 |
|
100.00% |
1 / 1 |
1 | |||
validateGetParams | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
30 | |||
sendHttpResponseCode | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
sendHeader | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
sendHttpBody | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
exitExecution | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
fromEnv | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace Olz\Utils; |
4 | |
5 | use Olz\Components\Error\OlzErrorPage\OlzErrorPage; |
6 | use Olz\Components\Page\OlzFooter\OlzFooter; |
7 | use Olz\Components\Page\OlzHeaderWithoutRouting\OlzHeaderWithoutRouting; |
8 | use Olz\Entity\Counter; |
9 | use PhpTypeScriptApi\PhpStan\ValidateVisitor; |
10 | use Symfony\Component\HttpFoundation\Request; |
11 | |
12 | class HttpUtils { |
13 | use WithUtilsTrait; |
14 | |
15 | /** @param array<string> $get_params */ |
16 | public function countRequest(Request $request, array $get_params = []): void { |
17 | $user_agent = $this->server()['HTTP_USER_AGENT'] ?? ''; |
18 | if ( |
19 | preg_match('/bingbot/i', $user_agent) |
20 | || preg_match('/googlebot/i', $user_agent) |
21 | || preg_match('/google/i', $user_agent) |
22 | || preg_match('/facebookexternalhit/i', $user_agent) |
23 | || preg_match('/applebot/i', $user_agent) |
24 | || preg_match('/yandexbot/i', $user_agent) |
25 | || preg_match('/ecosia\//i', $user_agent) |
26 | || preg_match('/phpservermon\//i', $user_agent) |
27 | || preg_match('/bot\//i', $user_agent) |
28 | || preg_match('/crawler\//i', $user_agent) |
29 | ) { |
30 | $this->log()->debug("Counter: user agent is bot: {$user_agent}"); |
31 | return; |
32 | } |
33 | $path = "{$request->getBasePath()}{$request->getPathInfo()}"; |
34 | $query = []; |
35 | foreach ($get_params as $key) { |
36 | $value = $request->query->get($key); |
37 | if ($value !== null) { |
38 | $query[] = "{$key}={$value}"; |
39 | } |
40 | } |
41 | $pretty_query = empty($query) ? '' : '?'.implode('&', $query); |
42 | $counter_repo = $this->entityManager()->getRepository(Counter::class); |
43 | $counter_repo->record("{$path}{$pretty_query}"); |
44 | $this->log()->debug("Counter: Counted {$path}{$pretty_query} (user agent: {$user_agent})"); |
45 | } |
46 | |
47 | public function dieWithHttpError(int $http_status_code): void { |
48 | $this->sendHttpResponseCode($http_status_code); |
49 | |
50 | $out = OlzErrorPage::render([ |
51 | 'http_status_code' => $http_status_code, |
52 | ]); |
53 | |
54 | $this->sendHttpBody($out); |
55 | $this->exitExecution(); |
56 | } |
57 | |
58 | public function redirect(string $redirect_url, int $http_status_code = 301): void { |
59 | $this->sendHeader("Location: {$redirect_url}"); |
60 | $this->sendHttpResponseCode($http_status_code); |
61 | |
62 | $out = ""; |
63 | $out .= OlzHeaderWithoutRouting::render([ |
64 | 'title' => "Weiterleitung...", |
65 | ]); |
66 | |
67 | $enc_redirect_url = json_encode($redirect_url); |
68 | $out .= <<<ZZZZZZZZZZ |
69 | <div class='content-full'> |
70 | <h2>Automatische Weiterleitung...</h2> |
71 | <p>Falls die automatische Weiterleitung nicht funktionieren sollte, kannst du auch diesen Link anklicken:</p> |
72 | <p><b><a href='{$redirect_url}' class='linkint'>{$redirect_url}</a></b></p> |
73 | <script type='text/javascript'> |
74 | window.setTimeout(function () { |
75 | window.location.href = {$enc_redirect_url}; |
76 | }, 1000); |
77 | </script> |
78 | </div> |
79 | ZZZZZZZZZZ; |
80 | |
81 | $out .= OlzFooter::render(); |
82 | $this->sendHttpBody($out); |
83 | $this->exitExecution(); |
84 | } |
85 | |
86 | /** |
87 | * @template T of array |
88 | * |
89 | * @param class-string<HttpParams<T>> $params_class |
90 | * @param ?array<string, ?(string|array<string>)> $get_params |
91 | * @param array{just_log?: bool} $options |
92 | * |
93 | * @return T |
94 | */ |
95 | public function validateGetParams(string $params_class, ?array $get_params = null, array $options = []): array { |
96 | if ($get_params === null) { |
97 | $get_params = $this->getParams(); |
98 | } |
99 | $class_info = new \ReflectionClass($params_class); |
100 | $params_instance = new $params_class(); |
101 | $params_instance->configure(); |
102 | $utils = $params_instance->phpStanUtils; |
103 | $php_doc_node = $utils->parseDocComment($class_info->getDocComment()); |
104 | $type = $php_doc_node?->getExtendsTagValues()[0]->type->genericTypes[0]; |
105 | $aliases = $utils->getAliases($php_doc_node); |
106 | if (!$type) { |
107 | $this->dieWithHttpError(400); |
108 | throw new \Exception('should already have failed'); |
109 | } |
110 | $result = ValidateVisitor::validateDeserialize($utils, $get_params, $type, $aliases); |
111 | if (!$result->isValid() && ($options['just_log'] ?? false) === false) { |
112 | $this->dieWithHttpError(400); |
113 | throw new \Exception('should already have failed'); |
114 | } |
115 | return $result->getValue(); |
116 | } |
117 | |
118 | // @codeCoverageIgnoreStart |
119 | // Reason: Mock functions for tests. |
120 | |
121 | protected function sendHttpResponseCode(int $http_response_code): void { |
122 | http_response_code($http_response_code); |
123 | } |
124 | |
125 | protected function sendHeader(string $http_header_line): void { |
126 | header($http_header_line); |
127 | } |
128 | |
129 | protected function sendHttpBody(string $http_body): void { |
130 | echo $http_body; |
131 | } |
132 | |
133 | protected function exitExecution(): void { |
134 | exit(''); |
135 | } |
136 | |
137 | // @codeCoverageIgnoreEnd |
138 | |
139 | public static function fromEnv(): self { |
140 | return new self(); |
141 | } |
142 | } |