Completed
Branch master (099915)
by Fabio
08:02
created

TSoapServer   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 319
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 319
ccs 0
cts 185
cp 0
rs 7.44
wmc 52

25 Methods

Rating   Name   Duplication   Size   Complexity  
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 setClassMaps() 0 3 1
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 setID() 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

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

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

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