プロジェクト

全般

プロフィール

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 の修正を再度行う。 修正内容を記入 

戻る