捣蛋phpwind控制器注入

在PwBaseController  里面,会有这个方法的存在

/**
	 * action Hook 注册
	 *
	 * @param string $registerKey 扩展点别名
	 * @param PwBaseHookService $bp        	
	 * @throws PwException
	 * @return void
	 */
	protected function runHook($registerKey, $bp) {
		if (!$registerKey) return;
		if (!$bp instanceof PwBaseHookService) {
			throw new PwException('class.type.fail', 
				array(
					'{parm1}' => 'src.library.base.PwBaseController.runHook', 
					'{parm2}' => 'PwBaseHookService', 
					'{parm3}' => get_class($bp)));
		}
		if (!$filters = PwHook::getRegistry($registerKey)) return;
		if (!$filters = PwHook::resolveActionHook($filters, $bp)) return;
		$args = func_get_args();
		$_filters = array();
		foreach ($filters as $key => $value) {
			$args[0] = isset($value['method']) ? $value['method'] : '';
			$_filters[] = array('class' => $value['class'], 'args' => $args);
		}
		$this->resolveActionFilter($_filters);
	}

我们先不理这个东西是什么,看它到底是怎样调用的

 

  

/**
	 * 发帖
	 */
	public function doaddAction() {
        
		list($title, $content, $topictype, $subtopictype, $reply_notice, $hide) = $this->getInput(array('atc_title', 'atc_content', 'topictype', 'sub_topictype', 'reply_notice', 'hide'), 'post');
		$pwPost = $this->post;
		$this->runHook('c_post_doadd', $pwPost);

		$postDm = $pwPost->getDm();
		$postDm->setTitle($title)
			->setContent($content)
			->setHide($hide)
			->setReplyNotice($reply_notice);
                   
		//set topic type
		$topictype_id = $subtopictype ? $subtopictype : $topictype;
		$topictype_id && $postDm->setTopictype($topictype_id);

		if (($result = $pwPost->execute($postDm)) !== true) {
			$data = $result->getData();
			$data && $this->addMessage($data, 'data');
			$this->showError($result->getError());
		}
		$tid = $pwPost->getNewId();

		$this->showMessage('success', 'bbs/read/run/?tid=' . $tid . '&fid=' . $pwPost->forum->fid, true);
	}

  

$this->runHook('c_post_doadd', $pwPost);

之前发帖的时候发现页面有添加话题的内容,但是在控制器入面却没有发现有这种逻辑的操作,后来才知道是通过注入去操作的,我们看看数据库入面的纪录


再看看它们是怎样定义的


/**
 * 帖子发布 - 话题相关
 *
 * @author jinlong.panjl <jinlong.panjl@aliyun-inc.com>
 * @copyright ©2003-2103 phpwind.com
 * @license http://www.phpwind.com
 * @version $Id$
 * @package wind
 */
class PwPostDoTagInjector extends PwBaseHookInjector {
	
	public function doadd() {
		$tagNames = (array)$this->getInput('tagnames', 'post');
		if (!is_array($tagNames) || !count($tagNames)) return;
		Wind::import('SRV:forum.srv.post.do.PwPostDoTag');
		return new PwPostDoTag($this->bp,$tagNames);
	}
	
	public function domodify() {
		$tagNames = (array)$this->getInput('tagnames', 'post');
		Wind::import('SRV:forum.srv.post.do.PwPostDoTag');
		return new PwPostDoTag($this->bp,$tagNames);
	}
}

  

doadd 这个方法就算添加标签的

它的父类是什么玩意

<?php
defined('WEKIT_VERSION') || exit('Forbidden');

Wind::import('WIND:filter.WindActionFilter');

/**
 * PwHook action拦截过滤器抽象接口定义
 * 
 * 通过继承该接口,可以实现在Controller层注入扩展实现.该接口默认调用'run'方法.
 * 支持多参数扩展.
 * @author Qiong Wu <papa0924@gmail.com> 2011-12-2
 * @copyright ©2003-2103 phpwind.com
 * @license http://www.windframework.com
 * @version $Id: PwBaseHookInjector.php 8692 2012-04-24 05:56:29Z jieyin $
 * @package src
 * @subpackage library.filter
 */
abstract class PwBaseHookInjector extends WindActionFilter {

	private $callback = 'run';
	private $args = array();
	/**
	 * @var PwBaseHookService
	 */
	protected $bp = null;

	/**
	 * @param WindForward $forward
	 * @param WindErrorMessage $errorMessage
	 * @param WindRouter $router
	 * @param array $args
	 */
	public function __construct($forward, $errorMessage, $router, $args = array()) {
		parent::__construct($forward, $errorMessage, $router);
		!empty($args[0]) && $this->callback = $args[0];
		isset($args[1]) && $this->bp = $args[1];
		if (count($args) > 2) {
			unset($args[0], $args[1]);
			$this->args = $args;
		}
	}

