Completed
Push — master ( a826f8...312899 )
by Yuichi
25s
created

Comments::allByRecords()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 3

Importance

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