Completed
Push — 0.1 ( 1296ef...144915 )
by Yuichi
19:51 queued 09:46
created

Comments::createPostRequestsCallback()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 0
cts 0
cp 0
rs 9.584
c 0
b 0
f 0
cc 3
nc 1
nop 3
crap 12
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 GuzzleHttp\Pool;
9
use GuzzleHttp\Psr7\Request;
10
use Psr\Http\Message\ResponseInterface;
11
12
/**
13
 * @author ochi51 <[email protected]>
14
 */
15
class Comments
16
{
17
    /**
18 2
     * @var Client
19
     */
20 2
    private $client;
21 2
22
    public function __construct(Client $client)
23
    {
24
        $this->client = $client;
25
    }
26
27
    /**
28
     * Get record comments
29
     * https://cybozudev.zendesk.com/hc/ja/articles/208242326
30
     *
31
     * @param int $appId
32
     * @param int $recordId
33
     * @param string $order "asc" or "desc"
34
     * @param int $offset
35 2
     * @param int $limit Max = 10
36
     * @param int $guestSpaceId
37
     * @return array
38 2
     */
39 2
    public function get($appId, $recordId, $order = 'desc', $offset = 0, $limit = 10, $guestSpaceId = null): array
40 2
    {
41 2
        $options = ['json' => [
42
            'app' => $appId,
43 2
            'record' => $recordId,
44
            'order' => $order,
45 2
            'offset' => $offset,
46 2
            'limit' => $limit
47 2
        ]];
48
49
        /** @var JsonStream $stream */
50
        $stream = $this->client
51
            ->get(KintoneApi::generateUrl('record/comments.json', $guestSpaceId), $options)
52
            ->getBody();
53
54
        return $stream->jsonSerialize()['comments'];
55
    }
56
57
    /**
58
     * @param int $appId
59
     * @param array $recordIds
60
     * @param int|null $guestSpaceId
61
     * @return array [recordId => comments, ...]
62
     */
63
    public function allByRecords($appId, array $recordIds, $guestSpaceId = null): array
64
    {
65
        $result = [];
66
        $concurrency = $this->client->getConfig('concurrency');
67
        $offset = 0;
68
        while (count($recordIds) > 0) {
69
            $tmpIds = [];
70
            $requests = $this->createGetRequestsCallback($appId, $recordIds, $guestSpaceId, $offset);
71
            $pool = new Pool($this->client, $requests(), [
72
                'concurrency' => $concurrency ?: 1,
73
                'fulfilled' => $this->createMergeCommentsCallback($result, $tmpIds, $recordIds)
74
            ]);
75
            $pool->promise()->wait();
76
            $recordIds = $tmpIds;
77
            $offset += 10;
78
        }
79
        ksort($result);
80
81
        return $result;
82
    }
83
84
    /**
85
     * @param integer $appId
86
     * @param array $recordIds
87
     * @param integer $guestSpaceId
88
     * @param int $offset
89
     * @return \Closure
90
     */
91
    private function createGetRequestsCallback($appId, $recordIds, $guestSpaceId = null, $offset = 0): callable
92
    {
93
        $headers = $this->client->getConfig('headers');
94
        $headers['Content-Type'] = 'application/json';
95
        $url = KintoneApi::generateUrl('record/comments.json', $guestSpaceId);
96
97
        return function () use ($appId, $recordIds, $url, $headers, $offset) {
98
            foreach ($recordIds as $id) {
99
                $body = \GuzzleHttp\json_encode([
100
                    'app' => $appId,
101
                    'record' => $id,
102
                    'order' => 'asc',
103
                    'offset' => $offset,
104
                    'limit' => 10
105
                ]);
106
                yield new Request('GET', $url, $headers, $body);
107
            }
108
        };
109
    }
110
111
    /**
112
     * @param array $result
113
     * @param array $tmpIds
114
     * @param array $ids
115
     * @return \Closure
116
     */
117
    private function createMergeCommentsCallback(array &$result, array &$tmpIds, array $ids): callable
118
    {
119
        return function (ResponseInterface $response, $index) use (&$result, &$tmpIds, $ids) {
120
            $recordId = $ids[$index];
121
            /** @var JsonStream $stream */
122
            $stream = $response->getBody();
123
            $body = $stream->jsonSerialize();
124
            if ($body['newer']) {
125
                $tmpIds[] = $recordId;
126
            }
127
            if (!isset($result[$recordId])) {
128
                $result[$recordId] = [];
129
            }
130
            /** @var array $comments */
131
            $comments = $body['comments'];
132
            foreach ($comments as $comment) {
133
                $result[$recordId][] = $comment;
134
            }
135
        };
136
    }
137
138
    /**
139
     * @param int $appId
140
     * @param array $comments [recordId => [['text' => 'comment message', 'mentions' => []], ...], ...]
141
     * @param int|null $guestSpaceId
142
     * @return array
143
     */
144
    public function postByRecords($appId, $comments, $guestSpaceId = null): array
145
    {
146
        $result = [];
147
        $concurrency = $this->client->getConfig('concurrency');
148
149
        while (count($comments) > 0) {
150
            $requests = $this->createPostRequestsCallback($appId, $comments, $guestSpaceId);
151
            $pool = new Pool($this->client, $requests(), [
152
                'concurrency' => $concurrency ?: 1,
153
                'fulfilled' => $this->createPostFinishedAtCallback($result, $comments)
154
            ]);
155
            $pool->promise()->wait();
156
        }
157
        ksort($result);
158
159
        return $result;
160
    }
161
162
    /**
163
     * @param int $appId
164
     * @param array $comments
165
     * @param int|null $guestSpaceId
166
     * @return \Closure
167
     */
168
    private function createPostRequestsCallback($appId, array $comments, $guestSpaceId = null): callable
169
    {
170
        $headers = $this->client->getConfig('headers');
171
        $headers['Content-Type'] = 'application/json';
172
        $url = KintoneApi::generateUrl('record/comment.json', $guestSpaceId);
173
174
        return function () use ($appId, $comments, $url, $headers) {
175
            foreach ($comments as $recordId => $values) {
176
                $comment = reset($values);
177
                if (!isset($comment['text'])) {
178
                    continue;
179
                }
180
                $body = \GuzzleHttp\json_encode([
181
                    'app' => $appId,
182
                    'record' => $recordId,
183
                    'comment' => $comment
184
                ]);
185
                yield new Request('POST', $url, $headers, $body);
186
            }
187
        };
188
    }
189
190
    /**
191
     * @param array $result
192
     * @param array $comments
193
     * @return \Closure
194
     */
195
    private function createPostFinishedAtCallback(array &$result, array &$comments): callable
196
    {
197
        $recordIds = array_keys($comments);
198
        return function (ResponseInterface $response, $index) use (&$result, &$comments, $recordIds) {
199
            /** @var JsonStream $stream */
200
            $stream = $response->getBody();
201
            $commentId = $stream->jsonSerialize()['id'];
202
            $recordId = $recordIds[$index];
203
            if (!isset($result[$recordId])) {
204
                $result[$recordId] = [];
205
            }
206
            $result[$recordId][] = $commentId;
207
            $keys = array_keys($comments[$recordId]);
208
            $firstKey = reset($keys);
209
            unset($comments[$recordId][$firstKey]);
210
            if (count($comments[$recordId]) === 0) {
211
                unset($comments[$recordId]);
212
            }
213
        };
214
    }
215
}
216