Bug(バグ) #2366
完了新規の環境にも関わらず/messageに遷移するとFatal errorが発生する
100%
説明
Overview (現象)¶
OpenPNE3.4.15 をインストールし、受信メッセージのあるメンバーが /message に遷移すると以下のような Fatal error が発生する。
/message/sendList などでも同様のエラーが発生する。
Fatal error: Call to undefined function op_link_to_member() in /home/user/sns/34x.example.jp/plugins/opMessagePlugin/apps/pc_frontend/modules/message/templates/listSuccess.php on line 135
※原因がplugin側にあるという確証を得る調査はまだ行われていないため、このチケットの作成プロジェクトに誤りがあった場合、作成すべきプロジェクトに変更して下さい。
再現バージョン¶
- OpenPNE-3.4.15
- バンドルプラグイン opMessagePlugin-0.9.2
原因から明らかですが、 op_link_to_member() が定義されていない OpenPNE のバージョンで opMessagePlugin-0.9.2 を用いた場合に問題が生じます。 3.4.15 は opMessagePlugin-0.9.2 がバンドルされているため特に問題です。
再現ブランチ¶
- OpenPNE-3.4.15
- stable-3.4.x
再現手順¶
- 新規に OpenPNE-3.4.15 を設置する
- メンバーを招待する(メッセージの送信相手を用意するため)
- メンバーAからメンバーBにメッセージを送信する
- メンバーAの送信箱、あるいはメンバーBの受信箱を開こうとすると、表示の途中で Fatal Error が発生する
- 一部のテンプレートの HTML のみが出力される(テンプレートの途中で処理が止まっており、CSSなど共通部分のHTMLも読み込まれていない)。
Causes (原因)¶
op_link_to_member() は #840 によって追加されたヘルパー関数だが、 #840 の対応内容の事情により 3.4 向けのバックポートは行なわれていなかった。
つまり 3.4 系ではこの関数は使えないことになる。しかし、コア側とバージョンが対応しないプラグインにおいて op_link_to_member() を使っている箇所があり、今回の問題が生じている。
発覚しているのは opMessagePlugin であり、このプラグインで op_link_to_member() を使ったのは 0.9.2 からであるらしい。 0.9.2 においては #1995 の修正で追加されている。
opMessagePlugin-0.9.2 がバンドルされているのは OpenPNE-3.4.15, OpenPNE-3.6beta12 からである。
Minoru Takai さんが約13年前に更新
- 説明 を更新 (差分)
考えられる修正方針¶
考えられる修正方針を示しておきます。思いついたものを示しているだけで、これに限るわけではありません。
- opMessagePlugin-0.9.2 では op_link_to_member() が定義されていることを前提とし(つまり 0.9.2 は OpenPNE-3.6 以降向けと考え)、
- (1) OpenPNE-3.4.15 以降では opMessagePlugin-0.9.1 以前をバンドルするようにする
- (2) OpenPNE-3.4.15 以降で、 op_link_to_member() を定義する(関数を定義するだけで、 #840 で定義された関数と同等の処理を実装する必要はない)
- OpenPNE-3.4 系では op_link_to_member() が定義されていないことを前提とし(つまり 0.9.2 は 3.4.x 以前にも対応するプラグインと考え)、
- (3) OpenPNE-3.4.15 以降では opMessagePlugin-0.9.1 以前をバンドルするようにする(プラグイン側の対応を待たずに対応)
- (4) opMessagePlugin-0.9.2 で op_link_to_member() が定義されているかどうかを確認した上でコールするようにする
- コールしている箇所が少なければ (4) を採用してもよいかもしれないが、コア側で定義されているかどうかを多くの箇所で気にする必要があるのであれば (5) または (6) の対応が考えられる。
- しかし、 (5) にも (6) にも回避しなければならない問題があるため (4) の対応が簡単かもしれない。
- (5) opMessagePlugin-0.9.2 で op_link_to_member() が定義されていなければその関数を定義する(関数の実装は #840 と同等の処理である必要はありません:未定義の関数が呼ばれることを避けるだけで十分です)
// PHP では以下のようなことが可能です function op_link_to_member() { return 'defined in core'; } if (!function_exists('op_link_to_member')) { function op_link_to_member() { return 'defined in opMessagePlugin'; } } var_dump(op_link_to_member());
- この対応は、コア側のヘルパー関数の定義が先に読み込まれていることを前提としなければならない。
- (6) opMessagePlugin-0.9.2 では op_link_to_member() を直接使わず、 opMessagePlugin 独自の op_bc_link_to_member() などを定義して使う(bc は Backward Compatible の意)。
- op_link_to_member() をコールしたい箇所では op_bc_link_to_member() を呼び、 opMessagePlugin ではヘルパー関数として次のような関数を定義する
function op_bc_link_to_member($value, $options = array(), $routeName = '@obj_member_profile') { if (!function_exists('op_link_to_member')) { return op_link_to_member($value, $options, $routeName); } return link_to($member->getName(), 'member/profile?id='.$value; }
- しかし op_bc_link_to_member() という関数で対応してしまうと、同じ発想で別のプラグインが対応できなくなる問題が生じる。
- だからといって op_bc_link_to_member() 自体が定義済みかどうかを確認するのは冗長ではないか(そもそもこのような場合に (6) の対応を取ることや、その場合の関数名の命名規則についての共通認識がないことは好ましくない)。
- しかし op_message_bc_link_to_member() のようにプラグイン名を紐付けて関数の多重定義の衝突を防ぐにしても、その関数名がどのような名前であると適切かについて考えなければならない。
- op_link_to_member() をコールしたい箇所では op_bc_link_to_member() を呼び、 opMessagePlugin ではヘルパー関数として次のような関数を定義する
※ 「OpenPNE-3.4.15 以降で」や「opMessagePlugin-0.9.2 で」と書いていますが、これらのバージョンは既にリリースされているため、これに後続するバージョンで対応する必要があります。
Minoru Takai さんが約13年前に更新
- 説明 を更新 (差分)
OpenPNEとしての問題について¶
opMessagePlugin-0.9.2 において op_link_to_member() が定義されていないことを考慮していない問題(*1)は opMessagePlugin 側で対応するとして、そもそもなぜ OpenPNE-3.4.15 は opMessagePlugin-0.9.2 をバンドルしているのでしょうか。
- (*1) 0.9.2 での差分
- "a7d4d6eb": replaced '' to nickname_of_member_who_does_not_have_credentials(SnsConfig) (refs #1995)
- この修正は op_link_to_member() が定義されている前提となっている
- "a7d4d6eb": replaced '' to nickname_of_member_who_does_not_have_credentials(SnsConfig) (refs #1995)
この答えによっては、
※原因がplugin側にあるという確証を得る調査はまだ行われていないため、このチケットの作成プロジェクトに誤りがあった場合、作成すべきプロジェクトに変更して下さい。
の通り、この問題の原因はプラグイン側ではなく本線側にあるものとして扱う可能性もあります。
3.4.15 のリリース告知 http://www.openpne.jp/archives/6222/ では
opMessagePlugin: 0.9.1.1 → 0.9.2
のリンク先で #1757 しか示されていませんが、 0.9.2 での差分 にある通り、実際は #1757, #1777, #1995 の修正が取り込まれています。
コアとプラグインの関係が単純ではない(同じバージョンのプラグインが、古いコアと新しいコアの両方で使われる可能性がある)ため、バンドルプラグインのバージョンを上げたりする場合は、本線側でプラグインの変更点に関わる動作テストが十分行なわれていないと致命的な問題に気づかぬままリリースされてしまう危険性があります。
この点について疑問提起しておきます。
3.4.15 に対する本問題の優先度¶
「OpenPNE3.6 のチケット優先度と今後のリリーススケジュールについて」 http://www.openpne.jp/archives/5361/ では 3.6 向けのチケットの優先度について示されていますが、
- Immediate(今すぐ)
- セットアップができない、データが壊れるような不具合
- Urgent(急いで)
- 機能が動作しない致命的な不具合(画面遷移出来ない、Fatal Errorが発生する等)
- セキュリティ・プライバシー関連の不具合
- High(高め)
- 正常動作に支障が出る不具合(処理に非常に時間がかかる等)
- 必ずリリースに含めたいと要望がある不具合
- Normal(通常)
- 他のどの基準にも当てはまらない不具合
- Low(低め)
- 未対応でもユーザに影響が少ない不具合(回避可能な不具合である等)
- 一部の特殊な環境のみで発生する不具合
これに基づくと本問題は「(提供されるべき)機能が動作しない致命的な不具合」(優先度 Urgent )に該当します。
OpenPNE 側での対応¶
note-3 で示したものは、本体側(バンドルプラグインのバージョンなど)を変更する対応が (1),(2),(3) で、プラグイン側を修正する対応が (4),(5),(6) でした。
既にリリースした OpenPNE(=3.4.15) にバンドルされている「プラグインのバージョン」を、以降の OpenPNE(3.4.15.x や 3.5.16) で「下げる」という選択肢はないようです。つまり、この問題を解消した新しいバージョンの opMessagePlugin (0.9.3 あるいは 0.9.2.x) をバンドルした OpenPNE-3.4.15.x(または 3.4.16)をリリースする必要があるようです。
なお OpenPNE-3.4.15 のバンドルプラグインリストを変更する(既にリリースしているバージョンの、バンドルプラグインリストのみを書き換える)という対応も考えられるようですが、これは混乱を招くように思います。
Maki Takahashi さんが約13年前に更新
- ステータス を New(新規) から Accepted(着手) に変更
- 担当者 を Maki Takahashi にセット
- 対象バージョン を 0.9.2 にセット
- 3.6 で発生するか を Yes にセット
Maki Takahashi さんが約13年前に更新
- ステータス を Accepted(着手) から Pending Review(レビュー待ち) に変更
- 進捗率 を 0 から 50 に変更
更新履歴 1cc0470856fc8ad648d305756013b1afc9d65eb8 で適用されました。
Shinichi Urabe さんが約13年前に更新
- ステータス を Pending Review(レビュー待ち) から Fixed(完了) に変更
- 進捗率 を 50 から 100 に変更
コード確認しました
3.6で動作させたときの結果が変わらないと想定できることと
3.4でも動作するコードとなっていることを確認しました