風柳メモ

ソフトウェア・プログラミング関連の覚書が中心。

WordPressをhttps化したら、Contact Form 7 の設定が消えてしまった⁉

WordPress を設置してあるサイトを SSL/TLS(http → https)化し、記事なども含めて http://~ となっていたサイトの URL を https://~ に置換したところ、Contact Form 7 の一部の設定が消えてしまった。
今後も似たような失敗をしそうなので、覚え書きとして記事にしておく。




現象

f:id:furyu-tei:20180607212208p:plain

のような、コンタクトフォーム(Contact Form 7)のメールテンプレート設定がなされていたところに、Search Regexを使用して、Post meta value 中のサイトの URL を http://~ から https://~ に置換した。

f:id:furyu-tei:20180607212720p:plain

すると、なぜか、コンタクトフォームのメールテンプレート設定が無くなってしまっていた。

f:id:furyu-tei:20180607212804p:plain

原因

バックアップして置いたデータベースのファイルを調べてみたところ、コンタクトフォームのメールテンプレートは、

(9, 5, '_mail', 'a:9:{s:6:\"active\";b:1;s:7:\"subject\";s:35:\"WordPressてすと \"[your-subject]\"\";s:6:\"sender\";s:42:\"[your-name] \";s:9:\"recipient\";s:18:\"xxxxxxxx@xxxxxxxxx\";s:4:\"body\";s:238:\"差出人: [your-name] <[your-email]>\n題名: [your-subject]\n\nメッセージ本文:\n[your-message]\n\n-- \nこのメールは WordPressてすと (http://xxxxxxxxxxxxxxxxxxxxxxxxx) のお問い合わせフォームから送信されました\";s:18:\"additional_headers\";s:22:\"Reply-To: [your-email]\";s:11:\"attachments\";s:0:\"\";s:8:\"use_html\";b:0;s:13:\"exclude_blank\";b:0;}'),

のような形で格納されていた。

勘のいい方はお気づきだろう……そう、つまり、PHPでシリアル化(serialize)された形式になっているため、http → https へと単純に置換してしまうと、文字数が1文字増えて、シリアル化データとしては壊れてしまい、コンタクトフォームでは不正な値として設定が無効化されてしまったのである。

対策

今回たまたま当方が気付いたのがコンタクトフォームだっただけで、似たような現象は他のプラグインでも発生しうると思われる。
Search Regex による Post meta value の機械的な置換は実施せず、各プラグインの設定にサイトの URL が含まれる場合には、逐次確認して手動で変更するのが無難だろう。
コンタクトフォームに限れば、データベースファイル中の '_mail' や '_mail_2' といった行の "body" 中にサイトの URL が含まれる場合、 "body" の長さをひとつ増加させるようなスクリプトでも組んでやれば対応可能ではあろうが。

より効率の良い方法やプラグインなどをご存知の方は、ご教示願いたい。

追記

はけた氏(@)にもツイートでご指摘いただいたが、こういう場合は
interconnectit.com
を使うのが定石の模様。

Search Replace DB を使うと、
f:id:furyu-tei:20180608090145p:plain
このように、Post meta value 等のシリアル化されたデータについても、それに考慮した変換を行ってくれる。

なお、実際に不具合で発生したサイトでも最初はこれを試そうとしたのだが、WordPress のバージョンの問題でうまく実行できなかったのであった……環境はなるべく最新のものを使おうね、というお話(自分が制作・管理していない場合、いかんともしがたいが・苦笑)。

【覚書】viewport指定について

モバイルデバイス用のviewport設定についてまじめに調べようとしたら深みにはまりそうだったので、とりあえず整理を兼ねて、覚え書きを残しておく。
また、viewportの簡易的な表示テストができるページも作ってみた




viewport の指定方法

viewportは、HTMLのhead内のmeta要素として指定する

<meta name="viewport" content="(viewportのパラメータ)" />

viewportのパラメータはカンマ(",")区切りで指定。

なお、これは主としてモバイルデバイス(スマートフォン・タブレットなど)用の設定であり、基本的にはデスクトップ用ブラウザの表示には影響を与えない。
ブラウザが常に全画面で表示されるために、基本、ウィンドウの幅=デバイスの表示幅となるモバイルデバイスにおいて(余白が出来たり見切れたりすることなく)適切なページを表示を行うための指定という認識。

viewportの主要なパラメータ

