WordPressプラグイン Auto URL Regeneratorを作成しました。

プラグインを作ったという報告をしたかったという理由だけで、Qiita初投稿です。

**【2020年5月27日追記】無事に公式プラグインページに登録出来ました。**

##お前誰やねん
フリーランスでシステムエンジニアとかをしている[MINES](https://twitter.com/mines_iccushe)というものです。
今話題の流行感染症のせいで、成果報酬で受けていたエンジニア系の仕事を思いっきり絞られ、予定していた飲食店向けのDTPデザイン制作の仕事が全部飛んで、後[イベントの主催や会場貸しの仲介と運用](https://misukaraproject.info/)とかもやっていたりしていますが当然のようにイベント全部飛んで、他に稼ぎ頭を用意しておらず暇になってしまいました。いやぁ月額の請負契約って偉大だなぁと改めて思いましたね。笑い事じゃない。
先週くらいまで[ニコニコ動画に動画を投稿](https://www.nicovideo.jp/user/22463133)していたり、積んでいたゲームを消化するなどで暇を潰したりしていましたが、いい加減エンジニアっぽいことしたいと思い、今回、暇を潰すための一環として、WordPressのプラグインを作成しました。

普段の成果報酬で受けていたエンジニア系の仕事では主に、WordPressサイトの構築、デザイナーが作ったデザインをテーマに組み込み、システムの設計や作成やプラグイン化、たまに運用やコンサル的なこともしています。

##公開ページ
WordPress公式プラグインページ:https://wordpress.org/plugins/auto-url-regenerator/
GitHub:https://github.com/minesiccushe/auto-url-regenerator

##概要
サイト上の記事ページのURLに、自動で一意の識別子を付与します。
例えば、domain.com/social-distance/ というURLの場合、
domain.com/social-distance **-9a33cd01**/ のように、URL末尾に識別子を付与します。
この識別子はハッシュ関数で生成しているので、基本的にはランダムな値となります。

また、この識別子を一定周期で変更することが出来るようになっています。
例えば、毎月1日に識別子を変更するというような設定をすることが可能です。

WordPressの標準投稿タイプの他、カスタム投稿タイプにも使用することが可能です。
その他、記事単位で設定の有効の可否も決めることが出来るようになっております。

##メリット
**特にありません。**
強いて言えば、他で紹介されているURL自動更新のシステムよりも軽いことがある点と、WP-Cronを使ってないので、何かWP-Cronがうまく動作しないなぁという場合でも動作させることが出来ます。

【他で紹介されているURL自動更新の方法】
[WordPressで記事URLを定期的に自動変更する方法](https://cree.fun/3399/)

軽いことがある点というのは、記事そのものの更新処理はしないため、タイミングによってはその更新のせいでサイトが重くなる、ということがほぼ無いという意味合いになります。
まあ基本的にはそれ以外の処理を毎回しているので、誤差の範囲ですがこっち使うほうが重いですけどね。

このプラグイン自体は、「何か定期的にURLを変更したいな～」というふわーっとした明確な目的を持っている人向けのプラグインなので、このプラグインを導入したからと言って、サイトの表示が早くなるわけでもないし、自動でブログの記事を書いてくれたりするわけでもありません。

##デメリット
**他のURL書き換えをするプラグインやシステムとほぼ間違いなく競合するので他のURL書き換えをするプラグインがやシステムが使えなくなります。**
具体的には、[Custom Post Type Permalinks](https://wordpress.org/plugins/custom-post-type-permalinks/)とかとは完全に競合して、最悪記事が一切表示されなくなりますし、どちらかを使わないくらいしか回避方法もありません。

##使い方
1. GitHubからダウンロードして、WordPressにインストールします。
2. 設定→Auto URL Regeneratorを選択します。
3. 「自動更新を動作させる」を有効にする に変更し、「動作させる投稿タイプ」で、URL自動更新したい投稿タイプにチェックを入れます。
4. タブの間隔設定を開いて、更新頻度を設定します。
5. (オプション)特定の記事で自動更新を動作させたくない場合、編集ページ内に「URL自動更新設定」のラジオボタンが生成されるので、それをオフにします。

##注意事項
###他のURL書き換えプラグインと併用しないでください
[デメリット](#デメリット)でも記載した通り、他のURL書き換えをするプラグインやシステムとはほぼ間違いなく競合するので、併用しないでください。
当プラグインの場合、URL末尾に識別子が付与されていても、識別子を除いた状態のスラッグの記事を取得できるように、リライトルールを書き換えております。
他のURL書き換えプラグインを入れた場合、**この識別子を含んだ状態をスラッグと認識して**、記事を取得しに行こうとしますが、元の記事に識別子は含まれてないので、「そんな記事は存在しない」と404を返されるようになります。
あるいは同様に、他のプラグインがURLを書き換えた結果、当プラグインが、「このURLはうちで生成されたパターンに合致しないから無視する」となって、結果1行前の事象が発生します。

###パーマリンク設定で必ずURLにスラッグを含めるようにしてください
先の注意事項で軽く触れましたが、このプラグインはスラッグ（投稿名）に識別子を付与します。
スラッグが含まれない場合、URLに識別子が付与されませんし、自動更新もされません。
URLにスラッグが含まれていない設定の場合、動作しない警告が出ますので、必ずどこかに`%post_name%`が含まれるようにしておいてください。

###出来るだけ特定のパターンをスラッグに含めないでください。
注文が多いなこのプラグイン。
スラッグの末尾に識別子を付与する都合上、スラッグそのものの末尾に、識別子として認識される値を含めると、誤認識してページが正しく表示されない場合があります。
具体的には、固定ページとメディアの単一ページについては、`-pXXXXXXXX`（Xの箇所は16進数8桁）、それ以外の投稿タイプについては、`-XXXXXXXX`（こっちもXの箇所は16進数8桁）となります。
後から考えると日付（-20200518）も含めてはいけないパターンの対象になるので、7桁にすればよかったとも思いましたが、誤差の範囲だと思いますので特に変える予定はありません。
なお、上記パターンを入れたからと言ってページがすぐに表示されなくなるわけではなく、個別ページごとの「URL自動更新設定」をオフにすると、上記のパターンの箇所が識別子と判断されて、それを取り除いた状態の記事を探しに行って「そんな記事は存在しない」と404を返されてしまいます。
オンの時は、そのパターンが付与されている状態に更にパターンを付与するので、後ろについたパターンだけが取り除かれた状態のスラッグを検索するので大体記事を取得できます。

##技術的な話
###結局このプラグインは何をしているの
記事のURLを生成する処理（`get_permalink()`とか）のところで識別子を付与して、その識別子が付与されていても問題なく記事が取得できるようリライトルールを追加しています。
また、記事に直接URLを書いたり、テーマに直接固定ページを`home_url()`とかで書いたり、さらに検索エンジンに識別子が付いてないURLがインデックスされていた場合でも、現在のURLにリダイレクトしてくれるような処理も行っております。

###なんでWP-Cronが必要ないの
定時的な処理を行う場合、WP-Cronを使うのが一般的ですが、このプラグインではWP-Cronを使用しておりません。
大きな理由としては、他のプラグインのWP-Cronの設定の影響等で定時処理系が全く処理出来なくなってしまったサイトを過去に何件も見てきて、出来るだけWP-Cron使わない方法取りたいと思ったからです。
WP-Cronを使用せずに済むように、このプラグインではphpの[DateTimeクラス](https://www.php.net/manual/ja/class.datetime.php)に[相対的な書式](https://www.php.net/manual/ja/datetime.formats.relative.php)を利用して日時を取得し、その日時をハッシュ関数のメッセージにすることで、識別子の値を期間中一定に保てるようにしています。
具体的に、例えば毎週識別子を更新する設定にした場合、

- 変更したい曜日の値を取得します。
    - ここでは仮に火曜日とします。
- DateTimeクラス変数を定義します。
    - 定義した日時をここでは仮に15日金曜日の12:00:00として、その時間が設定されます
- modifyメソッドで"tomorrow"を指定します
    - 今日から見て相対的に翌日の00:00:00、つまり16日土曜日の00:00:00に日付が変更されます
- modifyメソッドで"last {tuesday}"を指定します。
    - 現在設定されている16日土曜日の00:00:00の直前の火曜日、つまり12日火曜日の00:00:00に日付が変更されます
- 現在設定されている日時をメッセージ、投稿タイプのスラッグをソルトとしてハッシュ値を生成します。
- 上記で生成されたハッシュ値をメッセージ、投稿のスラッグをソルトとしてハッシュ値を生成し、生成されたハッシュの最初の8桁を識別子として使用します。

このようにして、12日火曜日00:00:00から18日月曜日23:59:59までは、12日火曜日の00:00:00という値を取得するため、ハッシュ関数の決定性（同じ値を入れたら常に同じ値を返すこと）を利用して、期間中は必ず同一の識別子を返すようにしています。
ハッシュ関数の性質を使ってコードを書く点は、[過去にBitcoin関係の解説動画作った](https://www.nicovideo.jp/watch/sm30364346)ときに調べたのが役に立ったなぁと思います。
では19日火曜日の00:00:00以降はどのような値を返すかというと、19日火曜日の00:00:00を返します。これは、

- DateTimeクラスを定義した時点で、19日火曜日の00:00:00が設定されます。
- modifyメソッドで"tomorrow"を指定することで20日水曜日の00:00:00が設定されます。
- modifyメソッドで"last {tuesday}"を指定することで19日火曜日の00:00:00が指定されます。

という流れになるためです。25日月曜日の23:59:59までは常時19日火曜日の00:00:00を返してくれます。。
この投稿タイプごとのベースとなるハッシュ値生成とその値の保存をアクセスがある度に毎回行っているため、その分だけ誤差の範囲で重くなります。あくまで誤差。All in one SEO Packとか入れている方がよっぽどか毎回やっている処理多くなって重くなりますしね（だからAll in one SEO Packがサイトを重くする原因であるとも、使うのやめた方がいいとも言いませんが）
ここら辺の処理は、プラグインの`set_interval`関数あたりに記載していますので、気になる人は見てね。

##最後に
今回WordPressの公式プラグインに登録することを前提としてプラグインの作成をしてみましたが、制作終盤に他のWordPressプラグインがどのようにコーディングされているかの参考にしてみたところ、自分のコードがいかに適当、というよりもメンテナンス性を考慮してないなーということを感じました。
ここら辺は、チームでコード制作をするという経験があまりにも乏しすぎるということで、今後はこのあたりを考慮しながら制作してきたいなと思いました。感想小学生か。

まだ流行感染症が落ち着く兆しが無く、仕事も大して多くないようだったら、次回はまた特定の人向けの、特にメリットの無いプラグイン作りたいと思います。