HtmlCompressRuntime::__invoke()   B
last analyzed

Complexity

Conditions 7
Paths 3

Size

Total Lines 13
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 7

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 5
c 1
b 0
f 0
nc 3
nop 3
dl 0
loc 13
ccs 5
cts 5
cp 1
crap 7
rs 8.8333
1
<?php
2
3
/*
4
 * This file is part of ocubom/twig-html-extension
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\Twig\Extension;
13
14
use Ocubom\Twig\Extension\Html\Exception\InvalidArgumentException;
15
use Symfony\Bundle\WebProfilerBundle\WebProfilerBundle;
16
use Twig\Environment;
17
use Twig\Extension\RuntimeExtensionInterface;
18
use WyriHaximus\HtmlCompress\Factory;
19
use WyriHaximus\HtmlCompress\HtmlCompressorInterface;
20
21
class HtmlCompressRuntime implements RuntimeExtensionInterface
22
{
23
    // Factory compression levels
24
    public const COMPRESSOR_NONE = 0;
25
    public const COMPRESSOR_FASTEST = 1;
26
    public const COMPRESSOR_NORMAL = 2;
27
    public const COMPRESSOR_SMALLEST = 3;
28
29
    private const FACTORIES = [
30
        // By COMPRESSOR_*
31
        self::COMPRESSOR_NONE => null,
32
        self::COMPRESSOR_FASTEST => [Factory::class, 'constructfastest'],
33
        self::COMPRESSOR_NORMAL => [Factory::class, 'construct'],
34
        self::COMPRESSOR_SMALLEST => [Factory::class, 'constructsmallest'],
35
        // By sort name
36
        '' => null,
37
        'none' => null,
38
        'fastest' => [Factory::class, 'constructfastest'],
39
        'normal' => [Factory::class, 'construct'],
40
        'smallest' => [Factory::class, 'constructsmallest'],
41
    ];
42
43
    private bool $force;
44
45
    private ?HtmlCompressorInterface $compressor = null;
46
47
    /**
48
     * Constructor.
49
     *
50
     * @param bool                                        $force      Always apply compression
51
     * @param HtmlCompressorInterface|callable|int|string $compressor The compressor level, a compressor instance or factory callable
52
     */
53 8
    public function __construct(bool $force = false, $compressor = self::COMPRESSOR_SMALLEST)
54
    {
55 8
        $this->force = $force;
56
57 8
        if ($compressor instanceof HtmlCompressorInterface) {
58 1
            $this->compressor = $compressor;
59
        } else {
60
            try {
61 7
                $factory = is_callable($compressor) ? $compressor : self::createFactory($compressor);
62 7
                $this->compressor = $factory();
63 1
            } catch (\Throwable $exc) {
64 1
                throw new InvalidArgumentException(
65 1
                    sprintf(
66 1
                        'Unable to build "%s" HTML compressor ',
67 1
                        is_scalar($compressor) ? $compressor : 'callable',
68 1
                    ),
69 1
                    0,
70 1
                    $exc
71 1
                );
72
            }
73
        }
74
    }
75
76 3
    public function __invoke(Environment $twig, string $html, bool $force = false): string
77
    {
78 3
        if (null !== $this->compressor && (!$twig->isDebug() || $this->force || $force)) {
79
            // Compress
80 2
            $html = $this->compressor->compress($html);
81
82
            // Add end body tag to allow profiler inject its code
83 2
            if ($twig->isDebug() && class_exists(WebProfilerBundle::class)) {
84
                $html .= '</body>'; // @codeCoverageIgnore
85
            }
86
        }
87
88 3
        return $html;
89
    }
90
91
    /**
92
     * @param int|string $compressor
93
     */
94 6
    private static function createFactory($compressor): callable
95
    {
96 6
        $key = is_string($compressor) ? self::cleanValue($compressor) : $compressor;
97 6
        if (array_key_exists($key, self::FACTORIES)) {
98 5
            return self::FACTORIES[$key] ?? function () {
99 2
                return null;
100 5
            };
101
        }
102
103 1
        return function () use ($key): HtmlCompressorInterface {
104 1
            $factory = [Factory::class, 'construct'.$key];
105
106 1
            return $factory();
107 1
        };
108
    }
109
110 3
    private static function cleanValue(string $name): string
111
    {
112 3
        $value = strtolower($name);
113
114 3
        if (str_starts_with($value, 'construct')) {
115 1
            $value = substr($value, 9);
116
        }
117
118 3
        return $value;
119
    }
120
}
121