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