<meta name="viewport"> の content の値
設定可能な値 説明
width 正の整数または文字列 device-width ウェブサイトを描画したいビューポートの幅をピクセル数で定義します。
height 正の整数またはテキスト device-height ビューポートの高さを定義します。どのブラウザーでも使用されていません。
initial-scale 0.0 から 10.0 までの、正の数値 デバイスの幅 (ポートレートモードでの device-width またはランドスケープモードでの device-height) とビューポートの寸法との比率を定義します。
maximum-scale 0.0 から 10.0 までの、正の数値 ズームの最大値を定義します。この値は minimum-scale と同じまたはより大きくしなければなりません。そうではないときの動作は未定義です。ブラウザーの設定でこの規則を無視できます。また、iOS 10 以降は既定で無視します。
minimum-scale 0.0 から 10.0 までの、正の数値 ズームの最小値を定義します。この値は maximum-scale と同じまたはより小さくしなければなりません。そうではないときの動作は未定義です。ブラウザーの設定でこの規則を無視できます。また、iOS 10 以降は既定で無視します。
user-scalable yes または no no を設定すると、ユーザーはページのズームができなくなります。既定値は yes です。ブラウザーの設定でこの規則を無視できます。また、iOS 10 以降は既定で無視します。

<meta>: 文書レベルメタデータ要素 - HTML | MDN
viewportを指定しないとどうなる?

viewport指定を省略した場合、モバイルデバイスでは、ブラウザが暗黙的にデフォルトのwidth値(ブラウザ毎に異なる、例えば980といった値)を用いて、これをウィンドウ(≒スクリーン)内に収めるように表示される。
例えば、デスクトップ向けのページなどで、横幅がこれより大きい値を前提として設計されていたら見切れてしまう。

device-width とは?

device-widthとは、モバイルデバイスが持つ画面(スクリーン)の論理解像度(ポイント実質解像度CSSピクセル)の横幅のことで、これはカタログに載っている解像度(画素数)とは異なる。
device-heightは同じく縦幅のことだが、ほとんど使うことはないと思われる。
例えば、iPhone X のディスプレイは5.8インチ・1125x2436ピクセルの解像度を持つが、device-widthは375(device-heightは812)となる。
すなわち、ブラウザのウィンドウで375px×812pxの画像を等倍で表示した場合、画面にピッタリと収まるサイズで表示されるということになる。

initial-scale とは?

基本的には、ページを表示した際の、最初の表示倍率(拡大率)のこと。
例えば、initial-scale=1 の時は等倍で、initial-scale=0.5の時は幅が半分に縮小(矩形としては4分の1)、initial-scale=2の時には幅が倍に拡大(矩形としては4倍)となる。

これだけならばよいのだが、ややこしいのが『条件によっては viewport の大きさに影響してしまう』ということ(後述)。

viewport が影響する主な要素

JavaScript

viewportの指定によりブラウザのウィンドウの大きさが決まることになるため、window.innerWidth・innerHeightといったパラメータに影響する。
なお、window.screen.widthやwindow.screen.availWidthは、viewportの指定によらず一定で、デバイス固有の値(≒device-width)を持つ。

viewport 設定テスト用ページについて

簡易的な viewport 設定テスト用ページを作成した。

viewport setting tester

  • radioボタンに応じて、meta[name="viewport"]を書き換えるようになっている。
  • 条件によっては、値を変更しても表示が変わらない場合がある。この場合、[Reload]を押すことで反映される。
    Mobile 版 Firefox では、[Reload]を押しても変わらない場合あり。この場合、ページをいったん閉じて、開きなおす必要がある。
  • Google Chrome の開発者ツールのモバイルデバイスエミュレータ(device toolbar)で、画面の拡大縮小(ピンチアウト/イン)の操作は、[Shift]+ドラッグ(スワイプ)で行う([Ctrl]+[+]/[-]では変化しないことに注意)。リセットは[Ctrl]+[0]。

具体的な viewport 指定の例

"width=device-width, initial-scale=1" で、万全!?

viewportについて調べていると、典型的な設定例として出てくるのは、

<meta name="viewport" content="width=device-width, initial-scale=1" />

のようなもの。

  • viewport(≒ブラウザのウィンドウ)幅を device-width に
  • 最初の表示倍率を 1 に

という指定。
f:id:furyu-tei:20180520095805p:plain

適切なレスポンシブ対応(メディアクエリのブレイクポイントの設定)が行われている場合には、この設定で問題は無い。

レスポンシブ対応がなされていない場合

レスポンシブ対応がなされておらず、『とりあえず、デスクトップ用の画面を、モバイルデバイスでも横幅が綺麗に収まる形で表示したい』という場合の設定。
例は、横幅1000pxで設計されているページの例

<meta name="viewport" content="width=1000, user-scalable=no" />

f:id:furyu-tei:20180520095818p:plain
本来ならば、width さえ指定しておけば、ブラウザが拡大率を適切に設定して、スクリーン内に収まるように調整してくれそうなもの。
ではなぜ user-scalable=no を設定しているのかというと、状況によってはこの自動調整がうまくいかないケース(等倍で表示されるケース)があったため
うまく自動調整されない場合の原因は不明。
いずれにしても、user-scalable=no にするとユーザーが拡大縮小できなくなってしまい不便なので、早期にきちんとレスポンシブ対応すべきではある。

