Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
33.87% covered (danger)
33.87%
21 / 62
40.00% covered (danger)
40.00%
2 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
HttpUtils
33.87% covered (danger)
33.87%
21 / 62
40.00% covered (danger)
40.00%
2 / 5
221.49
0.00% covered (danger)
0.00%
0 / 1
 countRequest
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
210
 dieWithHttpError
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 redirect
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
1
 validateGetParams
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
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% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace Olz\Utils;
4
5use Olz\Components\Error\OlzErrorPage\OlzErrorPage;
6use Olz\Components\Page\OlzFooter\OlzFooter;
7use Olz\Components\Page\OlzHeaderWithoutRouting\OlzHeaderWithoutRouting;
8use Olz\Entity\Counter;
9use PhpTypeScriptApi\PhpStan\ValidateVisitor;
10use Symfony\Component\HttpFoundation\Request;
11
12class 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}