	/* (non-PHPdoc)
	 * @see WindHandlerInterceptor::preHandle()
	 */
	public function preHandle() {
		if (!method_exists($this, $this->callback)) return;
		$injector = call_user_func_array(array($this, $this->callback), $this->args);
		if ($injector) $this->bp->appendDo($injector);
	}

	/* (non-PHPdoc)
	 * @see WindHandlerInterceptor::postHandle()
	 */
	public function postHandle() {}

}
?>

原来是继承了过滤器,呵呵,所以这个比较强大啊,可以这样用

 

我们在看看上面控制器的这个方法 resolveActionFilter

/**
	 * action过滤链策略部署
	 * 
	 * @example <pre>
	 *          $filters = array(array('expression'=>'', 'class'=>'',
	 *          args=array()));
	 *          </pre>
	 * @param array $filters
	 * @return void
	 */
	protected function resolveActionFilter($filters) {
		if (!$filters) return;
		$chain = WindFactory::createInstance('WindHandlerInterceptorChain');
		$args = array($this->getForward(), $this->getErrorMessage(), null);
		foreach ((array) $filters as $value) {
			$chain->addInterceptors(
				WindFactory::createInstance(Wind::import($value['class']), 
					(empty($value['args']) ? $args : array_merge($args, array($value['args'])))));
		}
		$chain->getHandler()->handle();
	}

  流程是这样的,先建立过滤链 ,把过滤器一一添加实例化,哈哈,跟我们之前的没什么区别

  但是事情还没有结速

  

class PwPostDoTag extends PwPostDoBase {

	private $loginUser;
	private $defaultType = 'threads';
	private $tagNames = array();
	private $typeId = '';
	
	public function __construct(PwPost $pwpost,$tagNames) {
		$this->loginUser = $pwpost->user;
		$tagNames = $tagNames ? $tagNames : array();
		$this->tagNames = array_unique($tagNames);
		$this->typeId = $this->_getService()->getTypeIdByTypeName($this->defaultType);
	}

	public function addThread($tid) {
		$this->_getService()->addTags($this->_buildTagDm($tid));
	}
	
	public function updateThread($tid) {
		$this->_getService()->updateTags($this->typeId,$tid,$this->_buildTagDm($tid));
	}
	
	public function getDm() {
		return new PwTagDm();
	}
	
	public function dataProcessing($postDm) {
		if (!is_array($this->tagNames) || !$this->tagNames) return $postDm;
		
		$postDm->setTags(implode(',',$this->tagNames));
		return $postDm;
	}
	
	private function _buildTagDm($tid) {
		if (!is_array($this->tagNames) || !$this->tagNames) return false;
		$dmArray = array();
		foreach ($this->tagNames as $value) {
			$value = trim($value);
			$dm = $this->getDm();
			$dmArray[$value] = 
				$dm->setName($value)
					->setTypeId($this->typeId)
					->setParamId($tid)
					->setIfhot(1)
					->setCreateUid($this->loginUser->uid)
			;
		}
		return $dmArray;
	}
	
	public function check($postDm) {
		if (!is_array($this->tagNames) || !$this->tagNames) return true;
		$count = count($this->tagNames);
		foreach ($this->tagNames as $v) {
			$dm = $this->getDm();
			$dm->setName($v);
			if(($return = $dm->beforeAdd()) instanceof PwError) return $return;
		}
		if ($count > 5) {
			return new PwError("Tag:tagnum.exceed");
		}
		if ($count && $this->loginUser->getPermission('tag_allow_add') < 1) {
			return new PwError("TAG:right.tag_allow_add.error");
		}
		return true;
	}
	
	/**
	 * Enter description here ...
	 *
	 * @return PwTagService
	 */
	protected function _getService() {
		return Wekit::load('tag.srv.PwTagService');
	}
}

  那么 addThread 是在什么时候调用的呢,又是怎样调用的呢 看这里

  

/**
	 * @see PwPostAction.afterRun
	 */
	public function afterRun() {
		$this->runDo('addThread', $this->tid);
	}

  这个类是 PwTopicPost 也正是我们在控制器里面刚刚实例化的 ,我们断点调式下看看 

  关键在这里

  

/* (non-PHPdoc)
	 * @see WindHandlerInterceptor::preHandle()
	 */
	public function preHandle() {
		if (!method_exists($this, $this->callback)) return;
		$injector = call_user_func_array(array($this, $this->callback), $this->args);
		if ($injector) $this->bp->appendDo($injector);
	}

  把过滤器又加入到_do里面,不知道为什么要这样呢

  $this->bp的值是多少呢

  

 

   原来是这个pwPost

