特定のHTMLタグのみ表示を許可する

例
---

```html
<><a href="http://hogehoge.com/><><"><B><b myattr="<><>">hogehoge<i>hoge<ins>hoge</ins></i></b></B><b<b<b>>>
```
に対して、タグ **a**, **b**, **i** を許可する

# CASE1: Tidyが使えない場合

**※ タグの入れ子が正しいかどうかを考慮していません**

HTMLエンティティに置換する場合
---------------------------------------

```php:コード
function filter_text($text, $allow_tags = array()) {
    
    $tags = implode('|', $allow_tags);
    $attr = '(?: ++[\\w-]++(?:=(?:[\\w-]++|"[^"]*+"|\'[^\']*+\'))?+)';
    $keep = $tags !== '' ?
        "</(?:{$tags}) *+>|<(?:{$tags}){$attr}*+ *+/? *+>|":
        ''
    ;
    $pattern = "@{$keep}(<)|(>)@i";
    return preg_replace_callback($pattern, function ($matches) {
        switch (true) {
            case isset($matches[2]): return '&gt;';
            case isset($matches[1]): return '&lt;';
            default:                 return $matches[0];
        }
    }, $text);
    
}
```

```html:結果
&lt;&gt;<a href="http://hogehoge.com/><><"><B><b myattr="<><>">hogehoge<i>hoge&lt;ins&gt;hoge&lt;/ins&gt;</i></b></B>&lt;b&lt;b<b>&gt;&gt;
```

削除する場合
----------------

```php:コード
function filter_text($text, $allow_tags = array()) {
    
    $tags = implode('|', $allow_tags);
    $attr = '(?: ++[\\w-]++(?:=(?:[\\w-]++|"[^"]*+"|\'[^\']*+\'))?+)';
    $keep = $tags !== '' ?
        "</(?:{$tags}) *+>|<(?:{$tags}){$attr}*+ *+/? *+>|":
        ''
    ;
    $pattern = "@{$keep}(</[\\w-]++ *+>|<[\\w-]++{$attr}*+ *+/? *+>|<[^<>]*+>|[<>])@i";
    return preg_replace_callback($pattern, function ($matches) {
        switch (true) {
            case isset($matches[1]): return '';
            default:                 return $matches[0];
        }
    }, $text);
    
}
```

```html:結果
<a href="http://hogehoge.com/><><"><B><b myattr="<><>">hogehoge<i>hogehoge</i></b></B>bb<b>
```

# CASE2: Tidyが使える場合

`php_tidy.dll` は php.ini の設定で有効化することが出来ます。
Tidyを使えば、不足している閉じタグを適切に補正してくれます。
また、存在しない属性もカットしてくれます。
ついでにhref属性内の未エンコード文字を自動的にURLエンコードしてくれます。

HTMLエンティティに置換する場合
---------------------------------------

```php:コード
function filter_text($text, $allow_tags = array()) {
    
    $tags = implode('|', $allow_tags);
    $attr = '(?: ++[\\w-]++(?:=(?:[\\w-]++|"[^"]*+"|\'[^\']*+\'))?+)';
    $keep = $tags !== '' ?
        "</(?:{$tags}) *+>|<(?:{$tags}){$attr}*+ *+/? *+>|":
        ''
    ;
    $pattern = "@{$keep}(<)|(>)@i";
    $text = preg_replace_callback($pattern, function ($matches) {
        switch (true) {
            case isset($matches[2]): return '&gt;';
            case isset($matches[1]): return '&lt;';
            default:                 return $matches[0];
        }
    }, $text);
    $tidy = new Tidy;
    return $tidy->repairString($text, array(
        'wrap'           => 0    ,
        'show-body-only' => true ,
    ), 'utf8');
    
}
```

```html:結果
&lt;&gt;<a href="http://hogehoge.com/%3E%3C%3E%3C"><b>hogehoge<i>hoge&lt;ins&gt;hoge&lt;/ins&gt;</i></b>&lt;b&lt;b<b>&gt;&gt;</b></a>
```

削除する場合
----------------

```php:コード
function filter_text($text, $allow_tags = array()) {
    
    $tags = implode('|', $allow_tags);
    $attr = '(?: ++[\\w-]++(?:=(?:[\\w-]++|"[^"]*+"|\'[^\']*+\'))?+)';
    $keep = $tags !== '' ?
        "</(?:{$tags}) *+>|<(?:{$tags}){$attr}*+ *+/? *+>|":
        ''
    ;
    $pattern = "@{$keep}(</[\\w-]++ *+>|<[\\w-]++{$attr}*+ *+/? *+>|<[^<>]*+>|[<>])@i";
    $text = preg_replace_callback($pattern, function ($matches) {
        switch (true) {
            case isset($matches[1]): return '';
            default:                 return $matches[0];
        }
    }, $text);
    $tidy = new Tidy;
    return $tidy->repairString($text, array(
        'wrap'           => 0    ,
        'show-body-only' => true ,
    ), 'utf8');
    
}
```

```html:結果
<a href="http://hogehoge.com/%3E%3C%3E%3C"><b>hogehoge<i>hogehoge</i></b>bb</a>
```