phxのinroleとisinroleで不具合?

質問全般・改善要望
masco
メンバー
メンバー
記事: 106
登録日時: 2014年9月26日(金) 10:43

phxのinroleとisinroleで不具合?

投稿記事by masco » 2015年3月20日(金) 00:52

----------------
1.0.14J-r9
php 5.5.19
mysql 5.0.95
apache 2.2
----------------

phxを調べています。

isinrole(ir,memberof,mo)とinroleが機能していないようなので、
phx.parser.class.inc.phpをいじって動くようにしみましたので報告です。

変更はしてみましたが、
実際の動作がそのようなものなのか、またPHP自体がよくわからないので変更後が合っているのかわかりません。


最初はエラーがでていました。
Error : array_key_exists() expects parameter 2 to be array, null given



変更後の挙動

変数が「&_PHX_INTERNAL_&」の場合、ウェブユーザーのIDを取得して判定
指定のウェブユーザーIDが指定のグループに所属していたらtrue、していなければfalse

コード: 全て選択

[*phx:if(&_PHX_INTERNAL_&):isinrole(ウェブユーザーのグループ名1,ウェブユーザーのグループ名2):then(true):else(false)*]
[*phx:if(ウェブユーザーID):isinrole(ウェブユーザーのグループ名):then(true):else(false)*]



指定のユーザーIDが指定のグループに所属していたら1、していなければ0を出力

コード: 全て選択

[*phx:if(ウェブユーザーID):inrole(ウェブユーザーのグループ名1,ウェブユーザーのグループ名2)*]



変更箇所
214〜222行目くらい
$modifier_valueが指定されていなかったみたいなので$optに変更してみました。
if ($value == '&_PHX_INTERNAL_&') $value = $this->user['id'];が何かわからなかったので、
ウェブログインした時の判定だと思ってみました。

変更前

コード: 全て選択

         case 'isinrole':
         case 'ir':
         case 'memberof':
         case 'mo':
            // Is Member Of  (same as inrole but this one can be stringed as a conditional)
            if ($value == '&_PHX_INTERNAL_&') $value = $this->user['id'];    //変更箇所ここから
            $grps = ($this->strlen($modifier_value) > 0 ) ? explode(',',$opt) :array();      //変更箇所ここまで
            $condition[] = intval($this->isMemberOfWebGroupByUserId($value,$grps));
            break;


変更後

コード: 全て選択

         case 'isinrole':
         case 'ir':
         case 'memberof':
         case 'mo':
            // Is Member Of  (same as inrole but this one can be stringed as a conditional)
            if ($value == '&_PHX_INTERNAL_&') $value = $modx->getLoginUserID('web');      //変更箇所ここから
            if (empty($value)){ $condition[] = intval(false);
            return $conditional;
            }                     
            $grps = ($this->strlen($opt) > 0 ) ? explode(',', $opt) :array();               //変更箇所ここまで
            $condition[] = intval($this->isMemberOfWebGroupByUserId($value,$grps));
            break;



713〜740行目くらい
変更したら先のエラーは出なくなりました。
$this->cache['mo']が何かよくわかりませんがnullっぽいです。
ユーザーの配列とoptの配列を比較しているところまではわかりました。

変更前

コード: 全て選択

function isMemberOfWebGroupByUserId($userid=0,$groupNames=array()) {
      global $modx;
      
      // if $groupNames is not an array return false
      if(!is_array($groupNames)) return false;
      
      // if the user id is a negative number make it positive
      if (intval($userid) < 0) { $userid = -($userid); }
      
      // Creates an array with all webgroups the user id is in
      if (!array_key_exists($userid, $this->cache['mo']))      //変更箇所ここから
      {
         $tbl_webgroup_names = $modx->getFullTableName('webgroup_names');
         $tbl_web_groups     = $modx->getFullTableName('web_groups');
         $sql = "SELECT wgn.name FROM {$tbl_webgroup_names} wgn INNER JOIN {$tbl_web_groups} wg ON wg.webgroup=wgn.id AND wg.webuser='{$userid}'";
         $this->cache['mo'][$userid] = $grpNames = $modx->db->getColumn('name',$sql);
      }
      else $grpNames = $this->cache['mo'][$userid];     //変更箇所ここまで
      
      // Check if a supplied group matches a webgroup from the array we just created
      foreach($groupNames as $k=>$v)
      {
         if(in_array(trim($v),$grpNames)) return true;
      }
      
      // If we get here the above logic did not find a match, so return false
      return false;
   }