レスポンシブ対応が不完全な場合

スマートフォンには対応したのだけれど、ある範囲(例えば横幅768px~1199px)のデバイス(タブレット)だけ表示が見切れる(デスクトップ用に1200px前提でページ設計)という場合の設定。

<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
( function () {
'use strict';

var min_screen_width_for_tablet = 768, // @media (min-width: <min_screen_width_for_tablet>px) { ... }
    viewport_width_for_tablet = 1200,
    screen_width = window.screen.width;

if ( min_screen_width_for_tablet <= screen_width ) {
    document.querySelector( 'meta[name="viewport"]' ).setAttribute( 'content', 'width=' + viewport_width_for_tablet + ', user-scalable=no' );
}
} )();
</script>

デフォルトとして、meta[name="viewport"]には"width=device-width, initial-scale=1"を指定しておき、JavaScript で window.screen.width によりデバイスのスクリーン幅(≒device-width)を調べ、条件に当てはまる場合だけ書き換えを行う。

注意点・問題点など

initial-scale について

上記のとおり、initial-scaleは初期の表示倍率を示すほかに、条件によっては viewport の大きさに影響してしまう。
具体的には、

X = device-width / initial-scale
とするとき、
width < X となる場合には、viewport の幅として X が適用される(widthの指定は無視される)。

模様。
例えばdevice-widthが360のモバイルデバイスの場合に、
"width=640, initial-scale=0.5"
のような指定をすると、実際の viewport の幅としては 720(=360/0.5)が適用されてしまう

また、initial-scale に 1 未満の値を指定しても、状況によってはうまく縮小表示されないケースもある。
具体的な条件は不明。ただし、この場合でも、user-scalable=no と併用すれば正しく縮小表示される模様。

ブラウザによってウィンドウサイズ(innerWidth/Height)の決定方法が異なっている?

f:id:furyu-tei:20180520095827p:plain

Google Chromeの場合
innerWidth/innerHeightは、ユーザーがscale(ピンチインで縮小表示)して表示可能な最大領域のピクセル数を示す模様。

この最大領域の横幅は、document.body の大きさと viewport の minimum-scale により、以下のように決まっている模様。

  • document.body の横幅が viewport の以下の場合には、viewport の幅
  • document.body の横幅が viewport より大きい場合、device-width / minimum-scale と document.body の横幅のうち、小さい方

あくまで最大領域に応じて決まるため、実際のユーザーの拡大縮小操作には影響されない。

Firefoxの場合
innerWidth/innerHeightは、ドキュメントのうち、ブラウザの表示領域に実際に表示されているピクセル数を示す模様。
ユーザーの拡大縮小操作に伴って変動する。

【未確認】Safariの場合
実機が無いため、確認できていない。

【未確認】Windows Tablet / Phone について

Windows 系のモバイルデバイスについては、meta[name="viewport"] による指定は効かないため、別途、CSS で @-ms-viewport による指定が必要
実機が無いこともあり、確認が取れていない。

【覚書】ノートン 360 のせいで、pip freeze がフリーズした件

Windows 10 上の Ubuntu で

$ pip freeze

を実行したら、文字通りフリーズしてしまった。
プロンプトに返ってこない。pip install 等を実行した場合も同様。

原因は、ノートン 360 Norton 360のファイアウォールだった。
同様の事が発生したときに焦らないように、メモ書きしておく。




原因と対策

Python 3(3.6.3)の python3 (実行ファイル) がブロックされていたのが原因。
ノートン 360 の
「設定」→「ファイアウォール」→「プログラム制御」
で確認すると、python3の『信頼』項目が『未確認』になっていた。
この状態で、アクセスが『自動』になっていると、ネットワークアクセスがブロックされてしまうため、これを手動で『許可』に変更して[適用する]必要があった。
ファイアウォールのプログラム制御画面

余談…というべきかどうか

ノートン 360 のライブアップデートで、インストール失敗

pip freeze や pip install が固まってしまう状態になった際、過去の経験


もあって、「どうせまた、ノートン 360 が原因だろう」と思い、軽い気持ちで手動でライブアップデートを実施したところ……再起動後に
ノートン 360のインストールでエラーがありました。続行できません。
と言われてしまい、往生した。
もちろん、ノートン 360 そのものも動作していないため、セキュリティ的にノーガード……。

その後の復旧

上記の状態で、どうしようもないのでそのまま強制的に再起動すると*1、今度は、
ライブアップデートエラー
のようなダイアログが現れた。
最初からこっちを出してくれ、と思わないでもない。
『サポートWebページに移動する』リンク先の指示に従って、『ノートン削除/再インストールツール』(NRnR.exe) をダウンロードして実行。
削除と再インストールを行うことで、なんとか復旧することができた。

*1:普通に再起動しようとすると、再起動をキャンセルしてとノートン360に言われてしまう……キャンセルせず、強制的に再起動する必要があった