wordpress用上静态缓存插件cos html cache,会让你的wordpress健步如飞,下面就对这款缓存插件的源码进行解读一番,文章转自:http://mosir.org/html/y2012/review-the-source-of-cos-html-cache.html
/* config */ // 是否创建首页的静态文件 define('IS_INDEX',true);// false = do not create home page cache /*end of config*/ define('COSVERSION','2.7.3'); // 定义插件版本 // 引入wp的文件操作函数,后面将用到其中的get_home_path require_once(ABSPATH . 'wp-admin/includes/file.php'); /* end of config */ $sm_locale = get_locale(); // 获取语言环境方便后面的本地化处理 // 得到语言环境对应的本地化翻译文件,当然现在只有中文的cosbeta-zh_CN.mo $sm_mofile = dirname(__FILE__) . "/cosbeta-$sm_locale.mo"; // 加载本地化的翻译(http://codex.wordpress.org/Function_Reference/load_textdomain) load_textdomain('cosbeta', $sm_mofile); // 得到博客网站的url (http://codex.wordpress.org/Option_Reference) $cossithome = get_option('home'); // 获取调用链接的完整url $script_uri = rtrim( "http://".$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"] ,"/"); $home_path = get_home_path(); // 得到wp所安装的绝对物理目录 define('SCRIPT_URI',$script_uri); // 定义调用链接 define('CosSiteHome',$cossithome); // 定义网站url define('CosBlogPath', $home_path); // 定义网站安装物理位置 // 定义插件生效标记 define("COSMETA","<!--this is a real static html file created at ".date("Y-m-d H:i:s"). " by cos-html-cache ".COSVERSION." -->"); // 创建静态文件的函数 function CreateHtmlFile($FilePath,$Content){ // 去掉文件名中的一些非法符号 $FilePath = preg_replace('/[ <>\'\"\r\n\t\(\)]/', '', $FilePath); // if there is http:// $FilePath will return its bas path // 分隔文件路径,比如/home/xxx/xxx/xxx/xxx.html, // 如果是类似http://xxx.com/html/y2012/xxx.html,将传入/html/y2012/xxx.html // (http://cn2.php.net/manual/zh/function.explode.php) $dir_array = explode("/",$FilePath); //split the FilePath $max_index = count($dir_array) ; $i = 0; $path = $_SERVER['DOCUMENT_ROOT']."/"; // 获取网站的根目录,比如/home/username/ while( $i < $max_index ){ $path .= "/".$dir_array[$i]; // 把子目录一级一级加到路径上 $path = str_replace("//","/",$path); // 如果有//则替换成/ if( $dir_array[$i] == "" ){ // 如果这目录值为空则跳过去,这个判断放在循环的最前面可能更合适 $i ++ ; continue; } // 上面的代码似乎可以写得更精练 if( substr_count($path, '&') ) return true; // 如果路径中有&符号,这不好处理,不管了 if( substr_count($path, '?') ) return true; // 有?也不管了 if( !substr_count($path, '.htm') ){ // 如果不包含.htm,原来传了个路径进来 //if is a directory // 如果路径不存在,贱之,并赋读写运行权,如果存在,那八成也是这里贱的 if( !file_exists( $path ) ){ @mkdir( $path, 0777); @chmod( $path, 0777 ); } } $i ++; // 这个搞完,继续 } if( is_dir( $path ) ){ // 如果上面折腾完后,发现是个目录,那就是说要创建index.html $path = $path."/index.html"; } // 如果html页面没创建完整,那还是不管算了 if ( !strstr( strtolower($Content), '</html>' ) ) return; //if sql error ignore... $fp = @fopen( $path , "w+" ); // 好了开始写了,文件在就准备覆盖内容,不在就贱之 if( $fp ){ // 说明有权限写 @chmod($path, 0666 ) ; // 给文件先赋个权限 @flock($fp ,LOCK_EX ); // 锁定 // write the file。 fwrite( $fp , $Content );// 写静态文件内容 @flock($fp, LOCK_UN); // 解锁 fclose($fp); // 完事 } } /* read the content from output buffer */ // 在用户登录后,才会有动静,先初始化为不管,这是个非常好的习惯, // 为了安全,一般的看不懂的东西还是躲开算了 $is_buffer = false; // 如果调用的是/year/y2012/xxx.html或访问的url就是网站url if( substr_count($_SERVER['REQUEST_URI'], '.htm') || ( SCRIPT_URI == CosSiteHome) ){ if( strlen( $_COOKIE['wordpress_logged_in_'.COOKIEHASH] ) < 4 ){ // 用户登录了,估计得干活了 $is_buffer = true; } if( substr_count($_SERVER['REQUEST_URI'], '?')) $is_buffer = false; // 参数调用,躲 if( substr_count($_SERVER['REQUEST_URI'], '../')) $is_buffer = false; // 太危险了,还是躲开好了 } if( $is_buffer ){ // 真得得干活了 ob_start('cos_cache_ob_callback'); // 开干 register_shutdown_function('cos_cache_shutdown_callback'); // 高潮并结束,很快的 } function cos_cache_ob_callback($buffer){ // 这里就是就会从wp的输出缓冲拿内容准备写到静态文件中 // 下面一堆正则表达式,不是给一般人看的,我是一般人,所以不看了 // 不过显然是在处理评论相关的信息 $buffer = preg_replace('/(<\s*input[^>]+?(name=["\']author[\'"])[^>]+?value=(["\']))([^"\']+?)\3/i', '\1\3', $buffer); $buffer = preg_replace('/(<\s*input[^>]+?value=)([\'"])[^\'"]+\2([^>]+?name=[\'"]author[\'"])/i', '\1""\3', $buffer); $buffer = preg_replace('/(<\s*input[^>]+?(name=["\']url[\'"])[^>]+?value=(["\']))([^"\']+?)\3/i', '\1\3', $buffer); $buffer = preg_replace('/(<\s*input[^>]+?value=)([\'"])[^\'"]+\2([^>]+?name=[\'"]url[\'"])/i', '\1""\3', $buffer); $buffer = preg_replace('/(<\s*input[^>]+?(name=["\']email[\'"])[^>]+?value=(["\']))([^"\']+?)\3/i', '\1\3', $buffer); $buffer = preg_replace('/(<\s*input[^>]+?value=)([\'"])[^\'"]+\2([^>]+?name=[\'"]email[\'"])/i', '\1""\3', $buffer); // 不是一般人看的东西结束 // 内容里没有插件做的标记,不能管 if( !substr_count($buffer, '<!--cos-html-cache-safe-tag-->') ) return $buffer; // 有密码保护的文章不能管 if( substr_count($buffer, 'post_password') > 0 ) return $buffer;//to check if post password protected $wppasscookie = "wp-postpass_".COOKIEHASH; // 还是不能管 if( strlen( $_COOKIE[$wppasscookie] ) > 0 ) return $buffer;//to check if post password protected /* 这些内容还是放在common.js.php里的,用js去处理吧 $comment_author_url=''; $comment_author_email=''; $comment_author='';*/ elseif( SCRIPT_URI == CosSiteHome) {// creat homepage // 噢,首页,这个得管 $fp = @fopen( CosBlogPath."index.bak" , "w+" ); // 先把内容弄进index.bak里 if( $fp ){ @flock($fp ,LOCK_EX ); // write the file。 fwrite( $fp , $buffer.COSMETA ); // 写,后面再加点标记说明静态文件创建成功 @flock($fp, LOCK_UN); fclose($fp); } if(IS_INDEX) // 如果真得要创建首页静态文件, 就把index.bak改成index.html @rename(CosBlogPath."index.bak",CosBlogPath."index.html"); } else // 其它情况,试着创建静态文件,并在后面加个标记 CreateHtmlFile($_SERVER['REQUEST_URI'],$buffer.COSMETA ); return $buffer; } function cos_cache_shutdown_callback(){ // 把静态文件真得写到物理硬盘上去,高潮过程总是很短 ob_end_flush(); flush(); } if( !function_exists('DelCacheByUrl') ){ function DelCacheByUrl($url) { // 通过url来删静态文件 $url = CosBlogPath.str_replace( CosSiteHome,"",$url ); // 如果是完整url,就把网站给去掉 $url = str_replace("//","/", $url ); // 把所有//替换成/ if( file_exists( $url )){ // 文件存在 // 如果是目录就先删里面的index.html,再删目录 if( is_dir( $url )) {@unlink( $url."/index.html" );@rmdir($url);} else @unlink( $url ); // 否则直接删静态文件 } } } if( !function_exists('htmlCacheDel') ){ // create single html function htmlCacheDel($post_ID) { // 通过文章id来删静态文件 if( $post_ID == "" ) return true; $uri = get_permalink($post_ID); DelCacheByUrl($uri ); } } if( !function_exists('htmlCacheDelNb') ){ // delete nabour posts // 如果把文章删了,那也得把邻居两文章的静态文章同时删除,避免上一篇下一篇出问题 // 不过你看出来了么,对于文章id 大于被删文章的sql语句有点小问题,新版将会解决(2.7.4版中已解决) function htmlCacheDelNb($post_ID) { if( $post_ID == "" ) return true; $uri = get_permalink($post_ID); DelCacheByUrl($uri ); global $wpdb; $postRes=$wpdb->get_results("SELECT `ID` FROM `" . $wpdb->posts . "` WHERE post_status = 'publish' AND post_type='post' AND ID < ".$post_ID." ORDER BY ID DESC LIMIT 0,1;"); $uri1 = get_permalink($postRes[0]->ID); DelCacheByUrl($uri1 ); $postRes=$wpdb->get_results("SELECT `ID` FROM `" . $wpdb->posts . "` WHERE post_status = 'publish' AND post_type='post' AND ID > ".$post_ID." ORDER BY ID DESC LIMIT 0,1;"); if( $postRes[0]->ID != '' ){ $uri2 = get_permalink($postRes[0]->ID); DelCacheByUrl($uri2 ); } } } //create index.html if( !function_exists('createIndexHTML') ){ // 用户编辑、删除、新建了文章,首页就会有变动了, // 所以得把首页静态文件先改个名,免得还是直接访问静态文件,看不到效果 function createIndexHTML($post_ID){ if( $post_ID == "" ) return true; //[menghao]@rename(ABSPATH."index.html",ABSPATH."index.bak"); @rename(CosBlogPath."index.html",CosBlogPath."index.bak");//[menghao] } } if(!function_exists("htmlCacheDel_reg_admin")) { // 把删除静态文件功能加到wp的管理菜单中 /** * Add the options page in the admin menu */ function htmlCacheDel_reg_admin() { if (function_exists('add_options_page')) { add_options_page('html-cache-creator', 'CosHtmlCache',8, basename(__FILE__), 'cosHtmlOption'); //add_options_page($page_title, $menu_title, $access_level, $file). } } } add_action('admin_menu', 'htmlCacheDel_reg_admin'); if(!function_exists("cosHtmlOption")) { // 这就是wp里cos-html-cache选项功能 function cosHtmlOption(){ do_cos_html_cache_action(); ?> <div class="wrap" style="padding:10px 0 0 10px;text-align:left"> <form method="post" action="<?php echo $_SERVER["REQUEST_URI"]; ?>"> <p> <?php _e("Click the button bellow to delete all the html cache files","cosbeta");?></p> <p><?php _e("Note:this will Not delete data from your databases","cosbeta");?></p> <p><?php _e("If you want to rebuild all cache files, you should delete them first,and then the cache files will be built when post or page first visited","cosbeta");?></p> <p><b><?php _e("specify a post ID or Title to to delete the related cache file","cosbeta");?></b> <input type="text" id="cache_id" name="cache_id" value="" /> <?php _e("Leave blank if you want to delete all caches","cosbeta");?></p> <p><input type="submit" value="<?php _e("Delete Html Cache files","cosbeta");?>" id="htmlCacheDelbt" name="htmlCacheDelbt" onClick="return checkcacheinput(); " /> </form> </div> <SCRIPT LANGUAGE="JavaScript"> <!-- function checkcacheinput(){ document.getElementById('htmlCacheDelbt').value = 'Please Wait...'; return true; } //--> </SCRIPT> <?php } } /* end of get url */ // deal with rebuild or delete function do_cos_html_cache_action(){ // 完成wp中cos-html-cache选项中删除静态文件的操作 if( !empty($_POST['htmlCacheDelbt']) ){ @rename(CosBlogPath."index.html",CosBlogPath."index.bak"); @chmod( CosBlogPath."index.bak", 0666 ); global $wpdb; if( $_POST['cache_id'] * 1 > 0 ){ //delete cache by id DelCacheByUrl(get_permalink($_POST['cache_id'])); $msg = __('the post cache was deleted successfully: ID=','cosbeta').$_POST['cache_id']; } else if( strlen($_POST['cache_id']) > 2 ){ $postRes=$wpdb->get_results("SELECT `ID` FROM `" . $wpdb->posts . "` WHERE post_title like '%".$_POST['cache_id']."%' LIMIT 0,1 "); DelCacheByUrl( get_permalink( $postRes[0]->ID ) ); $msg = __('the post cache was deleted successfully: Title=','cosbeta').$_POST['cache_id']; } else{ $postRes=$wpdb->get_results("SELECT `ID` FROM `" . $wpdb->posts . "` WHERE post_status = 'publish' AND ( post_type='post' OR post_type='page' ) ORDER BY post_modified DESC "); foreach($postRes as $post) { DelCacheByUrl(get_permalink($post->ID)); } $msg = __('HTML Caches were deleted successfully','cosbeta'); } } if($msg) echo '<div class="updated"><strong><p>'.$msg.'</p></strong></div>'; } $is_add_comment_is = true; // 下面是处理文章评论,增加了js来处理,相关js在common.js.php中 /* * with ajax comments */ if ( !function_exists("cos_comments_js") ){ function cos_comments_js($postID){ global $is_add_comment_is; if( $is_add_comment_is ){ $is_add_comment_is = false; ?> <script language="JavaScript" type="text/javascript" src="<?php echo CosSiteHome;?>/wp-content/plugins/cos-html-cache/common.js.php?hash=<?php echo COOKIEHASH;?>"></script> <script language="JavaScript" type="text/javascript"> //<![CDATA[ var hash = "<?php echo COOKIEHASH;?>"; var author_cookie = "comment_author_" + hash; var email_cookie = "comment_author_email_" + hash; var url_cookie = "comment_author_url_" + hash; var adminmail = "<?php echo str_replace('@','{_}',get_option('admin_email'));?>"; var adminurl = "<?php echo get_option('siteurl') ;?>"; setCommForm(); //]]> </script> <?php } } } function CosSafeTag(){ // 增加安全标记 if ( is_single() || (is_home() && IS_INDEX) ) { echo "<!--cos-html-cache-safe-tag-->"; } } function clearCommentHistory(){ // 原因查看 http://www.storyday.com/html/y2009/2270_cos-html-cache-upgrade-to-272.html global $comment_author_url,$comment_author_email,$comment_author; $comment_author_url=''; $comment_author_email=''; $comment_author=''; } //add_action('comments_array','clearCommentHistory'); add_action('get_footer', 'CosSafeTag'); // 让安全标记加在footer前 add_action('comment_form', 'cos_comments_js'); // 评论特殊处理一下 /* end of ajaxcomments*/ if(IS_INDEX) add_action('publish_post', 'createIndexHTML'); // 有新文章对首页处理一下 add_action('publish_post', 'htmlCacheDelNb'); // 有新文章对相关静态文件处理一下 if(IS_INDEX) add_action('delete_post', 'createIndexHTML'); // 删除了文章也对首页处理一下 add_action('delete_post', 'htmlCacheDelNb'); // 删除文件对相关静态文件处理一下 //if comments add add_action('edit_post', 'htmlCacheDel'); // 文章及评论有变动都要更新静态文件 if(IS_INDEX) add_action('edit_post', 'createIndexHTML'); // 可能影响首页,反正也更新一下吧
解读完成,其实在使用的过程中还会出现一个小bug:index.php文件会被修改成index.html,名字不一样,但是文件大小一样,这样会导致最新的文章直接显示首页的内容。
通过阅读东哥关于cos-html-cache的说明,再通过以上解读,可以发现cos-html-cache真是一个有超级高效率的wordpress缓存类插件,并且对服务器的资源占用非常小。通过这款插件,可以说让自己的网站快变成一个纯静态页面的网站了。不用一下,真是太对不起cosbeta了。
需要特别提醒的是:
- 使用前请仔细阅读说明
- cos-html-cache只会对文章和首页产生静态html文件,这对于以文章为主的博客或cms,cos-html-cache是再适合不过了。对于那些以页面为主的,除了首页,就没什么效果了。
很专业