月度归档:2015年02月

wordpress引流教程,发布文章后自动同步图文到新浪微博

经常上新浪微博并且关注了不少官网认证号的小伙伴一定会发现很多官方性质的微博都会把网站的最新文章或者动态同步到新浪微博这样一来就可以让微博用户快速的了解到网站的最新动态,并且也为网站增加了一个曝光以及流量入口,对于更新频繁的网站来说增加一个同步网站动态到微博的功能是非常有必要的,也不扯淡了,直接上代码:

class sync_sina {
    
    public $access_token = "";//access_token
       
    public $default_image = "";//默认图片地址
    
    public $host = "https://api.weibo.com/2/";
          
    public static $boundary = '';
          
    function __construct(){
        /**
         ** 事件绑定
         **/
        add_action('publish_post', array($this, 'new_post_photo'));
    }
    
    function do_mu_post($url, $data) {
        $ch = curl_init ();
        $headers = array("Content-Type:multipart/form-data;boundary=". self::$boundary);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, TRUE );
        curl_setopt ( $ch, CURLOPT_POST, TRUE );
        curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data );
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        $ret = curl_exec ( $ch );
        curl_close ( $ch );
        return $ret;
    }
    
    function build_http_query_multi($params) {
        if (!$params) return '';
        uksort($params, 'strcmp');
        $pairs = array();
        self::$boundary = $boundary = uniqid('------------------');
        $MPboundary = '--'.$boundary;
        $endMPboundary = $MPboundary. '--';
        $multipartbody = '';
        foreach ($params as $parameter => $value) {
            if( in_array($parameter, array('pic', 'image')) && $value{0} == '@' ) {
                $url = ltrim( $value, '@' );
                $content = file_get_contents( $url );
                $array = explode( '?', basename( $url ) );
                $filename = $array[0];
                $multipartbody .= $MPboundary . "\r\n";
                $multipartbody .= 'Content-Disposition: form-data; name="' . $parameter . '"; filename="' . $filename . '"'. "\r\n";
                $multipartbody .= "Content-Type: image/unknown\r\n\r\n";
                $multipartbody .= $content. "\r\n";
            } else {
                $multipartbody .= $MPboundary . "\r\n";
                $multipartbody .= 'content-disposition: form-data; name="' . $parameter . "\"\r\n\r\n";
                $multipartbody .= $value."\r\n";
            }
        }
        $multipartbody .= $endMPboundary;
        return $multipartbody;
    }
    
    function get_image($post_id){
        if( has_post_thumbnail($post_id) ){
            $timthumb_src = wp_get_attachment_image_src(get_post_thumbnail_id($post_id),'full');
            $output = $timthumb_src[0];
        } else {
            $content = get_post_field('post_content', $post_id);
            $defaltthubmnail = $this->default_image;
            preg_match_all('/<img.*?(?: |\\t|\\r|\\n)?src=[\'"]?(.+?)[\'"]?(?:(?: |\\t|\\r|\\n)+.*?)?>/sim', $content, $strResult, PREG_PATTERN_ORDER);
            $n = count($strResult[1]);
            if($n > 0){
                $output = $strResult[1][0];
            } else {
                $output = $defaltthubmnail;
            }
        }
        return $output;
    }
    
    function new_post_photo($post) {
        global $post;
        if( $post->post_status != "publish" ){
            $token = $this->access_token;
            $url = $this->host ."statuses/upload.json";
            $status = "我刚刚发布了新文章《".get_the_title()."》。".get_permalink();
            $status .= mb_strimwidth(strip_tags(apply_filters('the_content', $post->post_content)), 0,180,"..."); //顺手加了个文章摘要,不喜欢就去掉啦
            $pic_path = self::get_image($post->ID);
            $params = array();
            $params['access_token'] = $token;
            $params['status'] = $status;
            $params['pic'] = '@'.$pic_path;
            $body = self::build_http_query_multi($params);
            $result = self::do_mu_post($url,$body);
    
        }
    }
}
$HMT = new sync_sina();

