Passed
Push — feature/unit-tests ( 3fd24a...669eab )
by Yuichi
02:24
created

File::multiGet()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 15
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 22
ccs 0
cts 19
cp 0
crap 12
rs 9.7666
1
<?php
2
3
namespace CybozuHttp\Api\Kintone;
4
5
use CybozuHttp\Client;
6
use CybozuHttp\Api\KintoneApi;
7
use CybozuHttp\Middleware\JsonStream;
8
use CybozuHttp\Service\ResponseService;
9
use GuzzleHttp\Exception\RequestException;
10
use GuzzleHttp\Pool;
11
use GuzzleHttp\Psr7\MultipartStream;
12
use GuzzleHttp\Psr7\Request;
13
use Psr\Http\Message\ResponseInterface;
14
15
16
/**
17
 * @author ochi51 <[email protected]>
18
 */
19
class File
20
{
21
    /**
22
     * @var Client
23
     */
24
    private $client;
25
26 1
    public function __construct(Client $client)
27
    {
28 1
        $this->client = $client;
29
    }
30
31
    /**
32
     * Get file
33
     * https://cybozudev.zendesk.com/hc/ja/articles/202166180#step1
34
     *
35
     * @param string $fileKey
36
     * @param int $guestSpaceId
37
     * @return string
38
     */
39
    public function get($fileKey, $guestSpaceId = null): string
40
    {
41
        $options = ['json' => ['fileKey' => $fileKey]];
42
        $response = $this->client->get(KintoneApi::generateUrl('file.json', $guestSpaceId), $options);
43
44
        return (string)$response->getBody();
45
    }
46
47
    /**
48
     * Get file stream response
49
     * https://cybozudev.zendesk.com/hc/ja/articles/202166180#step1
50
     *
51
     * @param string $fileKey
52
     * @param int $guestSpaceId
53
     * @return ResponseInterface
54
     * @throws RequestException
55
     */
56
    public function getStreamResponse($fileKey, $guestSpaceId = null): ResponseInterface
57
    {
58
        $options = [
59
            'json' => ['fileKey' => $fileKey],
60
            'stream' => true
61
        ];
62
        $result = $this->client->get(KintoneApi::generateUrl('file.json', $guestSpaceId), $options);
63
        if ($result instanceof RequestException) {
64
            $this->handleJsonError($result);
65
            throw $result;
66
        }
67
68
        return $result;
69
    }
70
71
    /**
72
     * @param RequestException $result
73
     * @throws RequestException
74
     */
75
    private function handleJsonError(RequestException $result): void
76
    {
77
        $response = $result->getResponse();
78
        if ($response instanceof ResponseInterface) {
79
            $service = new ResponseService($result->getRequest(), $response);
80
            if ($service->isJsonResponse()) {
81
                $service->handleJsonError();
82
            }
83
        }
84
    }
85
86
    /**
87
     * @param array $fileKeys
88
     * @param int|null $guestSpaceId
89
     * @return array [contents, contents, ...] The order of $fileKeys
90
     */
91
    public function multiGet(array $fileKeys, $guestSpaceId = null): array
92
    {
93
        $result = [];
94
        $concurrency = $this->client->getConfig('concurrency');
0 ignored issues
show
Deprecated Code introduced by
The function GuzzleHttp\Client::getConfig() has been deprecated: Client::getConfig will be removed in guzzlehttp/guzzle:8.0. ( Ignorable by Annotation )

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

94
        $concurrency = /** @scrutinizer ignore-deprecated */ $this->client->getConfig('concurrency');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
95
        $headers = $this->client->getConfig('headers');
0 ignored issues
show
Deprecated Code introduced by
The function GuzzleHttp\Client::getConfig() has been deprecated: Client::getConfig will be removed in guzzlehttp/guzzle:8.0. ( Ignorable by Annotation )

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

95
        $headers = /** @scrutinizer ignore-deprecated */ $this->client->getConfig('headers');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
96
        $headers['Content-Type'] = 'application/json';
97
        $url = KintoneApi::generateUrl('file.json', $guestSpaceId);
98
        $requests = static function () use ($fileKeys, $url, $headers) {
99
            foreach ($fileKeys as $fileKey) {
100
                $body = \GuzzleHttp\json_encode(['fileKey' => $fileKey]);
0 ignored issues
show
Deprecated Code introduced by
The function GuzzleHttp\json_encode() has been deprecated: json_encode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonEncode instead. ( Ignorable by Annotation )

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

100
                $body = /** @scrutinizer ignore-deprecated */ \GuzzleHttp\json_encode(['fileKey' => $fileKey]);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
101
                yield new Request('GET', $url, $headers, $body);
102
            }
103
        };
104
        $pool = new Pool($this->client, $requests(), [
105
            'concurrency' => $concurrency ?: 1,
106
            'fulfilled' => static function (ResponseInterface $response, $index) use (&$result) {
107
                $result[$index] = (string)$response->getBody();
108
            }
109
        ]);
110
        $pool->promise()->wait();
111
112
        return $result;
113
    }
114
115
    /**
116
     * Post file
117
     * https://cybozudev.zendesk.com/hc/ja/articles/201941824#step1
118
     *
119
     * @param string $path
120
     * @param int|null $guestSpaceId
121
     * @param string|null $filename
122
     * @return string
123
     */
124
    public function post($path, $guestSpaceId = null, $filename = null): string
125
    {
126
        $options = ['multipart' => [self::createMultipart($path, $filename)]];
127
        $this->changeLocale();
128
129
        /** @var JsonStream $stream */
130
        $stream = $this->client
131
            ->post(KintoneApi::generateUrl('file.json', $guestSpaceId), $options)
132
            ->getBody();
133
134
        return $stream->jsonSerialize()['fileKey'];
135
    }
136
137
    /**
138
     * @param array $fileNames
139
     * @param int|null $guestSpaceId
140
     * @return array [fileKey, fileKey, ...] The order of $fileNames
141
     * @throws \InvalidArgumentException
142
     */
143
    public function multiPost(array $fileNames, $guestSpaceId = null): array
144
    {
145
        $this->changeLocale();
146
147
        $result = [];
148
        $concurrency = $this->client->getConfig('concurrency');
0 ignored issues
show
Deprecated Code introduced by
The function GuzzleHttp\Client::getConfig() has been deprecated: Client::getConfig will be removed in guzzlehttp/guzzle:8.0. ( Ignorable by Annotation )

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

148
        $concurrency = /** @scrutinizer ignore-deprecated */ $this->client->getConfig('concurrency');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
149
        $headers = $this->client->getConfig('headers');
0 ignored issues
show
Deprecated Code introduced by
The function GuzzleHttp\Client::getConfig() has been deprecated: Client::getConfig will be removed in guzzlehttp/guzzle:8.0. ( Ignorable by Annotation )

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

149
        $headers = /** @scrutinizer ignore-deprecated */ $this->client->getConfig('headers');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
150
        $url = KintoneApi::generateUrl('file.json', $guestSpaceId);
151
        $requests = static function () use ($fileNames, $url, $headers) {
152
            foreach ($fileNames as $filename) {
153
                $body = new MultipartStream([self::createMultipart($filename)]);
154
                yield new Request('POST', $url, $headers, $body);
155
            }
156
        };
157
        $pool = new Pool($this->client, $requests(), [
158
            'concurrency' => $concurrency ?: 1,
159
            'fulfilled' => static function (ResponseInterface $response, $index) use (&$result) {
160
                /** @var JsonStream $stream */
161
                $stream = $response->getBody();
162
                $result[$index] = $stream->jsonSerialize()['fileKey'];
163
            }
164
        ]);
165
        $pool->promise()->wait();
166
        ksort($result);
167
168
        return $result;
169
    }
170
171
    /**
172
     * Returns locale independent base name of the given path.
173
     *
174
     * @param string $name The new file name
175
     * @return string containing
176
     */
177
    public static function getFilename($name): string
178
    {
179
        $originalName = str_replace('\\', '/', $name);
180
        $pos = strrpos($originalName, '/');
181
        $originalName = false === $pos ? $originalName : substr($originalName, $pos + 1);
182
183
        return $originalName;
184
    }
185
186
    private function changeLocale(): void
187
    {
188
        $baseUri = $this->client->getConfig('base_uri');
0 ignored issues
show
Deprecated Code introduced by
The function GuzzleHttp\Client::getConfig() has been deprecated: Client::getConfig will be removed in guzzlehttp/guzzle:8.0. ( Ignorable by Annotation )

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

188
        $baseUri = /** @scrutinizer ignore-deprecated */ $this->client->getConfig('base_uri');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
189
        if (strpos($baseUri->getHost(), 'cybozu.com') > 0) { // Japanese kintone
190
            setlocale(LC_ALL, 'ja_JP.UTF-8');
191
        }
192
    }
193
194
    /**
195
     * @param string $path
196
     * @param string|null $filename
197
     * @return array
198
     */
199
    private static function createMultipart($path, $filename = null): array
200
    {
201
        return [
202
            'name' => 'file',
203
            'filename' => self::getFilename($filename ?: $path),
204
            'contents' => fopen($path, 'rb'),
205
            'headers' => ['Content-Type' => mime_content_type($path)]
206
        ];
207
    }
208
}
209