古怪猴子规律:WordPress插件機制實現原理

独家真实传授pt古怪猴子玩法规律 www.cfrtc.icu 一直對軟件的組件、插件架構非常感興趣,我認為現在開發任何應用程序,一定要有一個架構良好的插件機制,這樣可以吸引其他人來開發插件,極大的擴充 系統的功能。Eclipse就是一個非常棒…

一直對軟件的組件、插件架構非常感興趣,我認為現在開發任何應用程序,一定要有一個架構良好的插件機制,這樣可以吸引其他人來開發插件,極大的擴充 系統的功能。Eclipse就是一個非常棒的例子,幾乎你想什么功能,都可以從社區中找到相應的第三方插件。Firefox也同樣如此,它的插件機制非常 靈活(尤其是相對IE而言),因此Firefox社區中可以找到各種各樣的插件。

1)WordPress讀取所有可用的插件

在文件”/wp-admin/includes/plugin.php”中,函數 get_plugins() 用來從文件系統得到所有的插件。原理很簡單,就是讀取”wp-content/plugins”目錄下的所有PHP文件。這個函數允許一級的子文件夾,也 就是說在’wp-content/plugins’下面的PHP文件,以及所以在此目錄下的一級子文件夾內部的PHP文件被列作插件的候選,用下面的函數 去進一步提取插件信息。這樣的好處是方便用戶利用文件夾來對插件進行管理和組織。而函數 get_plugin_data() 則用來得到插件的描述(Plugin Descriptor),主要包括插件的版本、名稱、作者,等信息,而這些其實是以注釋的方式存在的。用WordPress中自帶的Hello插件來舉 例:

01 <?php
02 /*
03     Plugin Name: Hello Dolly
04     Plugin URI: //wordpress.org/#
05     Description: This is not just a plugin, it symbolizes the hope and enthusiasm of an entire generation summed up in two words sung most famously by Louis Armstrong: Hello, Dolly. When activated you will randomly see a lyric from <cite>Hello, Dolly</cite> in the upper right of your admin screen on every page.
06     Author: Matt Mullenweg
07     Version: 1.5
08     Author URI: //ma.tt/
09 */
10 ?>

這樣,在get_plugin_data函數中,就可以來得到插件的詳細信息。

01 <?php
02 function get_plugin_data( $plugin_file ) {
03     $plugin_data = implode( '', file( $plugin_file ));
04     preg_match( '|Plugin Name:(.*)$|mi'$plugin_data$plugin_name );
05     preg_match( '|Plugin URI:(.*)$|mi'$plugin_data$plugin_uri );
06     preg_match( '|Description:(.*)$|mi'$plugin_data$description );
07     preg_match( '|Author:(.*)$|mi'$plugin_data$author_name );
08     preg_match( '|Author URI:(.*)$|mi'$plugin_data$author_uri );
09     if ( preg_match( "|Version:(.*)|i"$plugin_data$version ))
10         $version = trim( $version[1] );
11     else
12         $version '';
13     $description = wptexturize( trim( $description[1] ));
14     $name $plugin_name[1];
15     $name = trim( $name );
16     $plugin $name;
17     if (" != trim($plugin_uri[1]) && " != $name ) {
18         $plugin '<a href="' . trim( $plugin_uri[1] ) . '" title="'.__('Visit plugin homepage' ).'">'.$plugin.'</a>';
19     }
20     if ('' == $author_uri[1] ) {
21         $author = trim( $author_name[1] );
22     else {
23         $author '<a href="' . trim( $author_uri[1] ) . '" title="'.__('Visit author homepage' ).'">' . trim( $author_name[1] ) . '</a>';
24     }
25     return array('Name' => $name'Title' => $plugin'Description' =>$description'Author' => $author'Version' => $version);
26 }
27 ?>

2)啟用 & 禁用插件

啟用(禁用)插件的操作都在Plugins.php中,比如我要Deactive “Hello”這個插件,最后的URL其實是這個樣子:

//localhost/blog/wp-admin/plugins.php?action=deactivate&plugin=hello.php

其中,”Action”表示動作,值為”active”或者”deactivate”,而”Plugin”表示動作的對象插件,此處為”hello.php”。得到動作指令后,首先 從數據庫中取出當前已經激活的插件。

1 <?php $current = get_settings('active_plugins'); ?>

然后根據動作,重新生成已激活插件數組,存入數據庫,并重新加載此頁。加載的時候就需要考慮這些已經激活的插件是怎么工作的了。
BTW:附上數據庫的Options表中0插件和只有1個插件的值:
沒有插件:

