WordPressからkintoneへファイルをアップロードする

この投稿は、「kintone」アドベントカレンダー12月22日分となります。

# はじめに
WordPressとkintoneの連携を行なっていた時にあまりPHPでのkintone Rest APIの記事が少なかったので備忘録として書こうと思いました。

# 環境
iMac (Retina5K,27-inch,Late2015)
MacOS Mojava var10.14.1
VCCW ver3.18.0
WordPress ver5.0.2–ja
Visual Studio Code
# やりたいこと
今回はWordPressのテーマフォルダ内に専用のディレクトリを作り、固定ページ用のテーマファイルにファイルアップロード用のフォームを作成。
アップロードが完成したらkintoneからデータを取得しフォームの下にアップロードしたファイル名を表示させたいと思います。
<img width="994" alt="スクリーンショット 2018-12-21 18.28.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/100644/29ec3290-3bf6-f241-3a1e-4eb1f08c3201.png">

# 参考にしたサイト
[developer network ファイルアップロード](https://developer.cybozu.io/hc/ja/articles/201941824-%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89)
[jquery.uploadThumbs.js](https://gist.github.com/kenzo0107/66609140fe7c144040fa)
[cURL 関数](http://php.net/manual/ja/ref.curl.php)
[Code Reference wp_remote_request](https://developer.wordpress.org/reference/functions/wp_remote_request/)

## WordPressにテーマファイルを作成
「twentynineteen」のテーマを使います。
テーマフォルダ内にディレクトリ「kintone」を作成し、その中に固定ページ用のテーマファイルを作成します。
作成するファイルは以下です。

 - kintone-style.css ---- css用
 - file-upload.js ---- ファイルのプレビュー
 - jquery.uploadThumbs.js ---- ファイルのプレビュー
 - file-upload.php ---- 設定や関数用
 - form.php ---- アップロードフォーム用

ファイルのプレビューには下記のプラグインを使用しました。
[jquery.uploadThumbs.js](https://gist.github.com/kenzo0107/66609140fe7c144040fa)

##　ファイルをアップロードするフォームを作成

```
<?php
/*

Template Name: form

 */
//file Upload
if(isset($_FILES['up_file'])){
	$files = $_FILES['up_file'];
	$file_desc = reArrayFiles($files); //$ _FILES配列を変換
	$record_num = 1; //今回はレコード番号は決め打ちで
	file_upload($file_desc, $record_num); //関数にファイルとレコード番号を渡します
}

function reArrayFiles($files)　
{
	$file_ary = array();
	$file_count = count($files['name']);
	$file_key = array_keys($files);
	
	for($i=0;$i<$file_count;$i++)
	{
		foreach($file_key as $val)
		{
			$file_ary[$i][$val] = $files[$val][$i];
		}
	}
	return $file_ary;
}

$record_num = 1; //今回はレコード番号は決め打ちで
$kintones = get_kintone_data($record_num);//kintoneのレコード取得

for($i=0; $i<count($kintones['records']); $i++){
	$date_time = $kintones['records'][$i]['日時']['value'];
}
get_header();
?>

<section id="primary" class="content-area">
		<main id="main" class="site-main">
        <div class="content">
				<div class="spot">
					<div class="oneBox">
						<h3 class='file-upload-Title'>ファイルアップロード</h3>
						<!--ここにフォームタグ入れる-->
						<form method="post" action="" enctype="multipart/form-data">
						<div id="drag-area">
							<div class="btn-group">
								<div class="file">
									<p>アップロードするファイルをドロップ、またはクリックして選択してください</p>
									<input type="file" name="up_file[]" multiple="multiple" onchange="OnFileSelect( this );"><br>
								</div>
								<ul id="filename" ></ul>
								<input type="submit" id="upload" value="アップロード">
							</div>
						</div>
						</form>
					<div>日時：<?php echo  $date_time; ?></div>
					<table class="case-upload">
						<?php
						for($i=0; $i<count($kintones['records']); $i++){
							$date_time = $kintones['records'][$i]['日時']['value'];
							$drawing_attach = $kintones['records'][$i]['添付ファイル']['value'];
							for($d=0; $d<count($drawing_attach); $d++)
							{
								$upload_file_name = $drawing_attach[$d]['name'];
								$upload_file_key = $drawing_attach[$d]['fileKey'];
								?>	
								<tr>
									<th><h6><?php echo $upload_file_name ?></h6></th>
									<td class="drawing-file-controll">
										<div class="drawing-upload-file"><p class="log"><button name="download" class="download files">ダウンロード</button></p></div>
										<div class="drawing-delete-file">
										<p class="log"><button name="download" class="delete files">削除</button></div>
										<div id="filekey" style="display:none"><?php echo $upload_file_key ?></div>
										<div id="filename" style="display:none"><?php echo $upload_file_name ?></div>
									</td>
								</tr>
								<?php
							}
						}
					// view data end
						?>
					</table>
					<!-- end drawing -->
				</div><!--end listBox-->
			</div><!--end oneBox-->
		</main><!-- .site-main -->
	</section><!-- .content-area -->
<?php
get_footer();

```

注意するのは２箇所！
1. `<form method="post" action="" enctype="multipart/form-data">`
formのenctypeは `multipart/form-data` にしてください。
2. ファイルを複数選択できるようにするので `name="up_file[]" multiple="multiple"` にしてください。

フォームの後のテーブルにはアップロードされたファイルが表示されるようにします。

## WordPressやkintoneの設定、ファイルアップロードの関数を作成

```
<?php

// kintoneの設定
    define("SUB_DOMAIN", "example"); //kintoneのサブドメイン
    define("APP_NO", "×××"); //kintoneのアプリID
    define("API_TOKEN", "××××××××××××××××××××××××××××××××××××"); //アプリで発行したトークン

//include for CSS and Javascript files
    add_action( 'wp_enqueue_scripts', 'kintone_enqueue_styles' ); 
    function kintone_enqueue_styles() { 
    wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/kintone/css/kintone-style.css' ); 
    }
    add_action( 'wp_enqueue_scripts', 'kintone_enqueue_script' );
    function kintone_enqueue_script() { 
        wp_enqueue_script('file-upload', get_template_directory_uri().'/kintone/js/file-upload.js', array('jquery'), '1.0.0', true);
        wp_enqueue_script('jquery.uploadThumbs', get_template_directory_uri().'/kintone/js/jquery.uploadThumbs.js', array('jquery'), '1.0.0', true);
    }
//*****************************************
// アプリデータ取得
//*****************************************/
function get_kintone_data($record_num){
        $url = "https://".SUB_DOMAIN.".cybozu.com/k/v1/records.json?app=".APP_NO."";	
    
        $search = "レコード番号 = \"{$record_num}\"";
        $url .= '&query='. utf8_uri_encode( $search );
    
        $args = array(
            'headers' => array(
                'X-Cybozu-API-Token' => API_TOKEN
            )
        );
    
        $kintone = wp_remote_get( $url, $args );

        $kintones = json_decode($kintone['body'],true);
    
        return $kintones;
    }
    

//*****************************************
// ファイルアップロード
//*****************************************/

function file_upload($files, $record_num) 
{
    //複数ファイルアップロードなのでfor文で一つづつアップロード
    for($f=0; $f<count($files); $f++){
        $upload_url = "https://".SUB_DOMAIN.".cybozu.com/k/v1/file.json";
        $file_path = $files[$f]['tmp_name'];
        $file_name = $files[$f]['name'];
        
        //今回はcurlでアップロードします。
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $upload_url);
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST" );
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, [
        'X-Cybozu-API-Token:'.API_TOKEN
        ]);
        curl_setopt($curl, CURLOPT_POST, true);
        $file = new CURLFile($file_path, 'application/octet-stream', $file_name);
        curl_setopt(
        $curl, CURLOPT_POSTFIELDS, array('file' => $file)
        );

        //php5.4以下はこちら
        // $data = array('name' => $file_name, 'file' => '@'.$file_path . ';filename=' . $file_name);
        // curl_setopt(
        //     $curl, CURLOPT_POSTFIELDS, $data
        //     );

        $res = curl_exec($curl);
        $resuponse = json_decode( $res , true );
        curl_close ($curl);

        //アップロードが成功するとkeyが返ってきます。
        for($i=0; $i<count($resuponse); $i++){
            $key = $resuponse['fileKey'];
        }

        //アプリデータ取得
        $url = "https://".SUB_DOMAIN.".cybozu.com/k/v1/records.json?app=".APP_NO."";	

        $search = "レコード番号 = \"{$record_num}\"";
        $url .= '&query='. utf8_uri_encode( $search );

        $args = array(
            'headers' => array(
                'X-Cybozu-API-Token' => API_TOKEN
            )
        );

        $kintone = wp_remote_get( $url, $args );
        $kintones = json_decode($kintone['body'],true);

        //添付ファイル
        $subtable = $kintones['records'][0]['添付ファイル']['value'];

        //keyを"fileKey" => $keyの形で配列に入れる
        if($key){
            $key_array = array(array("fileKey" => $key));
        }else{
            $key_array = "";
        }

        //取得した添付ファイルデータにアップロードするkeyを追加
        $result_key = array_merge($subtable, $key_array);

        //bodyにアプリ番号とレコード番号とkeyをセット
        $body =  array(
                "app" => APP_NO,
                "id" => $record_num,
                "record" => array(
                    "添付ファイル" => array (
                        "value" => $result_key
                    ),
                ),
            );

            //レコードの上書きなのでPUTで書き込みます。
            $options = array(
                    'method'=> 'PUT',
                    'headers' => array(
                        'X-Cybozu-API-Token' => API_TOKEN,
                        'Content-Type' => 'application/json'
                    ),
                    'body' => json_encode($body)
                );


            //PUTで書き込むのでwp_remote_requestを使います。
            $results = wp_remote_request("https://".SUB_DOMAIN.".cybozu.com/k/v1/record.json", $options);

            //書き込み成功だったらrevisionが返ってきます。
            print_r($results['body']);
    }
}
```
このファイルでcssやjsファイルを読み込み、kintoneの設定などをし、アップロードの関数を作ります。

kintoneへ添付ファイルを書き込む場合、

 1. ファイルをkintoneへアップロードするとkeyが返ってくる
 2. 取得したkeyをレコードに書き込む

という流れになります。複数ファイルをアップロードであれば上記を繰り返します。

ここで注意する点が１つ！

添付ファイルは複数アップロードできるので配列になっています。
書き込む際は現在のレコードを一旦取得し、添付ファイルの配列に新しくアップロードするファイルのkeyを `array_merge` で追加します。
※削除の場合はもう一工夫入りますが、それはまた今度書きます。

## WordPressに作った関数を読み込む
テーマファイル内の `functions.php` に `require_once(dirname(__FILE__).'/kintone/file-upload.php');` 設定ファイルを読み込みます。

## WordPress固定ページを作成
固定ページを作成し右サイドバーにある「固定ページの属性」の「テンプレート」で先ほど作った `form.php` を読み込ませます。
※ form.phpの上部に記述した名前が管理画面に表示されます。

```
/*

Template Name: form

 */
```
「公開」ボタンをクリックして保存してください。
<img width="1137" alt="スクリーンショット 2018-12-21 20.17.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/100644/2b9614b5-d786-e9cf-f4b8-8ba3ac02ff42.png">

## 完成
先ほど作った固定ページを表示させるとフォームができています。

<img width="994" alt="スクリーンショット 2018-12-21 18.28.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/100644/a1f092e9-a140-2838-d0fe-3fe234b2a70e.png">

ファイルを選択すると、下にファイル名が表示されます。

<img width="993" alt="スクリーンショット 2018-12-21 18.29.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/100644/166d1f5e-5b0e-5caf-94e9-37b82b6d900e.png">

「アップロード」ボタンをクリックしてファイルをアップロードします。
ちゃんとアップロードできるとフォームの下にファイル名が表示されます。
※画面左上には確認のためにわざとリビジョンを表示させています。

<img width="1097" alt="スクリーンショット 2018-12-21 19.16.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/100644/fca380ea-2819-1117-b2c2-8c09696feeaf.png">

kintoneにちゃんとアップロードできました。

<img width="921" alt="スクリーンショット 2018-12-21 19.16.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/100644/b1163e1d-0d61-ceaf-bbb2-8450b34afdf9.png">

## まとめ
今回は猛ダッシュでサンプルを作ったのでエラー処理などは入っていません。（ちょっと雑な記事ですみません）
また、CSSやJSの説明はカットしました。
あと、kintone SDKを使わずにやりました。
WordPressでAPIを使う日本語の使い方記事が少なかったので自己流のところも多いです。
アップロードだけ書きましたが、ダウンロードや削除なども作ったので、おいおい記事にしていきます。
後、kintone SDKをWordPressで使ってもみたのでこちらも順次書いていきます。
もっと、kintone × WordPressを広げていきたいなぁと思っています。

間違えてたり、もっとこうできるよ的な事があれば教えてください。よろしくお願いしますー。