Complex classes like ExchangeWebServices 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 ExchangeWebServices, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
29 | class ExchangeWebServices |
||
30 | { |
||
31 | const VERSION_2007 = 'Exchange2007'; |
||
32 | const VERSION_2007_SP1 = 'Exchange2007_SP1'; |
||
33 | const VERSION_2007_SP2 = 'Exchange2007_SP2'; |
||
34 | const VERSION_2007_SP3 = 'Exchange2007_SP3'; |
||
35 | |||
36 | const VERSION_2010 = 'Exchange2010'; |
||
37 | const VERSION_2010_SP1 = 'Exchange2010_SP1'; |
||
38 | const VERSION_2010_SP2 = 'Exchange2010_SP2'; |
||
39 | const VERSION_2010_SP3 = 'Exchange2010_SP3'; |
||
40 | |||
41 | const VERSION_2013 = 'Exchange2013'; |
||
42 | const VERSION_2013_SP1 = 'Exchange2013_SP1'; |
||
43 | |||
44 | /** |
||
45 | * Password to use when connecting to the Exchange server. |
||
46 | * |
||
47 | * @var string |
||
48 | */ |
||
49 | protected $password; |
||
50 | |||
51 | /** |
||
52 | * Location of the Exchange server. |
||
53 | * |
||
54 | * @var string |
||
55 | */ |
||
56 | protected $server; |
||
57 | |||
58 | /** |
||
59 | * SOAP client used to make the request |
||
60 | * |
||
61 | * @var NTLMSoapClient |
||
62 | */ |
||
63 | protected $soap; |
||
64 | |||
65 | /** |
||
66 | * Username to use when connecting to the Exchange server. |
||
67 | * |
||
68 | * @var string |
||
69 | */ |
||
70 | protected $username; |
||
71 | |||
72 | /** |
||
73 | * @var EmailAddressType |
||
74 | */ |
||
75 | protected $primarySmtpMailbox; |
||
76 | |||
77 | /** |
||
78 | * A setting to check whether or not responses should be drilled down before being returned. Setting this to false |
||
79 | * will return the raw responses without any filtering |
||
80 | * |
||
81 | * @var bool |
||
82 | */ |
||
83 | protected $drillDownResponses = true; |
||
84 | |||
85 | /** |
||
86 | * @return EmailAddressType |
||
87 | */ |
||
88 | 22 | public function getPrimarySmtpMailbox() |
|
92 | |||
93 | 1 | public function getPrimarySmtpEmailAddress() |
|
101 | |||
102 | 2 | public function setPrimarySmtpEmailAddress($emailAddress) |
|
110 | |||
111 | /** |
||
112 | * Miscrosoft Exchange version that we are going to connect to |
||
113 | * |
||
114 | * @var string |
||
115 | */ |
||
116 | protected $version; |
||
117 | |||
118 | protected $options; |
||
119 | |||
120 | /** |
||
121 | * The timezone for the client |
||
122 | * |
||
123 | * @var bool |
||
124 | */ |
||
125 | protected $timezone = false; |
||
126 | |||
127 | /** |
||
128 | * @param boolean $timezone |
||
129 | */ |
||
130 | public function setTimezone($timezone) |
||
131 | { |
||
132 | $this->timezone = $timezone; |
||
133 | } |
||
134 | |||
135 | /** |
||
136 | * @return string |
||
137 | */ |
||
138 | public function getVersion() |
||
142 | |||
143 | /** |
||
144 | * @return string |
||
145 | */ |
||
146 | public function getServer() |
||
150 | |||
151 | /** |
||
152 | * Constructor for the ExchangeWebServices class |
||
153 | * |
||
154 | * @deprecated Since 0.6.3 |
||
155 | * @param string $server |
||
156 | * @param string $username |
||
157 | * @param string $password |
||
158 | * @param array $options |
||
159 | */ |
||
160 | 31 | public function __construct( |
|
161 | $server = null, |
||
162 | $username = null, |
||
163 | $password = null, |
||
164 | $options = [] |
||
165 | ) { |
||
166 | 31 | if ($server !== null) { |
|
167 | 1 | $this->createClient( |
|
168 | 1 | $server, |
|
169 | 1 | ExchangeWebServicesAuth::fromUsernameAndPassword($username, $password), |
|
170 | $options |
||
171 | 1 | ); |
|
172 | 1 | } |
|
173 | 31 | } |
|
174 | |||
175 | 29 | public static function fromUsernameAndPassword($server, $username, $password, $options) |
|
182 | |||
183 | 1 | public static function fromCallbackToken($server, $token, $options) |
|
190 | |||
191 | 31 | protected function createClient($server, $auth, $options) |
|
192 | { |
||
193 | 31 | $location = 'https://'.$this->cleanServerUrl($server).'/EWS/Exchange.asmx'; |
|
194 | |||
195 | 31 | $options = array_replace_recursive([ |
|
196 | 31 | 'version' => self::VERSION_2007, |
|
197 | 31 | 'trace' => 1, |
|
198 | 31 | 'exceptions' => true, |
|
199 | 31 | 'classmap' => ClassMap::getClassMap(), |
|
200 | 'drillDownResponses' => true |
||
201 | 31 | ], $options); |
|
202 | |||
203 | 31 | $this->server = $server; |
|
204 | 31 | $this->version = $options['version']; |
|
205 | |||
206 | 31 | $this->soap = new NTLMSoapClient( |
|
207 | 31 | $location, |
|
208 | 31 | $auth, |
|
209 | 31 | dirname(__FILE__).'/../../Resources/wsdl/services.wsdl', |
|
210 | $options |
||
211 | 31 | ); |
|
212 | |||
213 | 31 | if (isset($options['primarySmtpEmailAddress'])) { |
|
214 | 1 | $this->setPrimarySmtpEmailAddress($options['primarySmtpEmailAddress']); |
|
215 | 1 | } |
|
216 | |||
217 | 31 | if (isset($options['impersonation'])) { |
|
218 | 1 | $this->setPrimarySmtpEmailAddress($options['impersonation']); |
|
219 | 1 | } |
|
220 | |||
221 | 31 | $this->drillDownResponses = $options['drillDownResponses']; |
|
222 | 31 | } |
|
223 | |||
224 | /** |
||
225 | * @codeCoverageIgnore |
||
226 | * |
||
227 | * @param $name |
||
228 | * @param $arguments |
||
229 | * @return Type |
||
230 | * @throws \garethp\ews\API\Exception |
||
231 | */ |
||
232 | public function __call($name, $arguments) |
||
238 | |||
239 | /** |
||
240 | * Returns the SOAP Client that may be used to make calls against the server |
||
241 | * |
||
242 | * @return NTLMSoapClient |
||
243 | */ |
||
244 | 28 | public function getClient() |
|
248 | |||
249 | /** |
||
250 | * Sets the client |
||
251 | * |
||
252 | * @param NTLMSoapClient $client |
||
253 | * @return $this |
||
254 | */ |
||
255 | 2 | public function setClient($client) |
|
261 | |||
262 | /** |
||
263 | * Cleans the server URL for usage |
||
264 | * |
||
265 | * @param $server |
||
266 | * @return string |
||
267 | */ |
||
268 | 38 | public function cleanServerUrl($server) |
|
289 | |||
290 | /** |
||
291 | * Process a response to verify that it succeeded and take the appropriate |
||
292 | * action |
||
293 | * |
||
294 | * @param \garethp\ews\API\Message\BaseResponseMessageType $response |
||
295 | * @return \garethp\ews\API\Message\ArrayOfResponseMessageType|\garethp\ews\API\Message\ResponseMessageType |
||
296 | * @throws \garethp\ews\API\Exception |
||
297 | */ |
||
298 | 26 | protected function processResponse($response) |
|
333 | |||
334 | /** |
||
335 | * @param $response |
||
336 | * @return array |
||
337 | * @throws \garethp\ews\API\Exception |
||
338 | */ |
||
339 | 24 | public function drillDownResponseLevels($response) |
|
373 | } |
||
374 |
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.