class PwPost extends PwBaseHookService {

	public $action;
	public $forum;
	public $user;
	public $special; // 帖子类型

	public function __construct(PwPostAction $action) {
		$this->action = $action;
		$this->forum = $action->forum;
		$this->user = $action->user;
		$this->special = $action->getSpecial();
		
		/** hook **/
		$this->action->setSrv($this);
	}

	/**
	 * 发帖之前检测
	 *
	 * @return bool
	 */
	public function check() {
		if (($result = $this->isInit()) !== true) {
			return new PwError('data.error');
		}
		if (($result = $this->checkForum()) !== true) {
			return $result;
		}
		if (($result = $this->checkPost()) !== true) {
			return $result;
		}
		if ($this->isBan()) {
			return new PwError('ban');
		}
		if (($result = $this->action->check()) !== true) {
			return $result;
		}
		return true;
	}

	/**
	 * 初始化信息是否满足要求
	 *
	 * @return bool
	 */
	public function isInit() {
		return $this->action->isInit();
	}

	/**
	 * 检测是否拥有该版操作权限
	 *
	 * @return bool
	 */
	public function checkForum() {
		if (!$this->forum->isForum()) {
			return new PwError('BBS:post.forum.not.exists');
		}
		if (($result = $this->forum->allowVisit($this->user)) !== true) {
			return new PwError('BBS:forum.permissions.visit.allow', 
				array('{grouptitle}' => $this->user->getGroupInfo('name')));
		}
		return true;
	}

	/**
	 * 检测是否允许发帖
	 *
	 * @return bool
	 */
	public function checkPost() {
		if ($this->user->groupid == 7) {
			return new PwError('REG_CHECK');
		}
		/*
		$config = Wekit::C('bbs');
		if ($config['post.timing.open'] && !$this->user->inGroup($config['post.timing.groups']) && !self::inTime($config['post.timing.start_hour'], $config['post.timing.start_min'], $config['post.timing.end_hour'], $config['post.timing.end_min'])) {
			return new PwError('BBS:post.timing');
		}
		*/
		return true;
	}

	/**
	 * 检测用户是否被禁言
	 *
	 * @return bool
	 */
	public function isBan() {
		if ($this->user->gid == 6) {
			Wind::import('SRV:user.srv.PwBanBp');
			$banBp = new PwBanBp($this->user->uid);
			$memberid = 0;
			if (false === $banBp->checkIfBanSpeak()) {
				$memberid = $banBp->recoveryBanSpeaKError();
			} elseif ($banBp->endDateTimeBanSpeak()) {
				$memberid = $banBp->callEndDateTimeBanSpeak();
			}
			if ($memberid) {
				$this->user->info['groups'] = '';
				$this->user->info['groupid'] = 0;
				$this->user->info['memberid'] = $memberid;
				$this->user->groups = array($memberid);
				$this->user->resetGid($memberid);
				return false;
			}
			return true;
		}
		return false;
	}

	public function getDm() {
		return $this->action->getDm();
	}

	/**
	 * 各应用获取该用户dm来设置,以达到更新用户信息的目的
	 *
	 * @return object PwUserInfoDm
	 */
	public function getUserDm() {
		return $this->action->getUserDm();
	}

	public function getAttachs() {
		return $this->action->getAttachs();
	}

	/**
	 * 发布
	 *
	 * @param object $postDm 帖子数据模型
	 * @return bool
	 */
	public function execute(PwPostDm $postDm) {
		if (($result = $this->action->beforeRun($postDm)) instanceof PwError) {
			return $result;
		}
		if (($result = $this->action->dataProcessing($postDm)) !== true) {
			return $result;
		}
		if (($result = $this->action->execute()) !== true) {
			return $result;
		}
		$this->action->afterRun();
		$this->updateUser();
		return true;
	}

	public function getInfo() {
		return $this->action->getInfo();
	}

	public function getNewId() {
		return $this->action->getNewId();
	}

	public function getDisabled() {
		return $this->action->isDisabled();
	}

	/**
	 * 更新用户信息 /积分/发帖数/等
	 */
	public function updateUser() {
		Wind::import('SRV:credit.bo.PwCreditBo');
		$credit = PwCreditBo::getInstance();
		if ($operation = $this->action->getCreditOperate()) {
			$credit->operate($operation, $this->user, true, 
				array('forumname' => $this->forum->foruminfo['name']), 
				$this->forum->getCreditSet($operation));
		}
		$credit->execute();
		$this->action->updateUser();
		if ($userDm = $this->action->getUserDm(false)) {
			Wekit::load('user.PwUser')->editUser($userDm, PwUser::FETCH_DATA);
		}
	}

