WordPress のテーマ自動生成のサンプルPluginを書いてみた

2014年12月7日

WordPress のテーマテンプレートを動的に書き換えるという、若干意味不明な物を作っていて、WordPressのソースコードを読んだ結果、一度テーマを切り替えてから編集する必要があるという結論に達し切り替え部分をどうするかを考えていて出来上がったコードです。

オリジナルテーマテンプレートを選択してボタンをクリックすると、Flexibe Sub Themeというサブテーマが自動生成され、テーマが切り替わります。

昨今の WordPress のプラグインの主流はクラス化してコンストラクタから立ち上げるという感じらしく、今回のコードをそれを風潮しまとめ上げています。

また、テーマの切り替えはajaxを利用して、外観に追加されたオプションメニューから行います。

flexible-sub-theme

WordPress のInclude内のfile.phpにファイル関連のファンクションも纏まっているし、オフィシャルディレクトリに登録できないような日本語専用テーマの自動アップグレードや、ファイルをドロップするだけでアンオフィシャルテーマを適応するとか、あとはやり方次第な気がします。

<?php
/*
 * Plugin Name: Flexible Sub Theme
 * Plugin URI: https://lab.planetleaf.com/wordpress/
 * Description: Flexible Sub Theme
 * Version: 0.0.1
 * Author: sekishi
 * Author URI: https://lab.planetleaf.com/
 * Text Domain: flexiblesubtheme
 * License: GPLv2
 * License URI: http://www.gnu.org/licenses/gpl-2.0.html
*/

new FlexibleSubTheme;


class FlexibleSubTheme{
	
	private $title	 = '';// 'Flexible Sub Theme';
	private $name	 = 'flexiblesubtheme';
	private $role	 = 'edit_theme_options';
	
	private $basedir = null;
	
	function __construct() 
	{
		if( false === get_option( 'flexiblesubtheme_bind_themename' ) )
			add_option( 'flexiblesubtheme_bind_themename', '' );

		$this->basedir = WP_PLUGIN_URL.'/'.dirname(plugin_basename(__FILE__));
		
		add_action('admin_init', array(&$this,'init') );
		add_action('admin_menu', array(&$this,'add_admin_page') );
		
		add_action('admin_print_scripts', array(&$this,'js_admin_header') );
		add_action('wp_ajax_flexiblesubtheme_elev_lookup', array(&$this,'ajax_elev_lookup') );
		
		add_action('admin_head', array(&$this,'custom_admin_css'), 100);
	}
	
	function init() 
	{
	}
	
	function custom_admin_css()
	{
?>
<style type="text/css">
<!--
input[type="button"][disabled], input[type="submit"][disabled], input[type="reset"][disabled] {
	align-items: flex-start;
	text-align: center;
	cursor: default;
//	color: buttontext;
//	padding: 2px 6px 3px;
	border: 2px outset buttonface;
	border-image-source: initial;
	border-image-slice: initial;
	border-image-width: initial;
	border-image-outset: initial;
	border-image-repeat: initial;
	background-color: buttonface;
	box-sizing: border-box;
}
//-->
</style>
<?php
	}
	
	function check_directory($path)
	{
		$result = false;
		if( file_exists( $path ) ){
			$result = true;
		}else{
			if (mkdir( $path , 0755,true) )
			{
				$result = true;
			}
		}
		return $result;
	}

	function ajax_elev_lookup()
	{
		$subthemedirectory = ABSPATH.'wp-content/themes/_flexiblesubtheme_maintenance';
		
		// build sub theme,change theme to maintenance theme.
		
		if( $this->check_directory( $subthemedirectory ) )
		{
			$filename = $subthemedirectory.'/index.php';
			
			if( file_exists( $filename ) )
			{
				file_put_contents( $filename,
					'<?php get_header(); ?>'."\n".
					'<div id="container">'."\n".
					'<div id="main">'."\n".
					'<p>UNDER MAINTENANCE</p>'."\n".
					'</div>'."\n".
					'</div>'."\n".
					'<?php get_footer(); ?>'."\n"
					);
			}
			
			$filename = $subthemedirectory.'/style.css';
			
			if( file_exists( $filename ) )
			{
				file_put_contents( $filename,
					'@charset "utf-8";'."\n".
					'/*'."\n".
					'Theme Name:     Flexibl Sub Theme Maintenance'."\n".
					'Theme URI:      http: //lab.planetleaf.com/'."\n".
					'Description:    Maintenance Theme'."\n".
					'Author:         Sekishi'."\n".
					'Author URI:     http: //lab.planetleaf.com/'."\n".
					'Version:        0.1.0'."\n".
					'*/'."\n"
					);
			}
			
			if ( current_user_can( 'flexiblesubtheme' ) )
			{
				$themename = '_flexiblesubtheme_maintenance';
				switch_theme( $themename );
			}
			
			$subthemedirectory = ABSPATH.'wp-content/themes/flexiblesubtheme';
			
			if( $this->check_directory( $subthemedirectory ) )
			{
				// build sub theme
				
				$stylesheet = $_POST['selecttheme'];
				$theme_data = wp_get_theme( $stylesheet );
				
				update_option('flexiblesubtheme_bind_themename', $stylesheet);
			
				file_put_contents($subthemedirectory.'/style.css',
					'@charset "utf-8";'."\n".
					'/*'."\n".
					'Theme Name:     Flexibl Sub Theme'."\n".
					"Template:       {$stylesheet}\n".
					'Theme URI:      http: //lab.planetleaf.com/'."\n".
					'Description:    Flexible Sub Theme'."\n".
					'Author:         Sekishi'."\n".
					'Author URI:     http: //lab.planetleaf.com/'."\n".
					'Version:        0.1.0'."\n".
					'*/'."\n".
					"@import url('../{$stylesheet}/style.css');\n"
					);
					
				// change theme to flexible sub theme.
				
				$themename = 'flexiblesubtheme';
				switch_theme( $themename );
			}
		}
		
		die("window.flexiblesubtheme_loading.style.visibility = 'hidden';".
			"window.flexiblesubtheme_swthemebutton.disabled = false;");
	}
	
