新規投稿
フォローする

kintone-PHP連携 アプリ&レコードコピー

kintone API SDK for PHPを使って、指定したアプリとそのレコードを一括でコピーするコードを書いてみました。

コード

<?php
//実行時間制限の変更
set_time_limit(300);

//「kintone API SDK for PHP」の設定
require 'vendor/autoload.php';
$api = new \CybozuHttp\Api\KintoneApi(new \CybozuHttp\Client([
  'domain' => 'cybozu.com',
  'subdomain' => '****',
  'login' => '****',
  'password' => '****',
  'use_basic' => true,
  'basic_login' => '****',
  'basic_password' => '****',
]));

//コピー元アプリのID
define('ORIGIN_APP_ID', ****);

//データ整形用関数
function copyFile($api, $file){
  $path = sys_get_temp_dir().'/'.$file['name'];
  file_put_contents($path, $api->file()->get($file['fileKey']));
  $fileKey = $api->file()->post($path);
  unlink($path);
  return $fileKey;
}
function formatProperties($properties){
  foreach(['レコード番号', '$id', '$revision', '作成者', '更新者', '作成日時', '更新日時', 'カテゴリー', '作業者', 'ステータス'] as $fieldCode){
    unset($properties[$fieldCode]);
  }
  return $properties;
}
function formatCustomize($api, $customize){
  return array_map(function($file) use ($api){
    if($file['type'] === 'URL') return $file;
    return [
      'type' => 'FILE',
      'file' => [
        'fileKey' => copyFile($api, $file['file'])
      ]
    ];
  }, $customize);
}
function formatRecords($api, $records){
  return array_map(function($record) use ($api){
    foreach(['レコード番号', '$id', '$revision', '作成者', '更新者', '作成日時', '更新日時'] as $fieldCode){
      unset($record[$fieldCode]);
    }
    return array_reduce(array_keys($record), function($carry, $fieldCode) use ($api, $record){
      if($record[$fieldCode]['type'] === 'FILE'){
        $carry[$fieldCode] = [
          'type' => 'FILE',
          'value' => array_map(function($file) use ($api){
            return [
              'fileKey' => copyFile($api, $file)
            ];
          }, $record[$fieldCode]['value'])
        ];
      }else if($record[$fieldCode]['type'] === 'SUBTABLE'){
        $carry[$fieldCode] = [
          'type' => 'SUBTABLE',
          'value' => array_map(function($row) use ($api){
            return [
              'value' => array_reduce(array_keys($row['value']), function($carry, $fieldCode) use ($api, $row){
                if($row['value'][$fieldCode]['type'] === 'FILE'){
                  $carry[$fieldCode] = [
                    'type' => 'FILE',
                    'value' => array_map(function($file) use ($api){
                      return [
                        'fileKey' => copyFile($api, $file)
                      ];
                    }, $row['value'][$fieldCode]['value'])
                  ];
                }else{
                  $carry[$fieldCode] = $row['value'][$fieldCode];
                }
                return $carry;
              }, [])
            ];
          }, $record[$fieldCode]['value'])
        ];
      }else{
        $carry[$fieldCode] = $record[$fieldCode];
      }
      return $carry;
    }, []);
  }, $records);
}

//コピー元アプリのデータ取得
$originApp = $api->app()->get(ORIGIN_APP_ID);
$originAppSettings = $api->app()->getSettings(ORIGIN_APP_ID);
$originAppFields = $api->app()->getFields(ORIGIN_APP_ID);
$originAppLayout = $api->app()->getLayout(ORIGIN_APP_ID);
$originAppViews = $api->app()->getViews(ORIGIN_APP_ID);
$originAppAcl = $api->app()->getAcl(ORIGIN_APP_ID);
$originAppRecordAcl = $api->app()->getRecordAcl(ORIGIN_APP_ID);
$originAppFieldAcl = $api->app()->getFieldAcl(ORIGIN_APP_ID);
$originAppCustomize = $api->app()->getCustomize(ORIGIN_APP_ID);
$originAppStatus = $api->app()->getStatus(ORIGIN_APP_ID);
$originAppRecords = $api->records()->all(ORIGIN_APP_ID, 'order by レコード番号 asc');

//コピー先アプリの作成
$copyAppName = $originApp['name'].'copy'.date("Ymd"); // コピー先アプリ名
$copyApp = $api->preview()->post($copyAppName);

//コピー先アプリの設定変更
$api->preview()->putSettings($copyApp['app'], $copyAppName, $originAppSettings['description'], $originAppSettings['icon'], $originAppSettings['theme']);
$api->preview()->postFields($copyApp['app'], formatProperties($originAppFields['properties']));
$api->preview()->putLayout($copyApp['app'], $originAppLayout['layout']);
if(!empty($originAppViews['views'])) $api->preview()->putViews($copyApp['app'], $originAppViews['views']);
$api->preview()->putAcl($copyApp['app'], $originAppAcl['rights']);
$api->preview()->putRecordAcl($copyApp['app'], $originAppRecordAcl['rights']);
$api->preview()->putFieldAcl($copyApp['app'], $originAppFieldAcl['rights']);
$api->preview()->putCustomize($copyApp['app'], formatCustomize($api, $originAppCustomize['desktop']['js']), formatCustomize($api, $originAppCustomize['desktop']['css']), formatCustomize($api, $originAppCustomize['mobile']['js']));
if(!empty($originAppStatus['states'])) $api->preview()->putStatus($copyApp['app'], $originAppStatus['states'], $originAppStatus['actions'], $originAppStatus['enable']);

//コピー先アプリのデプロイ
$api->preview()->deploy($copyApp['app']);
while(!isset($deployed)){ //デプロイ完了まで待機
  try{
    $api->app()->get($copyApp['app']);
    $deployed = true;
  }catch(Exception $e){
    sleep(1);
  }
}

//コピー先アプリのレコード登録
foreach(array_chunk(formatRecords($api, $originAppRecords), 100) as $recordChunk){
  $api->records()->post($copyApp['app'], $recordChunk);
}

echo ''.$originAppSettings['name'].'('.ORIGIN_APP_ID.')」を「'.$copyAppName.'('.$copyApp['app'].')」へコピーしました。'."\n";

$apiには、「kintoneのシステム管理権限」、「コピー元アプリのアプリ・レコード・フィールドの閲覧権限」を持ったユーザーを設定してください。
・APIが対応していない一部の設定値はコピー先に引き継がれません。場合によってはエラーになる可能性もあります。
・サンプルではコピー元アプリIDを固定値で処理していますが、引数渡しをすれば複数のアプリに対応できます。

2

0件のコメント

サインインしてコメントを残してください。