有时候一些文章不想公开让大家访问,所以设置了密码。但是 Typecho 的加密文章仍然会显示在主页上,最近文章中。并把标题替换为此内容被密码保护。所以我想把加密文章直接隐藏掉,这样主页会显得清爽。

之前一直是通过修改主题模板来隐藏加密文章。但是在实现方法上用的最简单的方法,就是在主题模板获取到文章的时候判断每篇文章是否是加密的,如果是则隐藏此文章。

但是这样会有几个问题:

  1. 首页模板获取到的的文章数量是恒定的,比如 10 篇,如果其中 9 篇都是加密文章,这时候你查看首页时,会发现,整个首页就只有 1 篇文章,非常影响阅读体验。当时为了解决这个问题,我只能把首页显示文章的数量调高。
  2. 加密文章下的评论依旧会被显示出来,并且显示为内容被隐藏
  3. 加密文章虽然在主页隐藏了,但是依旧可以直接通过网址访问到。存在密码被暴力破解的风险(虽然我觉得没人会闲着没事来破解这个密码)

所以我想着去写一个 Typecho 的插件来隐藏文章,同时解决以上的问题。


我首先去查看了 Typecho 的 文档,但是看完之后的我还是一知半解。

后来我看到了 老高的typecho插件编写教程,文章详细的介绍了插件的机制,我大概知道该怎么下手去写一个插件。

既然知道该怎么下手,便去建立了一个新的仓库来存放代码,并给插件取了一个直白的名字 Filter

首先尝试过滤加密的文章,我发现首页或者其他页面的文章都是通过 Widget_Archive 来获取数据,所以准备从这里下手。

我发现 Widget_Archive 中有一个 handleInit 接口可以用来过滤文章。

使用如下的函数即可过滤掉加密的文章。这样从数据库获取的文章便全是未加密的。

public static function archiveFilter($obj, $select)
    {
        # 获取用户
        $user = Typecho_Widget::widget('Widget_User');
        # 当用户权限低于编辑时,过滤掉加密文章
        if (!$user->pass('editor', true)) {
            // 过滤加密文章
            $select = $select->where('table.contents.password is null');
        }
        return $select;
    }

接下来的我尝试着去过滤掉最近回复处加密文章下的回复,我找了半天没找到合适的插件接口。我先尝试着给加密的回复添加一个 show 的属性,然后过滤掉这个属性值为 false 的回复。

但是这样就会遇到和之前一样的问题,那就是如果 10 个回复中,9 个都是加密的,就只能显示出 1 个,体验很不好。

最后我发现可以自定义 Widget,便在插件中实现了修改版的 Widget_Comments_RecentWidget_Contents_Post_Recent。通过在主题模板中调用自己实现的 Widget,这样就解决了之前遇到的问题。

因为使用这种方法来过滤加密的文章,同时也解决了之前我遇到的 在某些情况下错误的添加了 noindex 的问题。算是一举多得了。


插件地址:typecho-filter

标签: 隐藏, 加密, 文章