8月 162013
 

WordPressには色んなテーマがあるんですが、多すぎてお目当ての物を探すのには苦労します。そこらへんに転がってる野良テーマを使うとセキュリティ面で問題があるという話もあるし、公式に配布されているものを使うのが無難でしょう。タダだし、更新チェック効くし。そうして私が探した中で、唯一これだ!と思えたのが、現在使っている「Suffusion」です。

Suffusionはカスタマイズ項目が豊富なのですが、ほとんど手つけてないです。ヘッダの下にメニューバー追加したぐらいですかね。あとは直接コード書いてたりしてますが、それについてはあとで触れます。ともかく、ほとんどいじらなくていいぐらい完成度が高く気に入ってます。シンプルで見やすいのがいいんですよ。

WordPressは本体・テーマ・プラグインの最新版がないか自動でチェックしてくれます。Suffusionの開発は盛り上がってるみたいで、全然更新されなくて放置ということがないのも魅力だと思います。ただ、テーマを更新するとカスタマイズした項目がリセットされてしまいます。その度に設定し直すのはしんどいので、スマートな解決手段として、WordPressには子テーマというものが用意されています。

子テーマ(child theme)とは、ある既存のテーマを親として、親テーマの一部を書き換えたり、内容を追加したりすることができます。既存のテーマを拡張することになるので、一からテーマを作るより手間がかかりません。そして、親テーマに対するカスタマイズを子テーマとして切り出すことで、設定項目は子テーマとして管理されますから、親テーマを更新してもカスタマイズ内容が失われないわけです。便利ですね。なので、何らかのカスタマイズをしたいならば、子テーマで対応するのがいいでしょう。ということで、やったことをメモ書きの意味も兼ねてまとめます。

子テーマを作ろう

子テーマの作り方は上のページにまとまっています。最低限やることは子テーマのディレクトリを用意して、そこに必要な情報を記述したstyle.cssを配置するだけですね。子テーマでは親テーマのstyle.cssが無視されるので、この内容を反映させたかったら@importを使えばいいと説明されています。例えば、Suffusionなら、suffusionディレクトリにあるので、子テーマのstyle.cssに次のように書くとよさそうです。

/*
Theme Name: MySuffusion
Template: suffusion
*/
@import url('../suffusion/style.css');

しかし、これはSuffusionにおいては不完全です。Suffusionは複数のスキンを用意していて、それぞれにcssが用意されていてこれを読み込む必要があるからです。古いバージョンのSuffusionでは、直接スキンのcssを指定したりしていたみたいですが、今は子テーマ対応が進んでいて、手間が少なくなりました。最新版4.4.7では、[Suffusion Options]→[Back-end]→[Child Themes]にて「Inherit all stylesheets corresponding to the theme selection (You don’t need any @import in your style.css)」と書かれてる方にチェックが入っていればOKです。ここにチェックが入っていれば、スキンに対応したcssを勝手に読み込んでくれるようになり、@importの記述すらいらなくなります。なので、style.cssには子テーマ情報と追加のスタイルだけを記述することになります。

function.phpを用意すると、親テーマのfunction.phpの前に呼ばれます。処理の書き換えとかフックによる追加とかしたかったら、これをいじればいいわけですね。

さて、これらstyle.cssとfunction.phpですが、公式で雛形が公開されていますので、これを改造するのが手っ取り早いでしょう。

「available for use」と書かれているリンクから、suffu-scion.zipがダウンロードできます。これを解凍したものをwp-content/themes/に配置するだけで子テーマとして動きます。・・・と言いたいところなんですが、function.phpがphpコードを閉じ忘れているので、末尾に「?>」を追加しましょう。
(2014/02/20 追記)閉じないほうがいいらしいです。PHP経験浅すぎました。
参考:PHP TIPS – 16. PHPの最後の?>は不要なんです:ITpro

