ソフトウェア/pukiwiki/QRコードの表示 の変更点

更新


[[公開メモ]]

* 目的 [#vf82d490]

pukiwiki 内の重要なリンクについて、
ページを印刷したときにQRコードが表示されるようにしたかったので、
[[Google Chart>https://developers.google.com/chart/]] と [[Bitly>http://bitly.com]] 
を使って make_pagelink を拡張しました。

* QR コードを表示するには [#yc150815]

Google Chart へリンクを張ればOK

例えば、

 http://chart.apis.google.com/chart?cht=qr&chld=L%7c1&chs=120x120&chl=http://dora.bk.tsukuba.ac.jp/~takeuchi/

の url へアクセスすれば http://dora.bk.tsukuba.ac.jp/~takeuchi/ を表わすQRコードを画像として得られます。

&ref(http://chart.apis.google.com/chart?cht=qr&chld=L%7c1&chs=80x80&chl=http://dora.bk.tsukuba.ac.jp/~takeuchi/&.png);

詳しい使い方は他のページでいろいろ解説されています→ [[Google:qrコード google]] 

本家の解説はこちら:
https://developers.google.com/chart/infographics/docs/qr_codes
** 基本的には [#t9149dec]

 LANG:php
      $qr_img = 
          '<img src="' .
          'http://chart.apis.google.com/chart?cht=qr' .
          '&chs=80x80&chld=L|1&chl=' . urlencode($url) .
          '" class="visible-print-inline">';

のようにして画像を html に埋め込めます。

 class="visible-print-inline"

は bootstrap の css クラスで、印刷時のみ表示するように指定するためのものです。

* pukiwiki ページへのリンク [#j9584b0c]

アドレスが長いのでQRコード画像が大きくなってしまいます。

例えばこのページの URL は

 http://dora.bk.tsukuba.ac.jp/~takeuchi/?%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%2Fpukiwiki%2FQR%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E8%A1%A8%E7%A4%BA

なので、QRコードは

&ref(http://chart.apis.google.com/chart?cht=qr&chld=L%7c1&chs=120x120&chl=http%3A%2F%2Fdora.bk.tsukuba.ac.jp%2F%7Etakeuchi%2F%3F%25E3%2582%25BD%25E3%2583%2595%25E3%2583%2588%25E3%2582%25A6%25E3%2582%25A7%25E3%2582%25A2%252Fpukiwiki%252FQR%25E3%2582%25B3%25E3%2583%25BC%25E3%2583%2589%25E3%2581%25AE%25E8%25A1%25A8%25E7%25A4%25BA&.png);

となり、かなり大きく印刷しないと認識されません。

* bitly で url を短くする [#o05fa0c3]

url 短縮サービスを使うことでシンプルなQRコードを作成できます。

&ref(http://chart.apis.google.com/chart?cht=qr&chld=Q%7c1&chs=60x60&chl=http%3A%2F%2Fj.mp/1epCc4p&.png);

これなら小さめに印刷しても認識できます。

** bitly の api [#obc2c6ec]

こちらを参考に、bitly にアクセスして短縮urlを得るコードを書きました。

http://qiita.com/maruyam-a/items/96c8ad733c770a44117e

 LANG:php
 function shorten_url($url)
 {
   // to create your own access token, 
   // see http://qiita.com/maruyam-a/items/96c8ad733c770a44117e
   $access_token = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
   
   $api_url = 'https://api-ssl.bitly.com/v3/shorten?' .
              'access_token=' . $access_token .
              '&longUrl=' . urlencode($url);
 
   $curl = curl_init();
   curl_setopt($curl, CURLOPT_URL, $api_url);
   curl_setopt ($curl, CURLOPT_RETURNTRANSFER, TRUE);
   $result = json_decode( curl_exec( $curl ), true );
 
   return $result['data']['url'];
 }

* データベースへ格納する [#sa510877]

ページを表示する度に短縮アドレスを bitly に問い合せるのは無駄なので、
一度得た短縮アドレスをデータベースに格納しておくことにしました。

 LANG:php
 function fetch_short_url($url)
 {
   $db = new SQLite3('cache/short_urls.sqlite3');
   $db->query('CREATE TABLE IF NOT EXISTS short_urls ' .
              '(url VARCHAR(1024) PRIMARY KEY, short VARCHAR(32));');
 
   $short = $db->querySingle('SELECT short FROM short_urls ' . 
                             'WHERE url=\'' . SQLite3::escapeString($url) . '\';');
   if ($short == NULL) {
     $short = shorten_url($url);
     $db->query('INSERT INTO short_urls VALUES(\'' . 
         SQLite3::escapeString($url) . '\',\'' .
         SQLite3::escapeString($short) . '\');');
   }
   $db->close();
   
   return $short;
 }

pukiwiki では cache/ 以下にデータを保持できるので、
cache/short_urls.sqlite3 というデータベースを作成し、
短縮アドレスを格納しています。

こうすることで、一回目の表示では bitly にアクセスするため時間がかかりますが、
二回目以降は高速に表示が可能です。

* qr プラグイン [#w26e2d88]

ということで、QRコード表示用のプラグインを作成しました。

plugin/qr.inc.php
 LANG:php
 <?php
 //
 // pukiwiki用 QRコード プラグイン (qr.inc.php)
 //   Copywrite 2015 Osamu Takeuchi <osamu@big.jp>
 //
 // [履歴]
 //   2015.06.18 初期リリース
 //
 // [インストール]
 //   ソースファイルを (pukiwiki)/plugin/qr.inc.php として保存
 //
 // [使い方]
 //   &qr(http://www.example.com/); や &qr([[PageName]]); により、
 //   印刷時のみ表示される QRコードを埋め込む
 //   オプションを含めたフルセットの使い方は、
 //   &qr(AnyString_or_PageName[,chs=L|1][,chld=80x80][,visible]);
 //
 
 function shorten_url($url)
 {
   // to create your own access token, 
   // see http://qiita.com/maruyam-a/items/96c8ad733c770a44117e
   $access_token = '*********';
   $access_token = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
   
   $api_url = 'https://api-ssl.bitly.com/v3/shorten?' .
              'access_token=' . $access_token .
              '&longUrl=' . urlencode($url);
 
   $curl = curl_init();
   curl_setopt($curl, CURLOPT_URL, $api_url);
   curl_setopt ($curl, CURLOPT_RETURNTRANSFER, TRUE);
   $result = json_decode( curl_exec( $curl ), true );
 
   return $result['data']['url'];
 }
 
 function fetch_short_url($url)
 {
   $db = new SQLite3('cache/short_urls.sqlite3');
   $db->query('CREATE TABLE IF NOT EXISTS short_urls ' .
              '(url VARCHAR(1024) PRIMARY KEY, short VARCHAR(32));');
 
   $short = $db->querySingle('SELECT short FROM short_urls ' . 
                             'WHERE url=\'' . SQLite3::escapeString($url) . '\';');
   if ($short == NULL) {
     $short = shorten_url($url);
     $db->query('INSERT INTO short_urls VALUES(\'' . 
         SQLite3::escapeString($url) . '\',\'' .
         SQLite3::escapeString($short) . '\');');
   }
   $db->close();
   
   return $short;
 }
 
 function plugin_qr_inline()
 {
     global $script;
     $args = func_get_args();
     $str_or_bracket = trim(array_shift($args));
     
     $chs = '80x80';
     $chld = 'L|1';
     $class = ' class="visible-print-inline"';
 
     if (preg_match('/^\\[\\[(.*?)(#[A-Za-z0-9]+)?\\]\\]$/', $str_or_bracket, $match)) {
       $str = $script . '?' . urlencode($match[1]) . $match[2];
     } else {
       $str = $str_or_bracket;
     }
     
     if (preg_match('/^https?\:\/\//', $str)) {
       $str = fetch_short_url($str);
       $chs = '33x33';
       $chld = 'Q|1';
     }
     
     foreach ($args as $arg) {
       $arg = trim($arg);
       if (mb_substr($arg,0,4) == 'chs=') $chs = mb_substr($arg,4);
       if (mb_substr($arg,0,5) == 'chld=') $chld = mb_substr($arg,5);
       if ($arg == 'visible') $class = '';
     }
     
     return '<img src="' .
            'http://chart.apis.google.com/chart?cht=qr' .
            '&chs=' . urlencode($chs) .
            '&chld=' . urlencode($chld) .
            '&chl=' . urlencode($str) .
            '"' . $class . '>';
 }
 
 ?>

** 使用例 [#q78569eb]

 &qr(任意の文字列,chs=60x60,visible);

&qr(任意の文字列,chs=60x60,visible);

 &qr([[ソフトウェア/pukiwiki/QRコードの表示]],visible);

&qr([[ソフトウェア/pukiwiki/QRコードの表示]],visible);

 &qr([[ソフトウェア/pukiwiki/QRコードの表示]]);

&qr([[ソフトウェア/pukiwiki/QRコードの表示]]); ← 印刷時しか表示されません。
正しく表示されるかは印刷プレビューで確かめてください。

* make_pagelink を書き換える [#ja924d7a]

pukiwiki では

 [[目的Page名]]

という形で文中に目的ページへのリンクを埋め込みますが、

 [[@目的Page名]]

のようにページ名の前に @ を付けることにより、
印刷時にQRコードを表示するように改造しました。

 LANG:php
 // Make hyperlink for the page
 function make_pagelink($page, $alias = '', $anchor = '', $refer = '', $isautolink = FALSE)
 {
   $add_qr_code = false;
   if (substr($page, 0, 1)=='@') {
     $add_qr_code = true;
     $page = substr($page, 1);
   }
   
   $link = make_pagelink_without_qrcode($page, $alias, $anchor, $refer, $isautolink);
   
   if ($add_qr_code && preg_match('/href="([^"]*)"/', $link, $match)) {
     require_once(PLUGIN_DIR . 'qr.inc.php');
     return $link . plugin_qr_inline($match[1]);
   }
 
  return $link;
  }
 
 function make_pagelink_without_qrcode($page, $alias = '', $anchor = '', $refer = '', $isautolink = FALSE)
 {
   ...

- 元々の make_pagelink を make_pagelink_without_qrcode と改名して、
新しく作った make_pagelink の中から呼び出します
- ページ名の先頭に @ があれば、それを除いて make_pagelink_without_qrcode を呼びます
- 作成された html 内の href の値を読み取って qr プラグインを呼び出す

という動作です。

* 使い方 [#oe59e086]

例えば、

 [[このページへのリンク>@ソフトウェア/pukiwiki/QRコードの表示]]

のようにページ名の前に @ を付けて書くと、一見

[[このページへのリンク>@ソフトウェア/pukiwiki/QRコードの表示]]

のように普通のリンクができるように見えますが、
印刷しようとすると、上記リンクにQRコードが付きます。

めでたしめでたし。

* コメント・質問 [#icbe13bd]

#article_kcaptcha

Counter: 4662 (from 2010/06/03), today: 2, yesterday: 0