LOGIN ID Password Auto Login Register Now! Lost Password?
XUGJ Forum

XCL2.1ユーザ情報編集フォームの乗っ取り

  • このフォーラムに新しいトピックを立てることはできません
  • このフォーラムではゲスト投稿が禁止されています

投稿ツリー


前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 | 投稿日時 2009/11/11 12:33
GIJOE  Admiral 居住地: 2003年4月くらい  投稿数: 3708
XCL2.1ではユーザ情報のフィールド定義を簡単に変更することはできません。

だから、userモジュールのテンプレートを編集することで、ICQやAIMみたいなあまり利用価値のないフィールドを別の用途に流用する、なんて使われ方が意外と多いと思います。

ただ、テンプレート(HTML)編集だけでは、入力制約や権限といった機能を変更することはできません。かといって、userモジュールのforms/やactions/下のファイルを直接Hackするのは望ましくありません。

そこで、こんなpreloadを作ってみました。


2ファイル構成です。

(1) EditUserOverride.class.php (プリロード)
(2) _EditUserOverride.class.php (上記プリロードから呼び出されるサブクラス定義)

このうち、(2)は preload/ 直下ではなく、preload/disabled/ の下に置きます。

(1) html/preload/EditUserOverride.class.php
<?php

// ユーザ情報編集オーバーライド

if( ! defined( 'XOOPS_ROOT_PATH' ) ) exit ;

class EditUserOverride extends XCube_ActionFilter
{
	function preFilter()
	{
		// ユーザ関連のアクション作成部をフック
		$this->mRoot->mDelegateManager->add( 'User_ActionFrame.CreateAction' , array( &$this , 'hook' ) , XCUBE_DELEGATE_PRIORITY_FINAL ) ;
	}

	function hook( &$actionFrame )
	{
		if( strcasecmp( get_class( $actionFrame->mAction ) , 'User_EditUserAction' ) === 0 ) {
			// ユーザ編集Actionの時だけ、オーバーライドしたActionに差し替え
			require_once dirname(__FILE__).'/disabled/_EditUserOverride.class.php' ;
			$actionFrame->mAction =& new UserOverride_EditUserAction( $actionFrame->mAdminFlag ) ;
		}
	}
}



(2) html/preload/disabled/_EditUserOverride.class.php
<?php

// ユーザ情報編集オーバーライド(ActionおよびForm記述)

if( ! defined( 'XOOPS_ROOT_PATH' ) ) exit ;

// 差し替え用Action
class UserOverride_EditUserAction extends User_EditUserAction
{
	function _setupActionForm()
	{
		// フォームの差し替え
		$this->mActionForm =& new UserOverride_EditUserForm( $this->mConfig ) ;
		$this->mActionForm->prepare() ;
	}
}


// 差し替え用Form
class UserOverride_EditUserForm extends User_EditUserForm
{
	// フォーム定義をオーバーライド
	function prepare()
	{
		parent::prepare() ;
	
		// フォーム用フィールドの登録
		// 入力制約等の追加/変更/削除
	}

	// DB等からロードする際の処理をオーバーライド
	function load( &$obj )
	{
		parent::load( $obj ) ;

		// $obj->set( 'field' , $this->get( 'field' ) ) ;
	}

	// 更新時の処理をオーバーライド
	function update( &$obj )
	{
		// 入力データに置き換える前のオブジェクトを保存しておく
		$original_obj = unserialize( serialize( $obj ) ) ;
		// $original_obj = clone $obj ; とやると、php4でパースエラーになる

		parent::update( $obj ) ;

		if( ! $GLOBALS['xoopsUser']->isAdmin( 'user' ) ) {
			// Userモジュールの管理者権限が必要なフィールドについて書き戻す
			$obj->set( 'name' , $original_obj->get('name') ) ;
		}

		// $obj->set( 'field' , $this->get( 'field' ) ) ;
	}
}

この(2)の書き方次第で、たいていのロジックは記述可能です。

このサンプルでは、nameについては、管理者だけしか書き換えられないようにしています。

こんなことをしなくても、テンプレートカスタマイズで、フォームから該当の<input>を消せば良いではないか、と思った方は要注意です。

直接、name=hoge とPOSTしてくる可能性があるのですから。


正直、こんなサンプルだと、何の役に立つのか良く判らないと思いますが、時間があったら、有用な(2)のサンプルを書き足していきます。


ちなみに、XoopsUserオブジェクトの定義を簡単に置き換えられないので、「フィールドの追加」は意外と面倒です。

そんなわけで、「フィールドの流用」で目的が達成出来るならそれが一番楽です。
投票数:1 平均点:10.00
前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 | 投稿日時 2009/11/17 5:01
GIJOE  Admiral 居住地: 2003年4月くらい  投稿数: 3708
上の流れで、登録フォームの乗っ取りをやってみました。

これまた2ファイル構成です。

preload/UserRegisterOverride.class.php
<?php

// ユーザ情報編集オーバーライド

if( ! defined( 'XOOPS_ROOT_PATH' ) ) exit ;

class UserRegisterOverride extends XCube_ActionFilter
{
	function preFilter()
	{
		// ユーザ関連のアクション作成部をフック
		$this->mRoot->mDelegateManager->add( 'User_ActionFrame.CreateAction' , array( &$this , 'hook' ) , XCUBE_DELEGATE_PRIORITY_FINAL ) ;
	}

