Home

日記
参照を持つオブジェクトや配列の比較Edit

こんな感じのコードが、

$foo =& new stdclass();
$foo->foo =& $foo;
if ($foo === $foo) {
echo 'equal';
} else {
echo 'not equal';
}

無限再帰になってしまうのは、仕様なんだろうか?(PHP 4.4.0/Windows、4.4.1/Linux) var_dumpとかはちゃんとRECURSIVEを見つけて止めてくれるのに。

解決編

Published At2006-02-10 00:00Updated At2006-02-10 00:00

日記
オブジェクトを含む配列にin_arrayEdit

ついでにもう一つ。

$foo =& new stdclass();
$array = array(
$foo,
);
if (in_array($foo, $array)) {
echo 'found';
} else {
echo 'not found';
}

みたいなコードは、Wrong datatype for first argumentになるのも仕様なのか。まあちゃんとエラーメッセージが出るから仕様なんだろうけど、

Note: In PHP versions before 4.2.0 needle was not allowed to be an array.

とは書いてあるけど、objectはダメとは書いてないんだよな。

っつーかまあさっきの問題とこれとは同根で、オブジェクト同士の比較がうまくいかない(場合がある)から、in_arrayでオブジェクトが指定できないんだろうな。

せめてis_referenceとかができるなら、自前で実装できるんだけど、ある変数がリファレンスかどうかを判別する方法(別の変数と比較して同じシンボルテーブルを差しているかどうかがわかる、あるいは、そのシンボルテーブルを差す変数が複数存在するかどうかがわかる。)ってないよね。var_dumpのソースを見ればやり方は分かるんだろうけど。

Published At2006-02-10 00:00Updated At2006-02-10 00:00

日記
bigpresenのBloglines対応Edit

Bloglinesだとbigpresenで出力している部分が読めないんで、JavaScriptなしだと内容をホワイトスクリーンに初めから表示しておくようにしてみた(ついでにちょっとだけメッセージも変えてある)。

Index: bigpresen/trunk/bigpresen.rb
===================================================================
--- bigpresen/trunk/bigpresen.rb (revision 1)
+++ bigpresen/trunk/bigpresen.rb (revision 2)
@@ -48,5 +48,5 @@
else {
t#{scriptID} = 0;
-       document.getElementById("#{scriptID}").innerHTML="《REPLAY》";
+       document.getElementById("#{scriptID}").innerHTML="《CLICK to REPLAY》";
document.getElementById("#{scriptID}").style.fontSize='100%';
}
@@ -69,8 +69,13 @@
<tr>
<td width="#{width}" height="#{height}" onClick="#{scriptID}()" valign="middle" align="center" bgcolor="#ffffff">
-<span id="#{scriptID}" style="line-height:100%; color:black;">《START》</span>
+<span id="#{scriptID}" style="line-height:100%; color:black;">#{str.tr('/', ' ').split(/\|/).join('<br>')}</span>
</td>
</tr>
</table>
+<script type="text/javascript">
+<!--
+document.getElementById("#{scriptID}").innerHTML = "《CLICK to START》";
+-->
+</script>
HTML
end

なんで

splitしてjoinしているんだろう? tr("|", "<br>")でいいのに。何をやろうとしていたんだっけ。

Published At2006-02-11 00:00Updated At2006-02-11 00:00

日記
trac関連のメモEdit

複数tracプロジェクトは同じディレクトリ(/path/to/tracprojects/tracs)に配置した方がいい*1。同一ディレクトリ下のプロジェクト群を、tracdはまとめて管理してくれる。

関連するsubversionレポジトリについても、レポジトリ同士*2は同じディレクトリ(/path/to/tracprojects/svns)に作っておけば、mod_dav_svnでSVNParentPathとAuthzSVNAccessFileを組み合わせて、そのディレクトリ内のレポジトリをまとめて管理できる*3

また、tracdもmod_dav_svn経由のsubversionも、同じhtpasswd互換のパスワードファイルを使って認証することができるので、tracとsubversionで共通のアカウント管理が可能。

