Completed
Push — master ( 475fd8...dd137e )
by Yuichi
07:47 queued 01:16
created

File   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 190
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 10
dl 0
loc 190
ccs 66
cts 66
cp 1
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A handleJsonError() 0 10 3
A getFilename() 0 8 2
A __construct() 0 4 1
A get() 0 7 1
A getStreamResponse() 0 14 2
A multiGet() 0 23 3
A post() 0 12 1
A multiPost() 0 27 3
A changeLocale() 0 7 2
A createMultipart() 0 9 2
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 1
26
    public function __construct(Client $client)
27 1
    {
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 1
     */
39
    public function get($fileKey, $guestSpaceId = null): string
40 1
    {
41 1
        $options = ['json' => ['fileKey' => $fileKey]];
42
        $response = $this->client->get(KintoneApi::generateUrl('file.json', $guestSpaceId), $options);
43 1
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 1
     * @throws RequestException
55
     */
56
    public function getStreamResponse($fileKey, $guestSpaceId = null): ResponseInterface
57 1
    {
58
        $options = [
59
            'json' => ['fileKey' => $fileKey],
60
            'stream' => true
61 1
        ];
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 1
    }
70
71 1
    /**
72 1
     * @param RequestException $result
73 1
     * @throws RequestException
74 1
     */
75 1
    private function handleJsonError(RequestException $result): void
76
    {
77 1
        $response = $result->getResponse();
78 1
        if ($response instanceof ResponseInterface) {
79 1
            $service = new ResponseService($result->getRequest(), $response);
80
            if ($service->isJsonResponse()) {
81 1
                $service->handleJsonError();
82 1
            }
83 1
        }
84
    }
85 1
86 1
    /**
87
     * @param array $fileKeys
88 1
     * @param int|null $guestSpaceId
89
     * @return array [contents, contents, ...] The order of $fileKeys
90 1
     */
91
    public function multiGet(array $fileKeys, $guestSpaceId = null): array
92
    {
93
        $result = [];
94
        $concurrency = $this->client->getConfig('concurrency');
95
        $headers = $this->client->getConfig('headers');
96
        $headers['Content-Type'] = 'application/json';
97
        $url = KintoneApi::generateUrl('file.json', $guestSpaceId);
98
        $requests = function () use ($fileKeys, $url, $headers) {
99
            foreach ($fileKeys as $fileKey) {
100
                $body = \GuzzleHttp\json_encode(['fileKey' => $fileKey]);
101
                yield new Request('GET', $url, $headers, $body);
102 2
            }
103
        };
104 2
        $pool = new Pool($this->client, $requests(), [
105 2
            'concurrency' => $concurrency ?: 1,
106
            'fulfilled' => function (ResponseInterface $response, $index) use (&$result) {
107
                $result[$index] = (string)$response->getBody();
108 2
            }
109 2
        ]);
110 2
        $pool->promise()->wait();
111
112 2
        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 1
     * @param string|null $filename
122
     * @return string
123 1
     */
124
    public function post($path, $guestSpaceId = null, $filename = null): string
125 1
    {
126 1
        $options = ['multipart' => [self::createMultipart($path, $filename)]];
127 1
        $this->changeLocale();
128 1
129
        /** @var JsonStream $stream */
130 1
        $stream = $this->client
131 1
            ->post(KintoneApi::generateUrl('file.json', $guestSpaceId), $options)
132 1
            ->getBody();
133
134 1
        return $stream->jsonSerialize()['fileKey'];
135 1
    }
136 1
137
    /**
138
     * @param array $fileNames
139 1
     * @param int|null $guestSpaceId
140 1
     * @return array [fileKey, fileKey, ...] The order of $fileNames
141 1
     * @throws \InvalidArgumentException
142
     */
143 1
    public function multiPost(array $fileNames, $guestSpaceId = null): array
144 1
    {
145
        $this->changeLocale();
146 1
147
        $result = [];
148
        $concurrency = $this->client->getConfig('concurrency');
149
        $headers = $this->client->getConfig('headers');
150
        $url = KintoneApi::generateUrl('file.json', $guestSpaceId);
151
        $requests = 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 12
            }
156
        };
157 12
        $pool = new Pool($this->client, $requests(), [
158 12
            'concurrency' => $concurrency ?: 1,
159 12
            'fulfilled' => function (ResponseInterface $response, $index) use (&$result) {
160
                /** @var JsonStream $stream */
161 12
                $stream = $response->getBody();
162
                $result[$index] = $stream->jsonSerialize()['fileKey'];
163
            }
164 3
        ]);
165
        $pool->promise()->wait();
166 3
        ksort($result);
167 3
168 3
        return $result;
169
    }
170 3
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 3
    public static function getFilename($name): string
178
    {
179
        $originalName = str_replace('\\', '/', $name);
180 3
        $pos = strrpos($originalName, '/');
181 3
        $originalName = false === $pos ? $originalName : substr($originalName, $pos + 1);
182 3
183 3
        return $originalName;
184
    }
185
186
    private function changeLocale(): void
187
    {
188
        $baseUri = $this->client->getConfig('base_uri');
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