Completed
Push — issue-258 ( ffb78f )
by Eric
63:35
created

CKEditorRenderer::getTemplating()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 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 Ivory\CKEditorBundle\Renderer;
13
14
use Ivory\JsonBuilder\JsonBuilder;
15
use Symfony\Component\DependencyInjection\ContainerInterface;
16
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
17
18
/**
19
 * @author GeLo <[email protected]>
20
 */
21
class CKEditorRenderer implements CKEditorRendererInterface
22
{
23
    /** @var \Ivory\JsonBuilder\JsonBuilder */
24
    private $jsonBuilder;
25
26
    /** @var \Symfony\Component\DependencyInjection\ContainerInterface */
27
    private $container;
28
29
    /**
30
     * Creates a CKEditor renderer.
31
     *
32
     * @param \Symfony\Component\DependencyInjection\ContainerInterface $container The container.
33
     */
34
    public function __construct(ContainerInterface $container)
35
    {
36
        $this->jsonBuilder = new JsonBuilder();
37
        $this->container = $container;
38
    }
39
40
    /**
41
     * {@inheritdoc}
42
     */
43
    public function renderBasePath($basePath)
44
    {
45
        return $this->fixPath($this->fixUrl($basePath));
46
    }
47
48
    /**
49
     * {@inheritdoc}
50
     */
51
    public function renderJsPath($jsPath)
52
    {
53
        return $this->fixUrl($jsPath);
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     */
59
    public function renderWidget($id, array $config, array $options = array())
60
    {
61
        $config = $this->fixConfigLanguage($config);
62
        $config = $this->fixConfigContentsCss($config);
63
        $config = $this->fixConfigFilebrowsers(
64
            $config,
65
            isset($options['filebrowsers']) ? $options['filebrowsers'] : array()
66
        );
67
68
        $this->jsonBuilder
69
            ->reset()
70
            ->setValues($config);
71
72
        $this->fixConfigEscapedValues($config);
73
74
        $autoInline = isset($options['auto_inline']) && !$options['auto_inline']
75
            ? 'CKEDITOR.disableAutoInline = true;'.PHP_EOL
76
            : null;
77
78
        $widget = sprintf(
79
            'CKEDITOR.%s("%s", %s);',
80
            isset($options['inline']) && $options['inline'] ? 'inline' : 'replace',
81
            $id,
82
            $this->fixConfigConstants($this->jsonBuilder->build())
83
        );
84
85
        if (isset($options['input_sync']) && $options['input_sync']) {
86
            $variable = 'ivory_ckeditor_'.$id;
87
            $widget = 'var '.$variable.' = '.$widget.PHP_EOL;
88
89
            return $autoInline.$widget.$variable.'.on(\'change\', function() { '.$variable.'.updateElement(); });';
90
        }
91
92
        return $autoInline.$widget;
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98
    public function renderDestroy($id)
99
    {
100
        return sprintf('if (CKEDITOR.instances["%s"]) { delete CKEDITOR.instances["%s"]; }', $id, $id);
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function renderPlugin($name, array $plugin)
107
    {
108
        return sprintf(
109
            'CKEDITOR.plugins.addExternal("%s", "%s", "%s");',
110
            $name,
111
            $this->fixPath($this->fixUrl($plugin['path'])),
112
            $plugin['filename']
113
        );
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119
    public function renderStylesSet($name, array $stylesSet)
120
    {
121
        $this->jsonBuilder
122
            ->reset()
123
            ->setValues($stylesSet);
124
125
        return sprintf(
126
            'if (CKEDITOR.stylesSet.get("%s") === null) { CKEDITOR.stylesSet.add("%s", %s); }',
127
            $name,
128
            $name,
129
            $this->jsonBuilder->build()
130
        );
131
    }
132
133
    /**
134
     * {@inheritdoc}
135
     */
136
    public function renderTemplate($name, array $template)
137
    {
138
        if (isset($template['imagesPath'])) {
139
            $template['imagesPath'] = $this->fixPath($this->fixUrl($template['imagesPath']));
140
        }
141
142
        if (isset($template['templates'])) {
143
            foreach ($template['templates'] as &$rawTemplate) {
0 ignored issues
show
Bug introduced by
The expression $template['templates'] of type string is not traversable.
Loading history...
144
                if (isset($rawTemplate['template'])) {
145
                    $rawTemplate['html'] = $this->getTemplating()->render(
146
                        $rawTemplate['template'],
147
                        isset($rawTemplate['template_parameters']) ? $rawTemplate['template_parameters'] : array()
148
                    );
149
                }
150
151
                unset($rawTemplate['template']);
152
                unset($rawTemplate['template_parameters']);
153
            }
154
        }
155
156
        $this->jsonBuilder
157
            ->reset()
158
            ->setValues($template);
159
160
        return sprintf('CKEDITOR.addTemplates("%s", %s);', $name, $this->jsonBuilder->build());
161
    }
162
163
    /**
164
     * Fixes the config language.
165
     *
166
     * @param array $config The config.
167
     *
168
     * @return array The fixed config.
169
     */
170
    private function fixConfigLanguage(array $config)
171
    {
172
        if (!isset($config['language']) && ($language = $this->getLanguage()) !== null) {
173
            $config['language'] = $language;
174
        }
175
176
        if (isset($config['language'])) {
177
            $config['language'] = strtolower(str_replace('_', '-', $config['language']));
178
        }
179
180
        return $config;
181
    }
182
183
    /**
184
     * Fixes the config contents css.
185
     *
186
     * @param array $config The config.
187
     *
188
     * @return array The fixed config.
189
     */
190
    private function fixConfigContentsCss(array $config)
191
    {
192
        if (isset($config['contentsCss'])) {
193
            $cssContents = (array) $config['contentsCss'];
194
195
            $config['contentsCss'] = array();
196
            foreach ($cssContents as $cssContent) {
197
                $config['contentsCss'][] = $this->fixPath($this->fixUrl($cssContent));
198
            }
199
        }
200
201
        return $config;
202
    }
203
204
    /**
205
     * Fixes the config filebrowsers.
206
     *
207
     * @param array $config       The config.
208
     * @param array $filebrowsers The filebrowsers.
209
     *
210
     * @return array The fixed config.
211
     */
212
    private function fixConfigFilebrowsers(array $config, array $filebrowsers)
213
    {
214
        $filebrowsers = array_unique(array_merge(array(
215
            'Browse',
216
            'FlashBrowse',
217
            'ImageBrowse',
218
            'ImageBrowseLink',
219
            'Upload',
220
            'FlashUpload',
221
            'ImageUpload',
222
        ), $filebrowsers));
223
224
        foreach ($filebrowsers as $filebrowser) {
225
            $fileBrowserKey = 'filebrowser'.$filebrowser;
226
            $handler = $fileBrowserKey.'Handler';
227
            $url = $fileBrowserKey.'Url';
228
            $route = $fileBrowserKey.'Route';
229
            $routeParameters = $fileBrowserKey.'RouteParameters';
230
            $routeAbsolute = $fileBrowserKey.'RouteAbsolute';
231
232
            if (isset($config[$handler])) {
233
                $config[$url] = $config[$handler]($this->getRouter());
234
            } elseif (isset($config[$route])) {
235
                $config[$url] = $this->getRouter()->generate(
236
                    $config[$route],
237
                    isset($config[$routeParameters]) ? $config[$routeParameters] : array(),
238
                    $this->fixRoutePath(isset($config[$routeAbsolute]) && $config[$routeAbsolute])
0 ignored issues
show
Bug introduced by
It seems like $this->fixRoutePath(isse...config[$routeAbsolute]) targeting Ivory\CKEditorBundle\Ren...enderer::fixRoutePath() can also be of type boolean; however, Symfony\Component\Routin...orInterface::generate() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
239
                );
240
            }
241
242
            unset($config[$handler]);
243
            unset($config[$route]);
244
            unset($config[$routeParameters]);
245
            unset($config[$routeAbsolute]);
246
        }
247
248
        return $config;
249
    }
250
251
    /**
252
     * Fixes the config escaped values and sets them on the json builder.
253
     *
254
     * @param array $config The config.
255
     */
256
    private function fixConfigEscapedValues(array $config)
257
    {
258
        if (isset($config['protectedSource'])) {
259
            foreach ($config['protectedSource'] as $key => $value) {
260
                $this->jsonBuilder->setValue(sprintf('[protectedSource][%s]', $key), $value, false);
261
            }
262
        }
263
264
        $escapedValueKeys = array(
265
            'stylesheetParser_skipSelectors',
266
            'stylesheetParser_validSelectors',
267
        );
268
269
        foreach ($escapedValueKeys as $escapedValueKey) {
270
            if (isset($config[$escapedValueKey])) {
271
                $this->jsonBuilder->setValue(sprintf('[%s]', $escapedValueKey), $config[$escapedValueKey], false);
272
            }
273
        }
274
    }
275
276
    /**
277
     * Fixes the config constants.
278
     *
279
     * @param string $json The json config.
280
     *
281
     * @return string The fixed config.
282
     */
283
    private function fixConfigConstants($json)
284
    {
285
        return preg_replace('/"(CKEDITOR\.[A-Z_]+)"/', '$1', $json);
286
    }
287
288
    /**
289
     * Fixes a path.
290
     *
291
     * @param string $path The path.
292
     *
293
     * @return string The fixed path.
294
     */
295
    private function fixPath($path)
296
    {
297
        if (($position = strpos($path, '?')) !== false) {
298
            return substr($path, 0, $position);
299
        }
300
301
        return $path;
302
    }
303
304
    /**
305
     * Fixes an url.
306
     *
307
     * @param string $url The url.
308
     *
309
     * @return string The fixed url.
310
     */
311
    private function fixUrl($url)
312
    {
313
        $assetsHelper = $this->getAssetsHelper();
314
315
        return $assetsHelper !== null ? $assetsHelper->getUrl($url) : $url;
316
    }
317
318
    /**
319
     * @param bool $routePath
320
     *
321
     * @return int|bool
322
     */
323
    private function fixRoutePath($routePath)
324
    {
325
        if ($routePath) {
326
            return defined('Symfony\Component\Routing\Generator\UrlGeneratorInterface::ABSOLUTE_PATH')
327
                ? UrlGeneratorInterface::ABSOLUTE_PATH
328
                : true;
329
        }
330
331
        return defined('Symfony\Component\Routing\Generator\UrlGeneratorInterface::RELATIVE_PATH')
332
            ? UrlGeneratorInterface::RELATIVE_PATH
333
            : false;
334
    }
335
336
    /**
337
     * Gets the locale.
338
     *
339
     * @return string|null The locale.
340
     */
341
    private function getLanguage()
342
    {
343
        if (($request = $this->getRequest()) !== null) {
344
            return $request->getLocale();
345
        }
346
347
        if ($this->container->hasParameter($parameter = 'locale')) {
348
            return $this->container->getParameter($parameter);
349
        }
350
    }
351
352
    /**
353
     * Gets the request.
354
     *
355
     * @return \Symfony\Component\HttpFoundation\Request|null The request.
356
     */
357
    private function getRequest()
358
    {
359
        if ($this->container->has($service = 'request_stack')) {
360
            return $this->container->get($service)->getMasterRequest();
361
        }
362
363
        if ($this->container->has($service = 'request')) {
364
            return $this->container->get($service);
365
        }
366
    }
367
368
    /**
369
     * Gets the templating engine.
370
     *
371
     * @return \Symfony\Component\Templating\EngineInterface|\Twig_Environment The templating engine.
372
     */
373
    private function getTemplating()
374
    {
375
        return $this->container->has($templating = 'templating')
376
            ? $this->container->get($templating)
377
            : $this->container->get('twig');
378
    }
379
380
    /**
381
     * Gets the assets helper.
382
     *
383
     * @return \Symfony\Component\Asset\Packages|\Symfony\Component\Templating\Helper\CoreAssetsHelper|null The assets helper.
384
     */
385
    private function getAssetsHelper()
386
    {
387
        return $this->container->get('assets.packages', ContainerInterface::NULL_ON_INVALID_REFERENCE);
388
    }
389
390
    /**
391
     * Gets the router.
392
     *
393
     * @return \Symfony\Component\Routing\RouterInterface The router.
394
     */
395
    private function getRouter()
396
    {
397
        return $this->container->get('router');
398
    }
399
}
400