Passed
Pull Request — master (#120)
by
unknown
15:40
created

RichEditorExtension::getRichEditorFieldElements()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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