mediawiki1.24源码分析(一)_PHP_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > PHP > mediawiki1.24源码分析(一)

mediawiki1.24源码分析(一)

 2015/4/1 17:34:23  qepwqnp  程序员俱乐部  我要评论(0)
  • 摘要:所有分析说明采用文字使用浅红色、小四号楷体。Index.php//mediawiki程序入口ThisisthemainwebentrypointforMediaWiki.现在开始看程序的第一句代码,判断PHP版本是否是5.3.2及以上,如果不是就在页面报错提示。Php代码if(!function_exists('version_compare')||version_compare(PHP_VERSION,'5.3.2')<0){//Weneedtousedirname(__FILE__
  • 标签:源码 分析

class="MsoNormal">所有分析说明采用文字使用浅红色、小四号楷体。

Index.php

//mediawiki程序入口

This?is?the?main?web?entry?point?for?MediaWiki.?

现在开始看程序的第一句代码,判断PHP版本是否是5.3.2及以上,如果不是就在页面报错提示。

?

Php代码?
  1. if?(?!function_exists(?'version_compare'?)?||?version_compare(?PHP_VERSION,?'5.3.2'?)?<?0?)?{??
  2. //?We?need?to?use?dirname(?__FILE__?)?here?cause?__DIR__?is?PHP5.3+??
  3. require?dirname(?__FILE__?)?.?'/includes/PHPVersionError.php';??
  4. wfPHPVersionError(?'index.php'?);??
  5. }??

?

?

接下来是比较关键的代码了,引入一个PHP文件?Webstart.php。

?

Php代码?
  1. require?__DIR__?.?'/includes/WebStart.php';??

?

?

Webstart.php

?*?This?does?the?initial?set?up?for?a?web?request.

?*?It?does?some?security?checks,?starts?the?profiler?and?loads?the

?*?configuration,?and?optionally?loads?Setup.php?depending?on?whether

?*?MW_NO_SETUP?is?defined.

?*?Setup.php?(if?loaded)?then?sets?up?GlobalFunctions,?the?AutoLoader,

?*?and?the?configuration?globals?(though?not?$wgTitle).

?

WebStart.php的文件注解部分如上,大概说此文件执行的操作是为一个Web请求进行初始化设置:进行安全检查、调试开启、装载配置文件里的全局变量及常量。最后如果没有安装过mediawiki则调用setup.php执行安装mediawiki操作。这个文件中调用了Defines.php(常量)、LocalSettings.php(配置文件,全局变量),另外还在这里根据配置开启字符缓冲区,回调方法是OutputHandler.php的wfOutputHandler方法。?

?

?

?

Php代码?
  1. if?(?ini_get(?'register_globals'?)?)?{??
  2. die(?'MediaWiki?does?not?support?installations?where?register_globals?is?enabled.?'??
  3. .?'Please?see?<a?href="https://www.mediawiki.org/wiki/register_globals">mediawiki.org</a>?'??
  4. .?'for?help?on?how?to?disable?it.'?);??
  5. }??

?

?

如果PHP配置项register_globals是打开状态(ON),则mediawiki无法运行。

?

#?bug?15461:?Make?IE8?turn?off?content?sniffing.?Everybody?else?should?ignore?this

#?We're?adding?it?here?so?that?it's?*always*?set,?even?for?alternate?entry

#?points?and?when?$wgOut?gets?disabled?or?overridden.

?

Php代码?
  1. header(?'X-Content-Type-Options:?nosniff'?);??

?

?

针对IE8进行关闭内容嗅探,大家应该应该忽略这个

?

?

Php代码?
  1. $wgRequestTime?=?microtime(?true?);??

?

?

?函数返回当前?Unix?时间戳和微秒数。

?

Php代码?
  1. unset(?$IP?);??

?

?

注销定义$IP的变量

?

Php代码?
  1. define(?'MEDIAWIKI',?true?);??

?

?

定义一个常量mediawiki

#?Full?path?to?working?directory.

#?Makes?it?possible?to?for?example?to?have?effective?exclude?path?in?apc.

#?__DIR__?breaks?symlinked?includes,?but?realpath()?returns?false

#?if?we?don't?have?permissions?on?parent?directories.

?

Php代码?
  1. $IP?=?getenv(?'MW_INSTALL_PATH'?);??
  2. if?(?$IP?===?false?)?{??
  3. $IP?=?realpath(?'.'?)??:?dirname(?__DIR__?);??
  4. }??

