Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

358 rindas
8.6KB

  1. <?php
  2. namespace App\Kintone;
  3. use App\Exceptions\ConfigException;
  4. use App\Kintone\Models\KintoneModel;
  5. use Exception;
  6. use Illuminate\Http\Client\Response;
  7. use Illuminate\Support\Collection;
  8. use Illuminate\Support\Facades\Http;
  9. use Log;
  10. /**
  11. * @template TValue of KintoneModel
  12. */
  13. class KintoneAccess
  14. {
  15. private string $appName;
  16. private string $host;
  17. private string $apiToken;
  18. private int $appId;
  19. private const DEFAULT_FIELDS = [
  20. KintoneModel::FIELD_RECORD_NUMBER,
  21. KintoneModel::FIELD_UPDATED_TIME,
  22. KintoneModel::FIELD_RECORD_NUMBER,
  23. ];
  24. private array $fields = [];
  25. private string|null $cursor = null;
  26. private int $cursorDataCount = 0;
  27. private bool $hasNext = false;
  28. private const URL_RECORD = "/k/v1/record.json";
  29. private const URL_CURSOL = "/k/v1/records/cursor.json";
  30. private const URL_FILE = "/k/v1/file.json";
  31. public function __construct(string $appName)
  32. {
  33. $this->appName = $appName;
  34. $key = "kintone.host";
  35. $host = config($key);
  36. if (!$host) {
  37. throw new ConfigException("kintone.host", $host);
  38. }
  39. $key = "kintone.applications." . $appName . ".apiToken";
  40. $apiToken = config($key);
  41. if (!$apiToken) {
  42. throw new ConfigException($key, $apiToken);
  43. }
  44. $key = "kintone.applications." . $appName . ".appId";
  45. $appId = config($key);
  46. if (!$appId) {
  47. throw new ConfigException($key, $appId);
  48. }
  49. $this->host = $host;
  50. $this->apiToken = $apiToken;
  51. $this->appId = $appId;
  52. }
  53. public function setFields(array $fields): static
  54. {
  55. $this->fields = [
  56. ...$fields,
  57. ...self::DEFAULT_FIELDS,
  58. ];
  59. return $this;
  60. }
  61. public function __destruct()
  62. {
  63. $this->deleteCursor();
  64. }
  65. /**
  66. * @param integer $id
  67. * @param TValue $result
  68. * @return Response
  69. */
  70. public function find(int $id, KintoneModel &$result): Response
  71. {
  72. $response = Http::withHeaders([
  73. "X-Cybozu-API-Token" => $this->apiToken,
  74. ])->get($this->getRecordUrl(), [
  75. "app" => $this->appId,
  76. "id" => $id,
  77. 'fields' => $this->fields,
  78. ]);
  79. if ($response->failed()) {
  80. $e = $response->toException();
  81. if ($e instanceof Exception) {
  82. Log::error($e->getMessage());
  83. throw $e;
  84. }
  85. }
  86. $result->setDataFromRecordResponse($response['record']);
  87. return $response;
  88. }
  89. /**
  90. * @param TValue $model
  91. * @return void
  92. */
  93. public function update(KintoneModel &$model)
  94. {
  95. $response = Http::withHeaders([
  96. "X-Cybozu-API-Token" => $this->apiToken,
  97. ])->put($this->getRecordUrl(), [
  98. "app" => $this->appId,
  99. "id" => $model->getRecordId(),
  100. "record" => $model->getApiLayout(),
  101. "revision" => $model->getRevision(),
  102. ]);
  103. if ($response->failed()) {
  104. $e = $response->toException();
  105. if ($e instanceof Exception) {
  106. Log::error($e->getMessage());
  107. throw $e;
  108. }
  109. }
  110. $model->clean($response["revision"]);
  111. return $response;
  112. }
  113. /**
  114. * @param TValue $model
  115. * @return void
  116. */
  117. public function create(KintoneModel &$model)
  118. {
  119. $response = Http::withHeaders([
  120. "X-Cybozu-API-Token" => $this->apiToken,
  121. ])->post($this->getRecordUrl(), [
  122. "app" => $this->appId,
  123. "record" => $model->getApiLayout(),
  124. ]);
  125. if ($response->failed()) {
  126. $e = $response->toException();
  127. if ($e instanceof Exception) {
  128. Log::error($e->getMessage());
  129. throw $e;
  130. }
  131. }
  132. $model->clean($response["revision"]);
  133. $model->setRecordId($response["id"]);
  134. return $response;
  135. }
  136. public function createCursor(KintoneRecordQuery|null $query = null)
  137. {
  138. $data = [
  139. "app" => $this->appId,
  140. 'fields' => $this->fields,
  141. ];
  142. if ($query !== null) {
  143. $data["query"] = $query->toQuery();
  144. }
  145. $response = Http::withHeaders([
  146. "X-Cybozu-API-Token" => $this->apiToken,
  147. ])->post($this->getCursorUrl(), $data);
  148. if ($response->failed()) {
  149. $e = $response->toException();
  150. if ($e instanceof Exception) {
  151. Log::error($e->getMessage(), ['data' => $data]);
  152. throw $e;
  153. }
  154. }
  155. $cursor = $response["id"];
  156. $totalCount = $response["totalCount"];
  157. if (0 < $totalCount) {
  158. $this->hasNext = true;
  159. $this->cursor = $cursor;
  160. $this->cursorDataCount = $totalCount;
  161. } else {
  162. $this->cursor = null;
  163. $this->hasNext = false;
  164. $this->cursorDataCount = 0;
  165. }
  166. return $response;
  167. }
  168. /**
  169. * @return Collection<int,TValue>
  170. */
  171. public function next()
  172. {
  173. if (!$this->hasNext) {
  174. return collect();
  175. }
  176. $response = Http::withHeaders([
  177. "X-Cybozu-API-Token" => $this->apiToken,
  178. ])->get($this->getCursorUrl(), [
  179. "id" => $this->cursor,
  180. ]);
  181. if ($response->failed()) {
  182. $e = $response->toException();
  183. if ($e instanceof Exception) {
  184. Log::error($e->getMessage());
  185. throw $e;
  186. }
  187. }
  188. $ret = collect();
  189. $hasNext = $response["next"];
  190. if (!$hasNext) {
  191. $this->cursor = null;
  192. $this->hasNext = false;
  193. $this->cursorDataCount = 0;
  194. }
  195. foreach ($response["records"] as $data) {
  196. /**
  197. * @var KintoneModel $model
  198. */
  199. $model = new $this->appName();
  200. $model->setDataFromRecordResponse($data);
  201. $ret->push($model);
  202. }
  203. return $ret;
  204. }
  205. /**
  206. * @return Collection<int,TValue>
  207. */
  208. public function all(KintoneRecordQuery|null $query = null, array|null $fields = null)
  209. {
  210. if ($this->cursor !== null) {
  211. $this->deleteCursor();
  212. }
  213. $this->createCursor($query, $fields);
  214. $list = collect();
  215. while (true) {
  216. $ret = $this->next();
  217. foreach ($ret as $ele) {
  218. $list->push($ele);
  219. }
  220. if ($this->cursor === null) {
  221. break;
  222. }
  223. }
  224. return $list;
  225. }
  226. public function deleteCursor()
  227. {
  228. if ($this->cursor === null) {
  229. return;
  230. }
  231. $response = Http::withHeaders([
  232. "X-Cybozu-API-Token" => $this->apiToken,
  233. ])->delete($this->getCursorUrl(), [
  234. "id" => $this->cursor,
  235. ]);
  236. if ($response->failed()) {
  237. $e = $response->toException();
  238. if ($e instanceof Exception) {
  239. Log::error($e->getMessage());
  240. throw $e;
  241. }
  242. }
  243. $this->cursor = null;
  244. $this->hasNext = false;
  245. $this->cursorDataCount = 0;
  246. }
  247. public function fileGet(string $fileKey)
  248. {
  249. $response = Http::withHeaders([
  250. "X-Cybozu-API-Token" => $this->apiToken,
  251. "Content-Type" => "application/json",
  252. ])->get($this->getCursorUrl(), [
  253. "fileKey" => $fileKey,
  254. ]);
  255. if ($response->failed()) {
  256. $e = $response->toException();
  257. if ($e instanceof Exception) {
  258. Log::error($e->getMessage());
  259. throw $e;
  260. }
  261. }
  262. return $response;
  263. }
  264. public function filePut($file): string
  265. {
  266. $response = Http::withHeaders([
  267. "X-Cybozu-API-Token" => $this->apiToken,
  268. "Content-Type" => "multipart/form-data",
  269. ])->post($this->getCursorUrl(), $file);
  270. if ($response->failed()) {
  271. $e = $response->toException();
  272. if ($e instanceof Exception) {
  273. Log::error($e->getMessage());
  274. throw $e;
  275. }
  276. }
  277. return $response[''];
  278. }
  279. private function getRecordUrl()
  280. {
  281. return $this->getUrl(self::URL_RECORD);
  282. }
  283. private function getCursorUrl()
  284. {
  285. return $this->getUrl(self::URL_CURSOL);
  286. }
  287. private function getFileUrl()
  288. {
  289. return $this->getUrl(self::URL_FILE);
  290. }
  291. private function getUrl(string $path)
  292. {
  293. return $this->host . $path;
  294. }
  295. }