Completed
Push — master ( 8e2f23...0bdc89 )
by Maxime
18s queued 11s
created

RichEditorExtension::getFunctions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 3
c 2
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
/*
4
 * This file is part of Monsieur Biz' Rich Editor plugin for Sylius.
5
 *
6
 * (c) Monsieur Biz <[email protected]>
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
declare(strict_types=1);
13
14
namespace MonsieurBiz\SyliusRichEditorPlugin\Twig;
15
16
use MonsieurBiz\SyliusRichEditorPlugin\Exception\UiElementNotFoundException;
17
use MonsieurBiz\SyliusRichEditorPlugin\UiElement\RegistryInterface;
18
use MonsieurBiz\SyliusRichEditorPlugin\Validator\Constraints\YoutubeUrlValidator;
19
use Twig\Environment;
20
use Twig\Error\LoaderError;
21
use Twig\Error\RuntimeError;
22
use Twig\Error\SyntaxError;
23
use Twig\Extension\AbstractExtension;
24
use Twig\TwigFilter;
25
use Twig\TwigFunction;
26
27
final class RichEditorExtension extends AbstractExtension
28
{
29
    /**
30
     * @var RegistryInterface
31
     */
32
    private $uiElementRegistry;
33
34
    /**
35
     * @var Environment
36
     */
37
    private $twig;
38
39
    /**
40
     * RichEditorExtension constructor.
41
     *
42
     * @param RegistryInterface $uiElementRegistry
43
     * @param Environment $twig
44
     */
45
    public function __construct(
46
        RegistryInterface $uiElementRegistry,
47
        Environment $twig
48
    ) {
49
        $this->uiElementRegistry = $uiElementRegistry;
50
        $this->twig = $twig;
51
    }
52
53
    /**
54
     * @return TwigFilter[]
55
     */
56
    public function getFilters()
57
    {
58
        return [
59
            new TwigFilter('monsieurbiz_richeditor_render_element', [$this, 'renderRichEditorField'], ['is_safe' => ['html']]),
60
        ];
61
    }
62
63
    /**
64
     * @return array|TwigFunction[]
65
     */
66
    public function getFunctions()
67
    {
68
        return [
69
            new TwigFunction('monsieurbiz_richeditor_list_elements', [$this, 'listUiElements'], ['is_safe' => ['html', 'js']]),
70
            new TwigFunction('monsieurbiz_richeditor_youtube_link', [$this, 'convertYoutubeEmbeddedLink'], ['is_safe' => ['html', 'js']]),
71
        ];
72
    }
73
74
    /**
75
     * @param string $content
76
     *
77
     * @throws LoaderError
78
     * @throws RuntimeError
79
     * @throws SyntaxError
80
     *
81
     * @return string
82
     */
83
    public function renderRichEditorField(string $content)
84
    {
85
        $elements = json_decode($content, true);
86
        if (!\is_array($elements)) {
87
            return $content;
88
        }
89
90
        return $this->renderElements($elements);
91
    }
92
93
    /**
94
     * @param array $elements
95
     *
96
     * @throws LoaderError
97
     * @throws RuntimeError
98
     * @throws SyntaxError
99
     *
100
     * @return string
101
     */
102
    private function renderElements(array $elements): string
103
    {
104
        $html = '';
105
        foreach ($elements as $element) {
106
            try {
107
                $html .= $this->renderElement($element);
108
            } catch (UiElementNotFoundException $e) {
109
                continue;
110
            }
111
        }
112
113
        return $html;
114
    }
115
116
    /**
117
     * @param array $element
118
     *
119
     * @throws UiElementNotFoundException
120
     * @throws LoaderError [twig.render] When the template cannot be found
121
     * @throws SyntaxError [twig.render] When an error occurred during compilation
122
     * @throws RuntimeError [twig.render] When an error occurred during rendering
123
     *
124
     * @return string
125
     */
126
    private function renderElement(array $element): string
127
    {
128
        if (!isset($element['code'])) {
129
            if (!isset($element['type'], $element['fields'])) {
130
                throw new UiElementNotFoundException('unknown');
131
            }
132
            $element = [
133
                'code' => $element['type'],
134
                'data' => $element['fields'],
135
            ];
136
        }
137
138
        $uiElement = $this->uiElementRegistry->getUiElement($element['code']);
139
        $template = $uiElement->getFrontRenderTemplate();
140
141
        return $this->twig->render($template, [
142
            'ui_element' => $uiElement,
143
            'element' => $element['data'],
144
        ]);
145
    }
146
147
    /**
148
     * List available Ui Elements in JSON.
149
     *
150
     * @return string
151
     */
152
    public function listUiElements(): string
153
    {
154
        return (string) json_encode($this->uiElementRegistry);
155
    }
156
157
    /**
158
     * Convert Youtube link to embed URL.
159
     *
160
     * @param string $url
161
     *
162
     * @return string|null
163
     */
164
    public function convertYoutubeEmbeddedLink(string $url): ?string
165
    {
166
        $isValid = (bool) preg_match(YoutubeUrlValidator::YOUTUBE_REGEX_VALIDATOR, $url, $matches);
167
168
        if (!$isValid || !isset($matches[1])) {
169
            return null;
170
        }
171
172
        return sprintf('https://www.youtube.com/embed/%s', $matches[1]);
173
    }
174
}
175