Complex classes like AbstractBaseReporter 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 AbstractBaseReporter, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 18 | abstract class AbstractBaseReporter implements ReporterInterface |
||
| 19 | { |
||
| 20 | use HasEventEmitterTrait; |
||
| 21 | |||
| 22 | /** |
||
| 23 | * @var \Peridot\Configuration |
||
| 24 | */ |
||
| 25 | protected $configuration; |
||
| 26 | |||
| 27 | /** |
||
| 28 | * @var \Symfony\Component\Console\Output\OutputInterface |
||
| 29 | */ |
||
| 30 | protected $output; |
||
| 31 | |||
| 32 | /** |
||
| 33 | * @var array |
||
| 34 | */ |
||
| 35 | protected $errors = []; |
||
| 36 | |||
| 37 | /** |
||
| 38 | * @var int |
||
| 39 | */ |
||
| 40 | protected $passing = 0; |
||
| 41 | |||
| 42 | /** |
||
| 43 | * @var int |
||
| 44 | */ |
||
| 45 | protected $pending = 0; |
||
| 46 | |||
| 47 | /** |
||
| 48 | * @var double|integer |
||
| 49 | */ |
||
| 50 | protected $time; |
||
| 51 | |||
| 52 | /** |
||
| 53 | * Maps color names to left and right color sequences. |
||
| 54 | * |
||
| 55 | * @var array |
||
| 56 | */ |
||
| 57 | protected $colors = array( |
||
| 58 | 'white' => ['left' => "\033[37m", 'right' => "\033[39m"], |
||
| 59 | 'success' => ['left' => "\033[32m", 'right' => "\033[39m"], |
||
| 60 | 'error' => ['left' => "\033[31m", 'right' => "\033[39m"], |
||
| 61 | 'muted' => ['left' => "\033[90m", 'right' => "\033[0m"], |
||
| 62 | 'pending' => ['left' => "\033[36m", 'right' => "\033[39m"], |
||
| 63 | ); |
||
| 64 | |||
| 65 | /** |
||
| 66 | * Maps symbol names to symbols |
||
| 67 | * |
||
| 68 | * @var array |
||
| 69 | */ |
||
| 70 | protected $symbols = array( |
||
| 71 | 'check' => '✓' |
||
| 72 | ); |
||
| 73 | |||
| 74 | /** |
||
| 75 | * @param Configuration $configuration |
||
| 76 | * @param OutputInterface $output |
||
| 77 | * @param EventEmitterInterface $eventEmitter |
||
| 78 | */ |
||
| 79 | public function __construct( |
||
| 80 | Configuration $configuration, |
||
| 81 | OutputInterface $output, |
||
| 82 | EventEmitterInterface $eventEmitter |
||
| 83 | ) { |
||
| 84 | $this->configuration = $configuration; |
||
| 85 | $this->output = $output; |
||
| 86 | $this->eventEmitter = $eventEmitter; |
||
| 87 | |||
| 88 | $this->registerSymbols(); |
||
| 89 | |||
| 90 | $this->registerEvents(); |
||
| 91 | |||
| 92 | $this->init(); |
||
| 93 | } |
||
| 94 | |||
| 95 | /** |
||
| 96 | * Given a color name, colorize the provided text in that |
||
| 97 | * color |
||
| 98 | * |
||
| 99 | * @param $key |
||
| 100 | * @param $text |
||
| 101 | * @return string |
||
| 102 | */ |
||
| 103 | public function color($key, $text) |
||
| 104 | { |
||
| 105 | $colorsEnabled = $this->configuration->areColorsEnabled() && $this->hasColorSupport(); |
||
| 106 | $colorsEnabledExplicit = $this->configuration->areColorsEnabledExplicit(); |
||
| 107 | |||
| 108 | if (!$colorsEnabled && !$colorsEnabledExplicit) { |
||
| 109 | return $text; |
||
| 110 | } |
||
| 111 | |||
| 112 | $color = $this->colors[$key]; |
||
| 113 | |||
| 114 | return sprintf("%s%s%s", $color['left'], $text, $color['right']); |
||
| 115 | } |
||
| 116 | |||
| 117 | /** |
||
| 118 | * Fetch a symbol by name |
||
| 119 | * |
||
| 120 | * @param $name |
||
| 121 | * @return string |
||
| 122 | */ |
||
| 123 | public function symbol($name) |
||
| 127 | |||
| 128 | /** |
||
| 129 | * Return the OutputInterface associated with the Reporter |
||
| 130 | * |
||
| 131 | * @return \Symfony\Component\Console\Output\OutputInterface |
||
| 132 | */ |
||
| 133 | public function getOutput() |
||
| 137 | |||
| 138 | /** |
||
| 139 | * Return the Configuration associated with the Reporter |
||
| 140 | * |
||
| 141 | * @return \Peridot\Configuration |
||
| 142 | */ |
||
| 143 | public function getConfiguration() |
||
| 147 | |||
| 148 | /** |
||
| 149 | * Set the run time to report. |
||
| 150 | * |
||
| 151 | * @param float $time |
||
| 152 | */ |
||
| 153 | public function setTime($time) |
||
| 154 | { |
||
| 155 | $this->time = $time; |
||
| 156 | } |
||
| 157 | |||
| 158 | /** |
||
| 159 | * Get the run time to report. |
||
| 160 | * |
||
| 161 | * @return float |
||
| 162 | */ |
||
| 163 | public function getTime() |
||
| 167 | |||
| 168 | /** |
||
| 169 | * Output result footer |
||
| 170 | */ |
||
| 171 | public function footer() |
||
| 188 | |||
| 189 | /** |
||
| 190 | * Output a test failure. |
||
| 191 | * |
||
| 192 | * @param int $errorNumber |
||
| 193 | * @param TestInterface $test |
||
| 194 | * @param $exception - an exception like interface with ->getMessage(), ->getTraceAsString() |
||
| 195 | */ |
||
| 196 | protected function outputError($errorNumber, TestInterface $test, $exception) |
||
| 208 | |||
| 209 | /** |
||
| 210 | * Output a stack trace. |
||
| 211 | * |
||
| 212 | * @param array $trace |
||
| 213 | */ |
||
| 214 | protected function outputTrace(array $trace) |
||
| 237 | |||
| 238 | /** |
||
| 239 | * Determine if colorized output is supported by the reporters output. |
||
| 240 | * Taken from Symfony's console output with some slight modifications |
||
| 241 | * to use the reporter's output stream |
||
| 242 | * |
||
| 243 | * @return bool |
||
| 244 | */ |
||
| 245 | protected function hasColorSupport() |
||
| 253 | |||
| 254 | /** |
||
| 255 | * Register reporter symbols, additionally checking OS compatibility. |
||
| 256 | */ |
||
| 257 | protected function registerSymbols() |
||
| 264 | |||
| 265 | /** |
||
| 266 | * Return true if reporter is being used on windows |
||
| 267 | * |
||
| 268 | * @return bool |
||
| 269 | */ |
||
| 270 | protected function isOnWindows() |
||
| 274 | |||
| 275 | /** |
||
| 276 | * Register events tracking state relevant to all reporters. |
||
| 277 | */ |
||
| 278 | private function registerEvents() |
||
| 294 | |||
| 295 | /** |
||
| 296 | * Determine if the terminal has ansicon support |
||
| 297 | * |
||
| 298 | * @return bool |
||
| 299 | */ |
||
| 300 | private function hasAnsiSupport() |
||
| 304 | |||
| 305 | /** |
||
| 306 | * Determine if reporter is reporting to a tty terminal. |
||
| 307 | * |
||
| 308 | * @return bool |
||
| 309 | */ |
||
| 310 | private function hasTty() |
||
| 322 | |||
| 323 | /** |
||
| 324 | * See if stream output is a tty terminal. |
||
| 325 | * |
||
| 326 | * @return bool |
||
| 327 | */ |
||
| 328 | private function isTtyTerminal(StreamOutput $output) |
||
| 336 | |||
| 337 | private function renderTrace($exception) |
||
| 366 | |||
| 367 | |||
| 368 | private function isPeridotTraceEntry($entry) |
||
| 378 | |||
| 379 | /** |
||
| 380 | * Initialize reporter. Setup and listen for events |
||
| 381 | * |
||
| 382 | * @return void |
||
| 383 | */ |
||
| 384 | abstract public function init(); |
||
| 385 | } |
||
| 386 |