1 a:1:{i:0;s:0:"";}

只有Hello插件:

1 a:2:{i:0;s:0:"";i:1;s:9:"hello.php";}

3)如何加載啟用的插件到系統中

WordPress中的每頁都會包含”wp-config.php”文件,而”wp-config.php”中也會自動加載”wp- settings.php”文件。在”wp-settings.php”文件中,可以找到以下與插件相關的代碼片斷:

01 <?php
02 if ( get_option('active_plugins') ) {
03     $current_plugins = get_option('active_plugins');
04     if is_array($current_plugins) ) {
05         foreach ($current_plugins as $plugin) {
06             if '' != $plugin && 0 == validate_file($plugin) &&file_exists(WP_PLUGIN_DIR . '/' $plugin) )
07                 include_once(WP_PLUGIN_DIR . '/' $plugin);
08         }
09     }
10 }
11 ?>

可見,這段代碼會取出系統中所有啟用的插件,并包含進來。所以在每頁加載的時候,都會首先包含這些插件代碼。那么,這些插件自己在加載的時候都做了 什么呢?

4)插件的加載

插件的加載其實最重要的一個部分就是插件的事件注冊機制,WordPress插件中的事件注冊其實和Eclipse中的擴展點 (Extension-Point)機制非常相像,而這種類似”插銷”、”插銷座”的軟件插拔方式也成為了最近軟件組件架構方面應用最多的實踐。
事件注冊過程中比較重要的幾個函數分別是:do_action、add_action、add_filter。WordPress中默認定義了很多擴 展點(也可以叫做”鉤子”),或者說注冊了很多系統事件(WP中的正規叫法應該是”Action Tag”),比如”admin_head”表示Admin頁面的Head輸出事件,”publish_post”表示發布一篇帖子的事件等等。而插件要做 的就是擴展這些擴展點,或者說掛接這些鉤子,從而實現系統的擴展功能。add_action就是通常插件擴展某個擴展點用到的函數,而do_action 是擴展點本身開始執行的函數。
剛才說過WordPress中的每一頁執行前都會Include所有Active的插件代碼,而這些代碼通常都會用”add_action”來將自己 的函數注冊到系統的擴展點中。這樣,在擴展點執行的時候,就會找到系統中所有已經掛接到這個擴展點上的插件的函數來執行之,從而擴充系統的功能。
WordPress中的很多功能也都是通過這種插件結構來實現的,默認注冊了很多系統事件,都在’default-filter.php’中。比如:

1 <?php add_action('publish_post''generic_ping'); ?>

這個是用來在發布每篇帖子的時候發送XML-RPC Ping的。再比如:

1 <?php add_filter('the_content''convert_smilies'); ?>

用來將正文(content)中的笑臉符號轉換為圖像。
還是舉”Hello”插件來說。Hello插件會隨機的在Admin Page的右上角顯示一段話,它的工作原理是這樣的:
在每一個Admin page的前面都有

1 <?php require_once('admin-header.php'); ?>

而在”admin-head.php”中將會執行擴展點”admin-head”的所有擴展:

1 <?php do_action('admin_head', "); ?>

這樣,就會執行所有掛接到admin_head的函數,Admin Page 的 Footer 部分也是類似。

5)如果插件中涉及UI

其實是一樣的。以WordPress FeedBurner Plugin中添加菜單為例。
如果想添加一個菜單,就需要注冊”admin_menu”這個Action Tag(系統事件)即可:

1 <?php add_action('admin_menu''ol_add_feedburner_options_page'); ?>

插件中的這個函數為:

1 <?php
2 function ol_add_feedburner_options_page() {
3     if (function_exists('add_options_page')) {
4         add_options_page('FeedBurner''FeedBurner', 8, basename(__FILE__),'ol_feedburner_options_subpanel');
5     }
6 }
7 ?>

“add_options_page”這個函數就會在系統的”Options”菜單中添加”FeedBurner”這樣一個子菜單。

6)其它

還有一些簡單的插件就是只提供一些API函數。比如Most_Commented Plugin,它提供一個API “mdv_most_commented”:通過數據庫查詢得到評論最多的文章,并加以顯示。因為這個插件已經被Include過,所以可以用這個API 來進行顯示。

?轉載自://www.helloyi.cn/index.php/2010/02/09/wordpress-plugin/

為您推薦

返回頂部