PhantomJSでCasper.jsでphp.jsを使う

スパイダリングフリーカーなら一度触ったことはあるはず、、、
のみならず、TDD実践者からも注目を浴びるPhantomJSをより
使いやすくするCasper.js。自分が使う際には、
PHPの関数を使いたくて仕方がなくってたまらなくなったのでその手順。

Casper.jsはCommonJSのモジュール*1の擬似実装を0.6から採用みたいなので、
CommonJSでの"exports.functionname = " でのライブラリ形式で使います。
Casper.jsのインストール方法はリンク先通り。
http://n1k0.github.com/casperjs/
んで、

$git checkout 0.6

PHPの関数と言ってもphp.jsという実装があるので、それを使用。
phpjs.orgのサイトにcommonjsのパッケージがいくつかあって、それをCasper.jsのmodulesにぶち込めばいいと思いますが、
自分で最新のコードを用意したりカスタマイズする場合は

$git clone git://github.com/kvz/phpjs.git

このリポジトリにある、_tools/phpjscompile.php
を参考に自分の必要なオプションを指定するphpスクリプトを用意して、php.jsとしてコンパイル。

<?php
error_reporting(E_ALL);
require_once "PHPJS_Library/PHPJS/Library.php";

// Check for CLI
if ((php_sapi_name() != 'cli')) {
   die("CLI Only");
}

$dirFunctions = realpath(dirname(__FILE__)."/..")."/functions";
$dirCompile   = realpath(dirname(__FILE__)."/..")."";
$PHPJS_Compiler_Shell = new
PHPJS_Library_Compiler_Shell($dirFunctions, $dirCompile);

$PHPJS_Compiler_Shell->setSelection('function::_phpjs_shared_bc');
$PHPJS_Compiler_Shell->addToSelection("category::strings");
$PHPJS_Compiler_Shell->addToSelection("category::filesystem");
$PHPJS_Compiler_Shell->addToSelection("category::xml");
$PHPJS_Compiler_Shell->addToSelection("category::url");
$PHPJS_Compiler_Shell->addToSelection("category::math");

#$PHPJS_Compiler_Shell->setSelection("all");

// Set flags
$flags = 0;
//$flags = $flags | PHPJS_Library_Compiler::COMPILE_NAMESPACED;
//$flags = $flags | PHPJS_Library_Compiler::COMPILE_MINFIED;
$flags = $flags | PHPJS_Library_Compiler::COMPILE_COMMONJS;
#$flags = $flags | PHPJS_Library_Compiler::COMPILE_PACKED;

echo $PHPJS_Compiler_Shell->compile($flags);
$php _tools/mycompile.php > /path/to/git/casperjs/modules/php.js

Casper.jsでの呼び出しは、

require("php").pathinfo("/var/foo.txt");

これで、一応実行できるのだけれど、php.jsではechoとかでwindows.documentに依存した関数が一部あるので、
その関数はエラーになる。
(echoはPHPとしては言語機構だけで、php.js側では関数として実装・・・とか拘る人は俺よりモテない呪いにかかれ)

documentへの依存に対し、node.jsでの迂回作として、yssk22さんのsunrize、
https://github.com/yssk22/sunrise
lib/vendor/php.jsにある

var dummy = '<html><head></head><body>hello world</body></html>';
exports.window = require('jsdom').jsdom(dummy).createWindow();

としてjsdom使う方法があるんですが、今のところCasper.jsのbin/bootstarp.jsでのrequire実装は
階層が深い場合に対応できてないようなので若人へ未来を託す結論に至りました。まる。