Passed
Push — master ( d943e6...a9e422 )
by Fabio
05:14
created

TSoapServer   C

Complexity

Total Complexity 53

Size/Duplication

Total Lines 318
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 103
c 1
b 0
f 0
dl 0
loc 318
ccs 0
cts 185
cp 0
rs 6.96
wmc 53

25 Methods

Rating   Name   Duplication   Size   Complexity  
A setClassMaps() 0 3 1
A setVersion() 0 6 4
A createServer() 0 9 3
A setSessionPersistent() 0 3 1
A run() 0 21 6
A getSessionPersistent() 0 3 1
A setWsdlUri() 0 3 1
A getWsdl() 0 19 6
A setActor() 0 3 1
A getWsdlUri() 0 6 2
A getEncoding() 0 3 1
A getActor() 0 3 1
A getRequestedMethod() 0 3 1
A fault() 0 4 1
A getProvider() 0 3 1
A setProvider() 0 3 1
A getVersion() 0 3 1
A getUri() 0 6 2
A getClassMaps() 0 3 1
A setEncoding() 0 3 1
A setUri() 0 3 1
A guessMethodCallRequested() 0 8 3
B getOptions() 0 23 8
A getID() 0 3 1
A setID() 0 6 3

How to fix   Complexity   

Complex Class

Complex classes like TSoapServer 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.

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 TSoapServer, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * TSoapService and TSoapServer class file
4
 *
5
 * @author Knut Urdalen <[email protected]>
6
 * @author Qiang Xue <[email protected]>
7
 * @link https://github.com/pradosoft/prado
8
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
9
 * @package Prado\Web\Services
10
 */
11
12
namespace Prado\Web\Services;
13
14
use Prado\Exceptions\TInvalidDataValueException;
15
use Prado\TPropertyValue;
16
use Prado\Prado;
17
use Prado\TApplicationMode;
18
use Prado\Wsdl\WsdlGenerator;
19
20
/**
21
 * TSoapServer class.
22
 *
23
 * TSoapServer is a wrapper of the PHP SoapServer class.
24
 * It associates a SOAP provider class to the SoapServer object.
25
 * It also manages the URI for the SOAP service and WSDL.
26
 *
27
 * @author Qiang Xue <[email protected]>
28
 * @package Prado\Web\Services
29
 * @since 3.1
30
 * @method TSoapService getService()
31
 */