変更後

コード: 全て選択

function isMemberOfWebGroupByUserId($userid=0,$groupNames=array()) {
      global $modx;
      
      // if $groupNames is not an array return false
      if(!is_array($groupNames)) return false;
      
      // if the user id is a negative number make it positive
      if (intval($userid) < 0) { $userid = -($userid); }
      
      // Creates an array with all webgroups the user id is in
         $tbl_webgroup_names = $modx->getFullTableName('webgroup_names');//変更箇所ここから
         $tbl_web_groups     = $modx->getFullTableName('web_groups');
         $sql = "SELECT wgn.name FROM {$tbl_webgroup_names} wgn INNER JOIN {$tbl_web_groups} wg ON wg.webgroup=wgn.id AND wg.webuser='{$userid}'";
         $grpNames = $modx->db->getColumn('name',$sql);//変更箇所ここまで
      
      // Check if a supplied group matches a webgroup from the array we just created
      foreach($groupNames as $k=>$v)
      {
         if(in_array(trim($v),$grpNames)) return true;
      }
      
      // If we get here the above logic did not find a match, so return false
      return false;
   }
アバター
yama
管理人
記事: 2916
登録日時: 2009年7月29日(水) 02:50

Re: phxのinroleとisinroleで不具合?

投稿記事by yama » 2015年3月20日(金) 09:43

コード: 全て選択

case 'mo':
   // Is Member Of  (same as inrole but this one can be stringed as a conditional)
   if ($value == '&_PHX_INTERNAL_&') $value = $this->user['id'];
   $grps = ($this->strlen($modifier_value) > 0 ) ? explode(',',$opt) :array();
   $condition[] = intval($this->isMemberOfWebGroupByUserId($value,$grps));
   break;
上記の部分は

コード: 全て選択

case 'mo':
   // Is Member Of  (same as inrole but this one can be stringed as a conditional)
   $userID = $modx->getLoginUserID();
   $grps = ($this->strlen($opt) > 0 ) ? explode(',',$opt) :array();
   $condition[] = intval($this->isMemberOfWebGroupByUserId($userID,$grps));
   break;
これで動作すると思います。どうでしょうか?
masco
メンバー
メンバー
記事: 106
登録日時: 2014年9月26日(金) 10:43

Re: phxのinroleとisinroleで不具合?

投稿記事by masco » 2015年3月20日(金) 10:36

yama様

ありがとうございます。
書き換えてみました。

yama さんが書きました:

コード: 全て選択

case 'mo':
   // Is Member Of  (same as inrole but this one can be stringed as a conditional)
   $userID = $modx->getLoginUserID();
   $grps = ($this->strlen($opt) > 0 ) ? explode(',',$opt) :array();
   $condition[] = intval($this->isMemberOfWebGroupByUserId($userID,$grps));
   break;
これで動作すると思います。どうでしょうか?


下記の書き方だとユーザーがグループに所属していても常にfalseになります。

コード: 全て選択

[*phx:isinrole(test,test2,test3):then(true):else(false)*]
[+@:mo(test,test2,test3):then(true):else(false)+]


$valueに何かしら値があればウェブユーザーのログインとログオフで判定をしてくれます。

コード: 全て選択

[*phx:if(login):isinrole(test,test2,test3):then(true):else(false)*]
[*id:isinrole(test,test2,test3):then(true):else(false)*]
[+@login:mo(test,test2,test3):then(true):else(false)+]
アバター
yama
管理人
記事: 2916
登録日時: 2009年7月29日(水) 02:50

Re: phxのinroleとisinroleで不具合?

投稿記事by yama » 2015年3月20日(金) 11:02

コード: 全て選択

