Completed
Push — master ( c0f250...321e24 )
by Filipe
15:10
created

HtmlExtension::urlClosure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
3
/**
4
 * This file is part of slick/web_stack package
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Slick\WebStack\Renderer\Extension;
11
12
use Slick\Template\EngineExtensionInterface;
13
use Slick\Template\Extension\AbstractTwigExtension;
14
use Slick\WebStack\Service\UriGeneratorInterface;
15
use Twig\TwigFunction;
16
17
/**
18
 * HtmlExtension
19
 *
20
 * @package Slick\WebStack\Renderer\Extension
21
 */
22
class HtmlExtension extends AbstractTwigExtension implements EngineExtensionInterface
23
{
24
25
    /**
26
     * @var UriGeneratorInterface
27
     */
28
    private $generator;
29
30
    /**
31
     * @var array Default options for addCss and addJs template functions
32
     */
33
    private static $options = [
34
        'is_safe' => ['html']
35
    ];
36
37
    /**
38
     * Creates an HTML template extension
39
     *
40
     * @param UriGeneratorInterface $generator
41
     */
42
    public function __construct(UriGeneratorInterface $generator)
43
    {
44
        $this->generator = $generator;
45
    }
46
47
    /**
48
     * @return TwigFunction[]
49
     */
50
    public function getFunctions()
51
    {
52
        return [
53
            'url'    => new TwigFunction('url', $this->urlClosure()),
54
            'addCss' => new TwigFunction('addCss', $this->cssClosure(), self::$options),
55
            'addJs'  => new TwigFunction('addJs', $this->jsClosure(), self::$options)
56
        ];
57
    }
58
59
    /**
60
     * Generates URI for provided location
61
     *
62
     * @param string $location Location name, path or identifier
63
     * @param array $options Filter options
64
     *
65
     * @return null|\Psr\Http\Message\UriInterface
66
     */
67
    private function location($location, array $options = [])
68
    {
69
        return $this->generator->generate($location, $options);
70
    }
71
72
    /**
73
     * Creates a css link tag for provided css file
74
     *
75
     * @param string $file
76
     * @param string $path
77
     * @param array $options
78
     *
79
     * @return string
80
     */
81
    private function css($file, $path = 'css', array $options = [])
82
    {
83
        $attr = array_key_exists('attr', $options) ? $options['attr'] : [];
84
        $attr = array_merge(['rel' => 'stylesheet'], $attr);
85
        $location = $this->location("{$path}/{$file}", $options);
86
        return sprintf(
87
            '<link href="%s" %s>',
88
            $location,
89
            $this->attributesStr($attr)
90
        );
91
    }
92
93
    /**
94
     * Converts an attributes key/value array to its string representation
95
     *
96
     * @param array $attr
97
     *
98
     * @return string
99
     */
100
    private function attributesStr(array $attr)
101
    {
102
        $output = [];
103
        foreach ($attr as $name => $value) {
104
            $output[] = "{$name}=\"{$value}\"";
105
        }
106
        return implode(' ', $output);
107
    }
108
109
    /**
110
     * Creates the url() template function closure
111
     *
112
     * @return \Closure
113
     */
114
    private function urlClosure()
115
    {
116
        return function ($location, array $options = []) {
117
            return $this->location($location, $options);
118
        };
119
    }
120
121
    /**
122
     * Creates the addCss() template function closure
123
     *
124
     * @return \Closure
125
     */
126
    private function cssClosure()
127
    {
128
        return function ($file, $path = 'css', array $options = []) {
129
            return $this->css($file, $path, $options);
130
        };
131
    }
132
133
    /**
134
     * Creates the addJs() template function closure
135
     *
136
     * @return \Closure
137
     */
138
    private function jsClosure()
139
    {
140
        return function ($file, $path = 'js', array $options = []) {
141
            $attr = array_key_exists('attr', $options)
142
                ? $options['attr']
143
                : [];
144
            $location = $this->location("{$path}/{$file}", $options);
145
            return sprintf(
146
                '<script src="%s" %s></script>',
147
                $location,
148
                $this->attributesStr($attr)
149
            );
150
        };
151
    }
152
153
}
154