We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like PHP_Typography 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 PHP_Typography, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 45 | class PHP_Typography { |
||
| 46 | |||
| 47 | /** |
||
| 48 | * A DOM-based HTML5 parser. |
||
| 49 | * |
||
| 50 | * @var \Masterminds\HTML5 |
||
| 51 | */ |
||
| 52 | private $html5_parser; |
||
| 53 | |||
| 54 | /** |
||
| 55 | * The hyphenator cache. |
||
| 56 | * |
||
| 57 | * @var Hyphenator\Cache |
||
| 58 | */ |
||
| 59 | protected $hyphenator_cache; |
||
| 60 | |||
| 61 | /** |
||
| 62 | * The node fixes registry. |
||
| 63 | * |
||
| 64 | * @var Registry; |
||
| 65 | */ |
||
| 66 | private $registry; |
||
| 67 | |||
| 68 | /** |
||
| 69 | * Whether the Hyphenator\Cache of the $registry needs to be updated. |
||
| 70 | * |
||
| 71 | * @var bool |
||
| 72 | */ |
||
| 73 | private $update_registry_cache; |
||
| 74 | |||
| 75 | /** |
||
| 76 | * Sets up a new PHP_Typography object. |
||
| 77 | * |
||
| 78 | * @param Registry|null $registry Optional. A fix registry instance. Default null, |
||
| 79 | * meaning the default fixes are used. |
||
| 80 | */ |
||
| 81 | public function __construct( Registry $registry = null ) { |
||
| 85 | |||
| 86 | /** |
||
| 87 | * Modifies $html according to the defined settings. |
||
| 88 | * |
||
| 89 | * @param string $html A HTML fragment. |
||
| 90 | * @param Settings $settings A settings object. |
||
| 91 | * @param bool $is_title Optional. If the HTML fragment is a title. Default false. |
||
| 92 | * |
||
| 93 | * @return string The processed $html. |
||
| 94 | */ |
||
| 95 | public function process( $html, Settings $settings, $is_title = false ) { |
||
| 98 | |||
| 99 | /** |
||
| 100 | * Modifies $html according to the defined settings, in a way that is appropriate for RSS feeds |
||
| 101 | * (i.e. excluding processes that may not display well with limited character set intelligence). |
||
| 102 | * |
||
| 103 | * @param string $html A HTML fragment. |
||
| 104 | * @param Settings $settings A settings object. |
||
| 105 | * @param bool $is_title Optional. If the HTML fragment is a title. Default false. |
||
| 106 | * |
||
| 107 | * @return string The processed $html. |
||
| 108 | */ |
||
| 109 | public function process_feed( $html, Settings $settings, $is_title = false ) { |
||
| 112 | |||
| 113 | /** |
||
| 114 | * Applies specific fixes to all textnodes of the HTML fragment. |
||
| 115 | * |
||
| 116 | * @param string $html A HTML fragment. |
||
| 117 | * @param callable $fixer A callback that applies typography fixes to a single textnode. |
||
| 118 | * @param Settings $settings A settings object. |
||
| 119 | * @param bool $is_title Optional. If the HTML fragment is a title. Default false. |
||
| 120 | * |
||
| 121 | * @return string The processed $html. |
||
| 122 | */ |
||
| 123 | public function process_textnodes( $html, callable $fixer, Settings $settings, $is_title = false ) { |
||
| 168 | |||
| 169 | /** |
||
| 170 | * Determines whether two object arrays intersect. The second array is expected |
||
| 171 | * to use the spl_object_hash for its keys. |
||
| 172 | * |
||
| 173 | * @param array $array1 The keys are ignored. |
||
| 174 | * @param array $array2 This array has to be in the form ( $spl_object_hash => $object ). |
||
| 175 | * |
||
| 176 | * @return boolean |
||
| 177 | */ |
||
| 178 | protected static function arrays_intersect( array $array1, array $array2 ) { |
||
| 187 | |||
| 188 | /** |
||
| 189 | * Applies standard typography fixes to a textnode. |
||
| 190 | * |
||
| 191 | * @param \DOMText $textnode The node to process. |
||
| 192 | * @param Settings $settings The settings to apply. |
||
| 193 | * @param bool $is_title Optional. Default false. |
||
| 194 | */ |
||
| 195 | View Code Duplication | protected function apply_fixes_to_html_node( \DOMText $textnode, Settings $settings, $is_title = false ) { |
|
| 202 | |||
| 203 | /** |
||
| 204 | * Applies typography fixes specific to RSS feeds to a textnode. |
||
| 205 | * |
||
| 206 | * @param \DOMText $textnode The node to process. |
||
| 207 | * @param Settings $settings The settings to apply. |
||
| 208 | * @param bool $is_title Optional. Default false. |
||
| 209 | */ |
||
| 210 | View Code Duplication | protected function apply_fixes_to_feed_node( \DOMText $textnode, Settings $settings, $is_title = false ) { |
|
| 219 | |||
| 220 | /** |
||
| 221 | * Parse HTML5 fragment while ignoring certain warnings for invalid HTML code (e.g. duplicate IDs). |
||
| 222 | * |
||
| 223 | * @param \Masterminds\HTML5 $parser An intialized parser object. |
||
| 224 | * @param string $html The HTML fragment to parse (not a complete document). |
||
| 225 | * @param Settings $settings The settings to apply. |
||
| 226 | * |
||
| 227 | * @return \DOMDocument|null The encoding has already been set to UTF-8. Returns null if there were parsing errors. |
||
| 228 | */ |
||
| 229 | public function parse_html( \Masterminds\HTML5 $parser, $html, Settings $settings ) { |
||
| 256 | |||
| 257 | /** |
||
| 258 | * Silently handle certain HTML parsing errors. |
||
| 259 | * |
||
| 260 | * @param int $errno Error number. |
||
| 261 | * @param string $errstr Error message. |
||
| 262 | * @param string $errfile The file in which the error occurred. |
||
| 263 | * @param int $errline The line in which the error occurred. |
||
| 264 | * @param array $errcontext Calling context. |
||
| 265 | * |
||
| 266 | * @return boolean Returns true if the error was handled, false otherwise. |
||
| 267 | */ |
||
| 268 | public function handle_parsing_errors( $errno, $errstr, $errfile, $errline, array $errcontext ) { |
||
| 276 | |||
| 277 | /** |
||
| 278 | * Retrieves an array of nodes that should be skipped during processing. |
||
| 279 | * |
||
| 280 | * @param \DOMXPath $xpath A valid XPath instance for the DOM to be queried. |
||
| 281 | * @param \DOMNode $initial_node The starting node of the XPath query. |
||
| 282 | * @param Settings $settings The settings to apply. |
||
| 283 | * |
||
| 284 | * @return \DOMNode[] An array of \DOMNode (can be empty). |
||
| 285 | */ |
||
| 286 | public function query_tags_to_ignore( \DOMXPath $xpath, \DOMNode $initial_node, Settings $settings ) { |
||
| 310 | |||
| 311 | /** |
||
| 312 | * Replaces the given node with HTML content. Uses the HTML5 parser. |
||
| 313 | * |
||
| 314 | * @param \DOMNode $node The node to replace. |
||
| 315 | * @param string $content The HTML fragment used to replace the node. |
||
| 316 | * |
||
| 317 | * @return \DOMNode|array An array of \DOMNode containing the new nodes or the old \DOMNode if the replacement failed. |
||
| 318 | */ |
||
| 319 | public function replace_node_with_html( \DOMNode $node, $content ) { |
||
| 349 | |||
| 350 | /** |
||
| 351 | * Retrieves the fix registry. |
||
| 352 | * |
||
| 353 | * @return Registry |
||
| 354 | */ |
||
| 355 | public function get_registry() { |
||
| 365 | |||
| 366 | /** |
||
| 367 | * Retrieves the HTML5 parser instance. |
||
| 368 | * |
||
| 369 | * @return \Masterminds\HTML5 |
||
| 370 | */ |
||
| 371 | public function get_html5_parser() { |
||
| 381 | |||
| 382 | /** |
||
| 383 | * Retrieves the hyphenator cache. |
||
| 384 | * |
||
| 385 | * @return Hyphenator\Cache |
||
| 386 | */ |
||
| 387 | public function get_hyphenator_cache() { |
||
| 394 | |||
| 395 | /** |
||
| 396 | * Injects an existing Hyphenator\Cache (to facilitate persistent language caching). |
||
| 397 | * |
||
| 398 | * @param Hyphenator\Cache $cache A hyphenator cache instance. |
||
| 399 | */ |
||
| 400 | public function set_hyphenator_cache( Hyphenator\Cache $cache ) { |
||
| 408 | |||
| 409 | /** |
||
| 410 | * Retrieves the list of valid language plugins in the given directory. |
||
| 411 | * |
||
| 412 | * @param string $path The path in which to look for language plugin files. |
||
| 413 | * |
||
| 414 | * @return string[] An array in the form ( $language_code => $language_name ). |
||
| 415 | */ |
||
| 416 | private static function get_language_plugin_list( $path ) { |
||
| 445 | |||
| 446 | /** |
||
| 447 | * Retrieves the list of valid hyphenation languages. |
||
| 448 | * |
||
| 449 | * Note that this method reads all the language files on disc, so you should |
||
| 450 | * cache the results if possible. |
||
| 451 | * |
||
| 452 | * @return string[] An array in the form of ( LANG_CODE => LANGUAGE ). |
||
| 453 | */ |
||
| 454 | public static function get_hyphenation_languages() { |
||
| 457 | |||
| 458 | /** |
||
| 459 | * Retrieves the list of valid diacritic replacement languages. |
||
| 460 | * |
||
| 461 | * Note that this method reads all the language files on disc, so you should |
||
| 462 | * cache the results if possible. |
||
| 463 | * |
||
| 464 | * @return string[] An array in the form of ( LANG_CODE => LANGUAGE ). |
||
| 465 | */ |
||
| 466 | public static function get_diacritic_languages() { |
||
| 469 | } |
||
| 470 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.