以上代码添加至主题functions.php文件即可。

注:

需要服务器支持file_get_contents函数以及curl组件;

如果网站在国外服务器或者服务因特殊原因屏蔽了api.weibo.com域名,则可能造成发布文章卡死或者超时的问题。

如果网站未通过新浪审核微博小尾巴会显示为未审核应用。

文章参考:http://www.mywpku.com/wordpress-sync-sina-weibo.html

WordPress 3.0-3.9.2版本通杀跨站漏洞(csrf,xss)

据报道,使用3.0至3.9.2版本的WordPress平台不久前被曝出了跨站脚本漏洞,多个使用WordPress的网站均受影响。该漏洞在可用于在评论功能里注入指定JavaScript脚本,该脚本能够直接绕过用户登录需求直接发布,在管理员进行评论管理时自动执行,并可导致站点遭受潜在安全攻击威胁。

WordPress 3.0-3.9.2版本通杀跨站漏洞(csrf,xss)-wordpress资讯-代码笔记

目前该跨站脚本漏洞会影响3.0至3.9.2采用WordPress平台的网站,该漏洞最初由Klikki Oy于9月26日报告,11月20日WordPress和IT企业发布报告称,86%采用WordPress平台的网站遭受此漏洞影响。Klikki Oy与WordPress表示正在着手修补此漏洞,而目前升级至4.0版本以上的网站并不受此漏洞影响。

wordpress开发教程:wordpress条件判断函数

最近不少小伙伴都开始制作属于自己的wordpress模板了,初次制作wordpress模板肯定会遇到不少问题比如需要在特定页面执行特定代码或者是在特定的页面输出一段文字或样式,这里小V就将所有wordpress条件判断函数都挪列出来,所有的条件判断标签都会判断某个条件是否成立,然后返回 True 或者 False 。此外有些条件判断标签还可以使用一些参数进一步的判断,下面是所有的 WordPress 条件判断标签:

is_home()

判断当前页面是否为首页如果是当前页面是首页则会返回true,但是你在后台设置了首页静态页面作为首页的话则会返回false。

wordpress开发教程:wordpress条件判断函数-wordpress教程-代码笔记

is_front_page()

这个函数和上面的is_home()函数的作用也一样,唯一不同的就是就算你设置了静态页面为首页也恢返回true。

is_single()

该函数用来判断当前页面是否为文章页面或者自定义文章类型页面,并且该页面是可以附加参数的,下面那是示例代码:

//判断当前文章是否是 id 为 17 的文章。
is_single( '17' )
//判断当前文章的标题是否是 “Irish Stew”。
is_single( 'Irish Stew' )
//判断当前文章的别名(Slug)是否为 “beef-stew”。
is_single( 'beef-stew' )
//传递多个参数需要使用数组。上面条件判断标签判断满足 id 为 17 、别名为 beef-stew、标题为 Irish Stew 任意一个条件文章被访问时返回 True。
is_single( array( 17, 'beef-stew', 'Irish Stew' ) )
//判断多个文章的 id,用法同上。
is_single( array( 17, 19, 1, 11 ) )
//判断多个文章的别名,用法同上。
is_single( array( 'beef-stew', 'pea-soup', 'chili' ) )
//判断多个文章的标题,用法同上。
is_single( array( 'Beef Stew', 'Pea Soup', 'Chili' ) )

注意:这个函数对于传递的参数,并无法很明确的判断参数究竟是 id、文章标题或者是文章别名,如果参数为 17,当 id 为 17 的文章会返回 True,当 Slug 为 17 的文章也会返回 True。

is_sticky()

判断当前文章是否为置顶文章,也可以传递参数,大体的使用方法和is_single()函数一样。

is_singular()

判断是否满足 is_single、is_page 和 is_attachment 的任意一个条件,满足返回 True。可以用来判断任意类型的文章页面。

is_post_type_archive()

