Completed
Pull Request — master (#245)
by
unknown
64:31
created

CKEditorRenderer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 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\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
        /**
143
         * Using Templating service to render a twig view;
144
         * Before in config.yml (or CkeditorType::class) set the parameter 'html' : '@MyBundle:Templates:myTemplate-1.html.twig'
145
         * Exemple :
146
         *   ivory_ck_editor:
147
         *        configs:
148
         *           my_config:
149
         *           extraPlugins : "templates,htmlwriter"
150
         *        templates:    "my_templates"
151
         *   templates:
152
         *       my_templates:
153
         *            imagesPath: "/bundles/mybundle/templates/images"
154
         *            templates:
155
         *                -
156
         *                   title:       "My Template"
157
         *                   image:       "image.jpg"
158
         *                   description: "My awesome template"
159
         *                   html:        '@MyBundle:Templates:myTemplate-1.html.twig'
160
         */
161
        foreach ($template['templates'] as $key => $view) {
162
            if (substr($view['html'], 0, 1) === '@') {
163
                $template['templates'][$key]['html'] = $this->container->get('templating')->render(trim($view['html'], '@'));
164
            } 
165
        }
166
167
        $this->jsonBuilder
168
            ->reset()
169
            ->setValues($template);
170
171
        return sprintf('CKEDITOR.addTemplates("%s", %s);', $name, $this->jsonBuilder->build());
172
    }
173
174
    /**
175
     * Fixes the config language.
176
     *
177
     * @param array $config The config.
178
     *
179
     * @return array The fixed config.
180
     */
181
    private function fixConfigLanguage(array $config)
182
    {
183
        if (isset($config['language'])) {
184
            $config['language'] = strtolower(str_replace('_', '-', $config['language']));
185
        }
186
187
        return $config;
188
    }
189
190
    /**
191
     * Fixes the config contents css.
192
     *
193
     * @param array $config The config.
194
     *
195
     * @return array The fixed config.
196
     */
197
    private function fixConfigContentsCss(array $config)
198
    {
199
        if (isset($config['contentsCss'])) {
200
            $cssContents = (array) $config['contentsCss'];
201
202
            $config['contentsCss'] = array();
203
            foreach ($cssContents as $cssContent) {
204
                $config['contentsCss'][] = $this->fixPath($this->fixUrl($cssContent));
205
            }
206
        }
207
208
        return $config;
209
    }
210
211
    /**
212
     * Fixes the config filebrowsers.
213
     *
214
     * @param array $config       The config.
215
     * @param array $filebrowsers The filebrowsers.
216
     *
217
     * @return array The fixed config.
218
     */
219
    private function fixConfigFilebrowsers(array $config, array $filebrowsers)
220
    {
221
        $filebrowsers = array_unique(array_merge(array(
222
            'Browse',
223
            'FlashBrowse',
224
            'ImageBrowse',
225
            'ImageBrowseLink',
226
            'Upload',
227
            'FlashUpload',
228
            'ImageUpload',
229
        ), $filebrowsers));
230
231
        foreach ($filebrowsers as $filebrowser) {
232
            $fileBrowserKey = 'filebrowser'.$filebrowser;
233
            $handler = $fileBrowserKey.'Handler';
234
            $url = $fileBrowserKey.'Url';
235
            $route = $fileBrowserKey.'Route';
236
            $routeParameters = $fileBrowserKey.'RouteParameters';
237
            $routeAbsolute = $fileBrowserKey.'RouteAbsolute';
238
239
            if (isset($config[$handler])) {
240
                $config[$url] = $config[$handler]($this->getRouter());
241
            } elseif (isset($config[$route])) {
242
                $config[$url] = $this->getRouter()->generate(
243
                    $config[$route],
244
                    isset($config[$routeParameters]) ? $config[$routeParameters] : array(),
245
                    isset($config[$routeAbsolute])
246
                        ? $config[$routeAbsolute]
247
                        : (
248
                            defined('Symfony\Component\Routing\Generator\UrlGeneratorInterface::ABSOLUTE_PATH')
249
                                ? UrlGeneratorInterface::ABSOLUTE_PATH
250
                                : false
251
                        )
252
                );
253
            }
254
255
            unset($config[$handler]);
256
            unset($config[$route]);
257
            unset($config[$routeParameters]);
258
            unset($config[$routeAbsolute]);
259
        }
260
261
        return $config;
262
    }
263
264
    /**
265
     * Fixes the config escaped values and sets them on the json builder.
266
     *
267
     * @param array $config The config.
268
     */
269
    private function fixConfigEscapedValues(array $config)
270
    {
271
        if (isset($config['protectedSource'])) {
272
            foreach ($config['protectedSource'] as $key => $value) {
273
                $this->jsonBuilder->setValue(sprintf('[protectedSource][%s]', $key), $value, false);
274
            }
275
        }
276
277
        $escapedValueKeys = array(
278
            'stylesheetParser_skipSelectors',
279
            'stylesheetParser_validSelectors',
280
        );
281
282
        foreach ($escapedValueKeys as $escapedValueKey) {
283
            if (isset($config[$escapedValueKey])) {
284
                $this->jsonBuilder->setValue(sprintf('[%s]', $escapedValueKey), $config[$escapedValueKey], false);
285
            }
286
        }
287
    }
288
289
    /**
290
     * Fixes the config constants.
291
     *
292
     * @param string $json The json config.
293
     *
294
     * @return string The fixed config.
295
     */
296
    private function fixConfigConstants($json)
297
    {
298
        return preg_replace('/"(CKEDITOR\.[A-Z_]+)"/', '$1', $json);
299
    }
300
301
    /**
302
     * Fixes a path.
303
     *
304
     * @param string $path The path.
305
     *
306
     * @return string The fixed path.
307
     */
308
    private function fixPath($path)
309
    {
310
        if (($position = strpos($path, '?')) !== false) {
311
            return substr($path, 0, $position);
312
        }
313
314
        return $path;
315
    }
316
317
    /**
318
     * Fixes an url.
319
     *
320
     * @param string $url The url.
321
     *
322
     * @return string The fixed url.
323
     */
324
    private function fixUrl($url)
325
    {
326
        $assetsHelper = $this->getAssetsHelper();
327
328
        if ($assetsHelper !== null) {
329
            $url = $assetsHelper->getUrl($url);
330
        }
331
332
        return $url;
333
    }
334
335
    /**
336
     * Gets the assets helper.
337
     *
338
     * @return \Symfony\Component\Asset\Packages|\Symfony\Component\Templating\Helper\CoreAssetsHelper|null The assets helper.
339
     */
340
    private function getAssetsHelper()
341
    {
342
        return $this->container->get('assets.packages', ContainerInterface::NULL_ON_INVALID_REFERENCE);
343
    }
344
345
    /**
346
     * Gets the router.
347
     *
348
     * @return \Symfony\Component\Routing\RouterInterface The router.
349
     */
350
    private function getRouter()
351
    {
352
        return $this->container->get('router');
353
    }
354
}
355