?

?

通过获取PHP的环境变量,获取安装的安装目录。

?

#?Load?the?profiler

?

Php代码?
  1. require_once?"$IP/includes/profiler/Profiler.php";??
  2. $wgRUstart?=?wfGetRusage()??:?array();??

?

?

...

#?Start?the?profiler

//StartProfiler.php文件里只调用了ProfilerStub.php。根据上下文来看ProfilerStub.php里定义的两个主要的函数wfProfileIn()、wfProfileOut()应该是做Debug用的。

?

Php代码?
  1. $wgProfiler?=?array();??
  2. if?(?file_exists(?"$IP/StartProfiler.php"?)?)?{??
  3. require?"$IP/StartProfiler.php";??
  4. }??
  5. ...??
  6. if?(?!defined(?'MW_NO_SETUP'?)?)?{??
  7. require_once?"$IP/includes/Setup.php";??
  8. }??

?

?

?

require_once了一大堆文件:Profiler.php(分析其,主要用于DEBUG调试使用)、AutoLoader.php(类管理器,类似JAVA中SPRING的IOC容器)、Defines.php、StartProfiler.php、DefaultSettings.php、autoload.php、NoLocalSettings.php、OutputHandler.php、Setup.php……

?

接下来到了程序业务处理入口:?

?

Php代码?
  1. $mediaWiki?=?new?MediaWiki();??
  2. $mediaWiki->run();??

?

?

Mediawiki.php

?

?mediawiki.php里定义了MediaWiki类。其中包括很多的wiki对象的方法。接着为$mediaWiki对象开辟内存空间。

?

Php代码?
  1. public?function?__construct(?IContextSource?$context?=?null?)?{??
  2. if?(?!$context?)?{??
  3. $context?=?RequestContext::getMain();??
  4. }??
  5. ???
  6. $this->context?=?$context;??
  7. $this->config?=?$context->getConfig();??
  8. }??

?

?

通过构造方法,获取request请求对象、配置信息。

?

Php代码?
  1. public?function?run()?{??
  2. try?{??
  3. //请求中如果包含延迟请求,和系统最后一次操作时间对比。如果最后一次操作时间大于请求最大延迟,则提示超时??
  4. $this->checkMaxLag();??
  5. try?{??
  6. //关键方法,主要做业务流转相关操作。??
  7. $this->main();??
  8. }?catch?(?ErrorPageError?$e?)?{??
  9. //?Bug?62091:?while?exceptions?are?convenient?to?bubble?up?GUI?errors,??
  10. //?they?are?not?internal?application?faults.?As?with?normal?requests,?this??
  11. //?should?commit,?print?the?output,?do?deferred?updates,?jobs,?and?profiling.??
  12. wfGetLBFactory()->commitMasterChanges();??
  13. $e->report();?//?display?the?GUI?error??
  14. }??
  15. if?(?function_exists(?'fastcgi_finish_request'?)?)?{??
  16. fastcgi_finish_request();??
  17. }??
  18. $this->triggerJobs();??
  19. $this->restInPeace();??
  20. }?catch?(?Exception?$e?)?{??
  21. MWExceptionHandler::handle(?$e?);??
  22. }??
  23. }??
  24. 现在进入关键方法main()方法??
  25. //?Send?Ajax?requests?to?the?Ajax?dispatcher.??
  26. if?(?$this->config->get(?'UseAjax'?)?&&?$request->getVal(?'action',?'view'?)?==?'ajax'?)?{??
  27. ???
  28. //?Set?a?dummy?title,?because?$wgTitle?==?null?might?break?things??
  29. $title?=?Title::makeTitle(?NS_MAIN,?'AJAX'?);??
  30. $this->context->setTitle(?$title?);??
  31. $wgTitle?=?$title;??
  32. ???
  33. $dispatcher?=?new?AjaxDispatcher(?$this->config?);??
  34. $dispatcher->performAction(?$this->context->getUser()?);??
  35. wfProfileOut(?__METHOD__?);??
  36. return;??
  37. }??

?

判断是否启用AJAX请求,并且请求中$action值为ajax,则将Ajax请求发送到Ajax?dispather处理器

If?the?user?has?forceHTTPS?set?to?true,?or?if?the?user

//?is?in?a?group?requiring?HTTPS,?or?if?they?have?the?HTTPS

//?preference?set,?redirect?them?to?HTTPS.

