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