判断是否为存档页面(时间存档页、标签、分类、自定义分类),当然也可以加上一些参数比如post_tag,category来限制当前的存档页类型。

comments_open()

判断评论功能是否开启,必须用在循环中。

pings_open()

判断文章 ping 功能是否开启,必须用在主循环中。

is_page()

判断当前是否为页面类型文章,用法和is_single一致。

is_category()

判断当前页面是否为分类目录,以下是部分代码示例:

//判断当前分类页面的 ID 是否为 9。
is_category( '9' )
//判断当前分类页面的名字是否为“Stinky Cheeses”。
is_category( 'Stinky Cheeses' )
//判断当前分类页面的别名是否为“blue-cheese”。
is_category( 'blue-cheese' )
//用数组 传递参数,在前面的is_single里面讲过,作用类似。
is_category( array( 9, 'blue-cheese', 'Stinky cheeses' ) )

没什么特别的可讲

in_category(73)

判断当前文章是否属于某个特定分类目录(id 为 73),返回 True。注意,这里是 in 而不是 is,与上面的不同,用法和is_category类似。

is_tag()

判断当前页面是否为标签页面,当然可以传递参数,和is_category用法一致。

has_tag()

判断当前文章是否有一个标签,必须用在循环中。

is_tax()

判断当前页面是否为一个自定义分类的存档页面,下面那是用法示例:

//判断当前页面是否为一个名为 flavor 自定义分类的存档页面。
is_tax( 'flavor' )
//判断当前自定义分类 flavor 页面的别名是否为 mild。
is_tax( 'flavor', 'mild' )
//判断当前自定义分类 flavor 页面的页面是否为 sharp、mild、extreme 中的一个。
is_tax( 'flavor', array( 'sharp', 'mild', 'extreme' ) )

和is_category、is_tag用法不同请勿混淆。

has_term()

判断当前页面是否带有自定义分类。

//判断当前页面是否是否带有别名为 green 的自定义分类 color。
has_term( 'green', 'color' )
//判断当前页面是否是否带有数组中的自定义分类 color
has_term( array( 'green', 'orange', 'blue' ), 'color' )
is_author()

判断当前页面是否是一个作者存档页面,用法示例:

//判断当前页面是否为 id 为 4 的作者页面。
is_author( '4' )
//判断当前存档页面是否是 Vivian(Nickname) 的作者存档页面。
is_author( 'Vivian' )
//判断当前存档页面是否属于 id 为 4,或者名字为 “john-jones”、“Vivian” 的作者存档页面。
is_author( array( 4, 'john-jones', 'Vivian' ) )
is_date()

判断当前页面是否为任何的按时间存档的页面。

is_year()

判断当前页面是否为按年份存档的页面。

is_month()

判断当前页面是否为按月份存档的页面。

is_day()

判断当前页面是否为按日期存档的页面。

is_time()

判断当前页面是否为按照小时、分钟、秒存档的页面。

is_new_day()

判断当前页面是否为当天文章的时间存档页。

is_archive()

判断当前页面是否为一个存档页面,包括:分类、标签、作者页面、日期存档页面等。

is_search()

判断当前页面是否为一个搜索结果页面。

is_404()

判断当前页面是否为404页面

is_paged()

判断当前页面是否为分页。

is_attachment()

判断当前页面是否为附件页。

is_feed()

判断是否在订阅页面。

is_trackback()

判断trackback是否开启。

is_preview()

判断一篇文章是否在预览状态(文章本身处于草稿状态)。

has_excerpt()

判断当前文章是否有摘要内容。

in_the_loop()

判断是否在主循环内部。

如果发现一些判断失效了可能是循环未注销造成的全局变量错乱问题,可以使用以下函数来注销循环:

//使用WP_Query创建多个循环是使用,不接受任何参数,恢复$post全局变量的数据
wp_reset_postdata();
//使用query_posts()自定义循环时使用,不接受任何参数,不仅恢复$post全局变量,还会销毁之前的查询
wp_reset_query();
//需要重用同一个页面的查询结果时使用
rewind_posts();

