備忘録 blog

Docker/Machine Learning/Linux

ownCloudのアプリを作る

tl;dr

ownCloudはphp製のオープンソースオンラインストレージであり、社内Dropboxのようなものとして使えるが、プラグインのような形でAppを自作・追加することができます。このAppはHookやCronジョブのほか、ownCloud内にアプリ用のページを実装することもできます。しかし日本語の資料が乏しく、マニュアルも十分に整備されていないので自分でソースコードを読みながら適宜、実装を書いていく必要があります。

App Development — ownCloud Developer Manual 9.0 documentation

以下ではownCloud9.0を対象に、アプリを作る上で気になったことや引っかかったことをメモしておきます。

アプリの作り方とデバッグ方法

アプリは、\apps内にフォルダを作って置けば良い。予めocdevというコマンドラインツールをダウンロードしておいて、\appsフォルダ内で

ocdev startapp OwnNotes

というコマンドを叩くことでディレクトリが自動で生成されます。ここで注意しなければならないのは、イニシャルキャピタルのキャメルケースでアプリ名を定めなければならないということです。実際に生成されるフォルダはすべて小文字になっているので注意。ここで決めるアプリ名が、そのまま名前空間になります。モジュール名は例えば\OCA\MyApp\Controller\PageController が /apps/myapp/controller/pagecontroller.php に対応しているように、ファイル名のスラッシュの向きが入れ替わってキャメルケースになります。

デバッグですが、php初心者の私はひたすらownCloudのログに出力するという方法をとっていました。\data\ownCloud.logless +Fして眺めていましたが、このログはそのままでは少しみずらいです。一方でWeb上の管理画面でログを見ることはできますが、そうすると今度は自分で更新しなきゃならないので痛し痒しです。

Hookが効かない

https://doc.owncloud.org/api/classes/OCP.Files.Node.html

Fileが書き込まれたときにHookして、callback関数で書き込まれたファイルのNodeを取得して、中身をあれこれするコードを書こうと思った時のための備忘録。

https://doc.owncloud.org/server/9.0/developer_manual/app/init.html

\OCP\Util::connectHook('OC_Filesystem', 'post_write', 'OCA\OwnNotes\Hooks\UserHooks', 'postWrite');

こうすると、ownnotes/hooks/userhooks.phpclass UserHooksのシングルトンメソッドとしてstatic public def postWrite($args)を定義すればよいのですが、この戻り値が曲者で、返ってくる値は

{
"run" => 1,
"path" => "\aaa.txt",
}

みたいな形になります。(実際にはphpのデータ構造です。var_export($node, true)みたいなコードを書くと、文字列型として出力されます。)

https://github.com/owncloud/core/blob/master/lib/private/Files/Node/HookConnector.php

このコードを読む限り、このpathをNodeにするにはHookConnectorgetNodeForPathを呼ばなければならないのですが、private methodなのでクラスのインスタンスを作らなければなりません。しかしコンストラクタには$rootと$viewが必要となって、厄介なのでやはり引数として[$node]自体が返ってくるようにしたいです。

https://doc.owncloud.org/server/9.0/developer_manual/app/hooks.html

というわけで、上のページを参考にしてhookを定めます。registerメソッド内でHookをlistenしておいてapp起動時にregisterを呼ぶようにしておけば、この時呼ばれるcallbackメソッドの引数はNodeになります。

ファイルの作成/更新ができない

Filesystem — ownCloud Developer Manual 9.0 documentation

    public function writeTxt($content) {
        // check if file exists and write to it if possible
        try {
            try {
                $file = $this->storage->get('/myfile.txt');
            } catch(\OCP\Files\NotFoundException $e) {
                $this->storage->touch('/myfile.txt');
                $file = $this->storage->get('/myfile.txt');
            }

            // the id can be accessed by $file->getId();
            $file->putContent($content);

        } catch(\OCP\Files\NotPermittedException $e) {
            // you have to create this exception by yourself ;)
            throw new StorageException('Cant write to file');
        }
   }

ドキュメントにあるコードそのままですが、\OCP\Files\NotPermittedExceptionが出てしまってファイルを書き込めません。