解析 WordPress 插件机制
1)WordPress讀取所有可用的插件
在文件“/wp-admin/includes/plugin.php”中,函數(shù) get_plugins() 用來從文件系統(tǒng)得到所有的插件。原理很簡(jiǎn)單,就是讀取“wp-content/plugins”目錄下的所有PHP文件。這個(gè)函數(shù)允許一級(jí)的子文件夾,也 就是說在’wp-content/plugins’下面的PHP文件,以及所以在此目錄下的一級(jí)子文件夾內(nèi)部的PHP文件被列作插件的候選,用下面的函數(shù) 去進(jìn)一步提取插件信息。這樣的好處是方便用戶利用文件夾來對(duì)插件進(jìn)行管理和組織。
而函數(shù) get_plugin_data() 則用來得到插件的描述(Plugin Descriptor),主要包括插件的版本、名稱、作者,等信息,而這些其實(shí)是以注釋的方式存在的。用WordPress中自帶的Hello插件來舉例:
/*
Plugin Name: Hello Dolly
Plugin URI: http://wordpress.org/#
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.
Author: Matt Mullenweg
Version: 1.5
Author URI: http://ma.tt/
*/
?>
這樣,在get_plugin_data函數(shù)中,就可以來得到插件的詳細(xì)信息。
<?phpfunction get_plugin_data( $plugin_file ) {
?? ?$plugin_data = implode( '', file( $plugin_file ));
?? ?preg_match( '|Plugin Name:(.*)$|mi', $plugin_data, $plugin_name );
?? ?preg_match( '|Plugin URI:(.*)$|mi', $plugin_data, $plugin_uri );
?? ?preg_match( '|Description:(.*)$|mi', $plugin_data, $description );
?? ?preg_match( '|Author:(.*)$|mi', $plugin_data, $author_name );
?? ?preg_match( '|Author URI:(.*)$|mi', $plugin_data, $author_uri );
?
?? ?if ( preg_match( "|Version:(.*)|i", $plugin_data, $version ))
?? ? ? ?$version = trim( $version[1] );
?? ?else
?? ? ? ?$version = '';
?
?? ?$description = wptexturize( trim( $description[1] ));
?
?? ?$name = $plugin_name[1];
?? ?$name = trim( $name );
?? ?$plugin = $name;
?? ?if ('' != trim($plugin_uri[1]) && '' != $name ) {
?? ? ? ?$plugin = '<a href="' . trim( $plugin_uri[1] ) . '" title="'.__( 'Visit plugin homepage' ).'">'.$plugin.'</a>';
?? ?}
?
?? ?if ('' == $author_uri[1] ) {
?? ? ? ?$author = trim( $author_name[1] );
?? ?} else {
?? ? ? ?$author = '<a href="' . trim( $author_uri[1] ) . '" title="'.__( 'Visit author homepage' ).'">' . trim( $author_name[1] ) . '</a>';
?? ?}
?
?? ?return array('Name' => $name, 'Title' => $plugin, 'Description' => $description, 'Author' => $author, 'Version' => $version);
}
?>
2)啟用 & 禁用插件
啟用(禁用)插件的操作都在Plugins.php中,比如我要Deactive “Hello”這個(gè)插件,最后的URL其實(shí)是這個(gè)樣子:
http://localhost/blog/wp-admin/plugins.php?action=deactivate&plugin=hello.php其中,“Action”表示動(dòng)作,值為“active”或者“deactivate”,而“Plugin”表示動(dòng)作的對(duì)象插件,此處為“hello.php”。得到動(dòng)作指令后,首先從數(shù)據(jù)庫(kù)中取出當(dāng)前已經(jīng)激活的插件。
<?php $current = get_settings('active_plugins'); ?> 然后根據(jù)動(dòng)作,重新生成已激活插件數(shù)組,存入數(shù)據(jù)庫(kù),并重新加載此頁。加載的時(shí)候就需要考慮這些已經(jīng)激活的插件是怎么工作的了。
BTW:附上數(shù)據(jù)庫(kù)的Options表中0插件和只有1個(gè)插件的值:
沒有插件:
只有Hello插件:
a:2:{i:0;s:0:"";i:1;s:9:"hello.php";}3)如何加載啟用的插件到系統(tǒng)中
WordPress中的每頁都會(huì)包含“wp-config.php”文件,而“wp-config.php”中也會(huì)自動(dòng)加載“wp-settings.php”文件。在“wp-settings.php”文件中,可以找到以下與插件相關(guān)的代碼片斷:
<?phpif ( get_option('active_plugins') ) {
?? ?$current_plugins = get_option('active_plugins');
?? ?if ( is_array($current_plugins) ) {
?? ? ? ?foreach ($current_plugins as $plugin) {
?? ? ? ? ? ?if ( '' != $plugin && 0 == validate_file($plugin) && file_exists(WP_PLUGIN_DIR . '/' . $plugin) )
?? ? ? ? ? ? ? ?include_once(WP_PLUGIN_DIR . '/' . $plugin);
?? ? ? ?}
?? ?}
}
?>
可見,這段代碼會(huì)取出系統(tǒng)中所有啟用的插件,并包含進(jìn)來。所以在每頁加載的時(shí)候,都會(huì)首先包含這些插件代碼。那么,這些插件自己在加載的時(shí)候都做了什么呢?
4)插件的加載
插件的加載其實(shí)最重要的一個(gè)部分就是插件的事件注冊(cè)機(jī)制,WordPress插件中的事件注冊(cè)其實(shí)和Eclipse中的擴(kuò)展點(diǎn) (Extension-Point)機(jī)制非常相像,而這種類似“插銷”、“插銷座”的軟件插拔方式也成為了最近軟件組件架構(gòu)方面應(yīng)用最多的實(shí)踐。
事件注冊(cè)過程中比較重要的幾個(gè)函數(shù)分別是:do_action、add_action、add_filter。WordPress中默認(rèn)定義了很多擴(kuò) 展點(diǎn)(也可以叫做“鉤子”),或者說注冊(cè)了很多系統(tǒng)事件(WP中的正規(guī)叫法應(yīng)該是“Action Tag”),比如“admin_head”表示Admin頁面的Head輸出事件,“publish_post”表示發(fā)布一篇帖子的事件等等。而插件要做 的就是擴(kuò)展這些擴(kuò)展點(diǎn),或者說掛接這些鉤子,從而實(shí)現(xiàn)系統(tǒng)的擴(kuò)展功能。add_action就是通常插件擴(kuò)展某個(gè)擴(kuò)展點(diǎn)用到的函數(shù),而do_action 是擴(kuò)展點(diǎn)本身開始執(zhí)行的函數(shù)。
剛才說過WordPress中的每一頁執(zhí)行前都會(huì)Include所有Active的插件代碼,而這些代碼通常都會(huì)用“add_action”來將自己 的函數(shù)注冊(cè)到系統(tǒng)的擴(kuò)展點(diǎn)中。這樣,在擴(kuò)展點(diǎn)執(zhí)行的時(shí)候,就會(huì)找到系統(tǒng)中所有已經(jīng)掛接到這個(gè)擴(kuò)展點(diǎn)上的插件的函數(shù)來執(zhí)行之,從而擴(kuò)充系統(tǒng)的功能。
WordPress中的很多功能也都是通過這種插件結(jié)構(gòu)來實(shí)現(xiàn)的,默認(rèn)注冊(cè)了很多系統(tǒng)事件,都在’default-filter.php’中。比如:
這個(gè)是用來在發(fā)布每篇帖子的時(shí)候發(fā)送XML-RPC Ping的。再比如:
<?php add_filter('the_content', 'convert_smilies'); ?>用來將正文(content)中的笑臉符號(hào)轉(zhuǎn)換為圖像。
還是舉“Hello”插件來說。Hello插件會(huì)隨機(jī)的在Admin Page的右上角顯示一段話,它的工作原理是這樣的:
在每一個(gè)Admin page的前面都有
而在“admin-head.php”中將會(huì)執(zhí)行擴(kuò)展點(diǎn)“admin-head”的所有擴(kuò)展:
<?php do_action('admin_head', ''); ?>這樣,就會(huì)執(zhí)行所有掛接到admin_head的函數(shù),Admin Page 的 Footer 部分也是類似。
5)如果插件中涉及UI
其實(shí)是一樣的。以WordPress FeedBurner Plugin中添加菜單為例。
如果想添加一個(gè)菜單,就需要注冊(cè)“admin_menu”這個(gè)Action Tag(系統(tǒng)事件)即可:
插件中的這個(gè)函數(shù)為:
<?phpfunction ol_add_feedburner_options_page() {
?? ?if (function_exists('add_options_page')) {
?? ? ? ?add_options_page('FeedBurner', 'FeedBurner', 8, basename(__FILE__), 'ol_feedburner_options_subpanel');
?? ?}
}
?>
“add_options_page”這個(gè)函數(shù)就會(huì)在系統(tǒng)的“Options”菜單中添加“FeedBurner”這樣一個(gè)子菜單。
6)其它
還有一些簡(jiǎn)單的插件就是只提供一些API函數(shù)。比如Most_Commented Plugin,它提供一個(gè)API “mdv_most_commented”:通過數(shù)據(jù)庫(kù)查詢得到評(píng)論最多的文章,并加以顯示。因?yàn)檫@個(gè)插件已經(jīng)被Include過,所以可以用這個(gè)API 來進(jìn)行顯示。
轉(zhuǎn)載于:https://www.cnblogs.com/vicenteforever/articles/1867214.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的解析 WordPress 插件机制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: a programmer should
- 下一篇: 小心多任务设计被滥用