$_ = explode(',', 'id,ifempty,input,if,equals,is,eq,notequals,isnot,isnt,ne,find,preg,or,and,show,this,then,else,select,switch,summary,smart_description,smart_desc');
isEmpty関数に上記のような記述があると思いますが、ここにisinrole,ir,memberof,moを加えてみてください。
masco
メンバー
メンバー
記事: 106
登録日時: 2014年9月26日(金) 10:43

Re: phxのinroleとisinroleで不具合?

投稿記事by masco » 2015年3月20日(金) 11:36

yamaさま

ありがとうございます。
下記記述で無事判定されるようになりました。

コード: 全て選択

[*phx:isinrole(test,test2):then(true):else(false)*]
アバター
yama
管理人
記事: 2916
登録日時: 2009年7月29日(水) 02:50

Re: phxのinroleとisinroleで不具合?

投稿記事by yama » 2015年3月20日(金) 12:13

phx.parser.class.inc.zip
(7.62 KiB) ダウンロード数: 78 回
ありがとうございます、今回の修正をまとめたので上記ファイルに差し替えてテストしていただいてよいでしょうか?
masco
メンバー
メンバー
記事: 106
登録日時: 2014年9月26日(金) 10:43

Re: phxのinroleとisinroleで不具合?

投稿記事by masco » 2015年3月20日(金) 12:32

ありがとうございます。

inrole、isinrole共に問題なく機能しています。
masco
メンバー
メンバー
記事: 106
登録日時: 2014年9月26日(金) 10:43

モディファイアの不具合

投稿記事by masco » 2015年3月23日(月) 17:41

----------------
1.0.14J-r9
php 5.5.19
mysql 5.0.95
apache 2.2
----------------

新しくトピックを立てるほどではないので。

23日版のパッケージを使用しています。

モディファイアを調べている中でいくつか不具合と思われるものがありました。

1.新しい記法でオプションを使用した場合、変数に「)」があると途切れます。

コード: 全て選択

[*longtitle:ifempty([*pagetitle*])*]