tracプロジェクトの管理ユーザーの追加(*4)は、

trac-admin /path/to/tracproject permisson add [adminuser] TRAC_ADMIN

ただし、すべての管理をWeb経由でできるわけではないので、ある程度trac-adminあるいは/path/to/tracproject/conf/trac.iniをいじる必要がある(WebAdminPluginを要チェック)。

ネットワーク的にオープンな場所でクローズドなtracプロジェクトを運用するためには、tracを完全認証制(未ログイン者は閲覧アクセスもできない)にする設定方法があるのかどうか探す必要がある(anonymousからあらゆる権限をremoveすればいいのかな?)。

標準のCSS(文字が小さい)が気に入らない人は、/path/to/tracproject/templates/site_css.csをいじる。たとえば、

<?cs
##################################################################
# Site CSS - Place custom CSS, including overriding styles here.
?>
body {
font-size: 1em;
line-height: 1.5em;
}

とか*5

SVNParentPathを使ってマウントしたsubversionレポジトリ(http://example.com/[someproject])に対して、svn co http://example.com/[someproject]ができないな*6。svn co file:///path/to/[someproject]はできるんだけど。これは仕様なのかな? それとも俺の設定がどこかおかしいのかな?

デザイナーとかと共同作業をする際に、subversion(というかバージョン管理システムという概念)を説明しないままに、そこそこの恩恵を受けてもらおうというアプローチ案。smbで適当なディレクトリをマウント(/path/to/someproject/smb)し、そこにある時点のexportをコピーする。デザイナーにはそこをマウントして作業してもらう。そして、別にcoしたディレクトリ(/path/to/someproject/work)を用意し、そこに作業ディレクトリの内容を定期的にsync*7&commit*8すると、作業履歴がsubversionに残る*9。こうすることで、.svnディレクトリの存在とかに気を遣わずに、自由に編集ができる。ただこの方法と、ふつうのsubversionの使い方とは相容れないんで、作業ディレクトリの切り方とかを考えておく必要がある*10

とか書きながらsubversion関連のドキュメントをながめていたら、subversion 1.2以降ではWebDAVの自動バージョン化なんて機能が使えるようになっていたらしい。デザイナーとの共同作業とかで使うならこっちの方がいいかな? でもWebDAVディレクトリってsmbと比べると微妙に不便なんだよなー。

全部の権限を削除したらエラーが出た

trac-admin remove /path/to/project permission remove anonymous BROWSER_VIEW LOG_VIEW FILE_VIEW CHANGESET_VIEW TICKET_VIEW TICKET_CREATE TICKET_APPEND TICKET_CHGPROP TICKET_MODIFY TICKET_ADMIN MILESTONE_VIEW MILESTONE_CREATE MILESTONE_MODIFY MILESTONE_DELETE MILESTONE_ADMIN ROADMAP_VIEW ROADMAP_ADMIN REPORT_VIEW REPORT_SQL_VIEW REPORT_CREATE REPORT_MODIFY REPORT_DELETE REPORT_ADMIN WIKI_VIEW WIKI_CREATE WIKI_MODIFY WIKI_DELETE WIKI_ADMIN TIMELINE_VIEW SEARCH_VIEW CONFIG_VIEW

ってやったら*11、tracdの該当のプロジェクトにアクセスすると

Oops...
Trac detected an internal error:
iteration over non-sequence
Traceback (most recent call last):
File "/usr/lib/python2.3/site-packages/trac/web/standalone.py", line 303, in _do_trac_req
dispatch_request(path_info, req, env)
File "/usr/lib/python2.3/site-packages/trac/web/main.py", line 139, in dispatch_request
dispatcher.dispatch(req)
File "/usr/lib/python2.3/site-packages/trac/web/main.py", line 80, in dispatch
req.perm = PermissionCache(self.env, req.authname)
File "/usr/lib/python2.3/site-packages/trac/perm.py", line 276, in __init__
self.perms = PermissionSystem(env).get_user_permissions(username)
File "/usr/lib/python2.3/site-packages/trac/perm.py", line 132, in get_user_permissions
for perm in self.store.get_user_permissions(username):
File "/usr/lib/python2.3/site-packages/trac/perm.py", line 218, in get_user_permissions
for user, action in rows:
TypeError: iteration over non-sequence

というエラーが出るようになった。権限が一個もなくなると、きっと権限チェックをiterationで回しているあたりでエラーが出るんだろうな(ソース未確認)。権限が空でも動くように直せばいいのかな?

ちなみに権限を適当に一個addしておけばエラーは出ず、ほとんどの機能はつぶれてくれる(WIKI_VIEWもつぶれるんで、主要な情報は何も表示されなくなる)んだけど、ヘッダ・フッタ回り+ユーザー設定メニューが見えちゃうんで、ちょっと気持ち悪いんだよな。本当はヘッダ・フッタ回りも完全に消えて、/loginを直接叩かないと何も見えない方がいいんだけど。

tracdとCGI起動の重さの違い

日常的に負荷状況が高いサーバーで、tracd(+Apache2リバースプロキシ)と(Apache2)CGI起動のtracを同時に動かしてみたところ、tracd経由の方が圧倒的に軽かった。っつーかCGI起動は重すぎだな。mod_pythonって手もあるけど、手軽さからいうとtracdを基本にした方がいいかな。トップページの表現力に難があるが。

*1 シンボリックリンクを使ったりする手もあるけど

*2 「tracプロジェクトと同じ」ではないよ

*3 snvserveは使ったことがないので、そっちを使うとどういうことができるのか未検討

*4 最初TRAC_ADMINに気づかずにWIKI_ADMIN、TICKET_ADMINとかいちいち追加してたよ

*5 ひな形テンプレートを書き換えようと思ったんだけど、/usr/share/trac/templatesにはsite_css.csがないなー。どこにあるんだろう

*6 /に対してPROPFINDすると301 Moved Permanentlyが返って終了になるみたい。subversion 1.3.0

*7 rsync -r --delete --exclude="*.svn" /path/to/someproject/smb /path/to/someproject/work

*8 svn commit /path/to/someproject/work -m "auto commit" -q

*9 これだけだと削除したファイルがレポジトリから消えないんで、その辺は別途svn deleteする処理をかます必要がある

*10 デザイン系ディレクトリは上記方法にして、プログラム系ディレクトリはふつうにcommitするとか。あるいは自動コミットの処理をもうちょっと頭よくして対応できるかな?

*11 ちなみに上記はTracPermissionsからコピっただけで、不要なエイリアスとかも混ざってる

Published At2006-02-13 00:00Updated At2006-02-13 00:00

日記
えいご漬けEdit

オクサンが買ったんでやらせてもらったけど、なかなかいい感じ。

今やっている範囲では、高校生レベル程度までの簡単な英語しか出てきてないけど*1、ほどよく忘れかけている単語や言い回しを思い出させてくれる。あと文章として読まれたときの聞き取りって学校ではほとんどやってなかったから、そこかしこに新しい発見(と慣れ)がある*2。これをしばらくやっていたら、単文の聞き取りはだいぶうまくなりそう。

ただ、さほど難しくない単語で構成された単文に関しては、もともと聞き取るのは難しくないんだよな。問題は、沢山の文章を連続して聞き取ろうとしているときに、一カ所でも意味を把握できない場所が出てくると、その後の文章がなし崩しに全部聞き取れなくなっちゃったりするところなんだけど、英語の聞き取りに慣れてきたら、そういうのもなんとかなるのかな。

そういやこのゲームをやっていて思ったんだけど、プログラムを日々書いていると、結構幅広い英単語を使っているんだなー。変数名とか関数名とかクラス名とかで使われる英単語(人のつけたもの、自分でつけるもの)って、いわゆる技術系単語以外にもいろいろあるから、結構沢山の英単語の意味と綴り方をちゃんと覚えていた。漢字なんかはもうほとんど覚えていないのに。

*1 その後難しい単語が出てくるのかどうかは知らない

*2 設定で、日本語訳は答えが出た後に表示するようにしないと、聞き取りではなく、単に日本語を英文に翻訳してしまって、聞き取りの練習にならない

Published At2006-02-13 00:00Updated At2006-02-13 00:00

日記
labelがあった方がいいよねEdit

tDiaryでは、管理機能のチェックボックスにlabelが指定されていないけど、あった方が便利だよね*1。ということで、自分が使っている範囲のところに追加してみた。

でもこういうことは、場当たり的にやらずにちゃんと網羅的にやった方がいいんだろうな。あとlabel for="[ID]"を使うとinput type="checkbox"にidが必要になるんだけど、他の場所とのidの重複が怖いんで、専用のネームスペース(っつーかprefix)を使った方がいいかもしれない。

update.rhtml

*** update.rhtml.org    2006-02-13 18:05:49.000000000 +0900
--- update.rhtml        2006-02-13 18:22:31.637861952 +0900
***************
*** 38,44 ****
<input type="submit" tabindex="999" accesskey="A" name="<%%= submit_command %>" value=" <%%= submit_label %> ">
</span>
<span class="checkbox hidediary">
!                       この日の日記を隠す<input type="checkbox" name="hide" value="true" <% unless @diary.visible? then %>checked <% end %>tabindex="1000" accesskey="H">
</span>
</div></form>
</div>
--- 38,44 ----
<input type="submit" tabindex="999" accesskey="A" name="<%%= submit_command %>" value=" <%%= submit_label %> ">
</span>
<span class="checkbox hidediary">
!                       <label for="hide">この日の日記を隠す</label><input type="checkbox" name="hide" id="hide" value="true" <% unless @diary.visible? then %>checked <% end %>tabindex="1000" accesskey="H">
</span>
</div></form>
</div>
***************
*** 59,68 ****
@diary.each_comment( 100 ) do |comment| %>
<div class="commentator">
<span class="checkbox">
!                                       <input class="checkbox" type="checkbox" tabindex="<%=2000+idx%>" name="<%= idx += 1 %>" value="true"<% if comment.visible? then %> checked<% end %>>
</span>
<span class="commentator"><%= CGI::escapeHTML( comment.name ) %><%= CGI::escapeHTML( " <#{comment.mail}>" ) unless comment.mail.empty? %></span>
<span class="commenttime"><%%=comment_date( Time::at( <%=comment.date.to_i%> ) )%></span>
</div>
<p><%= comment.body.make_link.gsub( /\n/, "<br>" ).gsub( /<br><br>\Z/, '' ) %></p><%
end
--- 59,70 ----
@diary.each_comment( 100 ) do |comment| %>
<div class="commentator">
<span class="checkbox">
!                                       <input class="checkbox" type="checkbox" tabindex="<%=2000+idx%>" name="<%= idx += 1 %>" id="cid_<%= idx += 1 %>" value="true"<% if comment.visible? then %> checked<% end %>>
</span>
+                 <label for="cid_<%= idx %>">
<span class="commentator"><%= CGI::escapeHTML( comment.name ) %><%= CGI::escapeHTML( " <#{comment.mail}>" ) unless comment.mail.empty? %></span>
<span class="commenttime"><%%=comment_date( Time::at( <%=comment.date.to_i%> ) )%></span>
+                 </label>
</div>
<p><%= comment.body.make_link.gsub( /\n/, "<br>" ).gsub( /<br><br>\Z/, '' ) %></p><%
end

ping.rb

*** ping.rb.org 2006-02-13 18:14:32.000000000 +0900
--- ping.rb     2006-02-13 18:17:43.915602384 +0900
***************
*** 84,91 ****
def ping_edit_proc
r = <<-HTML
<div class="ping">
!       <input type="checkbox" name="plugin_ping_send" value="true" checked tabindex="400" />
#{@ping_label_send}
</div>
HTML
end
--- 84,93 ----
def ping_edit_proc
r = <<-HTML
<div class="ping">
!       <input type="checkbox" name="plugin_ping_send" id="plugin_ping_send" value="true" checked tabindex="400" />
!    <label for="plugin_ping_send">
#{@ping_label_send}
+    </label>
</div>
HTML
end

makerss.rb

*** makerss.rb.org      2006-02-13 18:18:15.032871840 +0900
--- makerss.rb  2006-02-13 18:18:49.595617504 +0900
***************
*** 301,308 ****
checked = @cgi.params['makerss_update'][0] == 'false' ? ' checked' : ''
r = <<-HTML
<div class="makerss">
!       <input type="checkbox" name="makerss_update" value="false"#{checked} tabindex="390" />
#{@makerss_edit_label}
</div>
HTML
end
--- 301,310 ----
checked = @cgi.params['makerss_update'][0] == 'false' ? ' checked' : ''
r = <<-HTML
<div class="makerss">
!       <input type="checkbox" name="makerss_update" id="makerss_update" value="false"#{checked} tabindex="390" />
!     <label for="makerss_update">
#{@makerss_edit_label}
+     </label>
</div>
HTML
end

*1 チェックボックス自体をクリックしなくても、その説明文とかをクリックしてチェックボックスのオン・オフを切り替えることができるようになる

Published At2006-02-13 00:00Updated At2006-02-13 00:00

日記
trac拡張探訪 tagsEdit

tracのWikiページにタグ入力と、タグ一覧・タグクラウドなどの表示をするためのマクロを追加するらしい。

けど、http://muness.textdriven.com/trac/wiki/tags/Setupを見ながらセットアップしようとしても認識してくれない。eggとcsテンプレートを追加して、trac-admin [project] upgradeしてもno upgrade necessaryになる。よくわからん。

まああまり使い勝手が良さそうでもないんで、使えないなら使わなくてもいいかも。

動いた

setuptoolsをあらかじめインストールしておかないと、.egg系拡張は動かないということだった

で、実際に使ってみたんだけど、ページ入力時にいちいち別枠でタグを入力しなければならないってのと、TagListとかTagCrowdsとかに、現在使われているタグ(その回数)が表示されるのはいいけど、そこからのリンク先が単にタグ名のWikiページ(通常は用意されていない)になってるのはつまらないなー。そのタグを利用しているページ一覧とかにリンクされているのがふつうだと思うんだけど。どこかで設定すればそうなるのかな?

Published At2006-02-14 00:00Updated At2006-02-14 00:00

日記
trac拡張探訪 AddCommentMacroEdit

Wikiページにコメント欄を追加するマクロ。wiki-macrosに突っ込むだけで動く。プレビュー付きの本文+投稿者フォームが表示され、投稿するとフォームの上に投稿内容が追加されるというシンプルな作り。

これは用途によっては結構使えそう。コメント本文でWiki記法がフルに使えるのも便利。

Published At2006-02-14 00:00Updated At2006-02-14 00:00

日記
trac拡張探訪 FootNoteMacroEdit

脚注マクロ。zipを展開し、tracのバージョンにあわせた.pyをwiki-macrosにコピーするだけで動く。

[[FootNote(脚注の文章)]]で脚注を書いていくと、そこが連番数値リンク付き表示に変わる。んでもって、文末なんかに[[FootNote]]と書くと、そこが実際の脚注文章のリンク先になる。

便利は便利だけど、tDiaryのfnみたいに[[FootNote]]がなければ、自動的にページ末に脚注を表示してくれると楽なのになー。

Published At2006-02-14 00:00Updated At2006-02-14 00:00

日記
trac拡張探訪 WikiCalendarMacroEdit

一月分のカレンダーを表示し、各日に対して指定した書式のWikiページへのリンクを張る。簡単に日付をタイトルの一部として使ったページへのナビゲーション(編集&閲覧)を用意することができるので、後で紹介するBlogマクロと組み合わせると、日記風の使い方が可能になる。

Published At2006-02-14 00:00Updated At2006-02-14 00:00