Complex classes like Resource 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 Resource, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
33 | class Resource |
||
34 | { |
||
35 | /** |
||
36 | * Available base access modes |
||
37 | * @var string base access mode must be one of these letters |
||
38 | */ |
||
39 | protected static $bases = "rwaxc"; |
||
40 | |||
41 | /** |
||
42 | * Hash of readable/writable stream open mode types. |
||
43 | * |
||
44 | * Mercilessly stolen from: |
||
45 | * https://github.com/guzzle/streams/blob/master/src/Stream.php |
||
46 | * |
||
47 | * My kudos and sincere thanks go out to Michael Dowling and Graham Campbell |
||
48 | * of the guzzle/streams PHP package. Thanks for the inspiration (in some cases) |
||
49 | * and the not suing me for outright theft (in this case). |
||
50 | * |
||
51 | * @var array Hash of readable and writable stream types |
||
52 | * @todo I think I can get rid of this by simply checking whether base is a |
||
53 | * particular letter OR plus is present... try it |
||
54 | * @todo Why are x and c (alone) not even on either of these lists? |
||
55 | * I just figured out why... readable and writable default to false. So |
||
56 | * only modes that change that default behavior are listed here |
||
57 | */ |
||
58 | protected static $readWriteHash = [ |
||
59 | 'read' => [ |
||
60 | 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true, |
||
61 | 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, |
||
62 | 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true, |
||
63 | 'x+t' => true, 'c+t' => true, 'a+' => true, |
||
64 | ], |
||
65 | 'write' => [ |
||
66 | 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true, |
||
67 | 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true, |
||
68 | 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true, |
||
69 | 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true, |
||
70 | ], |
||
71 | ]; |
||
72 | |||
73 | /** |
||
74 | * Stream URI. |
||
75 | * |
||
76 | * Contains the stream URI to connect to. |
||
77 | * |
||
78 | * @var string The stream uri |
||
79 | */ |
||
80 | protected $uri; |
||
81 | |||
82 | /** |
||
83 | * Stream resource handle. |
||
84 | * |
||
85 | * Contains the underlying stream resource handle (if there is one). |
||
86 | * Otherwise it will be null. |
||
87 | * |
||
88 | * @var resource The stream resource handle |
||
89 | */ |
||
90 | protected $conn; |
||
91 | |||
92 | /** |
||
93 | * Lazy open switch. |
||
94 | * |
||
95 | * Determines whether the actual fopen for this resource should be delayed |
||
96 | * until an I/O operation is performed. |
||
97 | * |
||
98 | * @var boolean True if connection is lazy |
||
99 | */ |
||
100 | protected $lazy; |
||
101 | |||
102 | /** |
||
103 | * Extra context to open the resource with. |
||
104 | * |
||
105 | * An associative array of context options and parameters. |
||
106 | * |
||
107 | * @var array An associative array of stream context options and params |
||
108 | * @see http://php.net/manual/en/stream.contexts.php |
||
109 | */ |
||
110 | protected $context = [ |
||
111 | 'options' => [], |
||
112 | 'params' => [] |
||
113 | ]; |
||
114 | |||
115 | /** |
||
116 | * Context resource handle. |
||
117 | * |
||
118 | * Holds a context resource handle object for $this->context |
||
119 | * |
||
120 | * @var resource The context resource handle |
||
121 | */ |
||
122 | protected $crh; |
||
123 | |||
124 | /** |
||
125 | * Should fopen use include path? |
||
126 | * |
||
127 | * @var boolean True if fopen should use the include path to find potential files |
||
128 | */ |
||
129 | protected $useIncludePath; |
||
130 | |||
131 | /** |
||
132 | * Base open mode. |
||
133 | * |
||
134 | * @var string A single character for base open mode (r, w, a, x or c) |
||
135 | */ |
||
136 | protected $base = ''; |
||
137 | |||
138 | /** |
||
139 | * Plus reading or plus writing. |
||
140 | * |
||
141 | * @var string Either a plus or an empty string |
||
142 | */ |
||
143 | protected $plus = ''; |
||
144 | |||
145 | /** |
||
146 | * Binary or text flag. |
||
147 | * |
||
148 | * @var string Either "b" or "t" for binary or text |
||
149 | */ |
||
150 | protected $flag = ''; |
||
151 | |||
152 | /** |
||
153 | * Does access mode string indicate readability? |
||
154 | * |
||
155 | * @var bool Whether access mode indicates readability |
||
156 | */ |
||
157 | protected $readable = false; |
||
158 | |||
159 | /** |
||
160 | * Does access mode string indicate writability |
||
161 | * |
||
162 | * @var bool Whether access mode indicates writability |
||
163 | */ |
||
164 | protected $writable = false; |
||
165 | |||
166 | /** |
||
167 | * Resource constructor. |
||
168 | * |
||
169 | * Instantiates a stream resource. If lazy is set to true, the connection |
||
170 | * is delayed until the first call to getResource(). |
||
171 | * |
||
172 | * @param string|resource $uri The URI to connect to OR a stream resource handle |
||
173 | * @param string $mode The connection mode |
||
174 | * @param boolean $lazy Whether connection should be deferred until an I/O |
||
175 | * operation is requested (such as read or write) on the attached stream |
||
176 | * @param boolean|null $use_include_path |
||
177 | * @param array|null $context_options |
||
178 | * @param array|null $context_params |
||
179 | * @todo Does stream_get_meta_data belong in Stream or Resource? |
||
180 | */ |
||
181 | 99 | public function __construct( |
|
205 | |||
206 | /** |
||
207 | * Initialize resource with PHP resource variable. |
||
208 | * |
||
209 | * Uses a PHP resource variable to initialize this class. |
||
210 | * |
||
211 | * @param resource $handle The stream resource to initialize |
||
212 | * @return bool |
||
213 | */ |
||
214 | 6 | protected function initWithResource($handle) |
|
231 | |||
232 | /** |
||
233 | * Class destructor |
||
234 | */ |
||
235 | 93 | public function __destruct() |
|
239 | |||
240 | /** |
||
241 | * Invoke magic method. |
||
242 | * |
||
243 | * Creates and returns a Stream object for this resource |
||
244 | * |
||
245 | * @return Streamable A stream for this resource |
||
246 | */ |
||
247 | 7 | public function __invoke() |
|
251 | |||
252 | /** |
||
253 | * Connect (open connection) to file/stream. |
||
254 | * |
||
255 | * File open is (by default) delayed until the user explicitly calls connect() |
||
256 | * or they request the resource handle with getHandle(). |
||
257 | * |
||
258 | * @return boolean True if connection was successful |
||
259 | * @throws \CSVelte\Exception\IOException if connection fails |
||
260 | */ |
||
261 | 82 | public function connect() |
|
284 | |||
285 | /** |
||
286 | * Close connection. |
||
287 | * |
||
288 | * Close the connection to this stream (if open). |
||
289 | * |
||
290 | * @return boolean|null Whether close was successful, or null if already closed |
||
291 | */ |
||
292 | 93 | public function disconnect() |
|
300 | |||
301 | /** |
||
302 | * Set stream URI. |
||
303 | * |
||
304 | * Set the stream URI. Can only be set if the connection isn't open yet. |
||
305 | * If you try to set the URI on an open resource, an IOException will be thrown |
||
306 | * |
||
307 | * @param string $uri The URI for this stream resource to open |
||
308 | * @return $this |
||
309 | * @throws \InvalidArgumentException if not a valid stream uri |
||
310 | * @throws \CSVelte\Exception\IOException if stream has already been opened |
||
311 | * @todo I'm pretty sure that the parse_url function is too restrictive. It |
||
312 | * will reject URIs that are perfectly valid. |
||
313 | */ |
||
314 | 98 | public function setUri($uri) |
|
331 | |||
332 | /** |
||
333 | * Set the fopen mode. |
||
334 | * |
||
335 | * Thank you to GitHub user "binsoul" whose AccessMode class inspired this |
||
336 | * Also thanks to the author(s) of Guzzle streams implementation, where the |
||
337 | * readwritehash idea came from. Both libraries are MIT licensed, so my |
||
338 | * merciless theft of their code is alright. |
||
339 | * |
||
340 | * @param string $mode A 1-3 character string determining open mode |
||
341 | * @return $this |
||
342 | * @throws \InvalidArgumentException if not a valid stream access mode |
||
343 | * @throws \CSVelte\Exception\IOException if stream has already been opened |
||
344 | * @see http://php.net/manual/en/function.fopen.php |
||
345 | * @see https://github.com/binsoul/io-stream/blob/master/src/AccessMode.php |
||
346 | * @see https://raw.githubusercontent.com/guzzle/streams/master/src/Stream.php |
||
347 | * @todo convert $mode to lower case and test it |
||
348 | */ |
||
349 | 97 | public function setMode($mode = null) |
|
369 | |||
370 | /** |
||
371 | * Update access parameters. |
||
372 | * |
||
373 | * After changing any of the access mode parameters, this method must be |
||
374 | * called in order for readable and writable to stay accurate. |
||
375 | * |
||
376 | * @return $this |
||
377 | */ |
||
378 | 97 | protected function updateAccess() |
|
384 | |||
385 | /** |
||
386 | * Set base access mode character. |
||
387 | * |
||
388 | * @param string $base The base mode character (must be one of "rwaxc") |
||
389 | * @return $this |
||
390 | * @throws \InvalidArgumentException If passed invalid base char |
||
391 | * @throws \CSVelte\Exception\IOException if stream has already been opened |
||
392 | */ |
||
393 | 97 | public function setBaseMode($base) |
|
402 | |||
403 | /** |
||
404 | * Set plus mode. |
||
405 | * |
||
406 | * @param boolean $isPlus Whether base access mode should include the + sign |
||
407 | * @return $this |
||
408 | * @throws \CSVelte\Exception\IOException if stream has already been opened |
||
409 | */ |
||
410 | 97 | public function setIsPlus($isPlus) |
|
416 | |||
417 | /** |
||
418 | * Set binary-safe mode. |
||
419 | * |
||
420 | * @param boolean $isBinary Whether binary safe mode or not |
||
421 | * @return $this |
||
422 | * @throws \CSVelte\Exception\IOException if stream has already been opened |
||
423 | */ |
||
424 | 97 | public function setIsBinary($isBinary) |
|
432 | |||
433 | /** |
||
434 | * Set text mode. |
||
435 | * |
||
436 | * @param boolean $isText Whether text mode or not |
||
437 | * @return $this |
||
438 | * @throws \CSVelte\Exception\IOException if stream has already been opened |
||
439 | */ |
||
440 | 97 | public function setIsText($isText) |
|
448 | |||
449 | /** |
||
450 | * Set lazy flag. |
||
451 | * |
||
452 | * Set the lazy flag, which tells the class whether to defer the connection |
||
453 | * until the user specifically requests it. |
||
454 | * |
||
455 | * @param boolean|null Whether or not to "lazily" open the stream |
||
456 | * @return $this |
||
457 | */ |
||
458 | 92 | protected function setLazy($lazy) |
|
464 | |||
465 | /** |
||
466 | * Set use include path flag. |
||
467 | * |
||
468 | * Sets whether or not fopen should search the include path for files. Can |
||
469 | * only be set if resource isn't open already. If called when resource is |
||
470 | * already open an exception will be thrown. |
||
471 | * |
||
472 | * @param boolean $use_include_path Whether to search include path for files |
||
473 | * @throws \CSVelte\Exception\IOException |
||
474 | * @return $this |
||
475 | */ |
||
476 | 92 | public function setUseIncludePath($use_include_path) |
|
482 | |||
483 | /** |
||
484 | * Set stream context options and params. |
||
485 | * |
||
486 | * Sets arrays of stream context options and params. Check out the URI below |
||
487 | * for more on stream contexts. |
||
488 | * |
||
489 | * @param array|null $options Stream context options |
||
490 | * @param array|null $params Stream Context params |
||
491 | * @return $this |
||
492 | * @see http://php.net/manual/en/stream.contexts.php |
||
493 | */ |
||
494 | 92 | public function setContext($options = null, $params = null) |
|
506 | |||
507 | /** |
||
508 | * Set context resource directly |
||
509 | * @param resource|null $context Stream context resource to set directly |
||
510 | * @return $this |
||
511 | * @see http://php.net/manual/en/function.stream-context-create.php |
||
512 | * @todo Need to write a unit test for passing this method a null value |
||
513 | */ |
||
514 | 78 | public function setContextResource($context) |
|
529 | |||
530 | /** |
||
531 | * Update the stream context. |
||
532 | * |
||
533 | * After setting/updating stream context options and/or params, this method |
||
534 | * must be called in order to update the stream context resource. |
||
535 | * |
||
536 | * @return $this |
||
537 | */ |
||
538 | 2 | protected function updateContext() |
|
553 | |||
554 | /** |
||
555 | * Set context options. |
||
556 | * |
||
557 | * Sets stream context options for this stream resource. |
||
558 | * |
||
559 | * @param array $options An array of stream context options |
||
560 | * @param string $wrapper The wrapper these options belong to (if no wrapper |
||
561 | * argument, then $options should be an associative array with key being |
||
562 | * a wrapper name and value being its options) |
||
563 | * @return $this |
||
564 | * @throws \InvalidArgumentException if passed invalid options or wrapper |
||
565 | * @see http://php.net/manual/en/stream.contexts.php |
||
566 | */ |
||
567 | 2 | public function setContextOptions($options, $wrapper = null) |
|
581 | |||
582 | /** |
||
583 | * Set context params. |
||
584 | * |
||
585 | * Set the context params for this stream resource. |
||
586 | * |
||
587 | * @param array $params An array of stream resource params |
||
588 | * @return $this |
||
589 | * @throws \InvalidArgumentException if passed invalid params |
||
590 | * @see http://php.net/manual/en/stream.contexts.php |
||
591 | */ |
||
592 | 2 | public function setContextParams($params) |
|
601 | |||
602 | /** |
||
603 | * Get context options for this stream resource. |
||
604 | * |
||
605 | * Returns the stream context options for this stream resource. Either all |
||
606 | * options for all wrappers, or just the options for the specified wrapper. |
||
607 | * |
||
608 | * @param string $wrapper If present, return options only for this wrapper |
||
609 | * @return array Context options (either all or for specified wrapper) |
||
610 | * @throws \InvalidArgumentException if the wrapper doesn't exist |
||
611 | */ |
||
612 | 82 | public function getContextOptions($wrapper = null) |
|
622 | |||
623 | /** |
||
624 | * Get context params for this stream resource. |
||
625 | * |
||
626 | * Returns the stream context params for this stream resource. |
||
627 | * |
||
628 | * @return array Context params for this stream resource |
||
629 | */ |
||
630 | 82 | public function getContextParams() |
|
634 | |||
635 | /** |
||
636 | * Get stream context resource. |
||
637 | * @return resource|null The stream context resource |
||
638 | */ |
||
639 | 85 | public function getContext() |
|
651 | |||
652 | /** |
||
653 | * Retrieve underlying stream resource handle. |
||
654 | * |
||
655 | * An accessor method for the underlying stream resource object. Also triggers |
||
656 | * stream connection if in lazy open mode. Because this method may potentially |
||
657 | * call the connect() method, it is possible that it may throw an exception |
||
658 | * if there is some issue with opening the stream. |
||
659 | * |
||
660 | * @return resource The underlying stream resource handle |
||
661 | * @throws \CSVelte\Exception\IOException |
||
662 | */ |
||
663 | 69 | public function getHandle() |
|
670 | |||
671 | /** |
||
672 | * Is the stream connection open? |
||
673 | * |
||
674 | * Tells you whether this stream resource is open or not. |
||
675 | * |
||
676 | * @return boolean Whether the stream is open |
||
677 | */ |
||
678 | 98 | public function isConnected() |
|
682 | |||
683 | /** |
||
684 | * Get the stream URI. |
||
685 | * |
||
686 | * Accessor method for stream URI. |
||
687 | * |
||
688 | * @return string The stream URI |
||
689 | */ |
||
690 | 82 | public function getUri() |
|
694 | |||
695 | /** |
||
696 | * Get the access mode. |
||
697 | * |
||
698 | * Tells you what the access mode is. This is the short string of characters |
||
699 | * that you would pass to the fopen function to tell it how to open a file/stream |
||
700 | * |
||
701 | * @return string The file/stream access mode |
||
702 | * @see http://php.net/manual/en/function.fopen.php |
||
703 | */ |
||
704 | 97 | public function getMode() |
|
713 | |||
714 | /** |
||
715 | * Is access mode binary-safe? |
||
716 | * @return boolean Whether binary-safe flag is set |
||
717 | */ |
||
718 | 4 | public function isBinary() |
|
722 | |||
723 | /** |
||
724 | * Is stream connected in text mode? |
||
725 | * @return boolean Whether text mode flag is set |
||
726 | */ |
||
727 | 3 | public function isText() |
|
731 | |||
732 | /** |
||
733 | * Is this a lazy open resource? |
||
734 | * @return boolean Whether this is a lazily-opened resource |
||
735 | */ |
||
736 | 92 | public function isLazy() |
|
740 | |||
741 | /** |
||
742 | * Should fopen search include path? |
||
743 | * @return boolean Whether fopen should search include path for files |
||
744 | */ |
||
745 | 82 | public function getUseIncludePath() |
|
749 | |||
750 | /** |
||
751 | * Does the access mode string indicate readability? |
||
752 | * |
||
753 | * Readable, in this context, only refers to the manner in which this stream |
||
754 | * resource was opened (if it even is opened yet). It is no indicator about |
||
755 | * whether or not the underlying stream actually supports read operations. |
||
756 | * It simply refers to the access mode string passed to it by the user. |
||
757 | * |
||
758 | * @return boolean Whether access mode indicates readability |
||
759 | */ |
||
760 | 54 | public function isReadable() |
|
764 | |||
765 | /** |
||
766 | * Does the access mode string indicate writability? |
||
767 | * |
||
768 | * Writable, in this context, only refers to the manner in which this stream |
||
769 | * resource was opened (if it even is opened yet). It is no indicator about |
||
770 | * whether or not the underlying stream actually supports write operations. |
||
771 | * It simply refers to the access mode string passed to it by the user. |
||
772 | * |
||
773 | * @return boolean Whether access mode indicates writability |
||
774 | */ |
||
775 | 21 | public function isWritable() |
|
779 | |||
780 | /** |
||
781 | * Is cursor positioned at the beginning of stream? |
||
782 | * |
||
783 | * Returns true if this stream resource's access mode positions the internal |
||
784 | * cursor at the beginning of the stream. |
||
785 | * |
||
786 | * @return boolean Whether cursor positioned at beginning of stream |
||
787 | */ |
||
788 | 2 | public function isCursorPositionedAtBeginning() |
|
792 | |||
793 | /** |
||
794 | * Is cursor positioned at the end of stream? |
||
795 | * |
||
796 | * Returns true if this stream resource's access mode positions the internal |
||
797 | * cursor at the end of the stream. |
||
798 | * |
||
799 | * @return boolean Whether cursor positioned at end of stream |
||
800 | */ |
||
801 | 2 | public function isCursorPositionedAtEnd() |
|
805 | |||
806 | /** |
||
807 | * Is content truncated to zero-length on opening? |
||
808 | * |
||
809 | * Returns true if this stream resource's access mode indicates truncation of |
||
810 | * stream content to zero-length upon opening. |
||
811 | * |
||
812 | * @return boolean Whether stream content is truncated on opening |
||
813 | */ |
||
814 | 3 | public function isTruncated() |
|
818 | |||
819 | /** |
||
820 | * Does stream access mode indicate file creation? |
||
821 | * |
||
822 | * Returns true if this stream's access mode implies that PHP will attempt to |
||
823 | * create a file if none exists. |
||
824 | * |
||
825 | * @return boolean Whether PHP should attempt to create file at $uri |
||
826 | */ |
||
827 | 1 | public function attemptsFileCreation() |
|
831 | |||
832 | /** |
||
833 | * Does stream access mode indicate the rejection of existing files? |
||
834 | * |
||
835 | * Returns true if this stream's access mode implies that PHP will fail to |
||
836 | * open a file if it already exists. |
||
837 | * |
||
838 | * @return boolean Whether PHP should attempt to create file at $uri |
||
839 | */ |
||
840 | 1 | public function rejectsExistingFiles() |
|
844 | |||
845 | /** |
||
846 | * Are write operations appended to the end of the stream? |
||
847 | * |
||
848 | * Returns true if write operations are appended to the end of the stream |
||
849 | * regardless of the position of the read cursor. |
||
850 | * |
||
851 | * @return boolean Whether write operations ore always appended |
||
852 | */ |
||
853 | 1 | public function appendsWriteOps() |
|
857 | |||
858 | /** |
||
859 | * Assert that stream resource is not open. |
||
860 | * |
||
861 | * Used internally to ensure that stream is not open, since some methods should |
||
862 | * only be called on unopened stream resources. |
||
863 | * |
||
864 | * @param string $method The method that is asserting |
||
865 | * @throws IOException if stream is open |
||
866 | */ |
||
867 | 98 | protected function assertNotConnected($method) |
|
873 | |||
874 | /** |
||
875 | * Assert that given wrapper is a valid, registered stream wrapper |
||
876 | * |
||
877 | * Used internally to ensure that a given stream wrapper is valid and available |
||
878 | * |
||
879 | * @param string $name The name of the stream wrapper |
||
880 | * @throws \InvalidArgumentException if wrapper doesn't exist |
||
881 | */ |
||
882 | 2 | protected function assertValidWrapper($name) |
|
888 | |||
889 | } |
||
890 |