空のディレクトリとしてcustom, layout, post-formatsが用意されていますが、詳しく知りません。とりあえず、customに関しては、既存のファイルを上書きするためにあるようで、既存のファイルを改造をしたいんだけど、元のファイルは残しておきたいというときに使うといいらしいです。私は使ってません。

テーマ選択画面で表示されるスクリーンショットはscreenshot.pngをテーマのディレクトリに含めばOKです。なくても問題ないけど、気になるなら。

今回は特殊な例だったので雛形を使いましたが、一般的な子テーマ、つまり、@importを記述するやり方なら、「One-Click Child Theme」プラグインあたりを使うと導入が簡単そうです。最終更新が2年前ですが、処理内容的に更新することがないんじゃないですかね。

Suffusion設定の移行

そもそも、子テーマというものがあることをテーマ改造しながら調査してる中で見つけました。なので、既存のカスタマイズの移行方法も知っておきたいです。とりあえず、Suffusion Optionsの移行はできました。

Suffusion Optionsにはインポート/エクスポート画面があるので、これを利用して親テーマでエクスポートして子テーマでインポートする流れになります。エクスポートは主要な設定をまとめたものと全てまとめたものの2種類ありますが、どう違うか詳しく知りませんが、メニューなどidに対応付けられた設定を含むかどうか、と書かれていますね。エクスポートしたファイルは名前がsuffusion_options.phpになっていると思いますが、インポートする時はこの名前でサーバに置くことになります。アップロード先のディレクトリはSuffusionのadminディレクトリ下です。子テーマだったら、そっちにadminディレクトリを作って入れます。例えば、子テーマのディレクトリ名がmy_suffusionなら、wp-content/themes/my_suffusion/admin/ですね。インポート対象のファイルがなくてもエラーメッセージ出ないみたいなので上手くいってるのか確認が難しいところ。

メニュー設定も含めたエクスポートファイルをインポートしてみたところ、メニュー定義は残ってますが、配置されてなかったので、ここは自分で設定し直しました。あと何故かスキンのカスタマイズした背景色が反映されません。スキンの種類は変えられるんですが、このへんの子テーマ対応は不完全なのかな・・・。

他の設定はデータベースに保存されてると思われるので、必要なら自分で調査するしかなさそう。

外観を日本語化する

Suffusionはデフォルトでは、すべての表記が英語です。ロケールに対応した翻訳ファイル(.moファイル)を持ってきて、suffusionテーマのtranslationディレクトリにつっこめば外観としては翻訳化ができます。管理画面は翻訳の対象ではありません。日本語の場合、必要となる翻訳ファイルはja.moですね。ja.poはテキストデータで、これをもとにja.moを作ります。翻訳を編集したいかもしれないので、持っておいていいでしょう。poEditといったソフトで編集できるらしいです。

Suffusion用のja.moは私が探したところ、2つ見つかりました。

まず前者を試してから、後者も試したんですが、前者で翻訳されていたところが後者で翻訳されてなかったので前者を選べばいいと思います。3.7.8対応と書いてありますが、注意書きにもあるように最新版でも問題なさそうです。後者は登録ユーザみんなで協力して翻訳しようというプロジェクトらしく、現在の状態に対して翻訳ファイルを生成する仕組みになっています。ページの左下にエクスポート用の項目があるので「all current」「as mo」として、「Export」を押せばja.moがダウンロードできます。

用意した翻訳ファイルはテーマのtranslationディレクトリに入れるということでした。子テーマのtranslationに入れることで、親テーマを更新しても翻訳が維持されます。例えば、子テーマのディレクトリ名がmy_suffusionなら、wp-content/themes/my_suffusion/translation/に入れます。ロケールがjaであるなら、これだけで翻訳が行われるはず。日本語版WordPressを使っていれば大丈夫かと。

ロケールの設定自体は、wp-config.php内にWPLANGとしてdefineしているようですが、対応する言語ファイルを用意するとか手間が発生するので、最初から日本語版WordPressだけを使えばいいんじゃないかなぁ。