实例:

$random_post = new WP_query();
$random_post->query('cat=3&showposts=1&orderby=rand');
while ($random_post->have_posts()) : $random_post->the_post();
<a href="<?php the_permalink() ?>" title="<?php the_title(); ?>">
    <img src="<?php echo get_post_meta($random_post->ID, 'featured', true); ?>">
</a>
endwhile;
wp_reset_postdata();
<?php query_posts('posts_per_page=3');
if (have_posts()) : while (have_posts()) : the_post(); ?>
<h1><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
<?php endwhile; endif; ?>
<?php wp_reset_query(); ?>
if (have_posts()) : while (have_posts()) : the_post(); ?>
<h1><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
<?php endwhile; endif; ?>
<?php rewind_posts(); ?>
<?php while (have_posts()) : the_post(); ?>
<?php the_content(); ?>
<?php endwhile; ?>

wordpress开发教程:原生态的wordpress ajax

最近小V在开发一款自适应的wordpress博客主题,该wordpress主题大量数据展示与提交都用到了ajax技术,所以小V特意写一篇教程记录下,方便其他wordpress开发者做wordpress ajax应用开发的时候做参考。如果有些小伙伴还不知道什么是ajax,请自行百度脑补~~,闲话就不多说了,教程开始。

不少开发者在写插件时喜欢用以下方式实现ajax:

require_once( '../../../../wp-config.php' );

就连百度站长平台官方开发的wordpress结构化数据提交插件也是如此实现ajax的,这是一种极其不合理的写法,因为一旦用户设置的目录不同, 相对路径就会失效.并且, 如果你在你的插件中使用的是面向对象的写法, 你将无法直接使用一些变量和私有方法. 最大的坏处就是会导致整个Wordpress的框架额外重新加载一遍,严重的影响了网站的运行效率。

其实,wordpress为了方便开发者开发带有ajax功能的插件主题已经预定义好了ajax方法,我们只需按照官方预留的方法去使用就好了。在开发wordpress ajax你要先了解的是,不管是后台还是前台任何的Ajax请求都是在admin-ajax.php处理的,向admin-ajax.php发送请求的时候, 有一个必须的参数是$_REQUEST['action'], 因为admin-ajax.php需要根据用户是否登陆了来触发不同的hooks。

if ( is_user_logged_in() ) {
    /**
     * Fires authenticated AJAX actions for logged-in users.
     *
     * The dynamic portion of the hook name, `$_REQUEST['action']`,
     * refers to the name of the AJAX action callback being fired.
     *
     * @since 2.1.0
     */
    do_action( 'wp_ajax_' . $_REQUEST['action'] );
} else {
    /**
     * Fires non-authenticated AJAX actions for logged-out users.
     *
     * The dynamic portion of the hook name, `$_REQUEST['action']`,
     * refers to the name of the AJAX action callback being fired.
     *
     * @since 2.8.0
     */
    do_action( 'wp_ajax_nopriv_' . $_REQUEST['action'] );
}

以上代码取自wordpress系统文件admin-ajax.php,从以上代码我们可以看出我们要发起一个请求首先要知道这个请求是否在登录状态下发起的?不同状态触发的hook也不一样,下面是个在主题利用jquery实现ajax的示例代码:

add_action( 'wp_head', 'v7v3AjaxScript');
function v7v3AjaxScript(){
    print '<script>var v7v3_ajaxurl = "'. admin_url( 'admin-ajax.php' ) . '"' . ";</script>\n";
    print "<script>
    $(docunment).ready(function(){
        $.ajax( {
            url: v7v3_ajaxurl,
            data:{
                action : 'is_login'
            },
            type:'post',
            cache:false,
            success:function(data) {
                alert(data);
            }
        });
    });
    </scrip>";
}
  
