sfTwigPluginのサンプルコード書いた

夜21時くらいからはじめてこんな時間までかかってしまったが、sfTwigPluginをこういう風に使いたいなーってサンプルコードを書いてみた。

http://github.com/cocoiti/cocowiki/

眠いのであとでちゃんと書くが、要約すると、デザインにかかわるテンプレートファイルは通常symfonyのレイアウトファイルを配置するディレクトリに配置する。
module側にはアプリケーションにかかわる部分(主にフォーム関係やエラーメッセージ)を入れる。

ということがやりたかった。

そして、それを実装するためには現在のsfTwigPluginは機能がたりなかったのでsfTwigPluginをforkしてEventListenerを追加した。

http://github.com/cocoiti/sfTwigPlugin/

下記のようなコードでEventを追加してやれば、継承や本体の書き換えを使うことなく設定の範囲で、好きなパスを、Twigのテンプレート読み取り先のディレクトリとして登録できる。

<?php
 
class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
    $this->enablePlugins('sfDoctrinePlugin');
    $this->enablePlugins('sfTwigPlugin');
    $this->dispatcher->connect('template.twig_template_paths', array($this, 'getTwigTemplatePaths'));
    $this->dispatcher->connect('template.twig_get_extensions', array($this, 'getTwigExtensions'));
  }
 
  public function getTwigTemplatePaths(sfEvent $event, $params)
  {
    $layout = array_filter(sfContext::getInstance()->getConfiguration()
                                            ->getDecoratorDirs(), 'file_exists');
    return array_merge($layout, $params);
  }
 
  public function getTwigExtensions(sfEvent $event, $params)
  {
    $escaper = new Twig_Extension_Escaper(true);
    return array_merge($params, array($escaper));
  }
 
}

ちなみに、cocowiki、gitで管理できるwikiみたいな実装をしてみた。

最初、外国の人にもわかるようにmarkdownシンタックスに対応しようとおもったけど、使ってみたいライブラリが見つからなかったので、id:anatooHatenaSyntaxを使わせていただいた。(すげー楽に使えました。)

あとgitの管理については、最近、PEPrにあがった、VersionControl_Gitを使わせていただいている。

もちろん、そういう用途で使う分にはちゃんとしたサービスとして作られてるid:sotarokwikihubを使うべきななのはいうまでもない。

思考実験と、最終的にsfTwigPluginの作者への説明のためにつくったアプリなので更新するつもりはあまりないし、パソコン破壊するとか、公開以外のディレクトリが全部みえちゃうかもしれないレベルで激しくちゃんと動く自身がないが、Twigや各ライブラリを使う参考にはなるんじゃないだろうかとおもうのでさらしておきます。

英語勉強してpullリクエストおくらないと。

sfTwigPlugin

連絡いただきました。
コードのほうは無事とりこ・・・まれず、よりエレガントなコードになりました。
http://github.com/henrikbjorn/sfTwigPlugin

そして気がついたら、ばんばん更新されるようになった。
エレガントすぎる。

もともとその計画だったのかもしれないけど、10月から更新されてなかったものトリガーを引けたかもしれないと思うとうれしい。

今の悩みは、githubで自分の更新を全部すてて再びこの人のをforkする作法がよくわらないこと。

一日目 インストール

openpeargithub にて公開となったので少しお手伝いすることにした。
とはいえまだ作業内容を自分の中でタスクとして落とし込めてないので、インストールから画面みれるところまで準備した。

開発者は随時募集しているのでやりたい人はいっぱいいるとおもうので参考にしていただきたい。


まずはおとしてくるforkについてはまたこんど

$ git clone git://github.com/nequal/Openpear.git

次にプロジェクトに必要なディレクトリを作成しイニシャライズして設定ファイルを上書き
プロジェクトのイニシャライズ時にrhacoの必要なファイルを自動でダウンロードする。
いろいろ設定値を聞いてくるがこれは無視して問題ない

