Completed
Pull Request — master (#17)
by
unknown
01:27
created

Ares::loadByIdentificationNumbers()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 52
rs 8.425
c 0
b 0
f 0
cc 6
nc 9
nop 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php declare(strict_types=1);
2
3
namespace h4kuna\Ares;
4
5
use h4kuna\Ares\Exceptions\ConnectionException;
6
use h4kuna\Ares\Exceptions\IdentificationNumberNotFoundException;
7
8
class Ares
9
{
10
11
	public const URL = 'https://wwwinfo.mfcr.cz/cgi-bin/ares/darv_bas.cgi';
12
	public const POST_URL = 'https://wwwinfo.mfcr.cz/cgi-bin/ares/xar.cgi';
13
	private const POST_IDENTIFICATION_NUMBERS_LIMIT = 100; // in one post request can be max 100 identification numbers
14
15
	/** @var IFactory */
16
	private $factory;
17
18
	/** @var DataProvider */
19
	private $dataProvider;
20
21
22
	public function __construct(IFactory $factory = null)
23
	{
24
		if ($factory === null) {
25
			$factory = new Factory();
26
		}
27
		$this->factory = $factory;
28
	}
29
30
31
	/**
32
	 * @param array|string[] $identificationNumbers
33
	 * @param array $options
34
	 * @return array|Data[]|Error[]
35
	 * @throws \GuzzleHttp\Exception\GuzzleException
36
	 * @throws \Exception
37
	 */
38
	public function loadByIdentificationNumbers(array $identificationNumbers, $options = []): array
39
	{
40
		$client = $this->factory->createGuzzleClient($options);
41
		$offset = 0;
42
		$output = [];
43
44
		$identificationNumbersCount = count($identificationNumbers);
45
		while (($identificationNumbersCount - $offset) > 0) {
46
			$identificationNumbersBatch = array_slice($identificationNumbers, $offset,self::POST_IDENTIFICATION_NUMBERS_LIMIT, TRUE);
47
			$offset += self::POST_IDENTIFICATION_NUMBERS_LIMIT;
48
49
			$response = $client->request('POST', self::POST_URL, [
50
				'headers' => [
51
					'Content-type' => 'application/xml'
52
				],
53
				'body' => $this->factory->createBodyFactory()->createBodyContent($identificationNumbersBatch)
54
			]);
55
56
57
			$simpleXml = simplexml_load_string($response->getBody()->getContents(), "SimpleXMLElement", 0, 'SOAP-ENV', true);
58
			if (!$simpleXml) {
59
				throw new ConnectionException();
60
			}
61
			$simpleXml->registerXPathNamespace('SOAP-ENV', 'http://schemas.xmlsoap.org/soap/envelope/');
62
63
64
			$responseData = $simpleXml->children('SOAP-ENV', true)
65
				->Body
66
				->children('are', true)
67
				->children('are', true);
68
69
			foreach ($responseData as $item) {
70
				$D = $item->children('D' , true);
71
				$pid = (int) $D->PID->__toString();
72
73
				try {
74
					if($D->E->asXML() !== FALSE) {
75
						$DE = $D->E->children('D', TRUE);
76
						throw new IdentificationNumberNotFoundException(trim($DE->ET->__toString()), $DE->EK->__toString());
77
					}
78
79
					$this->processXml($D->VBAS, $this->getDataProvider()->prepareData());
80
81
					$output[$pid] = $this->getData();
82
				} catch (IdentificationNumberNotFoundException $exception) {
83
					$output[$pid] = new Error($exception->getCode(), $exception->getMessage());
84
				}
85
			}
86
		}
87
88
		return $output;
89
	}
90
91
92
	/**
93
	 * Load fresh data.
94
	 * @throws IdentificationNumberNotFoundException
95
	 */
96
	public function loadData(string $in, array $options = []): Data
97
	{
98
		$this->loadXML($in, $options);
99
		return $this->getData();
100
	}
101
102
103
	/**
104
	 * Get temporary data.
105
	 */
106
	public function getData(): Data
107
	{
108
		return $this->getDataProvider()->getData();
109
	}
110
111
112
	/**
113
	 * Load XML and fill Data object
114
	 * @throws IdentificationNumberNotFoundException
115
	 */
116
	private function loadXML(string $in, array $options)
117
	{
118
		$client = $this->factory->createGuzzleClient($options);
119
		try {
120
			$xmlSource = $client->request('GET', $this->createUrl($in))->getBody()->getContents();
121
		} catch (\Throwable $e) {
122
			throw new ConnectionException($e->getMessage(), $e->getCode(), $e);
123
		}
124
		$xml = @simplexml_load_string($xmlSource);
125
		if (!$xml) {
126
			throw new ConnectionException();
127
		}
128
129
		$ns = $xml->getDocNamespaces();
130
		$answer = $xml->children($ns['are'])->children($ns['D']);
131
		$this->parseErrorAnswer($xml, $in);
132
		$this->processXml($answer->VBAS, $this->getDataProvider()->prepareData());
133
	}
134
135
136
	protected function processXml(\SimpleXMLElement $xml, DataProvider $dataProvider): void
137
	{
138
		$dataProvider->setIN((string) $xml->ICO)
139
			->setTIN((string) $xml->DIC)
140
			->setCompany((string) $xml->OF)
141
			->setZip(self::exists($xml->AA, 'PSC'))
142
			->setStreet(self::exists($xml->AA, 'NU'))
143
			->setCity(self::exists($xml->AA, 'N'))
144
			->setHouseNumber(self::exists($xml->AA, 'CD'), self::exists($xml->AA, 'CO'), self::exists($xml->AA, 'CA'))
145
			->setCityPost(self::exists($xml->AA, 'NMC'))
146
			->setCityDistrict(self::exists($xml->AA, 'NCO'))
147
			->setIsPerson(self::exists($xml->PF, 'KPF'))
148
			->setCreated((string) $xml->DV)
149
			->setNace(self::existsArray($xml->Nace, 'NACE'));
150
151
		$dataProvider->setDissolved(isset($xml->DZ) ? (string) $xml->DZ : null);
152
153
		if (isset($xml->ROR)) {
154
			$dataProvider
155
				->setFileNumber((string) $xml->ROR->SZ->OV)
156
				->setCourt((string) $xml->ROR->SZ->SD->T);
157
		} else {
158
			$dataProvider
159
				->setFileNumber('')
160
				->setCourt('');
161
		}
162
	}
163
164
165
	private function createUrl(string $inn): string
166
	{
167
		$parameters = [
168
			'ico' => $inn,
169
			'aktivni' => 'false',
170
		];
171
		return self::URL . '?' . http_build_query($parameters);
172
	}
173
174
175
	private function getDataProvider(): DataProvider
176
	{
177
		if ($this->dataProvider === null) {
178
			$this->dataProvider = $this->factory->createDataProvider();
179
		}
180
		return $this->dataProvider;
181
	}
182
183
184
	private static function exists(\SimpleXMLElement $element, string $property): string
185
	{
186
		return isset($element->{$property}) ? ((string) $element->{$property}) : '';
187
	}
188
189
190
	private static function existsArray(\SimpleXMLElement $element, string $property): array
191
	{
192
		return isset($element->{$property}) ? ((array) $element->{$property}) : [];
193
	}
194
195
196
	private function parseErrorAnswer(\SimpleXMLElement $answer, string $in): void
197
	{
198
		$errorMessage = self::xmlValue($answer, '//D:ET[1]');
199
		$errorCode = self::xmlValue($answer, '//D:EK[1]');
200
		if ($errorMessage === null && $errorCode === null) {
201
			return;
202
		}
203
204
		// 61 - subject disappeared
205
		// 71 - not exists
206
		if (empty($errorMessage)) {
207
			throw new ConnectionException();
208
		}
209
		throw new IdentificationNumberNotFoundException(sprintf('IN "%s". %s', $in, $errorMessage), (int) $errorCode);
210
	}
211
212
213
	private static function xmlValue(\SimpleXMLElement $xml, string $xpath): ?string
214
	{
215
		$result = $xml->xpath($xpath);
216
		if ($result === []) {
217
			return null;
218
		}
219
		return trim((string) $result[0]);
220
	}
221
222
}
223