	function js_admin_header()
	{
		// use SACK liblary
		wp_print_scripts( array( 'sack' ));
// ------------------------------------------------------------- //
?>
<script type="text/javascript">
//<![CDATA[
function flexiblesubtheme_ajax_change_bind_theme( selecttheme )
{
	var ajax = new sack( "<?php bloginfo( 'wpurl' ); ?>/wp-admin/admin-ajax.php" ); 
	window.flexiblesubtheme_loading.style.visibility = 'visible';
	window.flexiblesubtheme_swthemebutton.disabled = true;
	
	ajax.execute = 1;
	ajax.method = 'POST';
	ajax.setVar( "action", "flexiblesubtheme_elev_lookup" );
	ajax.setVar( "selecttheme", selecttheme );
	ajax.encVar( "cookie", document.cookie, false );
	ajax.onError = function() {
		alert('Ajax error in looking up elevation');
		window.flexiblesubtheme_loading.style.visibility = 'hidden';
		window.flexiblesubtheme_swthemebutton.disabled = false;
		};
	ajax.runAJAX();

	return true;
}
//]]>
</script>
<?php
// ------------------------------------------------------------- //
	}
	
	public function add_admin_page()
	{
		// localization
		load_plugin_textdomain(
			$this->name,
			PLUGINDIR.'/'.dirname(plugin_basename( __FILE__ )). '/languages',
			dirname(plugin_basename( __FILE__ )). '/languages' );
		
		$this->title = __('Flexible Sub Theme', $this->name);
		add_theme_page(
			$this->title,
			$this->title,
			$this->role,
			$this->name,
			array(&$this,'admin_page')
		);
		
	}


	public function dropdown_themes()
	{
		$p = '';
		$r = '';
		
		if ( current_user_can( 'switch_themes' ) )
			$themes = wp_prepare_themes_for_js();
		else
			$themes = wp_prepare_themes_for_js( array( wp_get_theme() ) );
		
		$bind_themename = get_option( 'flexiblesubtheme_bind_themename' , '' );
		foreach ( $themes as $theme )
		{
			$id 	= $theme['id'];
			$name	= $theme['name'];
			$selected = '';
			
			if( $id === "_flexiblesubtheme_maintenance" || $id === "flexiblesubtheme" ){
				//
			}else{
				$theme_data = wp_get_theme( $id );
				if( $theme_data->Template === $id )
				{
					if( $bind_themename === $id )
						$p = "\n\t<option value='$id' $selected> " . esc_html($name) . "</option>";
					else
						$r .= "\n\t<option value='$id'> " . esc_html($name) . "</option>";
				}
			}
			
		}
		return $p . $r;
	}
	
	public function admin_page() 
	{
		echo   '<h2>Flexible Sub Theme: '.__('Options', $this->name).'</h2>';
// ------------------------------------------------------------- //
?>
<tr>
<th scope="row"><?php _e('Themes') ?></th>
<td>
<form name="selecttheme">
<select name="bind_themename" id="bind_themename">
<?php echo $this->dropdown_themes() ?>
<input id="flexiblesubtheme_swthemebutton"	type="button" value="Change original theme" onclick="flexiblesubtheme_ajax_change_bind_theme( this.form.bind_themename.value );" />
<span id="flexiblesubtheme_loading" style="visibility:hidden;"><img src="<?php bloginfo( 'wpurl' ) ?>/wp-admin/images/loading.gif"></span>
</form>
</td>
</tr>
<?php
// ------------------------------------------------------------- //
	}
}

?>