Passed
Push — main ( ddb4d2...6be060 )
by Mariano
02:23 queued 10s
created

AmpOptimizerSubscriber::isAmpHtml()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 7

Importance

Changes 0
Metric Value
eloc 18
c 0
b 0
f 0
dl 0
loc 31
rs 8.8333
ccs 19
cts 19
cp 1
cc 7
nc 6
nop 2
crap 7
1
<?php
2
3
namespace Hola\AmpToolboxBundle\EventSubscriber;
4
5
use AmpProject\Optimizer\ErrorCollection;
6
use AmpProject\Optimizer\TransformationEngine;
7
use Psr\Log\LoggerInterface;
8
use Sunra\PhpSimple\HtmlDomParser;
9
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
10
use Symfony\Component\HttpFoundation\Request;
11
use Symfony\Component\HttpFoundation\Response;
12
use Symfony\Component\HttpKernel\Event\ResponseEvent;
13
use Symfony\Component\HttpKernel\KernelEvents;
14
15
/**
16
 * Listen response event and optimize html
17
 * Class AmpOptimizerSubscriber
18
 * @package Hola\AmpToolboxBundle\EventSubscriber
19
 */
20
class AmpOptimizerSubscriber implements EventSubscriberInterface
21
{
22
23
    /**
24
     * @var LoggerInterface
25
     */
26
    private $logger;
27
28
    /**
29
     * @var TransformationEngine
30
     */
31
    private $transformationEngine;
32
33
    /**
34
     * @var array
35
     */
36
    private $config;
37
38
    /**
39
     * @var ErrorCollection
40
     */
41
    private $errorCollection;
42
43
    /**
44
     * AmpOptimizerSubscriber constructor.
45
     * @param LoggerInterface $logger
46
     * @param TransformationEngine $transformationEngine
47
     * @param $config
48
     */
49 6
    public function __construct(LoggerInterface $logger, TransformationEngine $transformationEngine, $config)
50
    {
51 6
        $this->config = $config;
52 6
        $this->logger = $logger;
53 6
        $this->transformationEngine = $transformationEngine;
54 6
        $this->errorCollection = new ErrorCollection();
55 6
    }
56
57
    /**
58
     * @return array|array[]
59
     */
60 1
    public static function getSubscribedEvents()
61
    {
62
        return [
63 1
            KernelEvents::RESPONSE => ['onKernelResponse', -10],
64
        ];
65
    }
66
67
    /**
68
     * @param ResponseEvent $event
69
     * @return void
70
     */
71 6
    public function onKernelResponse(ResponseEvent $event): void
72
    {
73 6
        if (!array_key_exists('transform_enabled', $this->config) ||
74 6
            false === $this->config['transform_enabled']) {
75 2
            return;
76
        }
77
78 4
        if (!$event->isMasterRequest()) {
79 1
            return;
80
        }
81
82 3
        if (!$this->isAmpHtml($event->getResponse(), $event->getRequest())) {
83 1
            return;
84
        }
85
86 2
        $optimizedHtml = $this->transformationEngine->optimizeHtml(
87 2
            $event->getResponse()->getContent(),
88 2
            $this->errorCollection
89
        );
90
91 2
        $this->handleErrors();
92
93 2
        $event->getResponse()->setContent($optimizedHtml);
94 2
    }
95
96
    /**
97
     * @param Response $response
98
     * @param Request $request
99
     * @return bool
100
     */
101 3
    private function isAmpHtml(Response $response, Request $request): bool
102
    {
103 3
        $pathInfo = pathInfo($request->getUri());
104 3
        if (isset($pathInfo['extension']) && $pathInfo['extension'] !== 'html') {
105 1
            return false;
106
        }
107
108 3
        $contentType = $response->headers->get('Content-type');
109 3
        if (strpos($contentType, 'text/html') === false) {
110 1
            return false;
111
        }
112
113 3
        $content = $response->getContent();
114 3
        $dom = HtmlDomParser::str_get_html($content);
115
116 3
        if ($dom === false) {
0 ignored issues
show
introduced by
The condition $dom === false is always false.
Loading history...
117 1
            $this->logger->error('Content can not be parsed by HtmlDomParser');
118 1
            return false;
119
        }
120
121 3
        $htmlElement = $dom->find('html', 0);
122 3
        if (null === $htmlElement) {
123 1
            return false;
124
        }
125
126 3
        $htmlElementAttrs = $htmlElement->getAllAttributes();
127 3
        if (empty(array_intersect(['⚡', 'amp'], array_keys($htmlElementAttrs)))) {
128 1
            return false;
129
        }
130
131 2
        return true;
132
    }
133
134 2
    private function handleErrors(): void
135
    {
136 2
        if ($this->errorCollection->count() > 0) {
137 1
            foreach ($this->errorCollection as $error) {
138 1
                $this->logger->error(sprintf(
139 1
                    "AMP-Optimizer Error code: %s\nError Message: %s\n",
140 1
                    $error->getCode(),
141 1
                    $error->getMessage()
142
                ));
143
            }
144
        }
145 2
    }
146
147
    /**
148
     * @param bool $enabled
149
     */
150 1
    public function setEnabled(bool $enabled): void
151
    {
152 1
        $this->config['transform_enabled'] = $enabled;
153
    }
154
}