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 EEH_File 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 EEH_File, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
25 | class EEH_File extends EEH_Base implements EEHI_File |
||
26 | { |
||
27 | |||
28 | /** |
||
29 | * @var string $_credentials_form |
||
30 | */ |
||
31 | private static $_credentials_form; |
||
32 | |||
33 | /** |
||
34 | * @var WP_Filesystem_Base $_wp_filesystem |
||
35 | */ |
||
36 | protected static $_wp_filesystem; |
||
37 | |||
38 | |||
39 | /** |
||
40 | * @param string $filepath the filepath we want to work in. If its in the |
||
41 | * wp uploads directory, we'll want to just use the filesystem directly. |
||
42 | * If not provided, we have to assume its not in the uploads directory |
||
43 | * @return WP_Filesystem_Base |
||
44 | */ |
||
45 | private static function _get_wp_filesystem($filepath = ''): WP_Filesystem_Base |
||
57 | |||
58 | |||
59 | /** |
||
60 | * @return WP_Filesystem_Base |
||
61 | */ |
||
62 | private static function loadAlternateWpFileSystem(): WP_Filesystem_Base |
||
118 | |||
119 | |||
120 | /** |
||
121 | * @return WP_Filesystem_Base |
||
122 | */ |
||
123 | private static function loadWpFileSystem(): WP_Filesystem_Base |
||
197 | |||
198 | |||
199 | /** |
||
200 | * display_request_filesystem_credentials_form |
||
201 | */ |
||
202 | public static function display_request_filesystem_credentials_form() |
||
208 | |||
209 | |||
210 | /** |
||
211 | * verify_filepath_and_permissions |
||
212 | * checks that a file is readable and has sufficient file permissions set to access |
||
213 | * |
||
214 | * @access public |
||
215 | * @param string $full_file_path - full server path to the folder or file |
||
216 | * @param string $file_name - name of file if checking a file |
||
217 | * @param string $file_ext - file extension (ie: "php") if checking a file |
||
218 | * @param string $type_of_file - general type of file (ie: "module"), this is only used to improve error messages |
||
219 | * @return bool |
||
220 | */ |
||
221 | public static function verify_filepath_and_permissions( |
||
257 | |||
258 | |||
259 | /** |
||
260 | * _permissions_error_for_unreadable_filepath - attempts to determine why permissions are set incorrectly for a |
||
261 | * file or folder |
||
262 | * |
||
263 | * @access private |
||
264 | * @param string $full_file_path - full server path to the folder or file |
||
265 | * @param string $type_of_file - general type of file (ie: "module"), this is only used to improve error messages |
||
266 | * @return string |
||
267 | */ |
||
268 | private static function _permissions_error_for_unreadable_filepath( |
||
299 | |||
300 | |||
301 | /** |
||
302 | * ensure_folder_exists_and_is_writable |
||
303 | * ensures that a folder exists and is writable, will attempt to create folder if it does not exist |
||
304 | * Also ensures all the parent folders exist, and if not tries to create them. |
||
305 | * Also, if this function creates the folder, adds a .htaccess file and index.html file |
||
306 | * |
||
307 | * @param string $folder |
||
308 | * @return bool false if folder isn't writable; true if it exists and is writeable, |
||
309 | */ |
||
310 | public static function ensure_folder_exists_and_is_writable(string $folder = ''): bool |
||
344 | |||
345 | |||
346 | /** |
||
347 | * verify_is_writable - checks if a file or folder is writable |
||
348 | * |
||
349 | * @param string $full_path - full server path to file or folder |
||
350 | * @param string $file_or_folder - whether checking a file or folder |
||
351 | * @return bool |
||
352 | */ |
||
353 | public static function verify_is_writable(string $full_path = '', string $file_or_folder = 'folder'): bool |
||
370 | |||
371 | |||
372 | /** |
||
373 | * ensure_file_exists_and_is_writable |
||
374 | * ensures that a file exists and is writable, will attempt to create file if it does not exist. |
||
375 | * Also ensures all the parent folders exist, and if not tries to create them. |
||
376 | * |
||
377 | * @param string $full_file_path |
||
378 | * @return bool |
||
379 | */ |
||
380 | public static function ensure_file_exists_and_is_writable(string $full_file_path = ''): bool |
||
404 | |||
405 | |||
406 | /** |
||
407 | * Gets the parent folder. If provided with file, gets the folder that contains it. |
||
408 | * If provided a folder, gets its parent folder. |
||
409 | * |
||
410 | * @param string $file_or_folder_path |
||
411 | * @return string parent folder, ENDING with a directory separator |
||
412 | */ |
||
413 | public static function get_parent_folder(string $file_or_folder_path): string |
||
423 | |||
424 | |||
425 | /** |
||
426 | * get_file_contents |
||
427 | * |
||
428 | * @param string $full_file_path |
||
429 | * @return string |
||
430 | */ |
||
431 | public static function get_file_contents(string $full_file_path = ''): string |
||
446 | |||
447 | |||
448 | /** |
||
449 | * write_file |
||
450 | * |
||
451 | * @param string $full_file_path |
||
452 | * @param string $file_contents - the content to be written to the file |
||
453 | * @param string $file_type |
||
454 | * @return bool |
||
455 | */ |
||
456 | public static function write_to_file( |
||
499 | |||
500 | |||
501 | /** |
||
502 | * Wrapper for WP_Filesystem_Base::delete |
||
503 | * |
||
504 | * @param string $filepath |
||
505 | * @param boolean $recursive |
||
506 | * @param boolean|string $type 'd' for directory, 'f' for file |
||
507 | * @return boolean |
||
508 | */ |
||
509 | public static function delete(string $filepath, bool $recursive = false, $type = false): bool |
||
514 | |||
515 | |||
516 | /** |
||
517 | * exists |
||
518 | * checks if a file exists using the WP filesystem |
||
519 | * |
||
520 | * @param string $full_file_path |
||
521 | * @return bool |
||
522 | */ |
||
523 | public static function exists(string $full_file_path = ''): bool |
||
528 | |||
529 | |||
530 | /** |
||
531 | * is_readable |
||
532 | * checks if a file is_readable using the WP filesystem |
||
533 | * |
||
534 | * @param string $full_file_path |
||
535 | * @return bool |
||
536 | */ |
||
537 | public static function is_readable(string $full_file_path = ''): bool |
||
542 | |||
543 | |||
544 | /** |
||
545 | * remove_filename_from_filepath |
||
546 | * given a full path to a file including the filename itself, this removes the filename and returns the path, up |
||
547 | * to, but NOT including the filename OR slash |
||
548 | * |
||
549 | * @param string $full_file_path |
||
550 | * @return string |
||
551 | */ |
||
552 | public static function remove_filename_from_filepath(string $full_file_path = ''): string |
||
556 | |||
557 | |||
558 | /** |
||
559 | * get_filename_from_filepath. Arguably the same as basename() |
||
560 | * |
||
561 | * @param string $full_file_path |
||
562 | * @return string |
||
563 | */ |
||
564 | public static function get_filename_from_filepath(string $full_file_path = ''): string |
||
568 | |||
569 | |||
570 | /** |
||
571 | * get_file_extension |
||
572 | * |
||
573 | * @param string $full_file_path |
||
574 | * @return string |
||
575 | */ |
||
576 | public static function get_file_extension(string $full_file_path = ''): string |
||
580 | |||
581 | |||
582 | /** |
||
583 | * add_htaccess_deny_from_all so the web server cannot access this folder |
||
584 | * |
||
585 | * @param string $folder |
||
586 | * @return bool |
||
587 | */ |
||
588 | View Code Duplication | public static function add_htaccess_deny_from_all(string $folder = ''): bool |
|
599 | |||
600 | |||
601 | /** |
||
602 | * Adds an index file to this folder, so folks can't list all the file's contents |
||
603 | * |
||
604 | * @param string $folder |
||
605 | * @return boolean |
||
606 | */ |
||
607 | View Code Duplication | public static function add_index_file(string $folder): bool |
|
622 | |||
623 | |||
624 | /** |
||
625 | * Given that the file in $file_path has the normal name, (ie, CLASSNAME.whatever.php), |
||
626 | * extract that classname. |
||
627 | * |
||
628 | * @param string $file_path |
||
629 | * @return string |
||
630 | */ |
||
631 | public static function get_classname_from_filepath_with_standard_filename(string $file_path): string |
||
639 | |||
640 | |||
641 | /** |
||
642 | * standardise_directory_separators |
||
643 | * convert all directory separators in a file path. |
||
644 | * |
||
645 | * @param string $file_path |
||
646 | * @param bool $rtrim will remove trailing backslash |
||
647 | * @return string |
||
648 | */ |
||
649 | public static function standardise_directory_separators(string $file_path, bool $rtrim = false): string |
||
654 | |||
655 | |||
656 | /** |
||
657 | * end_with_directory_separator |
||
658 | * ensures that file path ends with '/' |
||
659 | * |
||
660 | * @param string $file_path |
||
661 | * @return string |
||
662 | */ |
||
663 | public static function end_with_directory_separator(string $file_path): string |
||
667 | |||
668 | |||
669 | /** |
||
670 | * shorthand for both EEH_FIle::end_with_directory_separator AND EEH_File::standardise_directory_separators |
||
671 | * |
||
672 | * @param string $file_path |
||
673 | * @return string |
||
674 | */ |
||
675 | public static function standardise_and_end_with_directory_separator(string $file_path): string |
||
679 | |||
680 | |||
681 | /** |
||
682 | * takes the folder name (with or without trailing slash) and finds the files it in, |
||
683 | * and what the class's name inside of each should be. |
||
684 | * |
||
685 | * @param array $folder_paths |
||
686 | * @param boolean $index_numerically if TRUE, the returned array will be indexed numerically; |
||
687 | * if FALSE (Default), returned array will be indexed by the filenames minus |
||
688 | * extensions. Set it TRUE if you know there are files in the directory with the |
||
689 | * same name but different extensions |
||
690 | * @return array if $index_numerically == TRUE keys are numeric , |
||
691 | * if $index_numerically == FALSE (Default) keys are what the class names SHOULD |
||
692 | * be; and values are their file paths |
||
693 | */ |
||
694 | public static function get_contents_of_folders(array $folder_paths = [], bool $index_numerically = false): array |
||
719 | |||
720 | |||
721 | /** |
||
722 | * Copies a file. Mostly a wrapper of WP_Filesystem::copy |
||
723 | * |
||
724 | * @param string $source_file |
||
725 | * @param string $destination_file |
||
726 | * @param boolean $overwrite |
||
727 | * @return boolean success |
||
728 | */ |
||
729 | public static function copy(string $source_file, string $destination_file, bool $overwrite = false): bool |
||
760 | |||
761 | |||
762 | /** |
||
763 | * Reports whether or not the filepath is in the EE uploads folder or not |
||
764 | * |
||
765 | * @param string $filepath |
||
766 | * @return boolean |
||
767 | */ |
||
768 | public static function is_in_uploads_folder(string $filepath): bool |
||
773 | |||
774 | |||
775 | /** |
||
776 | * Given a "local" filepath (what you probably thought was the only filepath), |
||
777 | * converts it into a "remote" filepath (the filepath the currently-in-use |
||
778 | * $wp_filesystem needs to use access the folder or file). |
||
779 | * See http://wordpress.stackexchange.com/questions/124900/using-wp-filesystem-in-plugins |
||
780 | * |
||
781 | * @param string $local_filepath the filepath to the folder/file locally |
||
782 | * @return string the remote filepath (eg the filepath the filesystem method, eg |
||
783 | * ftp or ssh, will use to access the folder |
||
784 | */ |
||
785 | public static function convert_local_filepath_to_remote_filepath(string $local_filepath): string |
||
790 | |||
791 | |||
792 | /** |
||
793 | * wrapper for WP_Filesystem::chmod() |
||
794 | * |
||
795 | * @param string $file Path to the file. |
||
796 | * @param int|false $mode Optional. The permissions as octal number, usually 0644 for files, |
||
797 | * 0755 for directories. Default false. |
||
798 | * @param bool $recursive Optional. If set to true, changes file permissions recursively. |
||
799 | * Default false. |
||
800 | * @return bool True on success, false on failure. |
||
801 | */ |
||
802 | public static function chmod(string $file, $mode = false, bool $recursive = false): bool |
||
807 | |||
808 | |||
809 | /** |
||
810 | * wrapper for WP_Filesystem::getchmod() |
||
811 | * |
||
812 | * @param string $file Path to the file. |
||
813 | * @return string Mode of the file (the last 3 digits). |
||
814 | */ |
||
815 | public static function permissions(string $file): string |
||
820 | |||
821 | |||
822 | /** |
||
823 | * wrapper for WP_Filesystem::owner() |
||
824 | * |
||
825 | * @param string $file Path to the file. |
||
826 | * @return string|false Username of the owner on success, false on failure. |
||
827 | */ |
||
828 | public static function owner(string $file) |
||
833 | |||
834 | |||
835 | /** |
||
836 | * wrapper for WP_Filesystem::group() |
||
837 | * |
||
838 | * @param string $file Path to the file. |
||
839 | * @return string|false The group on success, false on failure. |
||
840 | */ |
||
841 | public static function group(string $file) |
||
846 | |||
847 | |||
848 | /** |
||
849 | * wrapper for WP_Filesystem::move() |
||
850 | * |
||
851 | * @param string $source Path to the source file. |
||
852 | * @param string $destination Path to the destination file. |
||
853 | * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. |
||
854 | * Default false. |
||
855 | * @return bool True on success, false on failure. |
||
856 | */ |
||
857 | public static function move(string $source, string $destination, bool $overwrite = false): bool |
||
890 | |||
891 | |||
892 | /** |
||
893 | * @param string $source_file |
||
894 | * @return string |
||
895 | */ |
||
896 | private static function validateFileForCopyOrMove(string $source_file): string |
||
914 | |||
915 | |||
916 | /** |
||
917 | * @param string $destination_file |
||
918 | * @return string |
||
919 | */ |
||
920 | private static function validateFolderForCopyOrMove(string $destination_file): string |
||
939 | } |
||
940 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.