捣蛋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');
}
} 不同的类有不同的方法,可能就是调用时机不同,责任不同,总之就比较复杂
它的父类是什么玩意
相关文章推荐
- PHP命名空间(namespace)的使用详解
- PHP中一个好用的函数parse_url
- yii2 migrate 数据库迁移
- WordPress中用于创建以及获取侧边栏的PHP函数讲解
- rhel6配置vsftpd(debian8很简单)
- yii简单的单表查询
- php通过curl下载远程图片实例
- ATPCS, AAPCS
- ftp文件下载
- PHP正则验证类
- 【PHP入门篇】 WAMPServer集成环境安装与使用--慕课网【学习总结】
- php当前使用的ini配置文件
- PHP添加文本编辑器nicEditor
- PHP 性能分析第三篇: 性能调优实战
- Js实现类似PHP中的in_array方法
- 让你的PHP也能执行JS并获得JS函数的返回值
- YII CDbCriteria 的一些常用方法记录
- PHP获取浏览器版本号
- PHP 获取页面地址参数详解整理
- PHP获取优酷视频FLV地址