Bug(バグ) #4168
Youichi Kimura さんが7年以上前に更新
h3. Overview (概要) SnsTerm の "複雑な使用例":https://github.com/openpne/OpenPNE3-doc/blob/master/cookbook/3.6/ja/use-sns-term-from-plugin.rst#%E8%A4%87%E9%9B%91%E3%81%AA%E4%BD%BF%E7%94%A8%E4%BE%8B に記載されている下記のようなコードが正しく動作せず、語形変化が適用されていない「friend」のまま出力される。 <pre><code class="php"> <?php echo __('%friend% are removed.', array('%friend%' => $op_term['friend']->pluralize()->fronting())); ?> </code></pre> この問題は #1759 における commit:9b2f55d8 の修正以降から発生している。 これにより、opDiaryPlugin の日記作成画面を英語で表示した際に「My Friends」と表示されるべき箇所が「my friend」と表示される状態になっている。 !{width:567px}スクリーンショット_2017-02-27_18.00.07.png! h3. Causes (原因) 前提として、SnsTerm は以下のような性質を持っている。 バグが発生した原因を記入 # SnsTerm インスタンスに設定した語形変化は @SnsTerm::__toString()@ が呼ばれると初期状態に戻る #* <pre><code class="php"> $term = Doctrine_Core::getTable('SnsTerm')->get('my_friend'); $term->titleize(); var_dump((string)$term); // "My Friend" var_dump((string)$term); // "my friend" </code></pre> # SnsTerm インスタンスは SnsTermTable クラス内でキャッシュされる #* <pre><code class="php"> $term = Doctrine_Core::getTable('SnsTerm')->get('my_friend'); $term->titleize(); // $term と同一のインスタンスが返る $term2 = Doctrine_Core::getTable('SnsTerm')->get('my_friend'); var_dump((string)$term2); // "My Friend" </code></pre> それを踏まえて、@opI18N::__()@ メソッドの動作を追うと以下のようになる。 <pre><code class="php"> // 以下のように呼ばれる。期待する出力は「Friends are removed.」 echo __('%friend% are removed.', array('%friend%' => $op_term['friend']->pluralize()->fronting())); .... // lib/i18n/opI18N.class.php public function __($string, $args = array(), $catalogue = 'messages') { if (empty($this->parsed[$string])) // 初回の呼び出しでは true になる { $this->parsed[$string] = array(); $matches = array(); preg_match_all('/%([a-zA-Z_]+)%/', $string, $matches); // 「%friend%」がヒットする array_shift($matches); foreach ($matches as $match) { foreach ($match as $v) { if ($this->terms[$v]) { $term = $this->terms[$v]; // 性質 2 より、語形変化が適用されたままのインスタンスが返る if ($this->titleize) // デフォルトで false { $term = $term->titleize(); } $this->parsed[$string]['%'.$v.'%'] = (string)$term; // ここで返るのは「Friends」 } } } } $parsedString = $this->parsed[$string]; if (is_array($args)) { foreach ($args as $k => $v) { if ($v instanceof SnsTerm) { $args[$k] = (string)$v; // 性質 1 より、ここで返るのは「friend」 } } $parsedString = array_merge($parsedString, $args); // 「Friends」が「friend」に上書きされる } // 「friend are removed.」が出力される (不具合) return parent::__($string, $parsedString, $catalogue); } </code></pre> h3. Way to fix (修正内容) #1759 の修正を一旦取り消し、上記のような SnsTerm の不具合が生じないように #1759 の修正を再度行う。 修正内容を記入