月めくりカレンダー

ひさびさにmovable typeのカスタマイズ。
と言っても、こちらのブログではなくてTrackback Albirexの方なんだけど(^^;;
「月めくりカレンダー」を、まったく新しいタイプのものにしてみた。
参考にしたのはこちらのサイト
どんぐりころころ
<MTCalendar>タグを使わないでカレンダーを描画しているので、エントリーのあるなしにかかわらずに表示できるし、祝日・振替休日などにも対応しているところがgood。
しかし一方で、<MTCalendar>タグを使わずに個別エントリーへのリンクを貼るので、ちょっとした工夫が必要。ここがカスタマイズの重要ポイントになる。リンク部分にカーソルを合わせたときにエントリーのタイトル表示が出来ないのも、ちょっと残念なところ。


オリジナルのスクリプトの以下の部分が、カスタマイズの対象。

// 日付別アーカイブファイルが存在すれば、リンクさせる。 //
// 注意:Web上の論理パス //
$filename = “/archives/”.date(“Y”,$t).”/”.date(“m”, $t).”/”.date(“d”,$t).”/”;
// 注意:フルパスでの記述。レンタルサーバなどで //
//    バーチャルホストの場合は注意。 //
$full_filename = “/hogehoge/user1/web”.$filename.”index.html”;
// ファイル検査 //
if (file_exists($full_filename)) {
print (“<A href=\””);
print $filename;
print(“\” target=\”_top\”>”);
print date(“j”, $t);
print(“</A>”);
} else {
print date(“j”, $t);
}

「Trackback Albirex」の場合、個別アーカイブをphp化している関係上、名前付の規則はこのようにしてある。
<$MTArchiveDate format="%Y/%m/%d_%H%M"$>.php
つまり個別アーカイブは、「アーカイブ/年/月/」というフォルダ内に「日_時分.php」という名前のファイルで保存されている。したがって、カレンダー側から直接ファイル名を指定してファイルの存在を検査することは不可能(カレンダー側から引数としてひろえるのは「年月日」の数字だけだから)。
そこで、このようにファイルを検索してやることにした。
まずカレンダーの描画に入る前に、表示対象月のフォルダ内にあるアーカイブファイルのファイル名を読みとって配列に格納する。

<?php
$mon = sprintf(“%02d”,$month);
$dir = “アーカイブフォルダへのパス/”.$year.”/”.$mon;
//当該月のディレクトリが存在したらファイルのリストを配列に格納する
if(file_exists($dir)) {
$dh = opendir($dir);
while (false !== ($filename = readdir($dh))) {
$files[] = $filename;
}
closedir($dh);
sort($files);
}
?>

カレンダーの各日付を描画する際に、配列に格納されたファイル名「日_時分.php」の「日」部分を取り出してマッチングさせ、一致するものがあったら「エントリーあり」と判断して、そのファイルにリンクする。

if($files){
//当該月にエントリがある場合
$lir =”アーカイブフォルダ/”.$year.”/”.$mon;
//当該日を二桁表示にする
$cd = sprintf(“%02d”,date(“j”, $t));
$flag=0;
//配列から日付部分のみを取り出し、当該日とマッチするものがあればリンクする
foreach($files as $list) {
if ($cd == substr($list,0,2)) {
print (“<A href=\””);
print $lir . “/” . $list;
print(“\” target=\”_top\”>”);
print date(“j”, $t);
print(“</A>”);
$flag=1;
//同一日に複数エントリーがあったら一つ目にリンクしてループを抜ける
break;
}
}
//マッチするものがなければ数字のみ表示
if($flag == 0) { print date(“j”, $t); }
}
//エントリがない場合
  else {
print date(“j”, $t);
}

実はphpについては全くの素人なので、見よう見まねでスクリプトを書いてみた。
配列への格納と取り出しがcgiの書き方とは違うようで、なかなかうまくいかず四苦八苦。
とりあえず動くようには出来たわけだけど、もうすこしスッキリ書けるように勉強します。
【追記】
完成版は→こちらです

月めくりカレンダー」への10件のフィードバック

  1. すごく枝葉末節な上に動作にほぼ違いはないのですが、
    > if($files){

    > if(gettype($files)==”array”&&count($files)>0) {
    などの方がよりよさげな気がします。
    …すいません、もーちょい貢献できるようがんばります。
    でも神戸戦終わるまでは許してください。

  2. あ、なはさん!こんちわ!
    そうか。そういうふうに丁寧にやったほうがいいわけね。
    そうしておけば万一の時 foreach でエラーが出ずに済むよね・・・ふむふむ。
    引き続き、よろしくw

  3. ところで、なんでファイル名を配列にしてうんぬん、というふうにしたかというと、
    ファイル名を前方一致でマッチさせるやりかたが分からなかったからなのです。
    たとえば今日の投稿だと「archives/2005/07/06_****.php」という個別ファイルが
    できるんだけど、(****には投稿時刻が入る)
    これを「20005/07/06」までの前方一致で検索してやるには
    どしたらよかんべ?
    そしたら配列なんか使わなくて済みますよね。

  4. 適当ですけど…とりあえずglobって関数が使えるかと
    //当該月にエントリがある場合
    $lir =”アーカイブフォルダ/”.$year.”/”.$mon;
    //当該日を二桁表示にする
    $cd = sprintf(“%02d”,date(“j”, $t));
    $flag=0;
    //配列から日付部分のみを取り出し、当該日とマッチするもの
    があればリンクする
    $files=glob($lir.$cd.”_*.html”);
    if($files){
    foreach($files as $list) {
    print (“”);
    print date(“j”, $t);
    print(“”);
    $flag=1;
    //同一日に複数エントリーがあったら一つ目にリンクしてルー
    プを抜ける
    break;
    }
    }
    //マッチするものがなければ数字のみ表示
    else { print date(“j”, $t);
    }

  5. ごめんなさい
    $files=glob($lir.$cd.”_*.php”);
    ですね。

  6. あと言い忘れましたが、file_existsで配列に
    格納している最初のスクリプトは使わないで、
    メインのスクリプトが変わります

  7. ヤマギ、サンクスコ
    >最初のスクリプトは使わない
    分かりますがなw
    で、ちょっと困ってるのは、globで拾ってくるときはフルパスで拾うんだけど、
    リンクを書き出すときはホームディレクトリからの相対パスで書き出さないといけないんで、
    ワンクッション入れてやらないといけないようです。
    もすこし頑張ってみますね。

  8. こんなんでどうですかねー?
    文法的にヘン?
    一応は正常に表示はされるです。
    http://nagisa.skr.jp/calendar.php
    $fulldir =”サーバー上の絶対パス/”.$year.”/”.$mon.”/”;
    $dir = “webのホームからの相対パス/”.$year.”/”.$mon.”/”;
    $files=glob($fulldir.$cd.”_*.php”);
    if($files) {
    foreach($files as $list) {
    print (“<B><A href=\””);
    print ( $dir.basename($list));
    print(“\” target=\”_top\”>”);
    print date(“j”, $t);
    print(“</A></B>”);
    break;
    }
    }
    else { print date(“j”, $t); }

  9. 良いのではないでしょうか
    当方環境(WIN PHP5)ではglobは相対パス指定で
    もうまく動きますけど、たまたまかも
    basenameなんて言う便利な関数があったとは…
    前に同当の関数を作った覚えがw

  10. 実は私も、$listを”/”で分割して最後の要素を取り出して・・・とか
    考えましたw
    あちこちパラパラ見てたら、偶然basenameなる関数ハケーン!?(゜∀゜)/

コメントは停止中です。