您的位置:首页 > 编程语言 > PHP开发

捣蛋phpwind控制器注入

2015-12-29 14:54 666 查看
在PwBaseController 里面,会有这个方法的存在/** *actionHook注册 * *@paramstring$registerKey扩展点别名 *@paramPwBaseHookService$bp *@throwsPwException *@returnvoid */ protectedfunctionrunHook($registerKey,$bp){ if(!$registerKey)return; if(!$bpinstanceofPwBaseHookService){ thrownewPwException('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($filtersas$key=>$value){ $args[0]=isset($value['method'])?$value['method']:''; $_filters[]=array('class'=>$value['class'],'args'=>$args); } $this->resolveActionFilter($_filters); }我们先不理这个东西是什么,看它到底是怎样调用的  /** *发帖 */ publicfunctiondoaddAction(){ 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); //settopictype $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); 之前发帖的时候发现页面有添加话题的内容,但是在控制器入面却没有发现有这种逻辑的操作,后来才知道是通过注入去操作的,我们看看数据库入面的纪录再看看它们是怎样定义的/** *帖子发布-话题相关 * *@authorjinlong.panjl<jinlong.panjl@aliyun-inc.com> *@copyright©2003-2103phpwind.com *@licensehttp://www.phpwind.com*@version$Id$ *@packagewind */ classPwPostDoTagInjectorextendsPwBaseHookInjector{ publicfunctiondoadd(){ $tagNames=(array)$this->getInput('tagnames','post'); if(!is_array($tagNames)||!count($tagNames))return; Wind::import('SRV:forum.srv.post.do.PwPostDoTag'); returnnewPwPostDoTag($this->bp,$tagNames); } publicfunctiondomodify(){ $tagNames=(array)$this->getInput('tagnames','post'); Wind::import('SRV:forum.srv.post.do.PwPostDoTag'); returnnewPwPostDoTag($this->bp,$tagNames); } }  doadd 这个方法就算添加标签的
它的父类是什么玩意<?php defined('WEKIT_VERSION')||exit('Forbidden'); Wind::import('WIND:filter.WindActionFilter'); /** *PwHookaction拦截过滤器抽象接口定义 * *通过继承该接口,可以实现在Controller层注入扩展实现.该接口默认调用'run'方法. *支持多参数扩展. *@authorQiongWu<papa0924@gmail.com>2011-12-2 *@copyright©2003-2103phpwind.com *@licensehttp://www.windframework.com*@version$Id:PwBaseHookInjector.php86922012-04-2405:56:29Zjieyin$ *@packagesrc *@subpackagelibrary.filter */ abstractclassPwBaseHookInjectorextendsWindActionFilter{ private$callback='run'; private$args=array(); /** *@varPwBaseHookService */ protected$bp=null; /** *@paramWindForward$forward *@paramWindErrorMessage$errorMessage *@paramWindRouter$router *@paramarray$args */ publicfunction__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) *@seeWindHandlerInterceptor::preHandle() */ publicfunctionpreHandle(){ 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) *@seeWindHandlerInterceptor::postHandle() */ publicfunctionpostHandle(){} } ?>原来是继承了过滤器,呵呵,所以这个比较强大啊,可以这样用我们在看看上面控制器的这个方法 resolveActionFilter/** *action过滤链策略部署 * *@example<pre> *$filters=array(array('expression'=>'','class'=>'', *args=array())); *</pre> *@paramarray$filters *@returnvoid */ protectedfunctionresolveActionFilter($filters){ if(!$filters)return; $chain=WindFactory::createInstance('WindHandlerInterceptorChain'); $args=array($this->getForward(),$this->getErrorMessage(),null); foreach((array)$filtersas$value){ $chain->addInterceptors( WindFactory::createInstance(Wind::import($value['class']), (empty($value['args'])?$args:array_merge($args,array($value['args']))))); } $chain->getHandler()->handle(); }  流程是这样的,先建立过滤链 ,把过滤器一一添加实例化,哈哈,跟我们之前的没什么区别  但是事情还没有结速  classPwPostDoTagextendsPwPostDoBase{ private$loginUser; private$defaultType='threads'; private$tagNames=array(); private$typeId=''; publicfunction__construct(PwPost$pwpost,$tagNames){ $this->loginUser=$pwpost->user; $tagNames=$tagNames?$tagNames:array(); $this->tagNames=array_unique($tagNames); $this->typeId=$this->_getService()->getTypeIdByTypeName($this->defaultType); } publicfunctionaddThread($tid){ $this->_getService()->addTags($this->_buildTagDm($tid)); } publicfunctionupdateThread($tid){ $this->_getService()->updateTags($this->typeId,$tid,$this->_buildTagDm($tid)); } publicfunctiongetDm(){ returnnewPwTagDm(); } publicfunctiondataProcessing($postDm){ if(!is_array($this->tagNames)||!$this->tagNames)return$postDm; $postDm->setTags(implode(',',$this->tagNames)); return$postDm; } privatefunction_buildTagDm($tid){ if(!is_array($this->tagNames)||!$this->tagNames)returnfalse; $dmArray=array(); foreach($this->tagNamesas$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; } publicfunctioncheck($postDm){ if(!is_array($this->tagNames)||!$this->tagNames)returntrue; $count=count($this->tagNames); foreach($this->tagNamesas$v){ $dm=$this->getDm(); $dm->setName($v); if(($return=$dm->beforeAdd())instanceofPwError)return$return; } if($count>5){ returnnewPwError("Tag:tagnum.exceed"); } if($count&&$this->loginUser->getPermission('tag_allow_add')<1){ returnnewPwError("TAG:right.tag_allow_add.error"); } returntrue; } /** *Enterdescriptionhere... * *@returnPwTagService */ protectedfunction_getService(){ returnWekit::load('tag.srv.PwTagService'); } }  那么 addThread 是在什么时候调用的呢,又是怎样调用的呢 看这里  /** *@seePwPostAction.afterRun */ publicfunctionafterRun(){ $this->runDo('addThread',$this->tid); }  这个类是 PwTopicPost 也正是我们在控制器里面刚刚实例化的 ,我们断点调式下看看   关键在这里  /*(non-PHPdoc) *@seeWindHandlerInterceptor::preHandle() */ publicfunctionpreHandle(){ 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的值是多少呢  
   原来是这个pwPostclassPwPostextendsPwBaseHookService{ public$action; public$forum; public$user; public$special;//帖子类型 publicfunction__construct(PwPostAction$action){ $this->action=$action; $this->forum=$action->forum; $this->user=$action->user; $this->special=$action->getSpecial(); /**hook**/ $this->action->setSrv($this); } /** *发帖之前检测 * *@returnbool */ publicfunctioncheck(){ if(($result=$this->isInit())!==true){ returnnewPwError('data.error'); } if(($result=$this->checkForum())!==true){ return$result; } if(($result=$this->checkPost())!==true){ return$result; } if($this->isBan()){ returnnewPwError('ban'); } if(($result=$this->action->check())!==true){ return$result; } returntrue; } /** *初始化信息是否满足要求 * *@returnbool */ publicfunctionisInit(){ return$this->action->isInit(); } /** *检测是否拥有该版操作权限 * *@returnbool */ publicfunctioncheckForum(){ if(!$this->forum->isForum()){ returnnewPwError('BBS:post.forum.not.exists'); } if(($result=$this->forum->allowVisit($this->user))!==true){ returnnewPwError('BBS:forum.permissions.visit.allow', array('{grouptitle}'=>$this->user->getGroupInfo('name'))); } returntrue; } /** *检测是否允许发帖 * *@returnbool */ publicfunctioncheckPost(){ if($this->user->groupid==7){ returnnewPwError('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'])){ returnnewPwError('BBS:post.timing'); } */ returntrue; } /** *检测用户是否被禁言 * *@returnbool */ publicfunctionisBan(){ if($this->user->gid==6){ Wind::import('SRV:user.srv.PwBanBp'); $banBp=newPwBanBp($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); returnfalse; } returntrue; } returnfalse; } publicfunctiongetDm(){ return$this->action->getDm(); } /** *各应用获取该用户dm来设置,以达到更新用户信息的目的 * *@returnobjectPwUserInfoDm */ publicfunctiongetUserDm(){ return$this->action->getUserDm(); } publicfunctiongetAttachs(){ return$this->action->getAttachs(); } /** *发布 * *@paramobject$postDm帖子数据模型 *@returnbool */ publicfunctionexecute(PwPostDm$postDm){ if(($result=$this->action->beforeRun($postDm))instanceofPwError){ return$result; } if(($result=$this->action->dataProcessing($postDm))!==true){ return$result; } if(($result=$this->action->execute())!==true){ return$result; } $this->action->afterRun(); $this->updateUser(); returntrue; } publicfunctiongetInfo(){ return$this->action->getInfo(); } publicfunctiongetNewId(){ return$this->action->getNewId(); } publicfunctiongetDisabled(){ return$this->action->isDisabled(); } /** *更新用户信息/积分/发帖数/等 */ publicfunctionupdateUser(){ 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); } } publicfunctionappendDo($do){ $this->action->appendDo($do); } publicfunctionrunDo($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'); /** *帖子发布-话题 * *@authorjinlong.panjl<jinlong.panjl@aliyun-inc.com> *@copyright©2003-2103phpwind.com *@licensehttp://www.phpwind.com*@version$Id$ *@packagewind */ classPwReplyDoRemindextendsPwPostDoBase{ private$loginUser; private$_reminds=array(); private$_atc_title; private$_maxNum; publicfunction__construct(PwPost$pwpost){ $this->loginUser=$pwpost->user; $this->_maxNum=$this->loginUser->getPermission('remind_max_num'); } publicfunctionaddPost($pid,$tid){ $this->_addRemind($pid,$tid); } publicfunctionupdatePost($pid,$tid){ $this->_addRemind($pid,$tid); } publicfunctiondataProcessing($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; } privatefunction_addRemind($pid,$tid){ if($this->_check()!==true)returnfalse; if(!$this->_reminds)returnfalse; $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'=>'在回帖<ahref="'.WindUrlHelper::createUrl('bbs/read/run',array('tid'=>$tid),$pid).'"target="_blank">'.$this->_atc_title.'</a>@了您', ); //是否黑名单 $remindUids=$this->_checkBlack($remindUids); foreach($remindUidsas$uid){ $this->_getPwNoticeService()->sendNotice($uid,'remind',$pid,$extendParams); } } privatefunction_check(){ if($this->loginUser->getPermission('remind_open')<1){ returnnewPwError("bbs:remind.remind_open.error"); } returntrue; } /** *是否开启权限 * *@paramarray$remindUids *@returnbool */ privatefunction_checkBlack($remindUids){ $result=Wekit::load('user.PwUserBlack')->checkUserBlack($this->loginUser->uid,$remindUids); if($result){ $remindUids=array_diff($remindUids,$result); } return$remindUids; } /** *@returnPwNoticeService */ protectedfunction_getPwNoticeService(){ returnWekit::load('message.srv.PwNoticeService'); } /** *PwRemindService * *@returnPwRemindService */ privatefunction_getRemindService(){ returnWekit::load('remind.srv.PwRemindService'); } }  不同的类有不同的方法,可能就是调用时机不同,责任不同,总之就比较复杂    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: