论坛凯发k8国际首页 编程语言技术论坛

mediawiki1.24源码分析(一) -凯发k8国际

浏览 2873 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2015-04-01  
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 mediawiki.org '  
  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 不会检测到用户是否已断开连接

 
global site tag (gtag.js) - google analytics
网站地图