32
class TSoapServer extends \Prado\TApplicationComponent
33
{
34
	public const WSDL_CACHE_PREFIX = 'wsdl.';
35
36
	private $_id;
37
	private $_provider;
38
39
	private $_version = '';
40
	private $_actor = '';
41
	private $_encoding = '';
42
	private $_uri = '';
43
	private $_classMap;
44
	private $_persistent = false;
45
	private $_wsdlUri = '';
46
47
	private $_requestedMethod;
48
49
	private $_server;
50
51
	/**
52
	 * @return string the ID of the SOAP server
53
	 */
54
	public function getID()
55
	{
56
		return $this->_id;
57
	}
58
59
	/**
60
	 * @param string $id the ID of the SOAP server
61
	 * @throws TInvalidDataValueException if the ID ends with '.wsdl'.
62
	 */
63
	public function setID($id)
64
	{
65
		if ($this->_id !== null && (strrpos($this->_id, '.wsdl') === strlen($this->_id) - 5)) {
66
			throw new TInvalidDataValueException('soapserver_id_invalid', $id);
67
		}
68
		$this->_id = $id;
69
	}
70
71
	/**
72
	 * Handles the SOAP request.
73
	 */
74
	public function run()
75
	{
76
		if (($provider = $this->getProvider()) !== null) {
0 ignored issues
show
introduced by
The condition $provider = $this->getProvider() !== null is always true.
Loading history...
77
			Prado::using($provider);
78
			$providerClass = ($pos = strrpos($provider, '.')) !== false ? substr($provider, $pos + 1) : $provider;
79
			$this->guessMethodCallRequested($providerClass);
80
			$server = $this->createServer();
81
			$server->setClass($providerClass, $this);
82
			if ($this->_persistent) {
83
				$server->setPersistence(SOAP_PERSISTENCE_SESSION);
84
			}
85
		} else {
86
			$server = $this->createServer();
87
		}
88
		try {
89
			$server->handle();
90
		} catch (\Exception $e) {
91
			if ($this->getApplication()->getMode() === TApplicationMode::Debug) {
92
				$this->fault($e->getMessage(), $e->__toString());
93
			} else {
94
				$this->fault($e->getMessage());
95
			}
96
		}
97
	}
98
99
	/**
100
	 * Generate a SOAP fault message.
101
	 * @param string $title message title
102
	 * @param mixed $details message details
103
	 * @param string $code message code, defalt is 'SERVER'.
104
	 * @param string $actor actors
105
	 * @param string $name message name
106
	 */
107
	public function fault($title, $details = '', $code = 'SERVER', $actor = '', $name = '')
108
	{
109
		Prado::trace('SOAP-Fault ' . $code . ' ' . $title . ' : ' . $details, 'Prado\Web\Services\TSoapService');
110
		$this->_server->fault($code, $title, $actor, $details, $name);
111
	}
112
113
	/**
114
	 * Guess the SOAP method request from the actual SOAP message
115
	 *
116
	 * @param string $class current handler class.
117
	 */
118
	protected function guessMethodCallRequested($class)
119
	{
120
		$namespace = $class . 'wsdl';
121
		$message = file_get_contents("php://input");
122
		$matches = [];
123
		if (preg_match('/xmlns:([^=]+)="urn:' . $namespace . '"/', $message, $matches)) {
124
			if (preg_match('/<' . $matches[1] . ':([a-zA-Z_]+[a-zA-Z0-9_]+)/', $message, $method)) {
125
				$this->_requestedMethod = $method[1];
126
			}
127
		}
128
	}
129
130
	/**
131
	 * Soap method guessed from the SOAP message received.
132
	 * @return string soap method request, null if not found.
133
	 */
134
	public function getRequestedMethod()
135
	{
136
		return $this->_requestedMethod;
137
	}
138
139
	/**
140
	 * Creates the SoapServer instance.
141
	 * @return \SoapServer
142
	 */
143
	protected function createServer()
144
	{
145
		if ($this->_server === null) {
146
			if ($this->getApplication()->getMode() === TApplicationMode::Debug) {
147
				ini_set("soap.wsdl_cache_enabled", 0);
148
			}
149
			$this->_server = new \SoapServer($this->getWsdlUri(), $this->getOptions());
150
		}
151
		return $this->_server;
152
	}
153
154
	/**
155
	 * @return array options for creating SoapServer instance
156
	 */
157
	protected function getOptions()
158
	{
159
		$options = [];
160
		if ($this->_version === '1.1') {
161
			$options['soap_version'] = SOAP_1_1;
162
		} elseif ($this->_version === '1.2') {
163
			$options['soap_version'] = SOAP_1_2;
164
		}
165
		if (!empty($this->_actor)) {
166
			$options['actor'] = $this->_actor;
167
		}
168
		if (!empty($this->_encoding)) {
169
			$options['encoding'] = $this->_encoding;
170
		}
171
		if (!empty($this->_uri)) {
172
			$options['uri'] = $this->_uri;
173
		}
174
		if (is_string($this->_classMap)) {
175
			foreach (preg_split('/\s*,\s*/', $this->_classMap) as $className) {
176
				$options['classmap'][$className] = $className;
177
			} //complex type uses the class name in the wsdl
178
		}
179
		return $options;
180
	}
181
182
	/**
183
	 * Returns the WSDL content of the SOAP server.
184
	 * If {@link getWsdlUri WsdlUri} is set, its content will be returned.
185
	 * If not, the {@link setProvider Provider} class will be investigated
186
	 * and the WSDL will be automatically genearted.
187
	 * @return string the WSDL content of the SOAP server
188
	 */
189
	public function getWsdl()
190
	{
191
		if ($this->_wsdlUri === '') {
192
			$provider = $this->getProvider();
193
			$providerClass = ($pos = strrpos($provider, '.')) !== false ? substr($provider, $pos + 1) : $provider;
194
			Prado::using($provider);
195
			if ($this->getApplication()->getMode() === TApplicationMode::Performance && ($cache = $this->getApplication()->getCache()) !== null) {
196
				$wsdl = $cache->get(self::WSDL_CACHE_PREFIX . $providerClass);
197
				if (is_string($wsdl)) {
198
					return $wsdl;
199
				}
200
				$wsdl = WsdlGenerator::generate($providerClass, $this->getUri(), $this->getEncoding());
201
				$cache->set(self::WSDL_CACHE_PREFIX . $providerClass, $wsdl);
202
				return $wsdl;
203
			} else {
204
				return WsdlGenerator::generate($providerClass, $this->getUri(), $this->getEncoding());
205
			}
206
		} else {
207
			return file_get_contents($this->_wsdlUri);
208
		}
209
	}
210
211
	/**
212
	 * @return string the URI for WSDL
213
	 */
214
	public function getWsdlUri()
215
	{
216
		if ($this->_wsdlUri === '') {
217
			return $this->getRequest()->getBaseUrl() . $this->getService()->constructUrl($this->getID() . '.wsdl', false);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type array expected by parameter $getParams of Prado\Web\Services\TSoapService::constructUrl(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

217
			return $this->getRequest()->getBaseUrl() . $this->getService()->constructUrl($this->getID() . '.wsdl', /** @scrutinizer ignore-type */ false);
Loading history...
218
		} else {
219
			return $this->_wsdlUri;
220
		}
221
	}
222
223
	/**
224
	 * @param string $value the URI for WSDL
225
	 */
226
	public function setWsdlUri($value)
227
	{
228
		$this->_wsdlUri = $value;
229
	}
230
231
	/**
232
	 * @return string the URI for the SOAP service
233
	 */
234
	public function getUri()
235
	{
236
		if ($this->_uri === '') {
237
			return $this->getRequest()->getBaseUrl() . $this->getService()->constructUrl($this->getID(), false);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type array expected by parameter $getParams of Prado\Web\Services\TSoapService::constructUrl(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

237
			return $this->getRequest()->getBaseUrl() . $this->getService()->constructUrl($this->getID(), /** @scrutinizer ignore-type */ false);
Loading history...
238
		} else {
239
			return $this->_uri;
240
		}
241
	}
242
243
	/**
244
	 * @param string $uri the URI for the SOAP service
245
	 */
246
	public function setUri($uri)
247
	{
248
		$this->_uri = $uri;
249
	}
250
251
	/**
252
	 * @return string the SOAP provider class (in namespace format)
253
	 */
254
	public function getProvider()
255
	{
256
		return $this->_provider;
257
	}
258
259
	/**
260
	 * @param string $provider the SOAP provider class (in namespace format)
261
	 */
262
	public function setProvider($provider)
263
	{
264
		$this->_provider = $provider;
265
	}
266
267
	/**
268
	 * @return string SOAP version, defaults to empty (meaning not set).
269
	 */
270
	public function getVersion()
271
	{
272
		return $this->_version;
273
	}
274
275
	/**
276
	 * @param string $value SOAP version, either '1.1' or '1.2'
277
	 * @throws TInvalidDataValueException if neither '1.1' nor '1.2'
278
	 */
279
	public function setVersion($value)
280
	{
281
		if ($value === '1.1' || $value === '1.2' || $value === '') {
282
			$this->_version = $value;
283
		} else {
284
			throw new TInvalidDataValueException('soapserver_version_invalid', $value);
285
		}
286
	}
287
288
	/**
289
	 * @return string actor of the SOAP service
290
	 */
291
	public function getActor()
292
	{
293
		return $this->_actor;
294
	}
295
296
	/**
297
	 * @param string $value actor of the SOAP service
298
	 */
299
	public function setActor($value)
300
	{
301
		$this->_actor = $value;
302
	}
303
304
	/**
305
	 * @return string encoding of the SOAP service
306
	 */
307
	public function getEncoding()
308
	{
309
		return $this->_encoding;
310
	}
311
312
	/**
313
	 * @param string $value encoding of the SOAP service
314
	 */
315
	public function setEncoding($value)
316
	{
317
		$this->_encoding = $value;
318
	}
319
320
	/**
321
	 * @return bool whether the SOAP service is persistent within session. Defaults to false.
322
	 */
323
	public function getSessionPersistent()
324
	{
325
		return $this->_persistent;
326
	}
327
328
	/**
329
	 * @param bool $value whether the SOAP service is persistent within session.
330
	 */
331
	public function setSessionPersistent($value)
332
	{
333
		$this->_persistent = TPropertyValue::ensureBoolean($value);
334
	}
335
336
	/**
337
	 * @return string comma delimit list of complex type classes.
338
	 */
339
	public function getClassMaps()
340
	{
341
		return $this->_classMap;
342
	}
343
344
	/**
345
	 * @param string $classes comma delimit list of class names
346
	 */
347
	public function setClassMaps($classes)
348
	{
349
		$this->_classMap = $classes;
350
	}
351
}
352