Completed
Pull Request — master (#63)
by Yuichi
07:08 queued 02:00
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 77
cts 77
cp 1
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A get() 0 7 1
A getStreamResponse() 0 14 2
A handleJsonError() 0 10 3
A multiGet() 0 23 3
A post() 0 12 1
A multiPost() 0 27 3
A getFilename() 0 8 2
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
26 2
    public function __construct(Client $client)
27
    {
28 2
        $this->client = $client;
29 2
    }
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 1
    public function get($fileKey, $guestSpaceId = null): string
40
    {
41 1
        $options = ['json' => ['fileKey' => $fileKey]];
42 1
        $response = $this->client->get(KintoneApi::generateUrl('file.json', $guestSpaceId), $options);
43
44 1
        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 2
    public function getStreamResponse($fileKey, $guestSpaceId = null): ResponseInterface
57
    {
58
        $options = [
59 2
            'json' => ['fileKey' => $fileKey],
60
            'stream' => true
61
        ];
62 2
        $result = $this->client->get(KintoneApi::generateUrl('file.json', $guestSpaceId), $options);
63 2
        if ($result instanceof RequestException) {
64 1
            $this->handleJsonError($result);
65 1
            throw $result;
66
        }
67
68 1
        return $result;
69
    }
70
71
    /**
72
     * @param RequestException $result
73
     * @throws RequestException
74
     */
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 1
            if ($service->isJsonResponse()) {
81 1
                $service->handleJsonError();
82
            }
83
        }
84 1
    }
85
86
    /**
87
     * @param array $fileKeys
88
     * @param int|null $guestSpaceId
89
     * @return array [contents, contents, ...] The order of $fileKeys
90
     */
91 1
    public function multiGet(array $fileKeys, $guestSpaceId = null): array
92
    {
93 1
        $result = [];
94 1
        $concurrency = $this->client->getConfig('concurrency');
95 1
        $headers = $this->client->getConfig('headers');
96 1
        $headers['Content-Type'] = 'application/json';
97 1
        $url = KintoneApi::generateUrl('file.json', $guestSpaceId);
98
        $requests = static function () use ($fileKeys, $url, $headers) {
99 1
            foreach ($fileKeys as $fileKey) {
100 1
                $body = \GuzzleHttp\json_encode(['fileKey' => $fileKey]);
101 1
                yield new Request('GET', $url, $headers, $body);
102
            }
103 1
        };
104 1
        $pool = new Pool($this->client, $requests(), [
105 1
            'concurrency' => $concurrency ?: 1,
106
            'fulfilled' => static function (ResponseInterface $response, $index) use (&$result) {
107 1
                $result[$index] = (string)$response->getBody();
108 1
            }
109
        ]);
110 1
        $pool->promise()->wait();
111
112 1
        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 2
    public function post($path, $guestSpaceId = null, $filename = null): string
125
    {
126 2
        $options = ['multipart' => [self::createMultipart($path, $filename)]];
127 2
        $this->changeLocale();
128
129
        /** @var JsonStream $stream */
130 2
        $stream = $this->client
131 2
            ->post(KintoneApi::generateUrl('file.json', $guestSpaceId), $options)
132 2
            ->getBody();
133
134 2
        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 1
    public function multiPost(array $fileNames, $guestSpaceId = null): array
144
    {
145 1
        $this->changeLocale();
146
147 1
        $result = [];
148 1
        $concurrency = $this->client->getConfig('concurrency');
149 1
        $headers = $this->client->getConfig('headers');
150 1
        $url = KintoneApi::generateUrl('file.json', $guestSpaceId);
151
        $requests = static function () use ($fileNames, $url, $headers) {
152 1
            foreach ($fileNames as $filename) {
153 1
                $body = new MultipartStream([self::createMultipart($filename)]);
154 1
                yield new Request('POST', $url, $headers, $body);
155
            }
156 1
        };
157 1
        $pool = new Pool($this->client, $requests(), [
158 1
            'concurrency' => $concurrency ?: 1,
159
            'fulfilled' => static function (ResponseInterface $response, $index) use (&$result) {
160
                /** @var JsonStream $stream */
161 1
                $stream = $response->getBody();
162 1
                $result[$index] = $stream->jsonSerialize()['fileKey'];
163 1
            }
164
        ]);
165 1
        $pool->promise()->wait();
166 1
        ksort($result);
167
168 1
        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 12
    public static function getFilename($name): string
178
    {
179 12
        $originalName = str_replace('\\', '/', $name);
180 12
        $pos = strrpos($originalName, '/');
181 12
        $originalName = false === $pos ? $originalName : substr($originalName, $pos + 1);
182
183 12
        return $originalName;
184
    }
185
186 3
    private function changeLocale(): void
187
    {
188 3
        $baseUri = $this->client->getConfig('base_uri');
189 3
        if (strpos($baseUri->getHost(), 'cybozu.com') > 0) { // Japanese kintone
190 3
            setlocale(LC_ALL, 'ja_JP.UTF-8');
191
        }
192 3
    }
193
194
    /**
195
     * @param string $path
196
     * @param string|null $filename
197
     * @return array
198
     */
199 3
    private static function createMultipart($path, $filename = null): array
200
    {
201
        return [
202 3
            'name' => 'file',
203 3
            'filename' => self::getFilename($filename ?: $path),
204 3
            'contents' => fopen($path, 'rb'),
205 3
            'headers' => ['Content-Type' => mime_content_type($path)]
206
        ];
207
    }
208
}
209