Complex classes like MonitorConfigurator 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 MonitorConfigurator, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 14 | class MonitorConfigurator |
||
| 15 | { |
||
| 16 | use MonitorTrait; |
||
| 17 | |||
| 18 | /** |
||
| 19 | * @var string |
||
| 20 | */ |
||
| 21 | protected $base_directory = ''; |
||
| 22 | |||
| 23 | /** |
||
| 24 | * @var int |
||
| 25 | */ |
||
| 26 | protected $level = 1; |
||
| 27 | |||
| 28 | /** |
||
| 29 | * The nesting level to work on after analyzing the patterns in $files_to_monitor |
||
| 30 | * |
||
| 31 | * @internal |
||
| 32 | * @var int |
||
| 33 | */ |
||
| 34 | protected $effective_level = 0; |
||
| 35 | |||
| 36 | /** |
||
| 37 | * @var bool |
||
| 38 | */ |
||
| 39 | protected $monitor_created_only = false; |
||
| 40 | |||
| 41 | /** |
||
| 42 | * @var string[] |
||
| 43 | */ |
||
| 44 | protected $files_to_monitor = []; |
||
| 45 | |||
| 46 | /** |
||
| 47 | * @var bool |
||
| 48 | */ |
||
| 49 | protected $auto_create_not_found_monitor = false; |
||
| 50 | |||
| 51 | /** |
||
| 52 | * Array where keys are the patterns set by $this->setFilesToMonitor() after applying |
||
| 53 | * fixes to them by $this->fixPathsSlashes() (remove duplicated slashes and so) |
||
| 54 | * The value for each is an array with the following keys: |
||
| 55 | * 'end_with_slash' : Is the pattern ends with a slash? then it is considered |
||
| 56 | * a pattern for a directory which needs to be monitored |
||
| 57 | * 'is_not_recursive' : Is this pattern represents a specific level matcher (not recursive) |
||
| 58 | * this happens when the pattern has at least one slash character in |
||
| 59 | * the middle and in this case it will not be considered as a recursive |
||
| 60 | * pattern. |
||
| 61 | * 'path_level' : The path level of the pattern (count of slashes excluding the leading |
||
| 62 | * and the trailing, this should be 0 for recursive patterns and greater |
||
| 63 | * than 0 for non recursive. |
||
| 64 | * @internal |
||
| 65 | * @var [][] |
||
| 66 | */ |
||
| 67 | protected $analyzed_files_to_monitor = []; |
||
| 68 | |||
| 69 | /** |
||
| 70 | * Tell if the patterns passed to $this->setFilesToMonitor() has a pattern |
||
| 71 | * with empty string which indicates the caller wants to monitor the |
||
| 72 | * base directory for changes. |
||
| 73 | * |
||
| 74 | * @internal |
||
| 75 | * @var bool |
||
| 76 | */ |
||
| 77 | protected $files_to_monitor_has_empty_string = false; |
||
| 78 | |||
| 79 | /** |
||
| 80 | * This is for speed optimization, it indicates what all the patterns in |
||
| 81 | * $this->analyzed_files_to_monitor has the key: 'is_not_recursive' as true. |
||
| 82 | * |
||
| 83 | * @internal |
||
| 84 | * @var bool |
||
| 85 | */ |
||
| 86 | protected $is_all_files_to_monitor_not_recursive = false; |
||
| 87 | |||
| 88 | /** |
||
| 89 | * an array of dirname() calls to each pattern in the keys of: |
||
| 90 | * $this->analyzed_files_to_monitor -- recursively until we get |
||
| 91 | * the empty string. |
||
| 92 | * |
||
| 93 | * This is used for performance optimization. |
||
| 94 | * |
||
| 95 | * All the entries are without leading slash. |
||
| 96 | * |
||
| 97 | * This array does not contain the empty string, and do not have duplicates. |
||
| 98 | * |
||
| 99 | * @internal |
||
| 100 | * @var array |
||
| 101 | */ |
||
| 102 | protected $dirnames_from_files_to_monitor = []; |
||
| 103 | |||
| 104 | /** |
||
| 105 | * The base directory string applied to preg_quote($base_dir, '@') |
||
| 106 | * |
||
| 107 | * @internal |
||
| 108 | * @var string |
||
| 109 | */ |
||
| 110 | protected $preg_quoted_base_directory = ''; |
||
| 111 | |||
| 112 | /** |
||
| 113 | * Whether to fire the modified events on directories, default to false. |
||
| 114 | * |
||
| 115 | * @var bool |
||
| 116 | */ |
||
| 117 | protected $fire_modified_on_directories = false; |
||
| 118 | |||
| 119 | |||
| 120 | /** |
||
| 121 | * @return MonitorConfigurator |
||
| 122 | */ |
||
| 123 | public static function factory() |
||
| 127 | |||
| 128 | /** |
||
| 129 | * Tell if path (directory or file) is to be monitored by this config. |
||
| 130 | * |
||
| 131 | * Directories ends with slash. |
||
| 132 | * |
||
| 133 | * @param string $path |
||
| 134 | * |
||
| 135 | * @return bool |
||
| 136 | */ |
||
| 137 | public function isPathMatchMonitor(string $path) |
||
| 176 | |||
| 177 | /** |
||
| 178 | * Match string against all patterns saved in $this->getFilesToMonitor() |
||
| 179 | * array of patterns (or names) |
||
| 180 | * |
||
| 181 | * @param string $relative_path |
||
| 182 | * |
||
| 183 | * @return bool |
||
| 184 | */ |
||
| 185 | protected function isStringMatch($relative_path) |
||
| 219 | |||
| 220 | /** |
||
| 221 | * Tell if the passed directory may contain items that matches the patterns, |
||
| 222 | * it may contain them if its nest level is less than the configured level |
||
| 223 | * |
||
| 224 | * @param string $directory |
||
| 225 | * |
||
| 226 | * @return bool |
||
| 227 | */ |
||
| 228 | public function mayDirectoryContainMonitoredItems($directory) |
||
| 280 | |||
| 281 | /** |
||
| 282 | * Get an array of dirnames called on $path recursively. |
||
| 283 | * |
||
| 284 | * @param string $path |
||
| 285 | * |
||
| 286 | * @return array |
||
| 287 | */ |
||
| 288 | protected function getDirnamesWithoutEmpty(string $path): array |
||
| 298 | |||
| 299 | //////////////////////////////////// |
||
| 300 | // Getters and Setters come next // |
||
| 301 | //////////////////////////////////// |
||
| 302 | |||
| 303 | /** |
||
| 304 | * Base dir is always without trailing slash unless it is the root '/' directory. |
||
| 305 | * |
||
| 306 | * @return string |
||
| 307 | */ |
||
| 308 | public function getBaseDirectory(): string |
||
| 312 | |||
| 313 | /** |
||
| 314 | * Return Base dir with trailing slash. |
||
| 315 | * |
||
| 316 | * @return string |
||
| 317 | */ |
||
| 318 | public function getBaseDirectoryWithTrailingSlash(): string |
||
| 322 | |||
| 323 | /** |
||
| 324 | * Set Base dir, trailing slash is removed. |
||
| 325 | * |
||
| 326 | * The directory may exist or not, if it is a relative path, the current directory |
||
| 327 | * is used to construct an absolute path. |
||
| 328 | * |
||
| 329 | * If the directory exists and is a file, an Exception is thrown. |
||
| 330 | * |
||
| 331 | * @param string $base_directory |
||
| 332 | * |
||
| 333 | * @return MonitorConfigurator |
||
| 334 | * |
||
| 335 | * @throws \Exception |
||
| 336 | */ |
||
| 337 | public function setBaseDirectory(string $base_directory): MonitorConfigurator |
||
| 352 | |||
| 353 | /** |
||
| 354 | * @return int |
||
| 355 | */ |
||
| 356 | public function getLevel(): int |
||
| 360 | |||
| 361 | /** |
||
| 362 | * Report the effective level we operate at according to the analysis of the patterns. |
||
| 363 | * |
||
| 364 | * @return int |
||
| 365 | */ |
||
| 366 | public function getEffectiveLevel(): int |
||
| 370 | |||
| 371 | /** |
||
| 372 | * Set the deep level to look for files, 0 means all recursive, 1 means |
||
| 373 | * only directly inside Base-Dir, 2 means directly inside Base-Dir and |
||
| 374 | * directly inside any direct child-directories in it, and so on. |
||
| 375 | * |
||
| 376 | * @param int $level |
||
| 377 | * |
||
| 378 | * @return MonitorConfigurator |
||
| 379 | */ |
||
| 380 | public function setLevel(int $level): MonitorConfigurator |
||
| 391 | |||
| 392 | /** |
||
| 393 | * @return string[] |
||
| 394 | */ |
||
| 395 | public function getFilesToMonitor(): array |
||
| 399 | |||
| 400 | /** |
||
| 401 | * Set an array of Shell-Pattern for files or directories to monitor, |
||
| 402 | * directory pattern must end with trailing slash. |
||
| 403 | * |
||
| 404 | * These patterns are meant to be relative to the base directory set by |
||
| 405 | * $this->setBaseDirectory(), but leading slash has special meaning: it |
||
| 406 | * will cause the pattern not to be recursive. |
||
| 407 | * Leading slash in any pattern item will be removed internally and will |
||
| 408 | * set a flag that this pattern will has a directory level set. |
||
| 409 | * |
||
| 410 | * To match directories inside base directory, you can pass the path or |
||
| 411 | * path pattern as an item in the array, like: |
||
| 412 | * [ |
||
| 413 | * 'dir1/*.xml', |
||
| 414 | * '* /dir2/*.py', # space used because comment ending matched |
||
| 415 | * ] |
||
| 416 | * The previous two patterns are not recursive because they have a slash |
||
| 417 | * inside the pattern and they are equal to the following: |
||
| 418 | * [ |
||
| 419 | * '/dir1/*.xml', |
||
| 420 | * '/* /dir2/*.py', # space used because comment ending matched |
||
| 421 | * ] |
||
| 422 | * |
||
| 423 | * |
||
| 424 | * Example: |
||
| 425 | * ['*.yaml', 'log/'] |
||
| 426 | * This will monitor any file with extension 'yaml' inside Base-Dir and |
||
| 427 | * recursively up to level set by setLevel() for changes (create, modify, |
||
| 428 | * delete) and will do the same for any directory who's basename is 'log' |
||
| 429 | * |
||
| 430 | * Passing something like: |
||
| 431 | * |
||
| 432 | * ['*'.'/dir2/*.py'] will not search recursively, but will be limited to level 3 |
||
| 433 | * inside base directory no more and no less, and it can match if the level set |
||
| 434 | * is greater or equal to 3. |
||
| 435 | * |
||
| 436 | * Level is checked for all patterns those which has '/' (slash) or not. |
||
| 437 | * |
||
| 438 | * |
||
| 439 | * @param string[] $files_to_monitor |
||
| 440 | * |
||
| 441 | * @return MonitorConfigurator |
||
| 442 | */ |
||
| 443 | public function setFilesToMonitor(array $files_to_monitor): MonitorConfigurator |
||
| 546 | |||
| 547 | /** |
||
| 548 | * @return bool |
||
| 549 | */ |
||
| 550 | public function isFireModifiedOnDirectories(): bool |
||
| 554 | |||
| 555 | /** |
||
| 556 | * Set to true to also fire the modified event on directories. |
||
| 557 | * |
||
| 558 | * @param bool $fire_modified_on_directories |
||
| 559 | * |
||
| 560 | * @return MonitorConfigurator |
||
| 561 | */ |
||
| 562 | public function setFireModifiedOnDirectories(bool $fire_modified_on_directories): MonitorConfigurator |
||
| 567 | |||
| 568 | /** |
||
| 569 | * Is this monitor configuration to monitor the CREATED event only. |
||
| 570 | * |
||
| 571 | * @return bool |
||
| 572 | */ |
||
| 573 | public function isMonitorCreatedOnly(): bool |
||
| 577 | |||
| 578 | /** |
||
| 579 | * Set a config to monitor the created event only, no modified and no delete. |
||
| 580 | * |
||
| 581 | * @param bool $monitor_created_only |
||
| 582 | * |
||
| 583 | * @return MonitorConfigurator |
||
| 584 | */ |
||
| 585 | public function setMonitorCreatedOnly(bool $monitor_created_only): MonitorConfigurator |
||
| 590 | |||
| 591 | /** |
||
| 592 | * This instructs the monitor to create a child monitor when the base directory is not found. |
||
| 593 | * |
||
| 594 | * @return bool |
||
| 595 | */ |
||
| 596 | public function isAutoCreateNotFoundMonitor(): bool |
||
| 600 | |||
| 601 | /** |
||
| 602 | * Set to true to create another Monitor object which waits for the Base Directory to be created in case the |
||
| 603 | * Base Directory does not exists. |
||
| 604 | * |
||
| 605 | * @see \Dimsh\React\Filesystem\Monitor\Monitor::__construct() |
||
| 606 | * |
||
| 607 | * @param bool $auto_create_not_found_monitor |
||
| 608 | * |
||
| 609 | * @return MonitorConfigurator |
||
| 610 | */ |
||
| 611 | public function setAutoCreateNotFoundMonitor(bool $auto_create_not_found_monitor): MonitorConfigurator |
||
| 616 | } |
||
| 617 |