CKEditorRenderer   B
last analyzed

Complexity

Total Complexity 52

Size/Duplication

Total Lines 332
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 52
lcom 1
cbo 4
dl 0
loc 332
ccs 165
cts 165
cp 1
rs 7.9487
c 0
b 0
f 0

20 Methods

Rating   Name   Duplication   Size   Complexity  
A renderBasePath() 0 4 1
A renderJsPath() 0 4 1
A __construct() 0 4 1
C renderWidget() 0 32 8
A renderPlugin() 0 9 1
A renderStylesSet() 0 10 1
B renderTemplate() 0 26 6
A fixConfigLanguage() 0 12 4
A fixConfigContentsCss() 0 13 3
B fixConfigFilebrowsers() 0 38 6
B fixConfigEscapedValues() 0 19 5
A fixConfigConstants() 0 4 1
A renderDestroy() 0 10 1
A fixPath() 0 16 4
A getJsonBuilder() 0 4 1
A getLanguage() 0 10 3
A getRequest() 0 4 1
A getTemplating() 0 6 2
A getAssets() 0 4 1
A getRouter() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like CKEditorRenderer often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use CKEditorRenderer, and based on these observations, apply Extract Interface, too.

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