スタイルを変更する

Sandboxにも書いたとおりなのですが、そのままのスタイルでは見出しレベルの差異や引用ブロックがわかりにくく感じたので、これを修正するスタイルを子テーマのstyle.cssに記述します。現在、私のstyle.cssはこんな感じです。

@charset "utf-8";
/*
Theme Name:     MySuffusion
Description:    Child theme for Suffusion
Template:       suffusion
Version:        0.1.0
*/

blockquote{
    background-position: 5px 5px; /* changed from "left top" */
    background-color: #eeeeee;
    border: #bbbbbb 1px solid;
}

.entry h3 {
    background-color: #e7e7e7;
    border-left: solid 10px #bbbbbb;
    border-radius: 5px;
    padding: 10px 10px;
}
.entry h4 {
    background-color: #e7e7e7;
    border-radius: 5px;
    padding: 10px 15px;
}
.entry h5 {
    /*border-bottom: dotted 1px #bbbbbb;*/
    border-left:solid 10px #cccccc;
    padding: 5px 10px;
}
.entry h6 {
    padding-left: 5px;
}

トップページのカスタマイズ

WordPressではトップページを特定の固定ページに設定するとかいったカスタマイズも出来ますが、固定ページ設定されていなければhome.phpを優先するので、これで自由にカスタマイズできます。front-page.phpだと固定ページ設定も無視するらしいですが、ここではhome.phpということで。これも子テーマのディレクトリに配置すれば、親テーマの更新で消えません。

ここでやりたいことを説明します。私はWordPressを普通にブログとして使いたいので、最新記事が並んでいるデフォルト設定でほぼ満足です。しかし、告知したいことがあったら、お知らせページを最新記事より先に出したいわけです。よくある日付いじってトップに出すという強引な方法はかっこ悪いし、お知らせページは固定ページとして作りたいので、特定の固定ページを先頭に出すことができないか、ということですね。これはSuffusionで対応していることではないし、解決できそうなプラグインもありそうで見つからなかった(プラグイン化は不可能なのかも)ので、自分でページを作るしかないと判断し、home.phpを作成することで対応しました。

Suffusionにhome.phpはないため、自分で作ります。home.phpの編集についてはpage.phpをコピペして編集するものとして紹介しているサイトが多いですが、page.phpは固定ページ用のものなので、今回ベースとするのはindex.phpです。index.phpは優先すべきテンプレートファイルが存在しないときの最終候補であり、Suffusionでのトップページ表示はここに行き着くようです。index.phpにはそのページで表示すべき記事(トップページなら表示設定で設定されたもの)を取得するコードがあるので、これを利用させてもらいます。その上で、page.phpを参考にして、特定の固定ページをその上に置きたいわけです。結果として、home.phpはこんな感じになりました。

<?php
/**
 * Home page template
 *
 * @package MySuffusion
 * @subpackage Templates
 */
global $suf_index_excerpt, $suffusion, $suffusion_cpt_layouts;
get_header();
$suffusion->set_content_layout($suf_index_excerpt);
suffusion_query_posts();
$layout = $suffusion->get_content_layout();

// added
function remove_filters($filter_sets) {
    $removed_filter_sets = array();
    foreach($filter_sets as $tag => $filters) {
        foreach($filters as $filter) {
            if(remove_filter($tag, $filter)) {
                if(array_key_exists($tag, $removed_filter_sets)) {
                    $removed_filter_sets[$tag][] = $filter;
                } else {
                    $removed_filter_sets[$tag] = array($filter);
                }
            }
        }
    }
    return $removed_filter_sets;
}

function add_filters($filter_sets) {
    foreach($filter_sets as $tag => $filters) {
        foreach($filters as $filter) {
            add_filter($tag, $filter);
        }
    }
}

?>
    <div id="main-col">
<?php suffusion_before_begin_content(); ?>
        <div id="content">

