Passed
Pull Request — master (#3)
by Jitendra
01:23
created

Yall   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 83
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
eloc 42
c 3
b 0
f 1
dl 0
loc 83
rs 10
wmc 13

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getFunctions() 0 5 1
A __construct() 0 8 1
A yallify() 0 22 3
A normalizeSrc() 0 14 3
A lazify() 0 15 4
A getTokenParsers() 0 3 1
1
<?php
2
3
/*
4
 * This file is part of the TWIG-YALL package.
5
 *
6
 * (c) Jitendra Adhikari <[email protected]>
7
 *     <https://github.com/adhocore>
8
 *
9
 * Licensed under MIT license.
10
 */
11
12
namespace Ahc\TwigYall;
13
14
use Twig\Extension\AbstractExtension;
15
use Twig\Markup;
16
use Twig\TwigFunction;
17
18
class Yall extends AbstractExtension
19
{
20
    protected $config = [];
21
22
    public function __construct(array $config = [])
23
    {
24
        $this->config = $config + [
25
            'polyfillJs'  => 'https://polyfill.io/%s/polyfill.min.js?features=IntersectionObserver',
26
            // @see: https://stackoverflow.com/a/15960901
27
            'placeholder' => 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEAAAAALAAAAAABAAEAAAI=',
28
            'yallJs'      => 'https://unpkg.com/yall-js@%s/dist/yall.min.js',
29
            'lazyClass'   => 'lazy',
30
        ];
31
    }
32
33
    public function getFunctions(): array
34
    {
35
        return [
36
            new TwigFunction('lazify', [$this, 'lazify']),
37
            new TwigFunction('yallify', [$this, 'yallify']),
38
        ];
39
    }
40
41
    public function getTokenParsers()
42
    {
43
        return [new Parser($this->config['lazyClass'], $this->config['placeholder'])];
44
    }
45
46
    public function yallify(string $yall = null, string $polyfill = null, array $options = []): Markup
47
    {
48
        $yallJs   = \sprintf($this->config['yallJs'], $yall ?: '3.1.7');
49
        $options += ['lazyClass' => $this->config['lazyClass']];
50
        $jsonFlag = \JSON_UNESCAPED_SLASHES | \JSON_FORCE_OBJECT;
51
52
        $jsonOpts = \json_encode($options, $jsonFlag);
53
        $jsonOpts = \str_replace(['"<raw>', '</raw>"'], ['', ''], $jsonOpts);
54
55
        $markup = [
56
            $polyfill ?? 'v2'
57
                ? \sprintf('<script src="%s" async></script>', \sprintf($this->config['polyfillJs'], $polyfill ?? 'v2'))
58
                : '',
59
            \sprintf('<script src="%s" async></script>', $yallJs),
60
            '<script type="text/javascript">',
61
            'document.addEventListener("DOMContentLoaded", function() {',
62
            \sprintf('  window.setTimeout(function () { yall(%s); }, 99);', $jsonOpts),
63
            '});',
64
            '</script>',
65
        ];
66
67
        return new Markup(\implode("\n", $markup), 'UTF-8');
68
    }
69
70
    public function lazify($src, string $classes = '', string $dummy = ''): Markup
71
    {
72
        $attr = 'src';
73
        if (\is_array($src)) {
74
            list($attr, $src) = $this->normalizeSrc($src);
75
        }
76
77
        $classes = \trim("$classes {$this->config['lazyClass']} yall");
78
        if ('srcset' !== $attr) {
79
            $dummy = \sprintf(' %s="%s"', $attr, $dummy ?: $this->config['placeholder']);
80
        }
81
82
        $markup = \sprintf('class="%s"%s data-%s="%s"', $classes, $dummy, $attr, $src);
83
84
        return new Markup($markup, 'UTF-8');
85
    }
86
87
    protected function normalizeSrc(array $src): array
88
    {
89
        if ($src['poster'] ?? false) {
90
            return ['poster', $src['poster']];
91
        }
92
93
        if ($src['srcset'] ?? false) {
94
            return ['srcset', $src['srcset']];
95
        }
96
97
        $srcset = $src;
98
        $src    = \array_shift($srcset);
99
100
        return ['src', $src . '" data-srcset="' . \implode(', ', $srcset)];
101
    }
102
}
103