//?Note:?Do?this?after?$wgTitle?is?setup,?otherwise?the?hooks?run?from

//?isLoggedIn()?will?do?all?sorts?of?weird?stuff.

Php代码?
  1. if?(??
  2. $request->getProtocol()?==?'http'?&&??
  3. (??
  4. ...??
  5. wfProfileOut(?__METHOD__?);??
  6. return;??
  7. }??
  8. }??

?

如果forcehttps设置为true,并且使用https访问,进行重定项处理

?

Php代码?
  1. if?(?$this->config->get(?'UseFileCache'?)?&&?$title->getNamespace()?>=?0?)?{??
  2. wfProfileIn(?'main-try-filecache'?);??
  3. ...??
  4. wfProfileOut(?'main-try-filecache'?);??
  5. }??

?

判断配置是否开启文件缓存功能,并且命名空间大于等于1的情况,使用文件缓存机制相关功能

?

命名空间值

命名空间值含义

-1

Special:????????

0

Template:???????

1

Talk:???????????

2

User:???????????

3

User_talk:??????

4

Test:???????????

5

Test_talk:??????

6

Image:??????????

7

Image_talk:?????

8

MediaWiki:??????

9

MediaWiki_talk:?

10

Template:???????

11

Template_talk:??

12

Help:???????????

13

Help_talk:??????

14

Category:???????

15

Category_talk:??

16

ONLINEPAY

?

//?Actually?do?the?work?of?the?request?and?build?up?any?output

Php代码?
  1. $this->performRequest();??

?

处理请求的工作和建立输出。在此方法会生程一个输出对象$output,此对象有相应方法可以设置不同的输出结果。

Php代码?
  1. wfProfileIn(?__METHOD__?);??

?

方法第一句,发现mediawiki中基本方法入口都要这么一句,他的后面出现wfProfileOut(?__METHOD__?)跟踪发现为启动DEBUG模式后,进行相应数据的打印。开启打印方法LocationSettings.php里设置$wgDebugLogFile=d:\a.txt值。注意:wfProfileIn和wfProfileOut需要成对出现,否则会出错。而且调试信息的输出顺序是:先输出已经匹配好了的一对wfProfileIn和wfProfileOut的调试信息,也即遇到wfProfileOut时才输出该段调试信息,而不是wfProfileIn。。?

Php代码?
  1. if?(?$request->getVal(?'printable'?)?===?'yes'?)?{??
  2. $output->setPrintable();??
  3. }??

?

判断请求是否有打印请求。如果有就在输出对象中进行标注。

Php代码?
  1. $unused?=?null;?//?To?pass?it?by?reference??
  2. wfRunHooks(?'BeforeInitialize',?array(?&$title,?&$unused,?&$output,?&$user,?$request,?$this?)?);??

?

通过请求对象,进行初始化之前的检查工作。这个属于系统钩子程序,应该需要插件进行实现BeforeInitialize方法,我全文搜索没有此方法的具体实用。

//?Check?user's?permissions?to?read?this?page.

//?We?have?to?check?here?to?catch?special?pages?etc.

//?We?will?check?again?in?Article::view().

Php代码?
  1. $permErrors?=?$title->isSpecial(?'RunJobs'?)??
  2. ??array()?//?relies?on?HMAC?key?signature?alone??
  3. :?$title->getUserPermissionsErrors(?'read',?$user?);??
  4. if?(?count(?$permErrors?)?)?{??

?

根据title进行判断用户是否有次页面的访问read权限。如果权限不足构造项页面进行返回。

?

?

//?Either?all?DB?and?deferred?updates?should?happen?or?none.

//?The?later?should?not?be?cancelled?due?to?client?disconnect.

Php代码?
  1. ignore_user_abort(?true?);??

?

PHP提供的函数,如果设置为?true,则忽略与用户的断开。PHP?不会检测到用户是否已断开连接,直到尝试向客户机发送信息为止。

//?Now?commit?any?transactions,?so?that?unreported?errors?after

//?output()?don't?roll?back?the?whole?DB?transaction

Php代码?
  1. wfGetLBFactory()->commitMasterChanges();??

?

事物提交,存在错误进行回滚。

//?Output?everything!

Php代码?
  1. $this->context->getOutput()->output();??

?

页面输出到前台页面,在此句之前所有数据不携带样式。词句代码执行会按返回数据类型进行添加不同的skin。

Php代码?
  1. wfProfileOut(?__METHOD__?); ?
发表评论
用户名: 匿名