	function hook( &$actionFrame )
	{
		if( strcasecmp( get_class( $actionFrame->mAction ) , 'User_UserRegisterAction' ) === 0 ) {
			// ユーザ登録Actionの時だけ、オーバーライドしたActionに差し替え
			require_once dirname(__FILE__).'/disabled/_UserRegisterOverride.class.php' ;
			$actionFrame->mAction =& new UserOverride_UserRegisterAction( $actionFrame->mAdminFlag ) ;
		} else if( strcasecmp( get_class( $actionFrame->mAction ) , 'User_UserRegister_confirmAction' ) === 0 ) {
			// 確認画面でunserialize()するので、クラス定義だけ呼んでおく
			require_once dirname(__FILE__).'/disabled/_UserRegisterOverride.class.php' ;
		}
	}
}


preload/disabled/_UserRegisterOverride.class.php
<?php

// ユーザ登録オーバーライド(ActionおよびForm記述)

if( ! defined( 'XOOPS_ROOT_PATH' ) ) exit ;

// 確認画面でも呼ばれるため読み込んでおく
require_once XOOPS_MODULE_PATH . "/user/actions/UserRegisterAction.class.php";

// 差し替え用Action
class UserOverride_UserRegisterAction extends User_UserRegisterAction
{
	function _processActionForm()
	{
		if ($this->mConfig['reg_dispdsclmr'] != 0 && $this->mConfig['reg_disclaimer'] != null) {
			$this->mEnableAgreeFlag = true;
			// フォームの差し替え
			$this->mActionForm =& new UserOverride_RegisterAgreeEditForm($this->mConfig);
		} else {
			$this->mActionForm =& new UserOverride_RegisterEditForm($this->mConfig);
		}
		
		$this->mActionForm->prepare();
		
		$root =& XCube_Root::getSingleton();
		$this->mActionForm->set('timezone_offset', $root->mContext->getXoopsConfig('default_TZ'));
	}
}


// 差し替え用Form
class UserOverride_RegisterEditForm extends User_RegisterEditForm
{
	// フォーム定義をオーバーライド
	function prepare()
	{
		parent::prepare() ;

		// 入力制約をセットしなおす
		unset( $this->mFieldProperties['email'] ) ;
		$this->mFieldProperties['email'] =& new XCube_FieldProperty($this);
		$this->mFieldProperties['email']->setDependsByArray(array('maxlength', 'email'));
		$this->mFieldProperties['email']->addMessage('maxlength', _MD_USER_ERROR_MAXLENGTH, _MD_USER_LANG_EMAIL, '60');
		$this->mFieldProperties['email']->addVar('maxlength', 60);
		$this->mFieldProperties['email']->addMessage('email', _MD_USER_ERROR_EMAIL, _MD_USER_LANG_EMAIL);
	}

	// DB等からロードする際の処理をオーバーライド
	function load( &$obj )
	{
		parent::load( $obj ) ;
	}

	// 更新時の処理をオーバーライド
	function update( &$obj )
	{
		parent::update( $obj ) ;
	}
}

class UserOverride_RegisterAgreeEditForm extends UserOverride_RegisterEditForm
{
	function prepare()
	{
		parent::prepare();
		
		// set properties
		$this->mFormProperties['agree']=new XCube_IntProperty('agree');

		// set fields
		$this->mFieldProperties['agree']=new XCube_FieldProperty($this);
		$this->mFieldProperties['agree']->setDependsByArray(array('required','intRange'));
		$this->mFieldProperties['agree']->addMessage("required",_MD_USER_ERROR_UNEEDAGREE);
		$this->mFieldProperties['agree']->addMessage("intRange",_MD_USER_ERROR_UNEEDAGREE);
		$this->mFieldProperties['agree']->addVar("min",1);
		$this->mFieldProperties['agree']->addVar("max",1);
	}
}


この例では、メールアドレスの入力制約から「必須」だけを外しています。
利用許諾文の有無で、Formそのものが変わってくるから、その分コードも長くなってます。
(同一Formを使ってprepare()メソッド内で条件分けしてくれてたら、もう少しスッキリしたのに…)

# しかし、confirmActionでFormをオブジェクトごとunserializeしているのは罠だった…
# こんなの気づかなかったら延々とハマるところかも。
投票数:3 平均点:10.00
前の投稿 - 次の投稿 | 親投稿 - 子投稿なし | 投稿日時 2009/11/17 13:53 | 最終変更
tohokuaiki  Lieutenant 居住地: From:2004/12  投稿数: 420
引用:
# しかし、confirmActionでFormをオブジェクトごとunserializeしているのは罠だった…
# こんなの気づかなかったら延々とハマるところかも。
ですです。

なので、PHP5だとそれをunserializeする前にFormクラスをロードしておかないと、__PHP_Incomplete_Classになっちゃうんですよね。

最初、ConfirmとRegiesterを分けてファイルに記述しててハマりました。
「これはないだろー。てか、利用規約がセッションDBのtextフィールド越えたらアウトじゃん!」って


って、そういえば、このネタどっかでやったと思ったら、以前にほとんど同じ内容でやったのを思い出しました。その時は「登録時にアンケートを取って、メールでその内容が送信されればO.K」だったので、単純に登録フォームの追加だけでしたが。

あ、・・・ブログに書いてました。
投票数:0 平均点:0.00
  条件検索へ

Back to Page Top
MainMenu
Manuals
Search
XOOPS Official & Dev.
XOOPS Communities