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

Parser::isLazyloadEnd()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 1
c 1
b 0
f 1
nc 1
nop 1
dl 0
loc 3
rs 10
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\Node\Node;
15
use Twig\Node\TextNode;
16
use Twig\Token;
17
use Twig\TokenParser\AbstractTokenParser;
18
19
class Parser extends AbstractTokenParser
20
{
21
    protected $lazyClass;
22
    protected $placeholder;
23
24
    public function __construct(string $lazyClass, string $placeholder)
25
    {
26
        $this->lazyClass   = $lazyClass;
27
        $this->placeholder = $placeholder;
28
    }
29
30
    public function parse(Token $token): Node
31
    {
32
        $stream = $this->parser->getStream();
33
34
        $stream->expect(Token::BLOCK_END_TYPE);
35
        $nodes = $this->parser->subparse([$this, 'isLazyloadEnd'], true);
36
        $stream->expect(Token::BLOCK_END_TYPE);
37
38
        return $this->traverse($nodes);
39
    }
40
41
    protected function traverse(Node $nodes)
42
    {
43
        foreach ($nodes as $node) {
44
            if ($node instanceof TextNode) {
45
                $node->setAttribute('data', $this->doLazyload($node->getAttribute('data')));
46
            } else {
47
                $this->traverse($node);
48
            }
49
        }
50
51
        return $nodes;
52
    }
53
54
    protected function doLazyload(string $html): string
55
    {
56
        return \preg_replace_callback('/<(img|source|video)([^>]+)>/m', function ($match) {
57
            list($all, $tag, $props) = $match;
58
59
            if (empty(\trim($props, ' /')) || \stripos($props, $this->lazyClass) !== false) {
60
                return $all;
61
            }
62
63
            if (\stripos($props, 'data-src') !== false || \stripos($props, 'data-poster') !== false) {
64
                return $all;
65
            }
66
67
            // For video, dont need src if not already there!
68
            $needSrc = $tag !== 'video' || \strpos($props, 'src') !== false;
69
70
            if (\stripos($props, ' class') === false) {
71
                $tag .= " class=\"{$this->lazyClass} yall\"";
72
            }
73
            if (\stripos($props, ' poster') !== false) {
74
                $tag .= " poster=\"{$this->placeholder}\"";
75
            }
76
77
            $replacements = [
78
                ' src='      => ' data-src=',
79
                ' src ='     => ' data-src=',
80
                ' srcset='   => ' data-srcset=',
81
                ' srcset ='  => ' data-srcset=',
82
                ' class="'   => " class=\"{$this->lazyClass} yall ",
83
                ' class ="'  => " class=\"{$this->lazyClass} yall ",
84
                ' class = "' => " class=\"{$this->lazyClass} yall ",
85
                ' poster='   => ' data-poster=',
86
                ' poster ='  => ' data-poster=',
87
            ];
88
89
            $src = $needSrc ? " src=\"{$this->placeholder}\" " : ' ';
90
91
            return "<$tag$src" . \trim(\strtr($props, $replacements)) . '>';
92
        }, $html);
93
    }
94
95
    public function isLazyloadEnd(Token $token): bool
96
    {
97
        return $token->test('endlazyload');
98
    }
99
100
    public function getTag(): string
101
    {
102
        return 'lazyload';
103
    }
104
}
105