$ cd Openpear
$ mkdir work vender
$ chmod 777 work
$ php setup.php 
core path[/home/cocoiti/Openpear/core/]: 
install application: 
application url [http://localhost/Openpear]: 
working directory [/home/cocoiti/Openpear/work/]:
$ cp __settings__.php.default __settings__.php
$ vi __settings__.php #ドメイン、mysqlのサーバ設定などを変更

最後にopenpear独自の依存パッケージをインストール

$ sudo pear channel-discover openpear.org
$ sudo pear install openpear/HatenaSyntax-beta

上記でwebサーバ上に公開すれば足りないrhacoの設定ファイルなどは起動時に自動でインストールしてくれるが、僕の環境だとパーミッションの問題などでうごかないので下記のようにコマンドラインで入れた

$ php setup.php -import org.rhaco.storage.db.Dao
$ php setup.php -import org.rhaco.net.mail.Gmail
$ php setup.php -import org.rhaco.lang.DateUtil
$ php setup.php  -import org.rhaco.storage.db.module.DbcMysql
$ php setup.php  -import org.rhaco.io.log.LogFile

開発に興味があれば下記のあたりに集合するといいと思う
http://groups.google.com/group/openpear-project

Let's rhaco!!!!! じゃなくてopenpear!!

sfTwigPluginを弄ってる

Twigいいよ!とかいってたけど、それを使うフレームワーク書いてる精神的な余裕がなくなったので、symfony1.4と組み合わせて使えないかしらといいろごにょってみた。

オリジナルはここのなんだけど10月くらいに更新をやめてしまってる。

とうぜん絶賛開発中だったTwigがそのままでは動くわけもなくforkしてみた。

とりあえず試してみたいひとは下記な感じで

使い方

インストール
$ cd {PROJECT_DIR]/plugins/
$ git clone git://github.com/cocoiti/sfTwigPlugin.git
$ cd sfTwigPlugins/
$ git submodule init
$ git submodule update
設定

マニュアルにあるとおり。project本体か各アプリケーションのconfigディレクトリにmodule.ymlをおけばいい

all:
    view_class: sfTwig
    partial_view_class: sfTwig
テンプレート

たとえば、アプリケーションfrontendだったら下記のようなファイルを作る
{PROJECT_DIR]/apps/frontend/templates/layout.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    {{ ""|include_http_metas() }}
    {{ ""|include_metas() }}
    {{ ""|include_title() }}
    <link rel="shortcut icon" href="/favicon.ico" />
    {{ ""|include_stylesheets() }}
    {{ ""|include_javascripts() }}
  </head>
  <body>
    {{ sf_content }}
  </body>
</html>

あとは各モジュールのテンプレート側にいつもの通りファイルを置くことになる。
現在はレイアウト側のファイルをモジュール側のファイルは継承できない。

思ったこと

symfony標準helperに関しては、filterで定義しているらしく変換コードがあったのだが、
このシェルが動かないのでPHPで書き直した、symfonyコマンドから実行できるタスクもあるがこちらは弄ってない。

というか、下記が記述ダサすぎる。TwigはcoreなExtensionを書くの面倒っぽいのでそのせいかもしれないし僕の知らない別の構文があるのかもしれない。

    {{ ""|include_http_metas() }}

下記みたいな感じで書くようにするのがいいかDjango参考にするか考えてる。

    {% symfony::include_http_metas() %}

個人的にはレイアウト側のディレクトリにすべてのテンプレートファイルを配置して、アプリケーションが書き換えたいところ(formとかエラーメッセージ)だけ継承して使うという形を想定しているの
で現状の仕組みではそれを実現できない。

というか、元の作者もsfPHPView置き換えただけだよみたいなこといってたのでそれほどノリノリじゃないっぽいので、もうちょっとごにょごにょするか、がつっと別のものを作りたい。
その時の名前が悩ましい。

creoleのバグ

具体的にいうとMySQLのドライバの下記のあたり

    /**
     * Roll back (undo) the current transaction.
     * @throws SQLException
     * @return void
     */
    protected function rollbackTrans()
    {
        if ($this->database) {
            if (!@mysql_select_db($this->database, $this->dblink)) {
                throw new SQLException('No database selected', mysql_error($this->dblink));
            }
        }
        $result = @mysql_query('ROLLBACK', $this->dblink);
        $result = @mysql_query('SET AUTOCOMMIT=1', $this->dblink);
        if (!$result) {
            throw new SQLException('Could not rollback transaction', mysql_error($this->dblink));
        }
    }

「$result = @mysql_query('ROLLBACK', $this->dblink);」
この結果をチェックしてないので、ROLLBACK失敗時に"SET AUTOCOMMIT=1"をするため暗黙のcommitが働き、結果commitされてしまう。

もし、今だPropelの古いバージョンなどを使ってる人がいたらこの周辺のコードはパッチあてたほうがいい。

    /**
     * Roll back (undo) the current transaction.
     * @throws SQLException
     * @return void
     */
    protected function rollbackTrans()
    {
        if ($this->database) {
            if (!@mysql_select_db($this->database, $this->dblink)) {
                throw new SQLException('No database selected', mysql_error($this->dblink));
            }
        }

        $result = @mysql_query('ROLLBACK', $this->dblink);
        if (!$result) {
            throw new SQLException('Could not rollback transaction', mysql_error($this->dblink));
        }

        $result = @mysql_query('SET AUTOCOMMIT=1', $this->dblink);
        if (!$result) {
            throw new SQLException('Could not rollback transaction', mysql_error($this->dblink));
        }
    }

こんな極東のブログで日本語だけでかかずに、バグ報告したいのだが、creoleプロジェクトは終了したプロジェクトなので悩んだ挙句ここにさらすだけにとどめておく。

ちょっといけてるArrayObjectあたりつかったリクエストクラス考え中

文字コード云々の問題含めてPHPでもrackのrequestクラスみたいなのほしーなーとざっくり考え中。

とりあえず対応したい問題
(1) 文字コードのチェック
(2) nullバイトの削除
(3) isset($_POST)とか書きたくない

大まかにいうとこーいうイメージ(あくまでイメージ

<?php
//上書きしちゃう。不正な文字列の場合は例外が出る
$_POST = new Holo_Request_ArrayObject($_POST,
                         mb_string_internal_encoding(),
                         Holo_Request_ArrayObject::RESULT_DEFAULTVALUE
                         || Holo_Request_ArrayObject::ERROR_REMOVE_ONRY);
 
//配列に値は入ってないのでfalseを返す
assert(isset($_POST['notvalue']) === false);
 
//だけど配列に値がなくてもnoticeとか出力せずなんか返す(デフォルトはnull)
assert($_POST['notvalue'] === null);

//もちろん設定かえれば
$_POST->setDefaultValue('mote');
 
// "mote"を返す。
assert($_POST['notvalue'] === mote);

一応、(1)(2)(3)を満たしたけど、is_array($_POST)とかしたらfalse返すことに気がつく。
あーまぁそうだよね。これだと今まで動いたフレームワークを強引に書き換えという要件には使えないパターンがでてくるよなーと思った。

<?php
//上書きしちゃう。不正な文字列の場合は例外が出る
$value = new Holo_Request_ArrayObject($_POST,
                         mb_string_internal_encoding(),
                         Holo_Request_ArrayObject::RESULT_DEFAULTVALUE
                         || Holo_Request_ArrayObject::ERROR_REMOVE_ONRY);
$_POST = (array) $value;

で、たぶん(1)(2)は満たせるから、(3)に関しては、自分用として使おうかなと思った。
一応ソース


テストにphptをはじめてつかったけど、いまいち、手になじめてない。
コメントかかないとな。

forkとかpullとか大歓迎。原型とどめないようなやつがみたい。

あとやろうと思ってること

文字コードのセキュリティ

ごめんなさいあからさまにいいっぱなし投げっぱなしです。

不正な文字列は
+ バリデータではじく
+ そもそも最初の入力時点でエラーではじいてしまう

僕個人の考えではフレームワークにNULLの文字列削除のコードと一緒に削除するものを、(可能であればデフォルトで動作する)プラグインとして提供するほうがいいと考えてはいる。

その上で今ないものに対しては、マルチバイト圏の僕らが各フレームワークにつっこんでいく必要があるのかなぁと無責任に思った。

、外国産のフレームワークはmbstring系の拡張が嫌がられるというものあるので、id:t_komuraさんの下記の記事を参考に組み込むのがいいかなと考えてます。

うーん。なんか各フレームワークでどうなってるっていうのが知りたい。