Completed
Push — master ( 4f2cea...0c21fc )
by Milan
02:45
created

Queue   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
wmc 21
lcom 1
cbo 6
dl 0
loc 125
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A setLimitLoop() 0 4 1
A setDownloadOptions() 0 12 4
A setSleep() 0 4 1
A download() 0 6 1
A upload() 0 14 2
B request() 0 27 6
A sleep() 0 7 2
A loadFileName() 0 9 2
A safeProtocol() 0 4 1
1
<?php
2
3
namespace h4kuna\Fio\Request;
4
5
use GuzzleHttp,
6
	h4kuna\Fio,
7
	h4kuna\Fio\Response\Pay,
8
	Nette\Utils;
9
10
class Queue implements IQueue
11
{
12
13
	/** @var string[] */
14
	private static $tokens = [];
15
16
	/** @var int */
17
	private $limitLoop = 5;
18
19
	/** @var bool */
20
	private $sleep = TRUE;
21
22
	/** @var array */
23
	private $downloadOptions = [];
24
25
	/** @var string */
26
	private $tempDir;
27
28
	public function __construct($tempDir)
29
	{
30
		$this->tempDir = $tempDir;
31
	}
32
33
	public function setLimitLoop($limitLoop)
34
	{
35
		$this->limitLoop = $limitLoop;
36
	}
37
38
	public function setDownloadOptions($downloadOptions)
39
	{
40
		foreach ($downloadOptions as $define => $value) {
41
			if (is_string($define)) {
42
				if (!defined($define)) {
43
					throw new Fio\InvalidArgumentException('Value must be name of global constant like CURLOPT_*.');
44
				}
45
				$define = constant($define);
46
			}
47
			$this->downloadOptions[$define] = $value;
48
		}
49
	}
50
51
	public function setSleep($sleep)
52
	{
53
		$this->sleep = (bool) $sleep;
54
	}
55
56
	public function download($token, $url)
57
	{
58
		return $this->request($token, function(GuzzleHttp\Client $client) use ($url) {
59
				return $client->request('GET', $url, $this->downloadOptions);
60
			});
61
	}
62
63
	/** @return Pay\IResponse  */
64
	public function upload($url, $token, array $post, $filename)
65
	{
66
		$newPost = [];
67
		foreach ($post as $name => $value) {
68
			$newPost[] = ['name' => $name, 'contents' => $value];
69
		}
70
		$newPost[] = ['name' => 'file', 'contents' => fopen($filename, 'r')];
71
72
		/* @var $response GuzzleHttp\Psr7\Stream */
73
		$response = $this->request($token, function(GuzzleHttp\Client $client) use ($url, $newPost) {
74
			return $client->request('POST', $url, [GuzzleHttp\RequestOptions::MULTIPART => $newPost]);
75
		});
76
		return new Pay\XMLResponse($response->getContents());
77
	}
78
79
	private function request($token, $fallback)
80
	{
81
		$request = new GuzzleHttp\Client;
82
		$tempFile = $this->loadFileName($token);
83
		$file = fopen(self::safeProtocol($tempFile), 'w');
84
		$i = 0;
85
		do {
86
			$next = FALSE;
87
			++$i;
88
			try {
89
				$response = $fallback($request);
90
			} catch (GuzzleHttp\Exception\ClientException $e) {
91
				if ($e->getCode() !== self::HEADER_CONFLICT || !$this->sleep) {
92
					fclose($file);
93
					throw $e;
94
				} elseif ($i >= $this->limitLoop) {
95
					fclose($file);
96
					throw new Fio\QueueLimitException('You have limit up requests to server ' . $this->limitLoop);
97
				}
98
				self::sleep($tempFile);
99
				$next = TRUE;
100
			}
101
		} while ($next);
102
		fclose($file);
103
		touch($tempFile);
104
		return $response->getBody();
105
	}
106
107
	private static function sleep($filename)
108
	{
109
		$criticalTime = time() - filemtime($filename);
110
		if ($criticalTime < self::WAIT_TIME) {
111
			sleep(self::WAIT_TIME - $criticalTime);
112
		}
113
	}
114
115
	/**
116
	 * @param string $token
117
	 * @return string
118
	 */
119
	private function loadFileName($token)
120
	{
121
		$key = substr($token, 10, -10);
122
		if (!isset(self::$tokens[$key])) {
123
			self::$tokens[$key] = $this->tempDir . DIRECTORY_SEPARATOR . md5($key);
124
		}
125
126
		return self::$tokens[$key];
127
	}
128
129
	private static function safeProtocol($filename)
130
	{
131
		return Utils\SafeStream::PROTOCOL . '://' . $filename;
132
	}
133
134
}
135