自動的に段落を<p>で囲ってくれたり各行に<br>をつけてくれたりと、普段はとても便利なwpautopですが、投稿内にhtmlを直接記述する場合なんかは少し迷惑だったりしますよね.
かといってフックを外してしまうと<br>までいちいち自分で書かないといけなくなるので非常に面倒くさい.
ということで、投稿内の一部分でのみwpautopを無効化するコードを書いてみました.
ところでフックを丸ごと外すならfunctions.php内や各テーマファイルの本文出力前で次のようにしてもらえば問題ないです.
<?php remove_filter('the_content', 'wpautop'); ?>
ショートコードとあわせて使うと便利なので、今回は[code]から[/code]で囲んだ範囲でwpautopを無効化してみます.
まずは次のコードをfunctions.phpに貼り付けてください.
// 部分的にwpautopを無効化
function noautop($t){
$scode = 'code';// 対象となるショートコード
if( mb_strpos($t, "[{$scode}]") === false || mb_strpos($t, "[/{$scode}]") === false ) return $t;
remove_filter('the_content', 'wpautop');
$br = 0;
while( mb_strpos($t, "[{$scode}]") !== false && mb_strpos($t, "[/{$scode}]") !== false ){
$slice_start = mb_strpos($t, "[{$scode}]");
$slice_end = mb_strpos($t, "[/{$scode}]");
while( $slice_start > $slice_end ){
$slice_end = mb_strpos($t, "[/{$scode}]", $slice_end + 1);
if( $slice_end === false ) break 2;
}
$autop[] = mb_substr($t, 0, $slice_start);
$noautop[] = mb_substr($t, $slice_start, $slice_end + mb_strlen("[/{$scode}]") - $slice_start);
$t = mb_substr($t, $slice_end + mb_strlen("[/{$scode}]"));
if( $br++ > 1024 ) break;
}
$result = "";
if( isset($autop) && is_array($autop) ){
for($i = 0; $i < count($autop); $i++){
$result .= wpautop($autop[$i]).$noautop[$i];
}
}
$result .= wpautop($t);
return $result;
}
add_filter('the_content', 'noautop', 9);[/code]<p>これで、[code]から[/code]の範囲ではwpautopが効かなくなりました.</p>
<p> </p>
<p>まだこのままでは投稿中に[code]や[/code]と書くとそれ自体もそのまま出力されてしまうので、「code」というショートコードを登録します.</p>
<p>同じくfunctions.phpに次のコードを追加して、[code]や[/code]をショートコードとして認識させます.</p>
function scfunc_code($attributes, $content = ""){
// $content = htmlspecialchars($content);
// $content = str_replace("&#038;", "&", $content);
return '<pre><code>'.$content.'</code></pre>';
}
add_shortcode('code', 'scfunc_code');
以上のようにすることで[code]から[/code]で囲った部分は、wpautopが適用されずに一番外側を<pre><code>から</code></pre>で囲った状態で出力されるようになります.
お気づきの方もいると思いますが、このコード中のhtmlspecialchars()やstr_replace()のコメントアウトを外してもらえば、投稿作成時にhtmlやphpなどのソースコードをそのまま入力できるようになります.
投稿画面のテキストエリアに
[code]<div class="sample">
<p><?php echo 'usisan'; ?></p>
</div>[/code]と入力すれば、
<div class="sample">
<p><?php echo 'usisan'; ?></p>
</div>
このようにそのまま綺麗に表示してくれます.
動作の保証はしませんが、どうぞご自由にお使いください.
複数対応版
複数のショートコードでwpautopを無効化したい場合は、上のnoautop()の代わりに以下のnoautopX()を使ってください.
適用したいショートコードを2行目の配列で指定します.
// 部分的にwpautopを無効化
function noautopX($t){
$scodes = array('nop', 'code', 'result');// 対象となるショートコード
$scodes_exists = false;
foreach($scodes as $c){
if( mb_strpos($t, "[{$c}]") !== false && mb_strpos($t, "[/{$c}]") !== false ) $scodes_exists = true;
}
if( !$scodes_exists ) return $t;
remove_filter('the_content', 'wpautop');
$br = 0;
while( true ){
$pos = array();
foreach($scodes as $c){
if( mb_strpos($t, "[{$c}]") !== false && mb_strpos($t, "[/{$c}]") !== false ){
$pos[$c] = mb_strpos($t, "[{$c}]");
}
}
if( empty($pos) ) break;
asort($pos);
reset($pos);
$c = key($pos);
$slice_start = mb_strpos($t, "[{$c}]");
$slice_end = mb_strpos($t, "[/{$c}]");
while( $slice_start > $slice_end ){
$slice_end = mb_strpos($t, "[/{$c}]", $slice_end + 1);
if( $slice_end === false ) break 2;
}
$autop[] = mb_substr($t, 0, $slice_start);
$noautop[] = mb_substr($t, $slice_start, $slice_end + mb_strlen("[/{$c}]") - $slice_start);
$t = mb_substr($t, $slice_end + mb_strlen("[/{$c}]"));
if( $br++ > 1024 ) break;
}
$result = "";
if( isset($autop) && is_array($autop) ){
for($i = 0; $i < count($autop); $i++){
$result .= wpautop($autop[$i]).$noautop[$i];
}
}
$result .= wpautop($t);
return $result;
}
add_filter('the_content', 'noautopX', 9);[/code] 

この記事へコメントする
※承認制のため、即時には反映されません。