Completed
Pull Request — master (#340)
by Maximilian
30:50
created

CKEditorRenderer::getRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * This file is part of the Ivory CKEditor package.
5
 *
6
 * (c) Eric GELOEN <[email protected]>
7
 *
8
 * For the full copyright and license information, please read the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Ivory\CKEditorBundle\Renderer;
13
14
use Ivory\JsonBuilder\JsonBuilder;
15
use Symfony\Component\Asset\Packages;
16
use Symfony\Component\DependencyInjection\ContainerInterface;
17
use Symfony\Component\HttpFoundation\RequestStack;
18
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
19
use Symfony\Component\Routing\RouterInterface;
20
use Symfony\Component\Templating\EngineInterface;
21
22
/**
23
 * @author GeLo <[email protected]>
24
 */
25
class CKEditorRenderer implements CKEditorRendererInterface
26
{
27
    /**
28
     * @var JsonBuilder
29
     */
30
    private $jsonBuilder;
31
32
    /**
33
     * @var RouterInterface
34
     */
35
    private $router;
36
37
    /**
38
     * @var Packages
39
     */
40
    private $assetsPackages;
41
42
    /**
43
     * @var EngineInterface
44
     */
45
    private $templating;
46
47
    /**
48
     * @var RequestStack
49
     */
50
    private $requestStack;
51
52
    /**
53
     * @var null|string
54
     */
55
    private $locale;
56
57
    /**
58
     * @param JsonBuilder|ContainerInterface $containerOrJsonBuilder
59
     * @param RouterInterface $router
60
     * @param Packages $packages
61
     * @param RequestStack $requestStack
62
     * @param EngineInterface $templating
63
     * @param null|string $locale
64
     */
65 780
    public function __construct($containerOrJsonBuilder, RouterInterface $router = null, Packages $packages = null, RequestStack $requestStack = null, EngineInterface
66
    $templating = null, $locale = null)
67
    {
68 780
        if ($containerOrJsonBuilder instanceof ContainerInterface) {
69 10
            @trigger_error(sprintf('Passing a %s as %s first argument is deprecated since IvoryCKEditor 6.1, and will be removed in 7.0. Use %s instead.', ContainerInterface::class, __METHOD__, JsonBuilder::class), E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
70 10
            $jsonBuilder = $containerOrJsonBuilder->get('ivory_ck_editor.renderer.json_builder');
71 10
            $router = $containerOrJsonBuilder->get('router');
72 10
            $packages = $containerOrJsonBuilder->get('assets.packages');
73 10
            $requestStack = $containerOrJsonBuilder->get('request_stack');
74 10
            $templating = $containerOrJsonBuilder->get('templating');
75 780
        } elseif ($containerOrJsonBuilder instanceof JsonBuilder) {
76 780
            $jsonBuilder = $containerOrJsonBuilder;
77 780
            if ($router === null) {
78
                throw new \InvalidArgumentException(sprintf('%s 2nd argument must not be null when using %s as first argument', __METHOD__, JsonBuilder::class));
79 780
            } elseif ($packages === null) {
80
                throw new \InvalidArgumentException(sprintf('%s 3rd argument must not be null when using %s as first argument', __METHOD__, JsonBuilder::class));
81 780
            } elseif ($requestStack === null) {
82
                throw new \InvalidArgumentException(sprintf('%s 4th argument must not be null when using %s as first argument', __METHOD__, JsonBuilder::class));
83 780
            } elseif ($templating === null) {
84 156
                throw new \InvalidArgumentException(sprintf('%s 5th argument must not be null when using %s as first argument', __METHOD__, JsonBuilder::class));
85
            }
86 624
        } else {
87
            throw new \InvalidArgumentException(sprintf('%s first argument must be an instance of %s or %s (%s given).', __METHOD__, ContainerInterface::class, JsonBuilder::class, is_object($containerOrJsonBuilder) ? get_class($containerOrJsonBuilder) : gettype($containerOrJsonBuilder)));
88
        }
89
90 780
        $this->jsonBuilder = $jsonBuilder;
91 780
        $this->router = $router;
92 780
        $this->assetsPackages = $packages;
93 780
        $this->templating = $templating;
94 780
        $this->requestStack = $requestStack;
95 780
        $this->locale = $locale;
96 780
    }
97
98
    /**
99
     * {@inheritdoc}
100
     */
101 100
    public function renderBasePath($basePath)
102
    {
103 100
        return $this->fixPath($basePath);
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109 90
    public function renderJsPath($jsPath)
110
    {
111 90
        return $this->fixPath($jsPath);
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     */
117 610
    public function renderWidget($id, array $config, array $options = [])
118
    {
119 610
        $config = $this->fixConfigLanguage($config);
120 610
        $config = $this->fixConfigContentsCss($config);
121 610
        $config = $this->fixConfigFilebrowsers(
122 610
            $config,
123 610
            isset($options['filebrowsers']) ? $options['filebrowsers'] : []
124 488
        );
125
126 610
        $autoInline = isset($options['auto_inline']) && !$options['auto_inline']
127 494
            ? 'CKEDITOR.disableAutoInline = true;'."\n"
128 610
            : null;
129
130 610
        $builder = $this->jsonBuilder->reset()->setValues($config);
131 610
        $this->fixConfigEscapedValues($builder, $config);
132
133 610
        $widget = sprintf(
134 610
            'CKEDITOR.%s("%s", %s);',
135 610
            isset($options['inline']) && $options['inline'] ? 'inline' : 'replace',
136 610
            $id,
137 610
            $this->fixConfigConstants($builder->build())
138 488
        );
139
140 610
        if (isset($options['input_sync']) && $options['input_sync']) {
141 30
            $variable = 'ivory_ckeditor_'.$id;
142 30
            $widget = 'var '.$variable.' = '.$widget."\n";
143
144 30
            return $autoInline.$widget.$variable.'.on(\'change\', function() { '.$variable.'.updateElement(); });';
145
        }
146
147 580
        return $autoInline.$widget;
148
    }
149
150
    /**
151
     * {@inheritdoc}
152
     */
153 110
    public function renderDestroy($id)
154
    {
155 110
        return sprintf(
156
            'if (CKEDITOR.instances["%1$s"]) { '.
157 88
            'CKEDITOR.instances["%1$s"].destroy(true); '.
158 88
            'delete CKEDITOR.instances["%1$s"]; '.
159 110
            '}',
160 22
            $id
161 88
        );
162
    }
163
164
    /**
165
     * {@inheritdoc}
166
     */
167 40
    public function renderPlugin($name, array $plugin)
168
    {
169 40
        return sprintf(
170 40
            'CKEDITOR.plugins.addExternal("%s", "%s", "%s");',
171 40
            $name,
172 40
            $this->fixPath($plugin['path']),
173 40
            $plugin['filename']
174 32
        );
175
    }
176
177
    /**
178
     * {@inheritdoc}
179
     */
180 30
    public function renderStylesSet($name, array $stylesSet)
181
    {
182 30
        return sprintf(
183
            'if (CKEDITOR.stylesSet.get("%1$s") === null) { '.
184 24
            'CKEDITOR.stylesSet.add("%1$s", %2$s); '.
185 30
            '}',
186 30
            $name,
187 30
            $this->jsonBuilder->reset()->setValues($stylesSet)->build()
188 24
        );
189
    }
190
191
    /**
192
     * {@inheritdoc}
193
     */
194 60
    public function renderTemplate($name, array $template)
195
    {
196 60
        if (isset($template['imagesPath'])) {
197 60
            $template['imagesPath'] = $this->fixPath($template['imagesPath']);
198 48
        }
199
200 60
        if (isset($template['templates'])) {
201 60
            foreach ($template['templates'] as &$rawTemplate) {
0 ignored issues
show
Bug introduced by
The expression $template['templates'] of type string is not traversable.
Loading history...
202 60
                if (isset($rawTemplate['template'])) {
203 20
                    $rawTemplate['html'] = $this->templating->render(
204 20
                        $rawTemplate['template'],
205 20
                        isset($rawTemplate['template_parameters']) ? $rawTemplate['template_parameters'] : []
206 16
                    );
207 16
                }
208
209 60
                unset($rawTemplate['template']);
210 60
                unset($rawTemplate['template_parameters']);
211 48
            }
212 48
        }
213
214 60
        return sprintf(
215 60
            'CKEDITOR.addTemplates("%s", %s);',
216 60
            $name,
217 60
            $this->jsonBuilder->reset()->setValues($template)->build()
218 48
        );
219
    }
220
221
    /**
222
     * @param array $config
223
     *
224
     * @return array
225
     */
226 610
    private function fixConfigLanguage(array $config)
227
    {
228 610
        if (!isset($config['language']) && ($language = $this->getLanguage()) !== null) {
229 40
            $config['language'] = $language;
230 32
        }
231
232 610
        if (isset($config['language'])) {
233 60
            $config['language'] = strtolower(str_replace('_', '-', $config['language']));
234 48
        }
235
236 610
        return $config;
237
    }
238
239
    /**
240
     * @param array $config
241
     *
242
     * @return array
243
     */
244 610
    private function fixConfigContentsCss(array $config)
245
    {
246 610
        if (isset($config['contentsCss'])) {
247 80
            $cssContents = (array) $config['contentsCss'];
248
249 80
            $config['contentsCss'] = [];
250 80
            foreach ($cssContents as $cssContent) {
251 80
                $config['contentsCss'][] = $this->fixPath($cssContent);
252 64
            }
253 64
        }
254
255 610
        return $config;
256
    }
257
258
    /**
259
     * @param array $config
260
     * @param array $filebrowsers
261
     *
262
     * @return array
263
     */
264 610
    private function fixConfigFilebrowsers(array $config, array $filebrowsers)
265
    {
266 610
        $filebrowsers = array_unique(array_merge([
267 610
            'Browse',
268 488
            'FlashBrowse',
269 488
            'ImageBrowse',
270 488
            'ImageBrowseLink',
271 488
            'Upload',
272 488
            'FlashUpload',
273 488
            'ImageUpload',
274 610
        ], $filebrowsers));
275
276 610
        foreach ($filebrowsers as $filebrowser) {
277 610
            $fileBrowserKey = 'filebrowser'.$filebrowser;
278 610
            $handler = $fileBrowserKey.'Handler';
279 610
            $url = $fileBrowserKey.'Url';
280 610
            $route = $fileBrowserKey.'Route';
281 610
            $routeParameters = $fileBrowserKey.'RouteParameters';
282 610
            $routeType = $fileBrowserKey.'RouteType';
283
284 610
            if (isset($config[$handler])) {
285 70
                $config[$url] = $config[$handler]($this->router);
286 610
            } elseif (isset($config[$route])) {
287 140
                $config[$url] = $this->router->generate(
288 140
                    $config[$route],
289 140
                    isset($config[$routeParameters]) ? $config[$routeParameters] : [],
290 140
                    isset($config[$routeType]) ? $config[$routeType] : UrlGeneratorInterface::ABSOLUTE_PATH
291 112
                );
292 112
            }
293
294 610
            unset($config[$handler]);
295 610
            unset($config[$route]);
296 610
            unset($config[$routeParameters]);
297 610
            unset($config[$routeType]);
298 488
        }
299
300 610
        return $config;
301
    }
302
303
    /**
304
     * @param JsonBuilder $builder
305
     * @param array       $config
306
     */
307 610
    private function fixConfigEscapedValues(JsonBuilder $builder, array $config)
308
    {
309 610
        if (isset($config['protectedSource'])) {
310 10
            foreach ($config['protectedSource'] as $key => $value) {
311 10
                $builder->setValue(sprintf('[protectedSource][%s]', $key), $value, false);
312 8
            }
313 8
        }
314
315
        $escapedValueKeys = [
316 610
            'stylesheetParser_skipSelectors',
317 488
            'stylesheetParser_validSelectors',
318 488
        ];
319
320 610
        foreach ($escapedValueKeys as $escapedValueKey) {
321 610
            if (isset($config[$escapedValueKey])) {
322 138
                $builder->setValue(sprintf('[%s]', $escapedValueKey), $config[$escapedValueKey], false);
323 16
            }
324 488
        }
325 610
    }
326
327
    /**
328
     * @param string $json
329
     *
330
     * @return string
331
     */
332 610
    private function fixConfigConstants($json)
333
    {
334 610
        return preg_replace('/"(CKEDITOR\.[A-Z_]+)"/', '$1', $json);
335
    }
336
337
    /**
338
     * @param string $path
339
     *
340
     * @return string
341
     */
342 250
    private function fixPath($path)
343
    {
344 250
        if ($this->assetsPackages === null) {
345
            return $path;
346
        }
347
348 250
        $url = $this->assetsPackages->getUrl($path);
349
350 250
        if (substr($path, -1) === '/' && ($position = strpos($url, '?')) !== false) {
351 40
            $url = substr($url, 0, $position);
352 32
        }
353
354 250
        return $url;
355
    }
356
357
    /**
358
     * @return null|string
359
     */
360 590
    private function getLanguage()
361
    {
362 590
        $request = $this->requestStack->getCurrentRequest();
363 590
        if ($request !== null) {
364 590
            return $request->getLocale();
365
        }
366
367
        return $this->locale;
368
    }
369
}
370