一般的にWikiで悩ましいのがページのURLの長さだ。特にページ名に日本語を使うとそれがそのままエンコードされてURLとなり、非常に長くなる。長くなるならまだしも、URLに日本語が含まれるので、他のウェブサービス(特にSNS等)へ連動した時に正しくURLが認識されない場合がある。そこでURLを短縮するライブラリを作成し、前回の記事で作った「お問い合わせ」ページ(メールフォーム)で日本語ページのURLの検証を行う。
前回の記事と同様にサブドメインを連番で用意してあるので、今回はmuseum-09サブドメインの内容をmuseum-10サブドメインにコピーし、検証しながら作業を進めた。
※2019/06/20追記
さらに検証した結果、問題点があったためPukiWiki URL短縮ライブラリの仕様を一部変更し、記事内容を一部変更+追加修正をした。
※2019/07/02追記
その後まったく別サイトをサブドメインでオープンしたが、別の問題が発覚したのでPukiWiki URL短縮ライブラリの仕様を一部変更し、記事内容を一部変更+追加修正をした。
URLを短縮するには?
「お問い合わせ」ページのような日本語のページだと、URLが「https://museum-10.dajya-ranger.com/?お問い合わせ」となり、メールソフトや各種SNSへ連動する際に日本語部分がエンコードやデコードがかかってしまい、URLとして認識されない場合がある。
また、単純にエンコードされた場合でも十分に長いURLとなってしまうので、特に140字以内のTwitterでツイートするには何かと不便だ。
そこで、何らかの方法でURLを短縮させた方が良いと考えるワケだが、具体的に次の方法が思い付く。
- URL短縮サービスを利用する
- ページ名を単純な連番管理にする
- s.inc.phpプラグインを導入する
- 自作する(そしてボクは途方に暮れる♬)
まず1.だが、bitlyやTinyURL等のURL短縮サービスの利用を考えるだろう。これらのURL短縮サービスは無料だし、プログラムからWebAPIコールで短縮されたURLを得ることが出来るので、考える必要なくURLを短縮することが可能だ。しかし、ドメイン名を含むURL全体が短縮されるので、PukiWikiに組み込むとなると話は別だ。それにいつ何時サービスが停止するか、はたまた有料化するか?といった、回避しようのないリスクを内在させることになる。突然APIの仕様変更といったリスクが、いつ発生するとも限らない。
2.に関しては、アットウィキやウィキサンといった商用のレンタルウィキサービスの一部で採用されている(それ以外のレンタルウィキサービスはそもそもURLを短縮しようとしていない?)。ページ名(それが日本語だろうが何だろうが)を単純に連番で管理してそれをURLにするため、実質的なURLの短縮となる。実装もそう難しくないし、割り切ったアイデアとして悪くない。私のように「これから(イチから)Wikiをやるぞ!」であれば採用しても良いが、すでに存在するページをどうするか?で考えると、おいそれとは乗れない。
3.はPukiWiki公式サイトの自作プラグインとして公開されているので、最初は「コレが良い!」と思って導入してみた。しかし、実際に検証してみると日本語を含むページ名のURLを短縮はするものの、単純に302リダイレクトを利用したモノなので、各種SNSボタンでシェアやツイートをしようとした際に、元の長いURLに展開されてしまう。これじゃダメだ。
最終的に4.しか現実的な選択肢は存在せず、PukiWikiの内部を調べるところから始めなければならない。非常に面倒だし検証も大変だが、s.inc.phpプラグインのアイデアを応用することで、URL短縮ライブラリとして自作してみた。
URL短縮ライブラリとは?
恐らくPukiWikiのバージョンに大きく依存しない(どちらかと言えば文字コードとPHPのバージョンに依存する?)と思うので、PukiWiki URL短縮ライブラリとして本サイトのダウンロードページに掲載しておいた。
ダウンロードページからURL短縮ライブラリをダウンロードし、ローカルの作業フォルダに解凍する。「lib」フォルダに今回自作したURL短縮ライブラリが1本入っており、フォルダごとFTPしておく。パーミッションは次の通りに設定する。
- 644:「lib」フォルダshorturl.phpファイル
- 777:「shortener」および「shortener_counter」フォルダ(中身は空)
特に修正しなくても良いが、URL短縮ライブラリの設定と共にどのように動作するのかを説明しよう。
lib\shorturl.php
// url name map directory
define('SHORT_URL_DIR', 'shortener');
// url name counter map directory
define('SHORT_URL_COUNTER_DIR', 'shortener_counter');
// url string length
define('SHORT_URL_PAGEID_LENGTH', 10);
// page name minimum length
define('SHORT_URL_PAGENAME_MININUM_LENGTH', 12);
簡単に言えば、エンコードしたページ名がSHORT_URL_PAGENAME_MININUM_LENGTHより長ければSHORT_URL_PAGEID_LENGTHの長さのMD5ハッシュ値に変換し、「MD5ハッシュ値.txt」のファイル名でSHORT_URL_DIRフォルダにページ名を格納したファイルを保存する、というものだ。
なので、エンコードしたページ名が「n+1文字以上だったらm桁のURL(ページID=MD5ハッシュ値)」に変換するといった部分をお好みの長さに設定して貰えれば良い。
ページ全体のURLを取得(参照)する箇所に本ライブラリのget_short_url_from_pagename関数をコールするように組み込めば、自動的にページ名から短縮した(もしくは短縮しないままの)URLが得られるのと同時にSHORT_URL_DIRフォルダにページ名を格納したファイルが保存される。また、短縮した(もしくは短縮しないままの)URLからページ名を取得する箇所に本ライブラリのget_pagename_from_short_url関数をコールするように組み込めば、URLからSHORT_URL_DIRフォルダに該当するファイルを読みに行ってページ名が得られるので、PukiWikiの内部的に適切な場所で変数$vars[‘page’] の内容を上書きすれば良い。
すでにPukiWikiを運用していて、数百~数千ページもあるような場合でも、本ライブラリを組み込めば自動でURLを短縮してくれる。特にこの「エンコードしたページ名」がミソで、すでに日本語ページ名でリンクを貼っているページだろうが、ブラウザからダイレクトに日本語ページ名を入力しようが、ちゃんと自動で短縮したURLとページ名のファイルを作成するし、相互に逆引きが可能なので、従来のPukiWikiページに修正を加える必要は皆無である(Wiki内のページに新たにリンクを貼る場合も、MD5ハッシュ値ではなく日本語のページ名のままでOKだ)。
ちなみに、get_pagename_from_short_url関数がコールされるたびにSHORT_URL_COUNTER_DIRフォルダの「MD5ハッシュ値.count」ファイルの内容をインクリメントする。厳密な「ページカウンタ」としては運用しにくいが、コール数といった意味の擬似的な「ページカウンタ」としての利用も想定している。
URL短縮ライブラリの組み込み
URL短縮ライブラリをPukiWiki本体に組み込むのは難しくない。
まず、「lib」フォルダにあるpukiwiki.phpに組み込むが、具体的には46行目付近(「忍者おまとめボタン」スクリプトコードの上あたり)に次のコードを追加する。
lib\pukiwiki.php
// Load optional libraries
if ($notify) {
require(LIB_DIR . 'mail.php'); // Mail notification
}
// URL短縮ライブラリロード
require(LIB_DIR . 'shorturl.php');
// ページ名上書きセット
$vars['page'] = get_pagename_from_short_url($vars['page']);
// 「忍者おまとめボタン」スクリプトコード
$sns_button = <<< EOM
次に、同じく「lib」フォルダにあるfunc.phpのget_page_uri関数の内容を修正する。具体的には815行目近辺に当該関数がある。
lib\func.php(修正前)
function get_page_uri($page, $uri_type = PKWK_URI_RELATIVE)
{
global $defaultpage;
if ($page === $defaultpage) {
return get_base_uri($uri_type);
}
return get_base_uri($uri_type) . '?' . pagename_urlencode($page);
}
lib\func.php(修正後)※一部変更しています(2019/06/20追記)(2019/07/02追記)
function get_page_uri($page, $uri_type = PKWK_URI_RELATIVE)
{
return get_base_uri($uri_type) . get_short_url_from_pagename($page); // ※ライブラリの仕様を一部変更し、2019/06/03記事公開当初の記述に戻した
/* コメントアウト
global $defaultpage;
if ($page === $defaultpage) {
return get_base_uri($uri_type);
}
return get_base_uri($uri_type) . '?' . pagename_urlencode($page);
*/
}
※2019/06/20追記
さらに検証した結果、Wiki記法でブラケットによりページリンクを記述した場合(例:[[お問い合わせ]])、HTMLに変換する際に「lib」フォルダのmake_link.phpでページ名をエンコードしたURLに変換してしまう。この場合、URL欄にページ名がそのまま出てしまうため(例:/?お問い合わせ)、日本語ページ名の場合は結果的にエンコードされた長いURLになってしまう。
そこで、make_link.phpにget_pagename_from_short_url関数を組み込む。具体的には780行付近を修正する。
※2019/07/02追記
その後まったく別サイトをサブドメインでオープンしたが、デフォルトページを「FrontPage」のままにしておいて攻撃されるのもヤダなと思い、日本語ページ名に変更した。
すると、トップページ(デフォルトページ)のリンクなのに、URLの末尾が「/?84079dd13f」となっており、原因を調査したら2019/06/20追記分のPukiWiki URL短縮ライブラリの仕様変更(そもそも元のPukiWikiのソースと戻り値を同じレベルに合わせて‘?’を付加しないように変更したのだが)と、その組み込みをした時の検証が甘かった。
2019/06/20の時点では気が付かなかったが、museum-10サブドメインのトップページのリンク(この場合はデフォルトページが「FrontPage」)でもURLの末尾が「/?」となっていた。
さらに調査すると「FrontPage」ではURL短縮ライブラリ側で(別にページ名が長くないから)URLを短縮しないので、そうとは気が付かず原因を特定するのに余計に時間がかかった。
結論として、URL短縮ライブラリのget_short_url_from_pagename関数を一部仕様変更し、ページ名が有効かデフォルトページかを先に評価するようにして改めてURLに‘?’を付加して返すようにし、組み込み先(make_link.phpのmake_pagelink関数)でURLを編集する際に‘?’を削除するように変更した。
lib\make_link.php(修正前)
if ($page == '') return '<a href="' . $anchor . '">' . $s_alias . '</a>';
$r_page = pagename_urlencode($page); // ココを変更する!
$r_refer = ($refer == '') ? '' : '&refer=' . rawurlencode($refer);
$page_filetime = fast_get_filetime($page);
$is_page = $page_filetime !== 0;
if (! isset($related[$page]) && $page !== $vars['page'] && is_page)
$related[$page] = $page_filetime;
if ($isautolink || $is_page) {
// Hyperlink to the page
$attrs = get_filetime_a_attrs($page_filetime);
// AutoLink marker
if ($isautolink) {
$al_left = '<!--autolink-->';
$al_right = '<!--/autolink-->';
} else {
$al_left = $al_right = '';
}
$title_attr_html = '';
if ($s_page !== $s_alias) {
$title_attr_html = ' title="' . $s_page . '"';
}
// ↓ この return の戻り値から'?'を削除する 2019/07/02追記
return $al_left . '<a ' . 'href="' . $script . '?' . $r_page . $anchor .
lib\make_link.php(修正後)※2019/07/02追記
if ($page == '') return '<a href="' . $anchor . '">' . $s_alias . '</a>';
$r_page = get_short_url_from_pagename($page);
$r_refer = ($refer == '') ? '' : '&refer=' . rawurlencode($refer);
$page_filetime = fast_get_filetime($page);
$is_page = $page_filetime !== 0;
if (! isset($related[$page]) && $page !== $vars['page'] && is_page)
$related[$page] = $page_filetime;
if ($isautolink || $is_page) {
// Hyperlink to the page
$attrs = get_filetime_a_attrs($page_filetime);
// AutoLink marker
if ($isautolink) {
$al_left = '<!--autolink-->';
$al_right = '<!--/autolink-->';
} else {
$al_left = $al_right = '';
}
$title_attr_html = '';
if ($s_page !== $s_alias) {
$title_attr_html = ' title="' . $s_page . '"';
}
return $al_left . '<a ' . 'href="' . $script . $r_page . $anchor .
コードの追加と修正が完了したらファイルを保存し、「lib」フォルダに修正したファイルをFTPすればURL短縮ライブラリの組み込みは完了だ。では、実際にパソコンの画面を確認してみよう。
URL短縮ライブラリの組み込みが正常に完了していれば、図のように「お問い合わせ」ページのような日本語ページ名の長いURLが短いURLに短縮されているのが分かるだろう。
各種SNSボタンでページをシェアやツイートをする場合も、図のように短縮したURLをそのまま渡せる。じゃなければWikiでネックになるクソ長いURLを短縮する意味がない。
試しにTwitterのCard validatorでチェックすれば良い。ちゃんと図の通り連動可能なことが分かるだろう。
Facebookのシェアデバッガーでも当然だが、ちゃんと連動する。
ここまでの改造の成果
ここまでの改造の成果であるPukiWikiはこちらなので、「実際どうなのか?」を確認したい人は参照して欲しい。
せっかくWikiサイトを構築するのなら、サーチエンジンによる流入は当然としても、各種SNSへ積極的に発信し、SNSで拡散された方が苦労してでもコンテンツを作る甲斐があるというものだ。
ところが現状のPukiWikiでは、これまでずっと改造して来たように、かなり手を入れなければダメなのがお分かりになったと思う。社内だけで情報共有ツールとして限定的に利用するなら、ここまで手を入れる必要はないかも知れない。しかし、個人が趣味でWikiサイトを開設するのなら、これぐらい改造しなきゃダメってことですな。私に言わせれば、商用のレンタルウィキサービスがイマイチなのは仕方がない。
おわりに
PukiWikiでWikiサイトを運用する上で、(これまでの改造によって)やっと技術的にネックになる部分をほぼ解消したように思う。細かい点を挙げればキリがないが、それは追々対応して行くとするか。
目下の悩みは「サイトデザイン」で、私はプログラムならいくらでも書けるが、絵やイラストは一切描けず、しかも美的センスに問題があるため、Twitterで親しくさせてもらっている相互さんにサイト用のイラストをお願いしている。
イラストをお願いしたからと言ってすぐに良いモノが上がってくるハズはなく、色々と調整や打ち合わせを経てWikiサイトを立ち上げることになる。
私にサイト用のイラストを提供して下さる相互さんとしても、単にSNSやブログ記事にイラストをアップするよりかは、サイトの「顔」として不特定多数の人に見て貰え、反響があった方が嬉しいに違いない。ネットではこのように色々な人と繋がり得るし、お互いに協力し合えるという点も、モチベーションとして大きいのではないだろうか。
Warning: strpos() expects parameter 1 to be string, array given in /home/eware/dajya-ranger.com/public_html/wp-includes/compat.php on line 498
Warning: preg_match_all() expects parameter 2 to be string, array given in /home/eware/dajya-ranger.com/public_html/wp-includes/shortcodes.php on line 155
Array