We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 15497
    • 117 Posts
    スニペットを自作しています。

    条件によって、出力するHTMLのタグを切り替えるようなものなのですが、
    スニペットに渡すオプションの値として、
    HTMLのタグの属性のようなもの、例えば「&attr=`hoge="huga"`」とか、
    正規表現「&regex=`/^[\w]+$/`」等を、
    なんとか指定できないものかと試行錯誤しています。

    そのままではイコール「=」や括弧「[」「]」は、渡せないようですが、
    何か良い方法はありませんでしょうか?
    URLエンコードしてオプションに指定し、スニペットでデコードするとか、
    そういった方法もあるかと思いますが、それではちょっと使いづらそうなので、
    皆様のお知恵をお借りできればありがたいです。

    また、スニペットに使えない(使うと問題が起こる可能性がある)文字は、
    イコール「=」や括弧「[」「]」以外にもありますでしょうか?

    よろしくお願い致します。
      ★日本公式フォーラム2009年9月1日本格始動!★
      http://modxcms-jp.com/bb/

      ▼ウェブ屋のCMS→modxヒキダス流(備忘録)
      http://d.hatena.ne.jp/hikidas_ikeda/
      ▼制作済みHTMLページをmodxで更新するデモ
      http://www.hikidas.com/hikidas/modx_document/modx_demo_osc2009kansai.php
      • 36592
      • 970 Posts
      こんにちは~

      PHPプログラミングはほとんど分からないのでさらに突っ込まれると泣いちゃいますが... :’(

      Quote from: kazuike at Dec 10, 2007, 08:35 PM

      そのままではイコール「=」や括弧「[」「]」は、渡せないようですが、
      何か良い方法はありませんでしょうか?
      また、スニペットに使えない(使うと問題が起こる可能性がある)文字は、
      イコール「=」や括弧「[」「]」以外にもありますでしょうか?

      「=」「&」「?」は渡せないようですね。
      ZeRoさんのスニペット「pieX」でも、この3文字は引数としての記法が別指定されていますし。

      あと日本人にはあまり関係ありませんが、
      仏語や独語にあるような特殊文字も同じ不具合が出ているみたいです。

      バグレポート等を見ていると、この問題はかなり前からあるようですが、まだ解決策が見つかっていませんね。
      0.9.7では改善する方向で検討しているみたいです。

      プログラミングが良く分かっていませんが、
      例えばChunkに値を書いておいて、Chunk名でスニペットに引き渡して読み出す...
      なんてのはダメでしょうか?
      エンコード/デコード的な処理より少しは簡単になりそうな気はしますが... huh
        • 15497
        • 117 Posts
        tkfm さんありがとうございます。
        あと日本人にはあまり関係ありませんが、
        仏語や独語にあるような特殊文字も同じ不具合が出ているみたいです。

        バグレポート等を見ていると、この問題はかなり前からあるようですが、まだ解決策が見つかっていませんね。
        0.9.7では改善する方向で検討しているみたいです。
        そうなんですか…
        せめてバックスラッシュか何かでエスケープするぐらいになってくれると嬉しいです。
        #2007年「最も期待できるオープンソースCMS」ですから、期待大です。 smiley

        で、チャンクですが、あちこちで使えるようなものはチャンクは良いですよね。
        そういう時はとても助かるんで良いんですが、
        そこでしか使わないようなものをチャンクにするのもちょっと抵抗があったりするんですよね。
        とりあえず、DirectPHPを見習って、urlencodeで対応しようかな~
        って考えています。

        だいたい、以下の文字はurlencodeするってことで…
        = => %3D
        ? => %3F
        % => %25
        & => %26
        ` => %60
        [ => %5B
        ] => %5D
          ★日本公式フォーラム2009年9月1日本格始動!★
          http://modxcms-jp.com/bb/

          ▼ウェブ屋のCMS→modxヒキダス流(備忘録)
          http://d.hatena.ne.jp/hikidas_ikeda/
          ▼制作済みHTMLページをmodxで更新するデモ
          http://www.hikidas.com/hikidas/modx_document/modx_demo_osc2009kansai.php
          • 36592
          • 970 Posts
          Quote from: kazuike at Dec 11, 2007, 12:20 AM

          そこでしか使わないようなものをチャンクにするのもちょっと抵抗があったりするんですよね。
          やっぱり、良い案ではないですよね~ tongue

          あとはプレイスホルダで受け渡すとか、物理的にファイルに書いちゃうとか。
          あんまりChunkと変わらないか... wink

          どんなスニペットを作成されているのか分かりませんが、
          完成したら是非公開して下さいね!
            • 15497
            • 117 Posts
            tkfm さん
            ありがとうございます。
            とりあえずスニペットを作ることができました。

            条件分岐スニペット: StartIf & EndIf 1.00
            http://modxcms.com/forums/index.php/topic,20716.0.html

            とりあえず、urlencodeを使っていますが、そのうち、チャンクにも対応するオプションをつけたいと思っています。
            今後とも、よろしくお願いいたします。
              ★日本公式フォーラム2009年9月1日本格始動!★
              http://modxcms-jp.com/bb/

              ▼ウェブ屋のCMS→modxヒキダス流(備忘録)
              http://d.hatena.ne.jp/hikidas_ikeda/
              ▼制作済みHTMLページをmodxで更新するデモ
              http://www.hikidas.com/hikidas/modx_document/modx_demo_osc2009kansai.php
              • 23276
              • 85 Posts
              こんばんは。
              以前、同じようなことではまりました undecided

              これにまつわる処理は、/manager/includes/document.parser.class.inc.php の evalSnippetsメソッドにあるのですが、
              「[[」、「]]」、「&」、「`」、「?」、「=」の文字で単純に分割しているみたいなので、スニペットだけでは対応できなそうでした。

              マルチバイト関数に変えて、パラメータは正規表現でパースするようにするといいのかなあ、と思ったのですが、
              結局、アップデート時のことを考えて独自のエスケープ方法で対応しました。

              致命的というほどではないですが、0.9.7で改善されるといいですよね。
                • 36592
                • 970 Posts
                こんばんわ~

                Quote from: Phize at Dec 11, 2007, 06:27 AM

                これにまつわる処理は、/manager/includes/document.parser.class.inc.php の evalSnippetsメソッドにあるのですが、
                「[[」、「]]」、「&」、「`」、「?」、「=」の文字で単純に分割しているみたいなので、スニペットだけでは対応できなそうでした。
                なんだかすごくタイミングよく、昔のスレッド(1年半以上前のもの)が新規投稿で上がってきました。
                http://modxcms.com/forums/index.php/topic,3772.0.html
                Phizeさんの書かれた「単純に分割」ってこういうことなんですね~

                バグレポートを見ていると一旦解決されたのにまたバグが見つかったようですね。
                一旦解決したときの解決策が上記のスレッドに書かれているものなのかな?
                (PHP4の環境でUTF-8を使うと問題が起こるようなことが書かれています → ここ )
                  • 15497
                  • 117 Posts
                  Phize さんに触発されて、ちょっとソースを眺めてみました。

                  outputContentで、[! => [[、!] => ]] の全置換をしておいて、
                  evalSnippetsで、[[と]]ではさまれた部分を抽出、
                  それぞれ、最初に現われた?で前後に分けて(前がスニペット名、?を含めて後ろがパラメータ)、
                  パラメータについて、
                   ?を全て削除して(…これ最初の一つだけで良いのでは?)、
                   &を&に全て置換して、
                   &で分割して(…これもすごいな)、
                   分割したそれぞれについて、
                    =で分割して(…これまた強烈)
                    分割した2番目の要素の、最初と最後の`の間にある値を使う。
                  という処理を行ってますね。
                  (どこかで、パラメータは空白で分割するって読んだような気がしますが、関係ないですね)

                  つまり、スニペットのパラメータで問題になりそうな文字は、
                  [!、[[、!]、]]、?、&(&含む)、=、`
                  ということでしょうか?

                  でも、確か、[か]でも、何か不都合が起こっていたような気がするのですが…
                  きっと、これはスニペット以外の処理で関係あるのでしょうね。
                    ★日本公式フォーラム2009年9月1日本格始動!★
                    http://modxcms-jp.com/bb/

                    ▼ウェブ屋のCMS→modxヒキダス流(備忘録)
                    http://d.hatena.ne.jp/hikidas_ikeda/
                    ▼制作済みHTMLページをmodxで更新するデモ
                    http://www.hikidas.com/hikidas/modx_document/modx_demo_osc2009kansai.php
                    • 23276
                    • 85 Posts
                    >>tkfmさん

                    詳しい動作はkazuikeさんが書いてくださってますが、そのスレははじめて知りました。
                    ありがとうございます、チェックしてきます laugh


                    >>kazuikeさん

                    evalSnippetsあたりしか眺めてないのですが、その限りでは

                    [[スニペット? &パラメータ名=`パラメータ` &パラメータ名=`パラメータ`]]
                    [!スニペット? &パラメータ名=`パラメータ` &パラメータ名=`パラメータ`!]


                    という形式なら、正規表現などでもっと簡単に「[[」「]]」「[!」「!]」「=」「&」「&」を使えるようにパースできそうですよね。
                    正規表現を使わない理由があるのかはよくわかりませんが、パフォーマンスとかセキュリティ上の問題なんでしょうか…。
                      • 23276
                      • 85 Posts
                      正規表現を使って、スニペットでは通常使えない文字(「]]」、「`」を含む)を使えるようにできたっぽいので貼ってみます(強引っぽいですが)。
                      パラメータはバッククォートあり・なし、値なしのどの場合でも通常とほぼ同じような動作になります。

                      スニペットコールの例:
                      [[Snippet? param1  =  `?= ‵ [] &‵ &` &param2= &param3=[]?= &param4 &param?5=`[[Lea más...]]`]]

                      パラメータ名と値の解析結果($parameterのvar_dump):
                      array
                        'param1' => string '?= ` [] &` &' (length=11)
                        'param2' => string '' (length=0)
                        'param3' => string '[]?=' (length=4)
                        'param5' => string '[[Lea más...]]' (length=15)



                      • 通常の動作と同様に、1つ目のパラメータ名の「&」は補完されます。(param1の例)
                      • 通常の動作と同様に値のないパラメータは無視されます。(param4の例)
                      • 通常の動作と同様にパラメータ名の「?」は「?」の部分だけが削除されます。(param5の例)
                      • 値をバッククォートで囲んだ場合は、「`」以外の文字が使えます。(param1, 6の例)
                      • 値をバッククォートで囲まない場合は、通常使える文字に加えて「`」、「&」、空白文字以外の記号が使えます(param2, 3の例)。
                      • 値をバッククォートで囲んでいる場合に限って、数値文字参照「‵」や「&#x2035」が「`」に変換されます。(param1の例)
                      • マルチバイト文字は、うちのローカル環境(XAMPP+PHP 4.4.7&PHP 5.2.4)では問題ないみたいですが詳しくテストしてません。(param5の例)

                      パラメータ名と値をつなぐ「=」の前後の空白文字の扱いと「&」の扱いだけは、パース結果「param1」のように通常のMODxの動作とは異なります。
                      通常のMODxの動作は、1番目のパラメータ名は「param1 」になりますが、このコードでは前後の空白文字は削除したほうが自然だと思うのでそうしてます。
                      また、通常は「&paramx=`value`」という文字があると最初に「&」が「&」に変換され、その後「paramx=`value`」という一つのパラメータとして扱われますが、このコードではバッククォートの処理の後に変換しているためパラメータとしては扱われません。

                      あと「[[」と「]]」、「`」は相変わらず使えないです :’(
                      「[[」と「]]」はevalSnippetsメソッドの1行目の正規表現を工夫すればできそうな気もしないでもないですが…


                      2007/12/15 全ての文字を使えるようにしてみました。1つ目のパラメータ名に「&」が省略されていた場合にパラメータが無視されていた(通常の動作と異なる)のと、その他の細かい処理を修正しました。


                      MODx 0.9.5~0.9.6.1
                      /manager/includes/document.parser.class.inc.php evalSnippetsメソッド内
                      (行数は 0.9.6.1 のものです。)

                      784行目あたり~(変更前):
                          function evalSnippets($documentSource) {
                              preg_match_all('~\[\[(.*?)\]\]~', $documentSource, $matches);

                      784行目あたり~(変更後):
                          function evalSnippets($documentSource) {
                              preg_match_all('~\[\[((?:.*?(?:`(?:[^`]|[^]]\])*?`)?)*?)\]\]~', $documentSource, $matches);



                      836行目あたり~(変更前):
                                      // current params
                                      $currentSnippetParams= $snippetParams[$i];
                                      if (!empty ($currentSnippetParams)) {
                                          $tempSnippetParams= str_replace("?", "", $currentSnippetParams);
                                          $splitter= "&";
                                          if (strpos($tempSnippetParams, "&") > 0)
                                              $tempSnippetParams= str_replace("&", "&", $tempSnippetParams);
                                          //$tempSnippetParams = html_entity_decode($tempSnippetParams, ENT_NOQUOTES, $this->config['etomite_charset']); //FS#334 and FS#456
                                          $tempSnippetParams= split($splitter, $tempSnippetParams);
                                          $snippetParamCount= count($tempSnippetParams);
                                          for ($x= 0; $x < $snippetParamCount; $x++) {
                                              if (strpos($tempSnippetParams[$x], '=', 0)) {
                                                  if ($parameterTemp= explode("=", $tempSnippetParams[$x])) {
                                                      $fp= strpos($parameterTemp[1], '`');
                                                      $lp= strrpos($parameterTemp[1], '`');
                                                      if (!($fp === false && $lp === false))
                                                          $parameterTemp[1]= substr($parameterTemp[1], $fp +1, $lp -1);
                                                      $parameter[$parameterTemp[0]]= $parameterTemp[1];
                                                  }
                                              }
                                          }
                                      }


                      836行目あたり~(変更後):
                                      // current params
                                      $currentSnippetParams= $snippetParams[$i];
                                      if (!empty ($currentSnippetParams)) {
                                          $tempSnippetParams= preg_replace("~^\s*\?\s*~", "", $currentSnippetParams);
                                          $splitter= "&";
                                          if (strpos($tempSnippetParams, $splitter) != 0)
                                              $tempSnippetParams= $splitter . $tempSnippetParams;
                                          //$tempSnippetParams = html_entity_decode($tempSnippetParams, ENT_NOQUOTES, $this->config['etomite_charset']); //FS#334 and FS#456
                                          $snippetParamCount= preg_match_all("~" . $splitter
                                                            . "([^" . $splitter . "=]*(?:=\s*`[^`]*`"
                                                            . "|=[^" . $splitter . "\s]*"
                                                            . "|[^" . $splitter . "]*))~", $tempSnippetParams, $matches);
                                          $tempSnippetParams= @ $matches[1];
                                          for ($x= 0; $x < $snippetParamCount; $x++) {
                                              if (preg_match('~([^=\s]*)\s*=\s*`?([^`]*)`?~', $tempSnippetParams[$x], $parameterTemp)) {
                                                  $parameterTemp[2]= preg_replace("~&#0*8245;|&#x0*2035;~", "`", $parameterTemp[2]);
                                                  if (strpos($parameterTemp[2], "&") > 0)
                                                      $parameterTemp[2]= str_replace("&", "&", $parameterTemp[2]);
                                                  $parameterTemp[1]= str_replace("?", "", $parameterTemp[1]);
                                                  $parameter[$parameterTemp[1]]= $parameterTemp[2];
                                              }
                                          }
                                      }