Bug(バグ) #837
完了プロフィール項目設定の文字数制限でmax=0,min=0と設定できてしまう
100%
説明
現象¶
OpenPNE2→OpenPNE3のコンバート時、プロフィール項目で入力文字数の最小・最大を指定していなかったものがコンバート後に0~0文字になってしまう。
そのため、コンバート直後にプロフィールを編集すると「0文字以内で入力してください」というエラーメッセージが表示されてしまう。
コンバートでない場合でも、プロフィール項目の設定でmax=0,min=0と設定できてしまい、同様の不具合が起きる。
現象確認バージョン¶
OpenPNE3.0.9-dev
OpenPNE3.2.7-dev
OpenPNE3.4.7-dev
OpenPNE3.6beta1-dev
再現手順¶
1. OpenPNE2で以下のプロフィール項目を作成する
- 項目名: 氏名
- フォームタイプ: テキスト
- 入力値タイプ: 文字列
- 最小値~最大値: null ~ null
- 正規表現: null
2. OpenPNE2→OpenPNE3のコンバートを行う
3. コンバート後、OpenPNE3の管理画面から1で作成したプロフィール項目の編集画面を開く
4. 最小値~最大値が 0~0 になっている
Shogo Kawahara さんがほぼ15年前に更新
2系から3系にコンバートするとき、
2系のDB上(c_profile)では値がないときdefaultとして0がセットされており、
3系ではmax, minともに0に変換されます。
これはコンバートの問題ではなく、max=0,min=0であったときは、
文字数制限をかけないなどの対応をするのが適切かと思います。
Mutsumi Imamura さんが14年以上前に更新
- 題名 を 2系で入力文字数を指定していなかったプロフィール項目の文字数制限が、コンバート後に0~0文字になる から プロフィール項目設定の文字数制限でmax=0,min=0と設定できてしまう に変更
- 対象バージョン を OpenPNE 3.6beta1 にセット
Minoru Takai さんが14年以上前に更新
コンバート後の挙動を確認しました。
少なくとも2系では、最小値、最大値に関する制限が全くなく、min > max であるような指定や、文字列の長さとして負値を設定するようなことが可能になっています。
今回の問題は、最小値、最大値を未指定にしていた場合、コンバートすると3系で min, max が 0, 0 となってしまうというものですが、これは文字列の長さに関しては対応の仕様があるものの、数値の下限上限に関しては自然な対応が思いつきません。
数値に関して、2系で明示的に (min, max) = (1, 5) と指定していれば、数値として 1~5 が許されるプロフィール項目を意味します。 (min, max) = (1, 1) であれば 1 のみが許される項目になります。ここで、 (min, max) = (0, 0) が指定されていれば 0 のみが許される項目と考えるのが自然かと思われますが、これを (min, max) = (NULL, NULL) とみなすという対応は自然でしょうか。
と、ここまで書きましたが、
2系から3系にコンバートするとき、
2系のDB上(c_profile)では値がないときdefaultとして0がセットされており、
3系ではmax, minともに0に変換されます。
と示されている通り、2系では明示的に指定していても、(min, max) = (0, 0) の場合は下限上限なしという判断になっていました。ここで2つの対応方法が考えられます。
- (1) 2系の設計が悪いだけなので、3系では特に何も対応しない(コンバート直後は min, max が 0, 0 になるが、それをプロフィール設定で変更してもらうことを仕様とする)。
- (2) コンバート直後に「0文字以内で入力してください」というエラーが出ることを問題であると考え、(min, max) = (0, 0) だけは例外的に範囲指定がされていないものとして扱う。
文字列の長さに関して (min, max) = (0, 0) になるのが問題であると思っていたので、後者の対応を考えていましたが、数値の下限上限を考えると前者の方が好ましいように思いました(後者による対応は、数値 0 のみを入力として許すプロフィール項目の作成手段を提供しないことになります)。
コンバート直後に「0文字以内で入力してください」というエラーが出ることが問題かどうかの認識によって対応方法が異なるということを示しておきます。
Minoru Takai さんが14年以上前に更新
対応方法を更に示します。
- (3) コンバート時に (min, max) = (0, 0) であるレコードを (NULL, NULL) に変換して保存する
- (4) コンバート後に、どこかのタイミングで (0, 0) であるプロフィール項目の最小値最大値を持つレコードの値を (NULL, NULL) に変更する
(2)と(4) を併せた対応を考えていますが、修正すべきソースコードの箇所が分からず調査中です。
Minoru Takai さんが14年以上前に更新
対応方針
lib/util/opFormItemGenerator.class.php
generateValidator() メソッド内
if ($field['ValueType'] === 'integer' || $field['FormType'] === 'date') { if (!empty($field['ValueMin'])) { $option['min'] = $field['ValueMin']; } if (!empty($field['ValueMax'])) { $option['max'] = $field['ValueMax']; } } else { if (isset($field['ValueMin'])) { $option['min_length'] = $field['ValueMin']; } if (isset($field['ValueMax'])) { $option['max_length'] = $field['ValueMax']; } }
後半 else ブロック内で、isset() に加えて、max > 0 という条件を与えます。
更に、2系あるいは #940 修正前の3系にて、大小関係が不正な (min, max) が指定されたプロフィール項目がある場合にも対応できるよう、 min <= max という if 文をラップします。
if (isset($field['ValueMax'])) ブロック内の末に以下の記述を追記します。
if (1 > (int)$field['ValueMax'] || (isset($field['ValueMin']) && (int)$field['ValueMin'] > (int)$field['ValueMax'])) { unset($option['min_length']); unset($option['max_length']); }
Minoru Takai さんが14年以上前に更新
- ステータス を Accepted(着手) から Pending Review(レビュー待ち) に変更
- 進捗率 を 0 から 50 に変更
更新履歴 d41df217719462f71f29c6f30b0b4ae549b627ed で適用されました。
Shogo Kawahara さんが14年以上前に更新
- ステータス を Pending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
- 進捗率 を 50 から 70 に変更
#1449 での変更と合わさって若干冗長なコードになっている気もしますが、別問題としとします。
Minoru Takai さんが約14年前に更新
- ステータス を Pending Testing(テスト待ち) から Pending Review(レビュー待ち) に変更
- 進捗率 を 70 から 50 に変更
更新履歴 808691c0eaf4fbfb7fb5ffcd56ad8030634f0aae で適用されました。
↑3.4のコミットです
Minoru Takai さんが約14年前に更新
- ステータス を Pending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
- 進捗率 を 50 から 70 に変更
ステータスを正しいものに戻します。
Fumie Toyooka さんが約13年前に更新
- ステータス を Pending Testing(テスト待ち) から Fixed(完了) に変更
- 進捗率 を 70 から 100 に変更
テストOKです。