例えば、上記コードでlongtitleが空でpagetitleに「リソース(記事)のタイトル」とすると、「リソース(記事」までしか表示されません。


2.リソース関連のモディファイアで次のものが機能しませんでした。
リソースとテンプレートに記述して確認しました。

contentTypeは×の場合は変数の数字が表示されます。
[*id:contentType*] ×
[*phx:if(2):contentType*] ×
[*contentType:id(2)*] ○

contentは×の場合そのリソースのcontentが表示されます。
[*id:content*] ×
[*phx:if(2):content*] ×
[*content:id(2)*] ○

デモサイトのr9ではcontentは機能していますが、contentTypeは同様に機能しませんでした。
[*id:content*] ○
[*phx:if(2):content*] ○
[*content:id(2)*] ○
他のリソース関係のモディファイアは動作しているのでおそらく不具合かと思われます。

3.モディファイアとは別ですが、「コンテナとして扱う」にチェックを入れているリソースでリソース一覧ページにこんなエラーが出ました。
Warning: Invalid argument supplied for foreach() in /home/****/*****/public_html/manager/actions/resources_list.static.php on line 35

23日版より以前のものでは出ていませんでした。
アバター
yama
管理人
記事: 2916
登録日時: 2009年7月29日(水) 02:50

Re: モディファイアの不具合

投稿記事by yama » 2015年3月23日(月) 19:43

phx.parser.class.inc.zip
(7.8 KiB) ダウンロード数: 81 回
ありがとうございます、こちらを試していただいてよいでしょうか?
[*longtitle:ifempty(’[*pagetitle*]`)*]
[*longtitle:ifempty("[*pagetitle*]")*]
[*longtitle:ifempty(`[*pagetitle*]`)*]
というふうに、今回のような場合はクォートで囲みます。(クォート以外にも#や$などの記号が使えます)

masco さんが書きました:3.モディファイアとは別ですが、「コンテナとして扱う」にチェックを入れているリソースでリソース一覧ページにこんなエラーが出ました。
Warning: Invalid argument supplied for foreach() in /home/****/*****/public_html/manager/actions/resources_list.static.php on line 35

23日版より以前のものでは出ていませんでした。

resources_list.static.zip
(5.01 KiB) ダウンロード数: 87 回
このファイルを上書きしてみてください。
masco
メンバー
メンバー
記事: 106
登録日時: 2014年9月26日(金) 10:43

Re: phxのinroleとisinroleで不具合?

投稿記事by masco » 2015年3月23日(月) 20:35

yamaさま

早速有り難うございます。

ファイルを上書きしたら
オプションの()の問題とリソース一覧のエラーの2つが解決しました。
アバター
yama
管理人
記事: 2916
登録日時: 2009年7月29日(水) 02:50

Re: phxのinroleとisinroleで不具合?

投稿記事by yama » 2015年3月23日(月) 20:46

contentは×の場合そのリソースのcontentが表示されます。
[*id:content*] ×
[*phx:if(2):content*] ×
[*content:id(2)*] ○

PHxをよく理解してないんですが、これは合ってるのではないでしたっけ?
masco
メンバー
メンバー
記事: 106
登録日時: 2014年9月26日(金) 10:43

Re: phxのinroleとisinroleで不具合?

投稿記事by masco » 2015年3月23日(月) 21:51

contentは×の場合そのリソースのcontentが表示されます。


例えばDittoなどで[+id:content+]にすると本来はそのIDの本文が読み込まれます。
http://150323205325-22286.evo.demo.modx.jp/1.html

しかし現在の23日版では、
contentモディファイアを使用した場合、
それを記述している本文(デモの場合だとID16の本文)自体が出力されてしまうためにループになってエラーになります。
リソースに[*content*]を書いている状態と同じです。

これはDittoだから起きるわけではなく、[*phx:if(2):content*]でも起きるので本体側の問題だと思います。

この問題は現在のデモでは起きませんでした。
23日版にしていないr9でも試してみたところ、そちらも同様の問題は起きなかったので、
ここ最近の変更が関係あるのだと思われます。


contentTypeモディファイアの方はr8では機能していますが、r9からは処理されずに変数がそのまま表示されます。
r8
http://150323211027-22286.evo.demo.modx.jp/1.html

r9
http://150323205325-22286.evo.demo.modx.jp/2.html


先ほどファイルを上書きした後、
preg_matchモディファイアでエラーがでました。

この書き方だとエラーが出て、
[*phx:if(田中太郎):preg_match(/田中/):then(true)*]

こちらだと問題なく処理されましたので報告します。
[*phx:if(田中太郎):preg_match({田中}):then(true)*]

検索文字列を変えてみたところエラーがでました。
[*phx:if(aaa):preg_match(/a/):then(true)*]

Error : preg_match(): Delimiter must not be alphanumeric or backslash


----追記
contentモディファイアに関しては18日のものに戻しても問題は起きていました。
この問題が起きてないr9の方からmanagerフォルダを持ってきて上書きしても、
同じ問題が起きたのでこちらは再現性がないかもしれません。
もう少し条件を調べてみます。
アバター
yama
管理人
記事: 2916
登録日時: 2009年7月29日(水) 02:50

Re: phxのinroleとisinroleで不具合?

投稿記事by yama » 2015年3月23日(月) 23:35

ありがとうございます、さっそく修正の上で配布パッケージを差し替えました。ややこしいですが今回は安定バージョンとしてR9を当面のところ固定化しておきたいので、こういうふうにさせてもらってます。
contentモディファイアの件はこちらでは再現できませんでした。また詳しいことが分かれば教えてください。コードの整理が進んだので、たいていの不具合は修正できると思います。
masco
メンバー
メンバー
記事: 106
登録日時: 2014年9月26日(金) 10:43

Re: phxのinroleとisinroleで不具合?

投稿記事by masco » 2015年3月24日(火) 00:01

yama様

原因わかりました。

スニペット名にcontentとしていたからでした。

リソース変数とスニペット名は一緒にしたらダメなんですね。
初歩的なミスでした。

スニペット名を変更後contentモディファイアは問題なく機能しました。
アバター
yama
管理人
記事: 2916
登録日時: 2009年7月29日(水) 02:50

Re: phxのinroleとisinroleで不具合?

投稿記事by yama » 2015年3月24日(火) 01:07

リソース変数とスニペット名は一緒にしたらダメなんですね。
うーん、やっぱりそういうことありますね。スニペットとモディファイアの違いを特に意識せず、コンテキストに応じて自由に使い分けるノウハウが根付くとよいかなと思ってこのようにしたのですが(Revoもそうですし、他にもいくつか理由がありますが)。
グローバル設定にオプションを設けるなどしてプリフィックスphx:を必須とするかどうかなどを設定できるようにしたほうがいいかもしれませんね。
※追記 リソース変数とスニペット名が同じだからではなく、スニペット名がモディファイアとして認識されたためと思います
masco
メンバー
メンバー
記事: 106
登録日時: 2014年9月26日(金) 10:43

Re: phxのinroleとisinroleで不具合?

投稿記事by masco » 2015年3月24日(火) 02:08

yama さんが書きました:グローバル設定にオプションを設けるなどしてプリフィックスphx:を必須とするかどうかなどを設定できるようにしたほうがいいかもしれませんね。
※追記 リソース変数とスニペット名が同じだからではなく、スニペット名がモディファイアとして認識されたためと思います


yamaさま

何度もありがとうございます。

今回内蔵のモディファイアを全部書きだしてみましたが、
結構な数があるので知らないうちにスニペット名とモディファイア名がかぶってしまい、
いざ内蔵のモディファイアを使おうとした時に機能しないということは有り得そうです。
グローバル設定のOutput Filterのところに「重複しないように」と一言あればそれだけでよい気もしますが。


別件でhttp://modx.jp/news/20150319.htmlに

コード: 全て選択

<!--@IF:[*template:is(3)*]>
  <h2 class="blog">[*pagetitle*]</h2>
<@ELSEIF:[*template:is(7)*]>
  <h2 class="whatsnew">[*pagetitle*]</h2>
<@ELSE>
  <h2>[*pagetitle*]</h2>
<@ENDIF-->


とありますが、@ELSEIFが機能しないようです。
@IFが1のときに<@ELSEIF:0>と表示されます。
http://150323205325-22286.evo.demo.modx.jp/3.html

@ELSEではきちんと分岐ができます。
アバター
yama
管理人
記事: 2916
登録日時: 2009年7月29日(水) 02:50

Re: phxのinroleとisinroleで不具合?

投稿記事by yama » 2015年3月24日(火) 10:06

すいません、@ELSEIFはまだ実装してませんでした。今のところ自分自身がそこまで必要としてないので、今後考えますね。

グローバル設定のOutput Filterの説明を変更しました。
masco
メンバー
メンバー
記事: 106
登録日時: 2014年9月26日(金) 10:43

Re: phxのinroleとisinroleで不具合?

投稿記事by masco » 2015年3月24日(火) 10:25

yama さんが書きました:すいません、@ELSEIFはまだ実装してませんでした。今のところ自分自身がそこまで必要としてないので、今後考えますね。

グローバル設定のOutput Filterの説明を変更しました。


yamaさま

自分も@ELSEIFは必要としていませんでしたが、書かれていたので確認させていただきました。

説明の変更確認しました。ありがとうございます。
アバター
yama
管理人
記事: 2916
登録日時: 2009年7月29日(水) 02:50

Re: phxのinroleとisinroleで不具合?

投稿記事by yama » 2015年3月24日(火) 12:29

https://github.com/modxcms-jp/evolution ... ss.inc.php
複数のモディファイアを更新しました。(今月中はGitHub上のパッケージはマージしきれておらず動作しないため注意)

https://github.com/modxcms-jp/evolution ... 421e7b510c
このコミットは配布パッケージに一部適用しました
masco
メンバー
メンバー
記事: 106
登録日時: 2014年9月26日(金) 10:43

Re: phxのinroleとisinroleで不具合?

投稿記事by masco » 2015年3月24日(火) 17:57

yama さんが書きました:複数のモディファイアを更新しました。


ありがとうございます。オプションも設定できるようになるんですね。

また正式にリリースされたら追加していきます。