AddHttpHeadersListener::applyRule()   B
last analyzed

Complexity

Conditions 8
Paths 3

Size

Total Lines 25
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 13
c 1
b 0
f 0
dl 0
loc 25
ccs 15
cts 15
cp 1
rs 8.4444
cc 8
nc 3
nop 4
crap 8
1
<?php
2
3
/*
4
 * This file is part of ocubom/html-bundle
5
 *
6
 * © Oscar Cubo Medina <https://ocubom.github.io>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Ocubom\HtmlBundle\EventListener;
13
14
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
15
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
16
use Symfony\Component\HttpKernel\Event\ResponseEvent;
17
use Symfony\Component\HttpKernel\KernelEvents;
18
19
class AddHttpHeadersListener implements EventSubscriberInterface
20
{
21
    protected array $rules = [];
22
23 7
    public function __construct(array ...$rules)
24
    {
25 7
        $this->rules = \func_get_args() ?: [];
26
    }
27
28 7
    public function onKernelResponse(ResponseEvent $event): void
29
    {
30 7
        if (empty($this->rules) || !$event->isMainRequest()) {
31 2
            return;
32
        }
33
34 5
        $response = $event->getResponse();
35 5
        $content = $response->getContent();
36 5
        if (false === $content) {
37 1
            return; // Ignore special (binary or streamed) responses
38
        }
39
40 4
        $headers = $response->headers;
41 4
        $format = $headers->get('content-type') ?: ($event->getRequest()->getRequestFormat() ?? 'text/html');
42 4
        $format = explode(';', $format)[0];
43
44
        // Add custom headers and filter content
45 4
        foreach ($this->rules as $rule) {
46 4
            $content = $this->applyRule($rule, $content, $headers, $format);
47
        }
48
49
        try {
50 4
            $response->setContent($content);
51
        } catch (\LogicException $err) { // @codeCoverageIgnore
52
            // Just ignore exception
53
        }
54
    }
55
56
    /** @codeCoverageIgnore */
57
    public static function getSubscribedEvents(): array
58
    {
59
        return [
60
            KernelEvents::RESPONSE => 'onKernelResponse',
61
        ];
62
    }
63
64 4
    public function applyRule(array $rule, string $content, ResponseHeaderBag $headers, string $format): string
65
    {
66 4
        if (!$rule['enabled'] || (isset($rule['formats']) && !\in_array($format, $rule['formats'], true))) {
67 2
            return $content; // Ignore disabled or unsupported rules
68
        }
69
70 3
        if (isset($rule['pattern'])) {
71 2
            $content = preg_replace_callback(
72 2
                $rule['pattern'],
73 2
                function (array $match) use ($headers, $rule): string {
74
                    // Set header value
75 2
                    $value = vsprintf(isset($rule['value']) ? $rule['value'] : '%s', $match);
76 2
                    $headers->set($rule['name'], $value);
77
78
                    // Replace matched text
79 2
                    return vsprintf(isset($rule['replace']) ? $rule['replace'] : '%s', $match);
80 2
                },
81 2
                $content
82 2
            );
83
        } else {
84
            // Add value
85 1
            $headers->set($rule['name'], isset($rule['value']) ? $rule['value'] : '');
86
        }
87
88 3
        return $content;
89
    }
90
}
91