Complex classes like Client 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 Client, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
25 | class Client extends AbstractClient implements ClientInterface |
||
26 | { |
||
27 | protected $socket; |
||
28 | protected $chunk_size; |
||
29 | protected $verify_peer_name; |
||
30 | |||
31 | public function __construct(array $config, ObjectSpec $objectSpec = null) |
||
32 | { |
||
33 | parent::__construct($config, $objectSpec); |
||
34 | |||
35 | $this->chunk_size = (int) $this->getConfigDefault($config, 'chunk_size', 1024); |
||
36 | $this->verify_peer_name = $this->getConfigDefaultBool($config, 'verify_peer_name', true); |
||
37 | |||
38 | // override 'port' default to false from AbstractClient::prepareConnectionOptions |
||
39 | $this->port = (int) $this->getConfigDefault($config, 'port', 700); |
||
40 | } |
||
41 | |||
42 | public function __destruct() |
||
43 | { |
||
44 | $this->close(); |
||
45 | } |
||
46 | |||
47 | /** |
||
48 | * Setup context in case of ssl connection |
||
49 | * |
||
50 | * @return resource|null |
||
51 | */ |
||
52 | private function setupContext() |
||
53 | { |
||
54 | if (!$this->ssl) { |
||
55 | return null; |
||
56 | } |
||
57 | |||
58 | $context = stream_context_create(); |
||
59 | |||
60 | $options_array = [ |
||
61 | 'verify_peer' => false, |
||
62 | 'verify_peer_name' => $this->verify_peer_name, |
||
63 | 'allow_self_signed' => true, |
||
64 | 'local_cert' => $this->local_cert, |
||
65 | 'passphrase' => $this->passphrase, |
||
66 | 'cafile' => $this->ca_cert, |
||
67 | 'local_pk' => $this->pk_cert, |
||
68 | ]; |
||
69 | |||
70 | // filter out empty user provided values |
||
71 | $options_array = array_filter( |
||
72 | $options_array, |
||
73 | function ($var) { |
||
74 | return !is_null($var); |
||
75 | } |
||
76 | ); |
||
77 | |||
78 | $options = ['ssl' => $options_array]; |
||
79 | |||
80 | // stream_context_set_option accepts array of options in form of $arr['wrapper']['option'] = value |
||
81 | stream_context_set_option($context, $options); |
||
82 | |||
83 | return $context; |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Setup connection socket |
||
88 | * |
||
89 | * @param resource|null $context SSL context or null in case of tcp connection |
||
90 | * |
||
91 | * @throws Exception on socket errors |
||
92 | */ |
||
93 | private function setupSocket($context = null) |
||
94 | { |
||
95 | $proto = $this->ssl ? 'ssl' : 'tcp'; |
||
96 | $target = sprintf('%s://%s:%d', $proto, $this->host, $this->port); |
||
97 | |||
98 | $errno = 0; |
||
99 | $errstr = ''; |
||
100 | |||
101 | $this->socket = @stream_socket_client($target, $errno, $errstr, $this->connect_timeout, STREAM_CLIENT_CONNECT, $context); |
||
102 | |||
103 | if ($this->socket === false) { |
||
104 | // Socket initialization may fail, before system call connect() |
||
105 | // so the $errno is 0 and $errstr isn't populated . |
||
106 | // see https://www.php.net/manual/en/function.stream-socket-client.php#refsect1-function.stream-socket-client-errors |
||
107 | throw new Exception(sprintf('problem initializing socket: %s code: [%d]', $errstr, $errno), $errno); |
||
108 | } |
||
109 | |||
110 | // set stream time out |
||
111 | if (!stream_set_timeout($this->socket, $this->timeout)) { |
||
112 | throw new Exception('unable to set stream timeout'); |
||
113 | } |
||
114 | |||
115 | // set to non-blocking |
||
116 | if (!stream_set_blocking($this->socket, 0)) { |
||
117 | throw new Exception('unable to set blocking'); |
||
118 | } |
||
119 | } |
||
120 | |||
121 | /** |
||
122 | * {@inheritdoc} |
||
123 | * |
||
124 | * @see \AfriCC\EPP\ClientInterface::connect() |
||
125 | */ |
||
126 | public function connect($newPassword = false) |
||
140 | |||
141 | /** |
||
142 | * Closes a previously opened EPP connection |
||
143 | */ |
||
144 | public function close() |
||
155 | |||
156 | public function getFrame() |
||
157 | { |
||
158 | $hard_time_limit = time() + $this->timeout + 2; |
||
159 | do { |
||
179 | |||
180 | public function sendFrame(FrameInterface $frame) |
||
187 | |||
188 | protected function log($message, $color = '0;32') |
||
195 | |||
196 | /** |
||
197 | * check if socket is still active |
||
198 | * |
||
199 | * @return bool |
||
200 | */ |
||
201 | private function active() |
||
205 | |||
206 | /** |
||
207 | * receive socket data |
||
208 | * |
||
209 | * @param int $length |
||
210 | * |
||
211 | * @throws Exception |
||
212 | * |
||
213 | * @return string |
||
214 | */ |
||
215 | private function recv($length) |
||
254 | |||
255 | /** |
||
256 | * send data to socket |
||
257 | * |
||
258 | * @param string $buffer |
||
259 | */ |
||
260 | private function send($buffer) |
||
312 | } |
||
313 |