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.log
をless +F
して眺めていましたが、このログはそのままでは少しみずらいです。一方でWeb上の管理画面でログを見ることはできますが、そうすると今度は自分で更新しなきゃならないので痛し痒しです。
Hookが効かない
Fileが書き込まれたときにHookして、callback関数で書き込まれたファイルのNodeを取得して、中身をあれこれするコードを書こうと思った時のための備忘録。
\OCP\Util::connectHook('OC_Filesystem', 'post_write', 'OCA\OwnNotes\Hooks\UserHooks', 'postWrite');
こうすると、ownnotes/hooks/userhooks.php
のclass UserHooks
のシングルトンメソッドとしてstatic public def postWrite($args)
を定義すればよいのですが、この戻り値が曲者で、返ってくる値は
{ "run" => 1, "path" => "\aaa.txt", }
みたいな形になります。(実際にはphpのデータ構造です。var_export($node, true)
みたいなコードを書くと、文字列型として出力されます。)
このコードを読む限り、このpathをNodeにするにはHookConnector
のgetNodeForPath
を呼ばなければならないのですが、private methodなのでクラスのインスタンスを作らなければなりません。しかしコンストラクタには$rootと$viewが必要となって、厄介なのでやはり引数として[$node]
自体が返ってくるようにしたいです。
というわけで、上のページを参考にして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
が出てしまってファイルを書き込めません。