	public function appendDo($do) {
		$this->action->appendDo($do);
	}
	
	public function runDo($method) {
		$args = func_get_args();
		call_user_func_array(array($this->action, 'runDo'), $args);
	}

  

   原来是这样,看到这里基本明白啦

 

 

基本上发帖中就要牵涉到这里操作了,如果第三方插件要加入的话就要加上服务当中 

话题对应的hook 是 c_post_doadd

而发帖本身的hook是 m_PwTopicPost

来看看它是怎样定义的

<?php
defined('WEKIT_VERSION') || exit('Forbidden');

Wind::import('SRV:forum.srv.post.do.PwPostDoBase');
/**
 * 帖子发布 - 话题
 *
 * @author jinlong.panjl <jinlong.panjl@aliyun-inc.com>
 * @copyright ©2003-2103 phpwind.com
 * @license http://www.phpwind.com
 * @version $Id$
 * @package wind
 */
class PwReplyDoRemind extends PwPostDoBase {

	private $loginUser;
	private $_reminds = array();
	private $_atc_title;
	private $_maxNum;
	
	public function __construct(PwPost $pwpost) {
		$this->loginUser = $pwpost->user;
		$this->_maxNum = $this->loginUser->getPermission('remind_max_num');
	}

	public function addPost($pid, $tid) {
		$this->_addRemind($pid, $tid);
	}
	
	public function updatePost($pid, $tid) {
		$this->_addRemind($pid, $tid);
	}
	
	public function dataProcessing($postDm) {
		if ($this->_check() !== true) return $postDm;
		$atc_content = $postDm->getField('content');
		$atc_content = preg_replace('/\[quote(=.+?\,\d+)?\].*?\[\/quote\]/is', '', $atc_content);
		$this->_atc_title = Pw::substrs(trim(Pw::stripWindCode($atc_content,true)),20);
		
		$reminds = $this->_getRemindService()->bulidRemind($atc_content);
		$this->_reminds = $this->_getRemindService()->buildUsers($this->loginUser->uid,$reminds,$this->_maxNum);
		$reminds = $this->_getRemindService()->formatReminds($this->_reminds);
		$postDm->setReminds($reminds);
		return $postDm;
	}
	
	private function _addRemind($pid, $tid) {
		if ($this->_check() !== true) return false;
		if (!$this->_reminds) return false;
		$reminds = ($this->_maxNum && count($this->_reminds) > $this->_maxNum) ? array_slice($this->_reminds, 0, $this->_maxNum) : $this->_reminds;
		$remindUids = array_keys($reminds);
		$this->_getRemindService()->addRemind($this->loginUser->uid, $remindUids);
		
		//发送通知
		$extendParams = array(
			'remindUid' => $this->loginUser->uid,
			'title' =>    $this->_atc_title,
			'remindUsername' => $this->loginUser->username,
			'notice' => '在回帖 <a href="' . WindUrlHelper::createUrl('bbs/read/run', array('tid'=>$tid), $pid) . '" target="_blank">' . $this->_atc_title . '</a> @了您',
		);
		// 是否黑名单
		$remindUids = $this->_checkBlack($remindUids);
		foreach ($remindUids as $uid) {
			$this->_getPwNoticeService()->sendNotice($uid,'remind',$pid,$extendParams);
		}
	}
	
	private function _check() {
		if ($this->loginUser->getPermission('remind_open') < 1) {
			return new PwError("bbs:remind.remind_open.error");
		}
		return true;
	}
	
	/** 
	 * 是否开启权限
	 * 
	 * @param array $remindUids
	 * @return bool
	 */
	private function _checkBlack($remindUids) {
		$result = Wekit::load('user.PwUserBlack')->checkUserBlack($this->loginUser->uid, $remindUids);
		if ($result) {
			$remindUids = array_diff($remindUids,$result);
		}
		return $remindUids;
	}
	
	/** 
	 * @return PwNoticeService
	 */
	protected function _getPwNoticeService(){
		return Wekit::load('message.srv.PwNoticeService');
	}
	
	/**
	 * PwRemindService
	 * 
	 * @return PwRemindService
	 */
	private function _getRemindService(){
		return Wekit::load('remind.srv.PwRemindService');
	}
}

  不同的类有不同的方法,可能就是调用时机不同,责任不同,总之就比较复杂

 

 

 

 

 

 

 

 

   

 

 

 

 

 

 

 









 

转载于:https://www.cnblogs.com/simonlu/p/5085727.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值