0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PukiWikiAdvent Calendar 2024

Day 15

PukiWikiプラグイン開発から学ぶPHP #3

Posted at

前回

本題

今回は現在時刻をJSで更新して表示するプラグインをつくります。

ファイル名は「datetime.inc.php」とします。

設計

&datetime([表示形式],[UNIX時間]);

  • &datetime(y-m-d h:i:s); という形で呼び出すと「2024-12-17 16:27:32」という風に表示
  • フォーマットの指定がされていないときはデフォルトで「y-m-d h:i:s
  • UNIX時間が表示されていないときはデフォルトで現在時刻に (ぶっちゃけ必要ではないかも)
  • UNIX時間に -1 を指定することで現在時刻となる (表示形式のみ指定したらいい話なので勝手に内部で-1になる)

開発

datetime.inc.php
<?php
function plugin_datetime_inline() {
    // 引数を取得
    $args = func_get_args();

    // フォーマットとUNIX時間を取得、三項演算子で存在しない場合はデフォルトにしておく
    // (-1 は現在時刻を使用するためのフラグ的なもの)
    $format = !empty($args[0]) ? htmlsc($args[0]) : 'y-m-d h:i:s';
    $unixtime = !empty($args[1]) ? htmlsc($args[1]) : "-1";

    // UNIX時間が指定されていればその時間を使用
    // date() でフォーマットを適用して表示
    $date = get_date($format, $unixtime == "-1" ? time() : $unixtime);
    
    return <<<EOD
        <span class="plugin_datetime">
            <span>{$date}</span>
            <input type="hidden" class="plugin_datetime_property" value="{&quot;format&quot;:&quot;{$format}&quot;,&quot;unixtime&quot;:{$unixtime}}" />
        </span>
EOD;
}

function plugin_datetime_init() {
    global $head_tags;
    
    $head_tags[] = <<<EOD
    <script>
    function plugin_datetime_update() {
        document.querySelectorAll(".plugin_datetime").forEach((tag) => {
            let prop = JSON.parse(tag.querySelector(".plugin_datetime_property").value);
        
            let format = prop.format;
            let unixtime = prop.unixtime;

            if (unixtime != "-1") return;
        
            let date = new Date();

            let y = date.getFullYear();
            let m = ('0' + (date.getMonth() + 1)).slice(-2);
            let d = ('0' + date.getDate()).slice(-2);
            let h = ('0' + date.getHours()).slice(-2);
            let i = ('0' + date.getMinutes()).slice(-2);
            let s = ('0' + date.getSeconds()).slice(-2);
            
            // フォーマットを適用する
            let formatted = format.replace(/y/g, y).replace(/m/g, m).replace(/d/g, d).replace(/h/g, h).replace(/i/g, i).replace(/s/g, s);

            // 時刻の書き換え
            tag.querySelector("span").innerHTML = formatted;
        });
    }
    
    setInterval(plugin_datetime_update, 1000); // 1秒ごとに更新 1s = 1000ms
    </script>
EOD;
}

plugin_datetime_inline() 関数

&datetime([表示形式],[UNIX時間]);で呼び出される

  • 1番目の引数を表示形式、2番目の引数をUNIX時間として取得

    • PukiWikiプラグインでは一般的に可変長引数を扱うため、func_get_args() で引数を取得する
  • 表示形式の引数がない場合は 'y-m-d h:i:s' を、UNIX時間の引数がない場合は現在時刻を使う

  • get_date() はPukiWiki内部のfunc.phpで定義されている関数で、PHP標準関数と違ってPukiWikiの設定に沿って日付を取得できる

  • htmlsc() もPukiWiki内部の関数で、HTMLエスケープを行う、これしないとXSSされる可能性がある

  • 返り値はHTML、spanで囲んで表示形式に従って日付を表示するという仕組み

    • spanの中に、UNIX時間と表示形式をjson形式でinput[type=hidden]で持たせる
      • JavaScriptで1秒ごとに更新するために使う

plugin_datetime_init() 関数

プラグインが呼び出された(plugin_datetime_inline() が呼び出された)ときに呼び出される
ブラウザ上で継続的に時刻を更新するためにJavaScriptをheadタグに追加する

  • グローバル変数 $head_tags にJavaScriptを追加
    • JSで1秒ごとに plugin_datetime_update() を呼び出して、ページ内の datetime クラスを持つタグの時刻を更新する
    • JSON.parse() で input[type=hidden] のvalueに入ってるjsonを読み込める
    • setInterval() で1秒ごとに plugin_datetime_update() を呼び出す

最後に

PukiWiki側で定義されている $html_tags というグローバル変数を使うことで、headタグにタグを追加することができます。
使いこなせば、JavaScriptを使った機能を追加することも可能なので便利です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?