Completed
Push — master ( c011fc...384d9c )
by Milan
01:49
created

src/Request/Queue.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace h4kuna\Fio\Request;
4
5
use GuzzleHttp,
6
	h4kuna\Fio,
7
	h4kuna\Fio\Response\Pay,
8
	Nette\Utils;
9
use Psr\Http\Message\ResponseInterface;
10
11
class Queue implements IQueue
12
{
13
14
	/** @var string[] */
15
	private static $tokens = [];
16
17
	/** @var int */
18
	private $limitLoop = 5;
19
20
	/** @var bool */
21
	private $sleep = true;
22
23
	/** @var array */
24
	private $downloadOptions = [];
25
26
	/** @var string */
27
	private $tempDir;
28
29
	public function __construct($tempDir)
30
	{
31
		$this->tempDir = $tempDir;
32
	}
33
34
	/**
35
	 * @param int $limitLoop
36
	 */
37
	public function setLimitLoop($limitLoop)
38
	{
39
		$this->limitLoop = (int) $limitLoop;
40
	}
41
42
	/**
43
	 * @param array|\Iterator $downloadOptions
44
	 */
45
	public function setDownloadOptions($downloadOptions)
46
	{
47
		foreach ($downloadOptions as $define => $value) {
48
			if (is_string($define) && defined($define)) {
49
				$define = constant($define);
50
			}
51
			$this->downloadOptions[$define] = $value;
52
		}
53
	}
54
55
	public function setSleep($sleep)
56
	{
57
		$this->sleep = (bool) $sleep;
58
	}
59
60
	/**
61
	 * @param $token
62
	 * @param string $url
63
	 * @return mixed|string
64
	 * @throws Fio\QueueLimitException
65
	 * @throws Fio\ServiceUnavailableException
66
	 */
67
	public function download($token, $url)
68
	{
69
		$response = $this->request($token, function (GuzzleHttp\Client $client) use ($url) {
70
			return $client->request('GET', $url, $this->downloadOptions);
71
		});
72
		self::detectDownloadResponse($response);
73
		return $response->getBody();
74
	}
75
76
	/**
77
	 * @return Pay\IResponse
78
	 * @throws Fio\QueueLimitException
79
	 */
80
	public function upload($url, $token, array $post, $filename)
81
	{
82
		$newPost = [];
83
		foreach ($post as $name => $value) {
84
			$newPost[] = ['name' => $name, 'contents' => $value];
85
		}
86
		$newPost[] = ['name' => 'file', 'contents' => fopen($filename, 'r')];
87
88
		$response = $this->request($token, function (GuzzleHttp\Client $client) use ($url, $newPost) {
89
			return $client->request('POST', $url, [GuzzleHttp\RequestOptions::MULTIPART => $newPost]);
90
		});
91
		return self::createXmlResponse($response->getBody());
92
	}
93
94
	/**
95
	 * @param $token
96
	 * @param $fallback
97
	 * @param string $action
0 ignored issues
show
There is no parameter named $action. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
98
	 * @return ResponseInterface
99
	 * @throws Fio\QueueLimitException
100
	 * @throws Fio\ServiceUnavailableException
101
	 */
102
	private function request($token, $fallback)
103
	{
104
		$request = new GuzzleHttp\Client(['headers' => ['X-Powered-By' => 'h4kuna/fio']]);
105
		$tempFile = $this->loadFileName($token);
106
		$file = fopen(self::safeProtocol($tempFile), 'w');
107
		$i = 0;
108
		do {
109
			$next = false;
110
			++$i;
111
			try {
112
				$response = $fallback($request);
113
			} catch (GuzzleHttp\Exception\ClientException $e) {
114
				if ($e->getCode() !== self::HEADER_CONFLICT || !$this->sleep) {
115
					fclose($file);
116
					throw $e;
117
				} elseif ($i >= $this->limitLoop) {
118
					fclose($file);
119
					throw new Fio\QueueLimitException('You have limit up requests to server ' . $this->limitLoop);
120
				}
121
				self::sleep($tempFile);
122
				$next = true;
123
			} catch (GuzzleHttp\Exception\ServerException $e) {
124
				if($e->hasResponse()) {
125
					self::detectDownloadResponse($e->getResponse());
126
				}
127
				throw self::createServiceUnavailableException();
128
			} catch (GuzzleHttp\Exception\ConnectException $e) {
129
				throw self::createServiceUnavailableException();
130
			}
131
		} while ($next);
132
		fclose($file);
133
		touch($tempFile);
134
135
		return $response;
136
	}
137
138
	/**
139
	 * @param ResponseInterface $response
140
	 * @throws Fio\ServiceUnavailableException
141
	 */
142
	private static function detectDownloadResponse($response)
143
	{
144
		/* @var $contentTypeHeaders array */
145
		$contentTypeHeaders = $response->getHeader('Content-Type');
146
		$contentType = array_shift($contentTypeHeaders);
147
		if ($contentType === 'text/xml;charset=UTF-8') {
148
			$xmlResponse = self::createXmlResponse($response);
149
			if ($xmlResponse->getErrorCode() !== 0) {
150
				throw new Fio\ServiceUnavailableException($xmlResponse->getError(), $xmlResponse->getErrorCode());
151
			}
152
		}
153
	}
154
155
	private static function sleep($filename)
156
	{
157
		$criticalTime = time() - filemtime($filename);
158
		if ($criticalTime < self::WAIT_TIME) {
159
			sleep(self::WAIT_TIME - $criticalTime);
160
		}
161
	}
162
163
	/**
164
	 * @param string $token
165
	 * @return string
166
	 */
167
	private function loadFileName($token)
168
	{
169
		$key = substr($token, 10, -10);
170
		if (!isset(self::$tokens[$key])) {
171
			self::$tokens[$key] = $this->tempDir . DIRECTORY_SEPARATOR . md5($key);
172
		}
173
174
		return self::$tokens[$key];
175
	}
176
177
	private static function safeProtocol($filename)
178
	{
179
		return Utils\SafeStream::PROTOCOL . '://' . $filename;
180
	}
181
182
	/**
183
	 * @param ResponseInterface|GuzzleHttp\Psr7\Stream $response
184
	 * @return Pay\XMLResponse
185
	 */
186
	private static function createXmlResponse($response)
187
	{
188
		return new Pay\XMLResponse($response->getBody()->getContents());
189
	}
190
191
192
	private static function createServiceUnavailableException()
193
	{
194
		return new Fio\ServiceUnavailableException('Fio server does not response.');
195
	}
196
197
}
198