WordPressのフォトログ用テーマDuotoneを動かすまでの長い道のり

実は、マルチサイトで動作している本ブログの裏で、作るだけ作って今まで放置していたフォトログサイトを Simple Pictures としてようやく正式稼動させました。

採用したのは、Duotoneというテーマで、アップロードした画像に応じて背景や文字色が変わるWordPressのステキなフォトログ用テーマです。

Duotone

だが、しかし!
テーマをそのまま適用すると、エラー多発で全く動作しません・・・。
(automatticリリースなのだから、もう少しメンテしてよ。。。ブツブツ)

Duotone適用直後

ですが、使いたかったので、なんとか動かしてみることにしました。

is_vertical関数の修正

まずは、どどんと表示されてしまっているエラーメッセージがなんとも情けないし、分かりやすくもあるので、ここから手を付けることにします。is_vertical 関数の引数が無いよとのことなので、無くても動作するように /duotone/inc/duotonelibrary.phpの is_vertical 関数自体をCODE 1のように修正します。

CODE 1

function is_vertical($url = false) {
	global $post;
	$size = get_post_meta($post->ID, 'image_size', true);
	if ( ! $url ) {
		$url = get_post_meta( $post->ID, 'image_url', true );
	}

これで再度表示させてみると、

エラーメッセージ部分修正後

エラーは出なくなりましたが、未だ画像は表示されず。。
※ 環境によっては、getimagesizeでエラーが出ますが、これはPHPの allow_url_fopen が無効に設定されているためです。表示される画像がサイト外である可能性もあるため、ここは敢えて(横着して)そのままにしておきました。

HTMLのソースの画像部分

<img src="/wp-content/themes/duotone/inc/thumb.php?image=/files/2011/05/IMG_1330-560x840.jpg&w=560"   alt="白樺" title="白樺"   class="alignnone size-medium wp-image-57"  />

のsrc属性のアドレスにアクセスしてみると、

<br />
<b>Fatal error</b>:  Call to undefined function sys_get_temp_dir() in <b>/path/to/documentroot/wp-content/themes/duotone/inc/thumb.php</b> on line <b>26</b><br />

となにやら、sys_get_temp_dir なる関数がないとのメッセージ。

sys_get_temp_dirの追加

実は、sys_get_temp_dirは、PHP5.2から利用できる関数で、運用環境のバージョンがそれ以下であったことが原因。
PHPのマニュアルページにも書いてある代替関数(CODE 2)を thumb.php の関数がコールされる前に追記

CODE 2

if ( !function_exists('sys_get_temp_dir')) {
	function sys_get_temp_dir() {
		if( $temp=getenv('TMP') ) return $temp;
		if( $temp=getenv('TEMP') ) return $temp;
		if( $temp=getenv('TMPDIR') ) return $temp;
		$temp=tempnam(__FILE__,'');
		if (file_exists($temp)) {
			unlink($temp);
			return dirname($temp);
		}
		return null;
	}
}

で、再度画像のsrcのアドレスにアクセスしてみるものの、

File not found.

ファイルがない・・・だと!?

ファイルパスの修正

File not found.の検証を行っているのは、duotone/inc/thumb.php の Thumby メソッドにある CODE 3の部分。

CODE 3

	$gal_path = $_SERVER['DOCUMENT_ROOT'];
	$ext = strtolower(pathinfo($image, PATHINFO_EXTENSION));
	$extensions = explode(",", 'jpg,jpe,jpeg,png,gif');
  	$image_path = $gal_path.'/'.$image;

	if( strpos($image, './') or !in_array($ext, $extensions) or !file_exists($image_path))
  		$this->not_found();

このコード内で $this->not_found(); が実行されると、File not found. となります。
このメソッドが実行されるケースとしては、

  1. パスに ./ が含まれている
  2. 拡張子が画像以外のもの
  3. ファイルがそもそも存在しない

のいずれかになります。

実を言うと、今回は、マルチサイトで利用したために(マルチサイトの場合、画像のパスは実際のサーバのファイルの場所と異なる)見つからなかったわけです。(なので、マルチサイト以外の方はスルーして次へ)

対策としては、マルチサイトか否かの判別を行い、マルチサイトであれば、パスの変換処理を追加することになります。

thumb.phpへのWordPress読み込み

しかしながら、thumb.phpは、WordPressとは関係なく単一のプログラムとして動作しているため、そのままではマルチサイトか否かの判別はできません。そこで、thumb.phpにWordPressを読み込ませる処理(CODE 4)を thumb.php のglobal $cache; の直下に配置します。また、今回は、マルチサイトかどうかの判別ができればよいので、 define( ‘SHORTINIT’, true ); を定義し、プラグインなどの読み込みは行わないようにします。

CODE 4

global $cache;
define( 'SHORTINIT', true  );
$load_file = dirname( __FILE__ ) . '/../../../../wp-load.php';
require_once( $load_file );
var_dump( $wpdb, $blog_id );

パスの指定が少々みっともない感じですが、致し方ないところです。
画像のパスにアクセスして、$wpdbや$blog_idが正しく表示されれば、この段階まではオッケーです。(検証ができたら、消すかコメントアウトするようにしましょう。)

パスの判別ロジック追加

$image_path を生成している直前に、CODE 5のように、マルチサイト用の記述を追加します。
今回は、ディレクトリ型ではなく、マルチドメイン型でのマルチサイトだったので、固定のパスとブログidの数字をつなぎ合わせたものを、挟むだけで良かったのですが(本当は、wp-contentが変更されているケースを想定しなければなりません。)、ディレクトリ型での運用の場合は、もう少し複雑なロジックになるかもしれません。

CODE 5

	if ( is_multisite() ) {
		$image = 'wp-content/blogs.dir/' . $blog_id . $image;
	}
  	$image_path = $gal_path.'/'.$image;

あとは、Thumbyメソッド内で、$blog_id を利用するため、Thumby メソッドの冒頭に global 宣言を追加して、$blog_id が読めるようにしておきます。CODE 6は、パスの判別ロジックを追加した後の Thumby メソッドの冒頭部分になります。

CODE 6

function Thumby($image, $pathto_cache, $max_width = 1200, $max_height = 1200, $force_size = 0) {
	global $blog_id;
	if($force_size = '') $force_size = 0;
	if($max_width == 0) $max_width = 1200;
	if($max_height == 0) $max_height = 1200;

	// If you know what you're doing, you can set this to "im" for ImageMagick, make sure to change $convert_path below
	$software = 'gd';
	$gal_path = $_SERVER['DOCUMENT_ROOT'];
	$ext = strtolower(pathinfo($image, PATHINFO_EXTENSION));
	$extensions = explode(",", 'jpg,jpe,jpeg,png,gif');
	if ( is_multisite() ) {
		$image = 'wp-content/blogs.dir/' . $blog_id . $image;
	}
  	$image_path = $gal_path.'/'.$image;

これで、画像がようやく表示されるようになりました。

ようやく画像が表示できるようになりました

あとは、右上の ARCHIVE のリンクがエラーになってしまっているので、これを修正。
これは、header.phpのget_year_linkに引数を追加すれば解消します。

CODE 7

			<li><a href="<?php echo get_year_link( 0 ); ?>">archive</a></li>

get_year_linkの引数は、本来、年にあたる4桁の数字を指定するものですが、0や、false、空文字列など、falseと同義に判別できるものであれば、自動的に現在の年のリンクを返すようになっています。

これで一応、動作に問題はでなくなりましたが、本来あるはずのないオブジェクトのプロパティも参照するようになっていましたので、おそらく Notice レベルのエラーは多発していると思われます。

Google マップの追加

これは完全オリジナルですが、カスタムフィールドに、緯度・経度の情報を入力しておけば、該当する地域のマップを表示するようにしてみました。

まずは、head内にGoogle Map APIのスクリプトを出力するよう、functions.phpに下記を追記。

CODE 8

function print_google_map_script() {
?>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<?php
}
add_action( 'wp_head', 'print_google_map_script' );

次に、duotone/post.php に マップ表示用のコードを追記。
カスタムフィールドの lat,lng というデータの有無を確認し、存在していれば、該当する緯度経度を中心に Googleマップを表示するようにしています。

CODE 9

<?php if ( $latlng = get_post_meta( $post->ID, 'lat,lng', true ) ) : ?>
	<div id="map" style="margin-left: 5px; width: <?php echo (int)$content_width; ?>px; height: <?php echo ceil( (int)$content_width * 2 / 3 ); ?>px;">
	</div>
	<script type="text/javascript">
	google.maps.event.addDomListener(window, 'load', function() {
		var mapdiv = document.getElementById('map');
		var myOptions = {
			zoom: 11,
			center: new google.maps.LatLng( <?php echo esc_html( $latlng ); ?> ),
			mapTypeId: google.maps.MapTypeId.ROADMAP,
			scaleControl: true,
		};
		var map = new google.maps.Map(mapdiv, myOptions);
	
		var marker = new google.maps.Marker({
			icon: 'http://maps.google.co.jp/mapfiles/ms/icons/blue-pushpin.png',
			position: new google.maps.LatLng( <?php echo esc_html( $latlng ); ?> ),
			map: map, 
			title: '<?php the_title(); ?>'
		});
	
		var infowindow = new google.maps.InfoWindow({
			content: '<a href="<?php the_permalink() ?>"><?php the_title(); ?></a>',
			size: new google.maps.Size( 100, 50 )
		});
		google.maps.event.addListener(marker, 'click', function() {
			infowindow.open(map,marker);
		});
	});
	</script>
<?php endif; ?>

Google マップの追加

もうすこし、エラーなどを解消させたら、配布してみようかしら。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です