Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
31.67% |
19 / 60 |
|
40.00% |
2 / 5 |
CRAP | |
0.00% |
0 / 1 |
HttpUtils | |
31.67% |
19 / 60 |
|
40.00% |
2 / 5 |
241.70 | |
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% |
13 / 13 |
|
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->sendHttpResponseCode($http_status_code); |
60 | $this->sendHeader("Location: {$redirect_url}"); |
61 | |
62 | $out = ""; |
63 | $out .= OlzHeaderWithoutRouting::render([ |
64 | 'title' => "Weiterleitung...", |
65 | ]); |
66 | |
67 | $out .= <<<ZZZZZZZZZZ |
68 | <div class='content-full'> |
69 | <h2>Automatische Weiterleitung...</h2> |
70 | <p>Falls die automatische Weiterleitung nicht funktionieren sollte, kannst du auch diesenLink anklicken:</p> |
71 | <p><b><a href='{$redirect_url}' class='linkint'>{$redirect_url}</a></b></p> |
72 | </div> |
73 | ZZZZZZZZZZ; |
74 | |
75 | $out .= OlzFooter::render(); |
76 | $this->sendHttpBody($out); |
77 | $this->exitExecution(); |
78 | } |
79 | |
80 | /** |
81 | * @template T of array |
82 | * |
83 | * @param class-string<HttpParams<T>> $params_class |
84 | * @param ?array<string, ?(string|array<string>)> $get_params |
85 | * @param array{just_log?: bool} $options |
86 | * |
87 | * @return T |
88 | */ |
89 | public function validateGetParams(string $params_class, ?array $get_params = null, array $options = []): array { |
90 | if ($get_params === null) { |
91 | $get_params = $this->getParams(); |
92 | } |
93 | $class_info = new \ReflectionClass($params_class); |
94 | $params_instance = new $params_class(); |
95 | $params_instance->configure(); |
96 | $utils = $params_instance->phpStanUtils; |
97 | $php_doc_node = $utils->parseDocComment($class_info->getDocComment()); |
98 | $type = $php_doc_node?->getExtendsTagValues()[0]->type->genericTypes[0]; |
99 | $aliases = $utils->getAliases($php_doc_node); |
100 | if (!$type) { |
101 | $this->dieWithHttpError(400); |
102 | throw new \Exception('should already have failed'); |
103 | } |
104 | $result = ValidateVisitor::validateDeserialize($utils, $get_params, $type, $aliases); |
105 | if (!$result->isValid() && ($options['just_log'] ?? false) === false) { |
106 | $this->dieWithHttpError(400); |
107 | throw new \Exception('should already have failed'); |
108 | } |
109 | return $result->getValue(); |
110 | } |
111 | |
112 | // @codeCoverageIgnoreStart |
113 | // Reason: Mock functions for tests. |
114 | |
115 | protected function sendHttpResponseCode(int $http_response_code): void { |
116 | http_response_code($http_response_code); |
117 | } |
118 | |
119 | protected function sendHeader(string $http_header_line): void { |
120 | header($http_header_line); |
121 | } |
122 | |
123 | protected function sendHttpBody(string $http_body): void { |
124 | echo $http_body; |
125 | } |
126 | |
127 | protected function exitExecution(): void { |
128 | exit(''); |
129 | } |
130 | |
131 | // @codeCoverageIgnoreEnd |
132 | |
133 | public static function fromEnv(): self { |
134 | return new self(); |
135 | } |
136 | } |