add_action( 'wp_ajax_nopriv_is_login', 'v7v3_ajax_not_login' );
add_action( 'wp_ajax_is_login', 'v7v3_ajax_is_login' );
  
function v7v3_ajax_is_login(){
    global $current_user;
    get_currentuserinfo();
    printf( '登录用户您好 : %s!', $current_user->display_name );
    //函数结束前的die或exit很重要,一定要加。
    die;
}
  
function v7v3_ajax_not_login(){
    print '尊敬的访客您好!';
    //函数结束前的die或exit很重要,一定要加。
    die;
}

在开发wordpress ajax应用中最重要的一点就是函数结束之前一定要加die或者exit,如果不加的话会把整个wordpress框架都重新加载一遍。

wordpress开发教程:优化用户注册体验(自定义密码)

今天有位小伙伴在群中询问wordpress新用户注册显示密码的问题,由于wordpress默认的是不让用户自己去填写密码的,而是系统自动给用户生成一个密码并且发送到用户邮箱,相对来说可能有些用户会不习惯,今天小V就来教大家优化wordpress的用户注册体验,让用户自己设置账户密码,其实很简单只需要在主题的function.php加上以下代码:

<?php
add_action( 'register_form', 'v7v3_show_register' );
function v7v3_show_register(){
?>
    <p>
        <label for="password">密码:<br/>
        <input id="password" class="input" type="password" tabindex="30" size="25" value="" name="password" />
        </label>
    </p>
    <p>
        <label for="repeat_password">确认密码<br/>
        <input id="repeat_password" class="input" type="password" tabindex="40" size="25" value="" name="repeat_password" />
        </label>
    </p>
    <p>
        <label for="are_you_human" style="font-size:11px">挖掘机技术哪家强?(蓝翔)<br/>
        <input id="are_you_human" class="input" type="text" tabindex="40" size="25" value="" name="are_you_human" />
        </label>
    </p>
<?php
}
add_action( 'register_post', 'ts_check_extra_register_fields', 10, 3 );
function ts_check_extra_register_fields($login, $email, $errors) {
    if ( $_POST['password'] !== $_POST['repeat_password'] ) {
        $errors->add( 'passwords_not_matched', "<strong>ERROR</strong>: 两次密码不一致" );
    }
    if ( strlen( $_POST['password'] ) < 8 ) {
        $errors->add( 'password_too_short', "<strong>ERROR</strong>: 密码长度小于8位!" );
    }
    if ( $_POST['are_you_human'] !== '蓝翔' ) {
        $errors->add( 'not_human', "<strong>ERROR</strong>: 回答错误,请重新填写注册信息!" );
    }
}

为了保证不被注册机骚扰此代码中还自带了一个验证问题字段,防止注册机批量注册垃圾用户。虽然让用户可以自己填写密码,但是有些用户更加喜欢让系统为他生成密码,为了给这些用户提供方便,我们可以判断下当前用户注册时是否填了密码,如果没填再让系统生成一个,代码如下:

add_action( 'user_register', 'v7v3_register_extra_pass', 100 );
function v7v3_register_extra_pass( $user_id, $password="", $meta=array() ){
    $userdata = array();
    $userdata['ID'] = $user_id;
if( $_POST['password'] ){
    $userdata['user_pass'] = $_POST['password'];
}
    wp_update_user($userdata);
}
    
/*如果强制用户输入密码,则可将此段代码的注释去除
add_action('admin_init', 'remove_default_password_nag');
function remove_default_password_nag() {
    global $user_ID;
    delete_user_setting('default_password_nag', $user_ID);
    update_user_option($user_ID, 'default_password_nag', false, true);
}
*/

当然为了给用户更好的体验,我们可以在注册框下方加个提示,代码如下:

add_filter( 'gettext', 'v7v3_edit_text' );
function v7v3_edit_text( $text ) {
    if ( $text == 'A password will be e-mailed to you.' ) {
        $text = '如果您不填写密码,系统将为您生成一个密码, 并发送至您的邮箱。';
    }
    return $text;
}