<?php // added
global $post;
$my_query = new WP_Query('&amp;pagename=information');
if($my_query->have_posts()) {
    $removed_filter_sets = remove_filters(array(
        'the_content' => array(
            'wp_social_bookmarking_light_the_content',
        ),
    ));
    while($my_query->have_posts()) {
        $my_query->the_post();
        $original_post = $post;
//      if(get_post_meta($post->ID, 'show_on_home', true) !== 'true') {
        if($post->show_on_home !== 'true') {
            continue;
        }
        do_action('suffusion_before_post', $post->ID, 'blog');
?>
        <article <?php post_class(); ?> id="post-<?php echo $post->ID; ?>">
<?php suffusion_after_begin_post(); ?>
            <div class="entry-container fix">
                <div class="entry fix">
                    <?php suffusion_content(); ?>
                </div><!--/entry -->
            <?php
                // Due to the inclusion of Ad Hoc Widgets the global variable $post might have got changed. We will reset it to the original value.
                $post = $original_post;
                suffusion_after_content();
            ?>
            </div><!-- .entry-container -->
<?php
suffusion_before_end_post();
comments_template();
?>
        </article><!--/post -->
<?php
        do_action('suffusion_after_post', $post->ID, 'blog');
    }
    add_filters($removed_filter_sets);
}
?>

            <div class="hfeed">
<?php
if ($layout == 'list') {
    get_template_part('layouts/layout-list');
}
else if ($layout == 'tiles') {
    suffusion_after_begin_content();
    get_template_part('layouts/layout-tiles');
}
else if ($layout == 'mosaic') {
    get_template_part('layouts/layout-mosaic');
}
else {
    suffusion_after_begin_content();
    get_template_part('layouts/layout-blog');
}
?>
            </div><!-- hfeed -->
        </div><!-- content -->
    </div><!-- main col -->
<?php get_footer(); ?>

index.phpから追加した部分はコメントにaddedと書いています。以下、ちょっと説明。

特定の固定ページを表示するわけですが、ここではスラッグが「infomation」となるお知らせページを探すために、「&pagename=information」というパラメータで検索しています。これの検索結果をpage.phpの内容を参考に利用しています。

記事にTwitterやFacebookなどのSNSボタンを追加するプラグイン「WP Social Bookmarking Light」を導入しているのですが、これをトップのお知らせ記事から外したかったので、その実装を見て、該当するフィルタをremove_filter関数により除外しています。除外したフィルタを戻さないと以降の記事表示にも影響するため、add_filterで登録しなおしています。そのために用意した補助関数がremove_filtersとadd_filtersですが、フィルタの優先度を見てないので万能ではないです。

特にお知らせがないときのためにも、お知らせページを出さない選択も取れればいいですね。いちいちhome.phpを変更するのも面倒ですから、管理画面上から何らかの操作をして変更できるのならそれがいいです。そこで、お知らせページを表示すべきかどうかという情報をカスタムフィールドとして持つことにしました。カスタムフィールドとは、記事ごとに自由に付与できる情報です。記事編集画面でカスタムフィールドを編集できます。項目が存在しなければ、編集画面右上の表示オプションからカスタムフィールドにチェックを入れてください。新規追加で名前「show_on_home」、値を「true」という内容で設定しました。カスタムフィールドはget_post_meta関数で取得するのが従来の方法ですが、下のページにも説明されているように、最近はフィールドとして直接参照できるので、$post->show_on_homeで見ることができるわけです。

参考

home.phpを作ったのは1ヶ月以上前で色々と忘れましたが、周辺知識の調査がそれなりに大変だったと思います。日本語のドキュメントが優秀なので、よく見ればだいたいわかるんですけどもね。

サイドメニューのリファレンスにある項目が役立ちます。テンプレートタグ、関数、フィルター、フックあたりを理解すればリファレンス見ながら色々できるんじゃないですかね。データベースの内容については、下のページにまとまっています。

コメントを残す

Top