Completed
Push — master ( 8ebaed...b6d628 )
by Marko
16:21
created

CKEditorRenderer::__construct()   D

Complexity

Conditions 9
Paths 8

Size

Total Lines 31
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

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