|
- <?php
-
- namespace App\Kintone\Models;
-
- use App\Exceptions\AppCommonException;
- use App\Exceptions\ConfigException;
- use App\Kintone\File;
- use App\Kintone\KintoneAccess;
- use App\Kintone\KintoneAccessStore;
- use App\Kintone\KintoneRecordQuery;
- use App\Util\DateUtil;
- use Illuminate\Support\Arr;
- use Illuminate\Support\Carbon;
- use Illuminate\Support\Str;
- use LogicException;
- use stdClass;
-
- abstract class KintoneModel
- {
- const CONFIG_KEY = "";
-
- const BASE_MODEL = null;
-
- static public function configKey(): string
- {
- if (!static::CONFIG_KEY) {
- throw new LogicException(sprintf("Kintone 設定キー 未設定:%s", static::class));
- }
- return static::CONFIG_KEY;
- }
-
- static public function setConfig(): array
- {
-
- $configStr = env(static::configKey());
- if (!$configStr) {
- throw new ConfigException(static::configKey(), $configStr);
- }
-
- $params = explode(",", $configStr);
- if (count($params) !== 2) {
- throw new ConfigException(static::configKey(), $configStr);
- }
-
- [$apiToken, $appId] = $params;
-
- return [static::class => [
- 'apiToken' => $apiToken,
- 'appId' => (int)$appId,
- ]];
- }
-
- /**
- * @return KintoneAccess<static>
- */
- static public function getAccess(): KintoneAccess
- {
- $target = static::BASE_MODEL ?? static::class;
-
- $store = KintoneAccessStore::instance();
- if ($store->has($target)) {
- return $store->get($target);
- }
-
- $access = new KintoneAccess($target);
- $access->setFields(array_keys(static::FIELDS));
-
- foreach (static::RELATIONS as $relation) {
- $access->addAppToken($relation);
- }
-
- $store->set($target, $access);
- return $access;
- }
-
- /**
- * @return KintoneRecordQuery<static>
- */
- static public function getQuery(): KintoneRecordQuery
- {
- $target = static::BASE_MODEL ?? static::class;
- return new KintoneRecordQuery($target);
- }
-
- /**
- * @return static
- */
- public static function find(string $recordId)
- {
- return static::getAccess()->find($recordId);
- }
-
- public static function getDropDownOptions(string $fieldCode): array
- {
- $ret = [];
- $properties = static::getAccess()->getAppFormFields();
- $options = Arr::get($properties, sprintf("%s.options", $fieldCode));
- $ret = Arr::pluck(Arr::sort($options, function ($option) {
- return data_get($option, "index");
- }), "label");
- return $ret;
- }
-
- protected ?string $recordId = null;
-
- protected ?int $revision = null;
-
- protected ?Carbon $createdAt = null;
-
- protected ?Carbon $updatedAt = null;
-
- protected ?stdClass $dataOrigin = null;
- protected stdClass $data;
-
- protected const FIELDS = [];
-
- protected const FIELD_NAMES = [];
-
- protected const RELATIONS = [];
-
- private array $changed = [];
-
- public function __construct()
- {
- $this->data = new stdClass();
- }
-
- public function __get($name)
- {
- $field = "FIELD_" . Str::of($name)->snake()->upper()->toString();
- $constantPath = sprintf("%s::%s", static::class, $field);
- if (defined($constantPath)) {
- return $this->get(constant($constantPath));
- } else {
- throw new LogicException(sprintf("未定義のメンバアクセス %s %s", static::class, $field));
- }
- }
- public function __set($name, $value)
- {
- $field = "FIELD_" . Str::of($name)->snake()->upper()->toString();
- $constantPath = sprintf("%s::%s", static::class, $field);
- if (defined($constantPath)) {
- return $this->set(constant($constantPath), $value);
- } else {
- throw new LogicException(sprintf("未定義のメンバアクセス %s %s", static::class, $field));
- }
- }
-
- public function set(string $fieldCode, $value)
- {
- $field = Arr::get(static::FIELDS, $fieldCode);
- if ($field instanceof FieldType) {
- $this->setData($fieldCode, $field, $value);
- } else if (is_array($field)) {
- $this->setTable($fieldCode, $value);
- }
-
- data_set($this->changed, $fieldCode, true);
- return $this;
- }
-
- private function setTable(string $fieldCode, array $table)
- {
- foreach ($table as $index => $row) {
- $row = data_get($row, "value");
- $this->setTableRow($fieldCode, $index, $row);
- }
- }
-
- private function setTableRow(string $fieldCode, int $index, array $row)
- {
- foreach ($row as $columnFieldCode => $column) {
- $value = $column["value"];
- $type = static::FIELDS[$fieldCode][$columnFieldCode];
- $insertKey = sprintf("%s.%d.%s", $fieldCode, $index, $columnFieldCode);
- $this->setData($insertKey, $type, $value);
- }
- }
-
- private function setData(string $path, FieldType $type, $value)
- {
- data_set($this->data, $path, $value);
-
- return $this;
- // if (
- // $type === FieldType::STRING ||
- // $type === FieldType::ARRAY
- // ) {
- // data_set($this->data, $path, $value);
- // // logger([$path, $value]);
- // return $this;
- // }
- // if ($type === FieldType::DATETIME) {
- // data_set($this->data, $path, DateUtil::parse($value));
- // return $this;
- // }
- }
-
- public function setDataFromRecordResponse(array $data): bool
- {
- $ret = true;
- foreach ($data as $fieldCode => $ele) {
- $type = data_get($ele, "type");
- $value = data_get($ele, "value");
- if ($type === "__ID__") {
- $this->recordId = $value;
- continue;
- }
- if ($type === "__REVISION__") {
- $this->revision = $value;
- continue;
- }
- if ($type === "CREATED_TIME") {
- $this->createdAt = DateUtil::parse($value);
- continue;
- }
- if ($type === "UPDATED_TIME") {
- $this->updatedAt = DateUtil::parse($value);
- continue;
- }
-
- $type = FieldType::tryFrom($type);
- if ($type === null) continue;
-
- if (in_array($type, [FieldType::DATETIME, FieldType::DATE])) {
- if ($value) {
- data_set($this->data, $fieldCode, DateUtil::parse($value));
- } else {
- data_set($this->data, $fieldCode, null);
- }
- continue;
- }
- if ($type === FieldType::FILE) {
- $ret = [];
- foreach ($value as $f) {
- $ret[] = new File($f);
- }
- data_set($this->data, $fieldCode, $ret);
- continue;
- }
- if ($type === FieldType::SUBTABLE) {
- continue;
- }
-
-
- // 以外はそのまま格納
- data_set($this->data, $fieldCode, $value);
- }
-
- if ($this->recordId === null) {
- throw new LogicException(sprintf("レコード番号取得失敗 :%s", static::class));
- }
-
- $ret = $this->setDataCustom($data);
- if ($ret) {
- $this->clean();
- }
- return $ret;
- }
-
-
-
- /**
- * 変更前データを現在データで上書きする
- *
- * @return void
- */
- public function clean(?int $revision = null)
- {
- $this->dataOrigin = clone $this->data;
- if ($revision !== null) {
- $this->revision = $revision;
- }
- $this->changed = [];
- }
-
- public function getApiLayout(): array
- {
- $ret = [];
- foreach (static::FIELDS as $fieldCode => $type) {
-
- // 変更があった項目のみレイアウトへ出力する
- if (!Arr::has($this->changed, $fieldCode)) {
- continue;
- }
-
- $path = sprintf("%s.value", $fieldCode);
- if ($type === FieldType::DATETIME) {
- $data = $this->getDate($fieldCode);
- if ($data) {
- data_set($ret, $path, $data->toIso8601ZuluString());
- }
- continue;
- }
- if ($type === FieldType::DATE) {
- $data = $this->getDate($fieldCode);
- if ($data) {
- data_set($ret, $path, $data->format("Y-m-d"));
- data_set($ret, $path, $data->toDateString());
- }
- continue;
- }
- data_set($ret, $path, data_get($this->data, $fieldCode));
- }
-
- return array_merge($ret, $this->getApiLayoutCustom());
- }
-
- public function get(string $key)
- {
- return data_get($this->data, $key);
- }
-
- public function getStr(string $key): ?string
- {
- return $this->get($key);
- }
-
- public function getNumber(string $key): ?int
- {
- return $this->get($key);
- }
-
- public function getDate(string $key): ?Carbon
- {
- return $this->get($key);
- }
-
- public function getTable(string $key): ?array
- {
- return $this->get($key);
- }
-
- public function setRecordId(string $id): static
- {
- $this->recordId = $id;
- return $this;
- }
- public function getRecordId(): ?string
- {
- return $this->recordId;
- }
-
- public function getRevision(): ?int
- {
- return $this->revision;
- }
-
- public function getUpdatedAt(): ?Carbon
- {
- return $this->updatedAt;
- }
- public function getCreatedAt(): ?Carbon
- {
- return $this->createdAt;
- }
-
- public function save()
- {
- $access = static::getAccess();
- if ($this->recordId === null) {
- $access->create($this);
- } else {
- $access->update($this);
- }
- }
-
- public function toArray($column = ['*']): array
- {
- if ($this->recordId === null) {
- throw new LogicException("保存前モデルのシリアライズ検知");
- }
-
- $ret = [
- 'record_no' => $this->recordId,
- 'revision' => $this->revision,
- ];
-
- $columnAll = data_get($column, 0) === '*';
-
- /**
- * @var string $fieldCode
- */
- foreach ($this->data as $fieldCode => $value) {
-
- if (!$columnAll && !in_array($fieldCode, $column)) {
- continue;
- }
-
- $type = data_get(static::FIELDS, $fieldCode);
-
- $columnName = data_get(static::FIELD_NAMES, $fieldCode, null);
- if ($columnName === null) {
- continue;
- }
-
- if ($type === null) {
- $ret[$columnName] = $value;
- continue;
- }
-
- if ($type === FieldType::DATETIME) {
- if ($value instanceof Carbon) {
- $ret[$columnName] = $value->format('Y/m/d H:i:s');
- } else {
- $ret[$columnName] = $value;
- }
- continue;
- }
- if ($type === FieldType::DATE) {
- if ($value instanceof Carbon) {
- $ret[$columnName] = $value->format('Y/m/d');
- } else {
- $ret[$columnName] = $value;
- }
- continue;
- }
-
-
- $ret[$columnName] = $value;
- }
- $ret = array_merge($ret, $this->toArrayCustom());
-
- return $ret;
- }
-
- protected function toArrayCustom(): array
- {
- return [];
- }
-
-
- /**
- * オーバーライドを期待
- *
- * @param array $data
- * @return boolean
- */
- protected function setDataCustom(array $data): bool
- {
- return true;
- }
- /**
- * オーバーライドを期待
- *
- * @return array
- */
- protected function getApiLayoutCustom(): array
- {
- return [];
- }
- }
|