Qiita:team の自分が書いた記事を共同編集にする

# 背景

Qiita:team に記事を作成する時に共同編集にしてねって言われてるんだけどいつも忘れてしまう。
というわけで、自分が書いた記事をとりあえず全部共同編集にする方法を考えました。

# 概要

[Qiita API](https://qiita.com/api/v2/docs) を用いて自分が書いた記事を取得して、それをループして更新をかけていく。

なお、一度共同編集にした記事を個人作成には戻せないので注意が必要だ。

# 詳細

まずは記事取得のAPIを使う。

## トークンの取得

その前に、APIをコールするには、トークンを作らないといけない。

ここ https://qiita.com/settings/tokens/new から作成しよう。

今回は記事の状態変更をするので `write_qiita_team` が必要だ。

作ったらコピってどっかにおいとく。

## 記事一覧の取得

記事取得のAPI。ちょっといけてなくて、ページングが柔軟じゃない。最大100件の記事を1度に取得できるが、101件あるかどうかは、次のページを参照しないとわからない。

https://qiita.com/api/v2/docs#get-apiv2authenticated_useritems

今回は、パラメータとして、page=1, per_page=2で呼んでみる。

```php
define('TOKEN', '自分のトークン');

$base = "https://{team}.qiita.com";

$items = getItems($base, ["page" => 1, "per_page" => 2]);
foreach($items as $item) {
    var_dump($item->title, $item->id);
}

function getItems($base, $params) {
    $path = "/api/v2/authenticated_user/items";
    $url = $base . $path;
    return get($url, $params);
}

function get($url, $params) {
    if (!empty($params)) {
        $query = http_build_query($params);
        $url = $url . "?" . $query;
    }
    $ch = curl_init($url);
    $authorization = "Authorization: Bearer " . TOKEN;
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json' , $authorization ));
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    $result = curl_exec($ch);
    if($errno = curl_errno($ch)) {
        $error_message = curl_strerror($errno);
        echo "cURL error ({$errno}):\n {$error_message}";
    }
    curl_close($ch);
    return json_decode($result);
}
```

これを実行してみると、最近の記事のタイトル,IDが2件取れる。

タイトル以外もいろいろ取れるので見てみてください。

## 記事に対して更新をかける

投稿更新のAPI。

https://qiita.com/api/v2/docs#patch-apiv2itemsitem_id

詳細は不明だが、body, coediting, tags, titleを投げればいいらしい。
これらはさっきの記事取得APIで、$item->body のようにすれば取れる。

したがって以下のようにすれば良い。

```php

setCoeditingTrue($base, $item);

function setCoeditingTrue($base, $item) {
    $path = "/api/v2/items/" . $item->id;
    $url = $base . $path;
    $params = [
        "body"      => $item->body,
        "tags"      => $item->tags,
        "title"     => $item->title,
        "coediting" => true,
    ];
    return patch($url, $params);
}
function patch($url, $params) {
    $ch = curl_init($url);
    $authorization = "Authorization: Bearer " . TOKEN;
    $patch = json_encode($params);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json' , $authorization, 'Content-Length: ' . strlen($patch) ));
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS,$patch);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    $result = curl_exec($ch);
    if($errno = curl_errno($ch)) {
        $error_message = curl_strerror($errno);
        echo "cURL error ({$errno}):\n {$error_message}";
    }
    curl_close($ch);
    return json_decode($result);
}



```

# できあがり

```php
<?php

define('TOKEN', 'トークン');

$base = "https://{team}.qiita.com";

$items = getItems($base, ["page" => 1, "per_page" => 100]);
foreach($items as $item) {
    setCoeditingTrue($base, $item);
}

function getItems($base, $params) {
    $path = "/api/v2/authenticated_user/items";
    $url = $base . $path;
    return get($url, $params);
}
function setCoeditingTrue($base, $item) {
    $path = "/api/v2/items/" . $item->id;
    $url = $base . $path;
    $params = [
        "body"      => $item->body,
        "tags"      => $item->tags,
        "title"     => $item->title,
        "coediting" => true,
    ];
    return patch($url, $params);
}


function get($url, $params) {
    if (!empty($params)) {
        $query = http_build_query($params);
        $url = $url . "?" . $query;
    }
    $ch = curl_init($url);
    $authorization = "Authorization: Bearer " . TOKEN;
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json' , $authorization ));
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    $result = curl_exec($ch);
    if($errno = curl_errno($ch)) {
        $error_message = curl_strerror($errno);
        echo "cURL error ({$errno}):\n {$error_message}";
    }
    curl_close($ch);
    return json_decode($result);
}
function patch($url, $params) {
    $ch = curl_init($url);
    $authorization = "Authorization: Bearer " . TOKEN;
    $patch = json_encode($params);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json' , $authorization, 'Content-Length: ' . strlen($patch) ));
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS,$patch);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    $result = curl_exec($ch);
    if($errno = curl_errno($ch)) {
        $error_message = curl_strerror($errno);
        echo "cURL error ({$errno}):\n {$error_message}";
    }
    curl_close($ch);
    return json_decode($result);
}
```



# 感想

- itemsを取る時にそもそも何件あるのかを取りたい
- PATCH送ったとき更新されないのに200返すのやめてほしい
- curlでデータ部にJSONを送るのは注意が必要（ヘッダーを適切に設定）
  - PATCHなのにPOSTDATAとはこれいかに
- 関数もっときれいにかけるはずだけどとりあえずわかりやすさ優先