ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
这是一份快速而肮脏的文档,可帮助您编写满足自己的URL过滤需求的自定义URI过滤器。您为什么要编写URI过滤器?如果您需要将您的用户放入HTML中的URI,以神奇的方式将其更改为其他URI,这正是您所需要的! ## **创建class** 您创建的任何URI过滤器都是`HTMLPurifier_URIFilter`的子类。 ~~~ class HTMLPurifier_URIFilter_NameOfFilter extends HTMLPurifier_URIFilter { public $name = 'NameOfFilter'; public function prepare($config) {} public function filter(&$uri, $config, $context) {} } ~~~ `$name`用过滤器的名称填写变量,然后看一下这两种方法。`prepare()`是一种初始化方法,在对HTML进行任何过滤之前,只能调用一次初始化方法。使用它可以执行任何昂贵的设置工作,只需完成一次。`filter()`是我们过滤器的内部结构:它获取URI,并对其执行任何需要执行的操作。 如果您使用过HTML Purifier,则可以识别`$config`和`$context`参数。另一方面,`$uri`对于应用程序的这一部分来说是唯一的:它是一个`HTMLPurifier_URI`对象。因此,接口为: ~~~ class HTMLPurifier_URI { public $scheme, $userinfo, $host, $port, $path, $query, $fragment; public function HTMLPurifier_URI($scheme, $userinfo, $host, $port, $path, $query, $fragment); public function toString(); public function copy(); public function getSchemeObj($config, $context); public function validate($config, $context); } ~~~ 前三种方法很容易解释:您有一个构造函数,一个序列化程序和一个克隆器。通常,在处理URI对象本身时不会使用它们。`getSchemeObj()`是一种专用方法,它返回`HTMLPurifier_URIScheme`与手头特定URI相对应的对象。`validate()`对URI的内部组件执行通用验证。再一次,您不必担心这些:它们已经为您处理。 ## URI格式 作为URIFilter,我们对URI对象的成员变量感兴趣。 **Scheme** 用于识别(并可能定位)资源(http,ftp,https)的协议 **Userinfo** 用户信息,例如用户名(bob) **Host** 服务器的域名或IP地址(example.com,127.0.0.1) **Port** 服务器的网络端口号(80、12345) **Path** 标识资源的数据,可能是分层的(/path/to,ed@example.com) **Query** 资源要解释的信息字符串(?q =搜索词) **Fragment** 检索后资源的附加信息(#bookmark) 因为URI是以这种形式显示的,而不是`http://bob@example.com:8080/foo.php?q=string#hash`,它为我们省去了很多麻烦,每次我们想要过滤URI时都要解析它。作为记录,上述URI具有以下组成部分: 方案http用户信息鲍勃主办example.com港口8080路径/foo.php询问q =字符串分段杂凑 **Scheme** http **Userinfo** bob **Host** example.com **Port** 8080 **Path** /foo.php **Query** q=string **Fragment** hash 请注意,查询或片段中没有问号或十进制字符:在解析过程中将其删除。 有了这些信息,您就可以直接实现您的`filter()`方法。但是还有一件事... ## 返回值:布尔值,不是URI 您可能已经注意到URI是通过引用传递的。这意味着无论您对它进行什么更改,这些更改都会反映在被调用者拥有的URI对象中。**不要返回URI对象:这是不必要的,并且会导致错误。** 而是返回一个布尔值,如果过滤成功,则返回true;如果URI无法修复且需要删除,则返回false。 假设我想编写一个过滤器,该过滤器将具有自定义`image`方案的链接转换为我们网站上相应的真实路径: ~~~ class HTMLPurifier_URIFilter_TransformImageScheme extends HTMLPurifier_URIFilter { public $name = 'TransformImageScheme'; public function filter(&$uri, $config, $context) { if ($uri->scheme !== 'image') return true; $img_name = $uri->path; //覆盖前面的URI对象 //HTMLPurifier_URI($scheme, $userinfo, $host, $port, $path, $query, $fragment) $uri = new HTMLPurifier_URI('http', null, null, null, '/img/' . $img_name . '.png', null, null); return true; } } ~~~ 注意我没有`return $uri;`。该过滤器将`image:Foo`变为`/img/Foo.png`。 ## 激活过滤器 拥有过滤器是件好事,但是您需要告诉HTML Purifier使用它。幸运的是,这部分很简单: ~~~ $uri = $config->getDefinition('URI'); $uri->addFilter(new HTMLPurifier_URIFilter_NameOfFilter(), $config); ~~~ ## 后置过滤器 还记得我们的TransformImageScheme过滤器吗?这个过滤器在我们执行方案验证之前就起作用了。否则,当发现没有图像方案时,该URI将被过滤掉。好吧,后过滤器是在特定于方案的验证之后运行的,因此它是对URI进行批量后处理(包括压缩)的理想选择。要将URI指定为后过滤器,请将`$post`成员变量设置为TRUE。 ~~~ class HTMLPurifier_URIFilter_MyPostFilter extends HTMLPurifier_URIFilter { public $name = 'MyPostFilter'; public $post = true; // ... extra code here } ~~~ ## 例子 检查[URIFilter](http://repo.or.cz/w/htmlpurifier.git?a=tree;hb=HEAD;f=library/HTMLPurifier/URIFilter)目录以获取更多实现示例,并查看[新的指令提案文档](http://htmlpurifier.org/docs/proposal-new-directives.txt)以获取有关可以作为过滤器实现的想法。