【PHP】特定のタグだけescape(エスケープ)しないSmarty関数

EC-CUBEの開発で、mtb_allowed_tagに登録されたタグのみ有効にし
それ以外はescapeする処理を組み込んだときのメモ。
EC-CUBE開発元のロックオン開発チームブログが参考に。ここ
このブログにあったのを下のように修正(正規表現とか)。

<?php
/**
* 許可したHtmlタグだけエスケープせず出力する。他のタグはエスケープ.
*
* @param  string $sValue      変換する文字列.
* @param  array  $arrAllowTag 許可するHtmlタグを格納した配列.
* @return string              変換した文字列.
*/
function smarty_modifier_htmlescape($sValue, $arrAllowTag = array())
{
    $sValue = htmlspecialchars($sValue);

    if (count($arrAllowTag) == 0 ) return $sValue;

    foreach($arrAllowTag as $sTag) {
        if (strpos($sTag, '/') === false) {
            $sValue = preg_replace_callback("/&lt;\/?". $sTag . "( .*?&gt;|\/?&gt;)/i","htmlescape_unhtmlescape", $sValue);
        }
    }
    return $sValue;
}

/**
* タグを変換する.
*
* @param  string $sValue 変換する文字列.
* @return string         変換した文字列.
*/
function htmlescape_unhtmlescape($sValue){
    $sString = $sValue[0];
    $sString = str_replace("&lt;", "<", $sString);
    $sString = str_replace("&gt;", ">", $sString);
    $sString = str_replace("&quot;", "\"", $sString);
    return $sString;
}
?>

これをmodifier.htmlescape.phpという名前でSmartyのPluginフォルダに保存して、テンプレートでescapeしている箇所を下記のように変更
<!--{$arrProduct.name|htmlescape:$aTags}-->

○○_Ex側はSmartyに渡す前にDBからmtb_allowed_tagを取得する処理を追加。

$objMaster = new SC_DB_MasterData_Ex();
$arrTags = $objMaster->getMasterData("mtb_allowed_tag");
$this->aTags = $arrTags;

このSmarty関数はEC-CUBEだけでなく他でも役に立ちそう。

htmlタグを見つけ出す正規表現で少し悩みましたが、こことかを参考に。
PHPで正規表現で試すときはここのサイトを利用すると便利。
preg_*のPHP関数を使う場合はPCREのタブを選択して試す。