アルファサード株式会社 代表取締役 野田 純生のブログ


静的生成と動的生成, Webページをビルドするコストは最初の訪問者に支払ってもらいましょう(完結編!?)。


公開日 : 2007-06-27 11:26:17


追記(2007年7月2日):
一連のエントリーで作成したものを取りまとめて公開しました。


驚くのはまだ早い!(なんて言ったりして)

そして、今回頂いた反応の中で、一番驚いたのがこれ。

* ↑トラックバックがHTTP error: 403 Throttledで弾かれる...

ここまで来たら...やっちゃえ!

Movable Type10分間Cooking!(Part4)

まぁ10分で出来るのはこれまでに書きためたプラグインの各種パターンがあるからですが、テストやドキュメント、設定のUIとかそのあたりは手抜きで。

関連エントリー

静的生成されたファイルの全削除

今回の件でいえば「再構築」の代わりが「全削除」です。全削除しておくとあとは各ページが最初に閲覧された段階でそれぞれ再構築されます。リクエストのないページに対する無駄な再構築もありません。

my $plugin = new MT::Plugin::RebuildAt1stView({
	name => 'RebuildAt1stView',
	app_methods => {
		'MT::App::CMS' => {
			'remove_all_entry_archive' => ¥&_remove_all_entry_archive
		},
	},
});

MT->add_plugin($plugin);

MT->add_plugin_action('blog',
	'../'.MT->config('AdminScript').'?__mode=remove_all_entry_archive',
	'Remove All Entry Archives'
);

MT->add_plugin_action('list_entries',
	'../'.MT->config('AdminScript').'?__mode=remove_all_entry_archive',
	'Remove All Entry Archives'
);

プラグイン・アクション

全削除の場合はプログラム書くだけじゃなくて管理画面へのインターフェイスが必要です。add_plugin_action を使うと簡単です。

mt.cgi?__mode=remove_all_entry_archive;from=blog_home;blog_id=3

上記のように呼び出して動作させます。app_methods についてはこちらのエントリーに少し書いていますのでそちらも参考にしてください。

全削除は以下の通り。たかだか250程度のエントリーですが、感覚的には1秒以内で全削除できます(本当はちゃんとHTML組み立てて結果を返した方が良いですしエラーも拾った方がいいですけど)。

*ちょっと修正。is_superuserでスーパーユーザーかどうかチェックするようにした。


sub _remove_all_entry_archive {
	my $app = shift;
	my $user = $app->user;
	if ($user->is_superuser) {
		my $blog_id = $app->param('blog_id');
		my $iter = MT::Entry->load_iter({
			blog_id => $blog_id},{
			sort => 'modified_on',
			direction => 'descend',
		});
		if (defined $iter) {
			while (my $entry = $iter->()) {
				$app->publisher->remove_entry_archive_file(Entry => $entry, ArchiveType => 'Individual');
			}
			return 'エントリーアーカイブを削除しました!';
		} else {
			return 'エントリーが見つかりません。';		
		}
	} else {
		return '権限がありません。';		
	}
}

あとは各エントリーの保存や削除時に前々回のエントリーで作成した mt_permalink テーブルの更新が必要ですが、CMSPostSave.entry, CMSPostDelete_entryコールバックが呼ばれたタイミングで処理させます(MT4ではコールバック名が変更になっているかもしれませんがおそらく同等のコールバックは用意されていると思います)。


MT->add_callback('CMSPostSave.entry', 10, $plugin, ¥&_post_save_entry);
MT->add_callback('CMSPostDelete_entry', 10, $plugin, ¥&_delete_entry);

sub _post_save_entry {
	my ($eh, $app, $entry, $original) = @_;
	my $permalink = MT::Permalink->load({id => $entry->id});
	if ($entry->status != 2) {
		$app->publisher->remove_entry_archive_file(Entry => $entry, ArchiveType => 'Individual');
		if (defined $permalink) {
			$permalink->remove or die "Removing permalink failed: ", $permalink->errstr;
		}
	} else {
		if (defined $permalink) {
			$permalink->permalink($entry->permalink);
			$permalink->modified_on($entry->modified_on);
			$permalink->save or die "Saving permalink failed: ", $permalink->errstr;
		} else {
			$permalink = MT::Permalink->new;
			$permalink->id($entry->id);
			$permalink->blog_id($entry->blog_id);
			$permalink->permalink($entry->permalink);
			$permalink->modified_on($entry->modified_on);
			$permalink->save or die "Saving permalink failed: ", $permalink->errstr;
		}
	}
}

sub _delete_entry {
	my ($eh, $app, $entry) = @_;
	my $permalink = MT::Permalink->load({permalink => $entry->permalink});
	if (defined $permalink) {
		$permalink->remove or die "Removing permalink failed: ", $permalink->errstr;
	}
	$app->publisher->remove_entry_archive_file(Entry => $entry, ArchiveType => 'Individual');
}

残りタスク

ということで、ソースはこちらに晒しておきます。一旦削除します。後ほどアーカイブとして最新のものをアップします。ライセンスはGPLです! (しつこい?)
っていうか誰か完成させてください。以下残りタスクを挙げておきます。

追記:ソース一式を以下のページからダウンロードできます。
  • (何よりもまず)動作の検証・テスト
  • コメント・トラックバック反映時の再構築(というかページの削除)対応済み
  • Googlebot以外のロボット対策取り急ぎYahoo! とmsnbot対応
  • データベーステーブル mt_permalink 作成, 初期データ登録のインターフェイス(ウィザード?)
  • mtview.cgiをFastCGI対応させる(Bootstrap.pm を使ったアプリケーションにする)
  • 各処理の中のエラー処理
  • 全削除後の表示画面対応済み
  • ブログ毎の設定(オン・オフできるようにする、等)対応済み


このブログを書いている人
野田純生の写真
野田 純生 (のだ すみお)

大阪府出身。ウェブアクセシビリティエバンジェリスト。 アルファサード株式会社の代表取締役社長であり、現役のプログラマ。経営理念は「テクノロジーによって顧客とパートナーに寄り添い、ウェブを良くする」。 プロフィール詳細へ